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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h78
-rw-r--r--source/blender/blenkernel/BKE_action.h187
-rw-r--r--source/blender/blenkernel/BKE_anim_data.h63
-rw-r--r--source/blender/blenkernel/BKE_anim_path.h11
-rw-r--r--source/blender/blenkernel/BKE_anim_visualization.h21
-rw-r--r--source/blender/blenkernel/BKE_animsys.h60
-rw-r--r--source/blender/blenkernel/BKE_appdir.h100
-rw-r--r--source/blender/blenkernel/BKE_armature.h193
-rw-r--r--source/blender/blenkernel/BKE_asset.h3
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog.hh17
-rw-r--r--source/blender/blenkernel/BKE_attribute_access.hh27
-rw-r--r--source/blender/blenkernel/BKE_autoexec.h4
-rw-r--r--source/blender/blenkernel/BKE_blender.h11
-rw-r--r--source/blender/blenkernel/BKE_blender_copybuffer.h40
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h43
-rw-r--r--source/blender/blenkernel/BKE_blendfile_link_append.h222
-rw-r--r--source/blender/blenkernel/BKE_boids.h6
-rw-r--r--source/blender/blenkernel/BKE_bpath.h211
-rw-r--r--source/blender/blenkernel/BKE_brush.h73
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h67
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h6
-rw-r--r--source/blender/blenkernel/BKE_callbacks.h3
-rw-r--r--source/blender/blenkernel/BKE_camera.h29
-rw-r--r--source/blender/blenkernel/BKE_cloth.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h112
-rw-r--r--source/blender/blenkernel/BKE_collision.h20
-rw-r--r--source/blender/blenkernel/BKE_colortools.h75
-rw-r--r--source/blender/blenkernel/BKE_constraint.h109
-rw-r--r--source/blender/blenkernel/BKE_context.h33
-rw-r--r--source/blender/blenkernel/BKE_crazyspace.h8
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.h3
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.hh20
-rw-r--r--source/blender/blenkernel/BKE_curve.h108
-rw-r--r--source/blender/blenkernel/BKE_curve_to_mesh.hh14
-rw-r--r--source/blender/blenkernel/BKE_curveprofile.h83
-rw-r--r--source/blender/blenkernel/BKE_customdata.h313
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h10
-rw-r--r--source/blender/blenkernel/BKE_deform.h105
-rw-r--r--source/blender/blenkernel/BKE_displist.h6
-rw-r--r--source/blender/blenkernel/BKE_duplilist.h3
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h40
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h20
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h10
-rw-r--r--source/blender/blenkernel/BKE_editmesh_tangent.h7
-rw-r--r--source/blender/blenkernel/BKE_effect.h29
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h247
-rw-r--r--source/blender/blenkernel/BKE_fcurve_driver.h51
-rw-r--r--source/blender/blenkernel/BKE_fluid.h4
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h4
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.h2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh323
-rw-r--r--source/blender/blenkernel/BKE_geometry_set_instances.hh15
-rw-r--r--source/blender/blenkernel/BKE_global.h88
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h408
-rw-r--r--source/blender/blenkernel/BKE_gpencil_curve.h29
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h276
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h126
-rw-r--r--source/blender/blenkernel/BKE_icons.h104
-rw-r--r--source/blender/blenkernel/BKE_idprop.h139
-rw-r--r--source/blender/blenkernel/BKE_idtype.h94
-rw-r--r--source/blender/blenkernel/BKE_image.h217
-rw-r--r--source/blender/blenkernel/BKE_ipo.h13
-rw-r--r--source/blender/blenkernel/BKE_key.h83
-rw-r--r--source/blender/blenkernel/BKE_keyconfig.h12
-rw-r--r--source/blender/blenkernel/BKE_lattice.h1
-rw-r--r--source/blender/blenkernel/BKE_layer.h128
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h289
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h227
-rw-r--r--source/blender/blenkernel/BKE_lib_query.h75
-rw-r--r--source/blender/blenkernel/BKE_lib_remap.h31
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h4
-rw-r--r--source/blender/blenkernel/BKE_main.h114
-rw-r--r--source/blender/blenkernel/BKE_main_idmap.h11
-rw-r--r--source/blender/blenkernel/BKE_mask.h128
-rw-r--r--source/blender/blenkernel/BKE_material.h88
-rw-r--r--source/blender/blenkernel/BKE_mball.h42
-rw-r--r--source/blender/blenkernel/BKE_mesh.h347
-rw-r--r--source/blender/blenkernel/BKE_mesh_boolean_convert.hh10
-rw-r--r--source/blender/blenkernel/BKE_mesh_iterators.h5
-rw-r--r--source/blender/blenkernel/BKE_mesh_mapping.h79
-rw-r--r--source/blender/blenkernel/BKE_mesh_mirror.h14
-rw-r--r--source/blender/blenkernel/BKE_mesh_remap.h13
-rw-r--r--source/blender/blenkernel/BKE_mesh_runtime.h26
-rw-r--r--source/blender/blenkernel/BKE_mesh_tangent.h21
-rw-r--r--source/blender/blenkernel/BKE_modifier.h72
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h30
-rw-r--r--source/blender/blenkernel/BKE_multires.h72
-rw-r--r--source/blender/blenkernel/BKE_nla.h198
-rw-r--r--source/blender/blenkernel/BKE_node.h319
-rw-r--r--source/blender/blenkernel/BKE_object.h276
-rw-r--r--source/blender/blenkernel/BKE_object_deform.h88
-rw-r--r--source/blender/blenkernel/BKE_ocean.h42
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h44
-rw-r--r--source/blender/blenkernel/BKE_paint.h103
-rw-r--r--source/blender/blenkernel/BKE_particle.h121
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h75
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h81
-rw-r--r--source/blender/blenkernel/BKE_pointcloud.h2
-rw-r--r--source/blender/blenkernel/BKE_preferences.h10
-rw-r--r--source/blender/blenkernel/BKE_report.h7
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h129
-rw-r--r--source/blender/blenkernel/BKE_scene.h122
-rw-r--r--source/blender/blenkernel/BKE_screen.h80
-rw-r--r--source/blender/blenkernel/BKE_shader_fx.h22
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h86
-rw-r--r--source/blender/blenkernel/BKE_softbody.h39
-rw-r--r--source/blender/blenkernel/BKE_spline.hh168
-rw-r--r--source/blender/blenkernel/BKE_studiolight.h8
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h18
-rw-r--r--source/blender/blenkernel/BKE_text.h48
-rw-r--r--source/blender/blenkernel/BKE_texture.h12
-rw-r--r--source/blender/blenkernel/BKE_tracking.h267
-rw-r--r--source/blender/blenkernel/BKE_type_conversions.hh84
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h103
-rw-r--r--source/blender/blenkernel/BKE_unit.h54
-rw-r--r--source/blender/blenkernel/BKE_vfont.h3
-rw-r--r--source/blender/blenkernel/BKE_vfontdata.h6
-rw-r--r--source/blender/blenkernel/BKE_volume.h5
-rw-r--r--source/blender/blenkernel/BKE_volume_to_mesh.hh2
-rw-r--r--source/blender/blenkernel/BKE_workspace.h59
-rw-r--r--source/blender/blenkernel/BKE_writeavi.h4
-rw-r--r--source/blender/blenkernel/CMakeLists.txt10
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c4
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h17
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_legacy.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc67
-rw-r--r--source/blender/blenkernel/intern/action.c128
-rw-r--r--source/blender/blenkernel/intern/anim_data.c83
-rw-r--r--source/blender/blenkernel/intern/anim_path.c12
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c71
-rw-r--r--source/blender/blenkernel/intern/anim_visualization.c14
-rw-r--r--source/blender/blenkernel/intern/appdir.c107
-rw-r--r--source/blender/blenkernel/intern/armature.c192
-rw-r--r--source/blender/blenkernel/intern/armature_deform.c1
-rw-r--r--source/blender/blenkernel/intern/armature_update.c90
-rw-r--r--source/blender/blenkernel/intern/asset.cc5
-rw-r--r--source/blender/blenkernel/intern/asset_catalog.cc31
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_path.cc2
-rw-r--r--source/blender/blenkernel/intern/asset_library.cc4
-rw-r--r--source/blender/blenkernel/intern/asset_library_service.cc3
-rw-r--r--source/blender/blenkernel/intern/asset_library_service_test.cc4
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc135
-rw-r--r--source/blender/blenkernel/intern/autoexec.c4
-rw-r--r--source/blender/blenkernel/intern/blender.c9
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c153
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c4
-rw-r--r--source/blender/blenkernel/intern/blender_user_menu.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c70
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c1615
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c914
-rw-r--r--source/blender/blenkernel/intern/bpath_test.cc181
-rw-r--r--source/blender/blenkernel/intern/brush.c36
-rw-r--r--source/blender/blenkernel/intern/bvhutils.cc63
-rw-r--r--source/blender/blenkernel/intern/cachefile.c15
-rw-r--r--source/blender/blenkernel/intern/callbacks.c1
-rw-r--r--source/blender/blenkernel/intern/camera.c8
-rw-r--r--source/blender/blenkernel/intern/cloth.c3
-rw-r--r--source/blender/blenkernel/intern/collection.c112
-rw-r--r--source/blender/blenkernel/intern/collision.c8
-rw-r--r--source/blender/blenkernel/intern/colortools.c30
-rw-r--r--source/blender/blenkernel/intern/constraint.c55
-rw-r--r--source/blender/blenkernel/intern/context.c13
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c5
-rw-r--r--source/blender/blenkernel/intern/cryptomatte.cc18
-rw-r--r--source/blender/blenkernel/intern/curve.cc (renamed from source/blender/blenkernel/intern/curve.c)560
-rw-r--r--source/blender/blenkernel/intern/curve_bevel.c44
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c6
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc56
-rw-r--r--source/blender/blenkernel/intern/curve_to_mesh_convert.cc14
-rw-r--r--source/blender/blenkernel/intern/curveprofile.cc79
-rw-r--r--source/blender/blenkernel/intern/customdata.c105
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c10
-rw-r--r--source/blender/blenkernel/intern/data_transfer_intern.h4
-rw-r--r--source/blender/blenkernel/intern/deform.c134
-rw-r--r--source/blender/blenkernel/intern/displist.cc45
-rw-r--r--source/blender/blenkernel/intern/displist_tangent.c4
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c20
-rw-r--r--source/blender/blenkernel/intern/editmesh.c16
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c6
-rw-r--r--source/blender/blenkernel/intern/editmesh_tangent.c7
-rw-r--r--source/blender/blenkernel/intern/effect.c62
-rw-r--r--source/blender/blenkernel/intern/extern_implementations.cc27
-rw-r--r--source/blender/blenkernel/intern/fcurve.c108
-rw-r--r--source/blender/blenkernel/intern/fcurve_cache.c5
-rw-r--r--source/blender/blenkernel/intern/fcurve_driver.c26
-rw-r--r--source/blender/blenkernel/intern/fluid.c6
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c56
-rw-r--r--source/blender/blenkernel/intern/freestyle.c4
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curve.cc227
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc175
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc62
-rw-r--r--source/blender/blenkernel/intern/geometry_component_pointcloud.cc9
-rw-r--r--source/blender/blenkernel/intern/geometry_component_volume.cc7
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc196
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc389
-rw-r--r--source/blender/blenkernel/intern/gpencil.c403
-rw-r--r--source/blender/blenkernel/intern/gpencil_curve.c29
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc370
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c221
-rw-r--r--source/blender/blenkernel/intern/hair.c5
-rw-r--r--source/blender/blenkernel/intern/icons.cc98
-rw-r--r--source/blender/blenkernel/intern/idprop.c124
-rw-r--r--source/blender/blenkernel/intern/idtype.c71
-rw-r--r--source/blender/blenkernel/intern/image.c169
-rw-r--r--source/blender/blenkernel/intern/image_gpu.cc (renamed from source/blender/blenkernel/intern/image_gpu.c)128
-rw-r--r--source/blender/blenkernel/intern/ipo.c13
-rw-r--r--source/blender/blenkernel/intern/key.c72
-rw-r--r--source/blender/blenkernel/intern/keyconfig.c5
-rw-r--r--source/blender/blenkernel/intern/lattice.c2
-rw-r--r--source/blender/blenkernel/intern/layer.c174
-rw-r--r--source/blender/blenkernel/intern/layer_utils.c8
-rw-r--r--source/blender/blenkernel/intern/lib_id.c280
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c49
-rw-r--r--source/blender/blenkernel/intern/lib_id_eval.c5
-rw-r--r--source/blender/blenkernel/intern/lib_override.c304
-rw-r--r--source/blender/blenkernel/intern/lib_query.c70
-rw-r--r--source/blender/blenkernel/intern/lib_remap.c34
-rw-r--r--source/blender/blenkernel/intern/library.c23
-rw-r--r--source/blender/blenkernel/intern/light.c2
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c2
-rw-r--r--source/blender/blenkernel/intern/linestyle.c6
-rw-r--r--source/blender/blenkernel/intern/main.c106
-rw-r--r--source/blender/blenkernel/intern/main_idmap.c12
-rw-r--r--source/blender/blenkernel/intern/mask.c32
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c5
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c3
-rw-r--r--source/blender/blenkernel/intern/material.c25
-rw-r--r--source/blender/blenkernel/intern/mball.c72
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c18
-rw-r--r--source/blender/blenkernel/intern/mesh.cc143
-rw-r--r--source/blender/blenkernel/intern/mesh_boolean_convert.cc10
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc5
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.cc81
-rw-r--r--source/blender/blenkernel/intern/mesh_iterators.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c88
-rw-r--r--source/blender/blenkernel/intern/mesh_merge.c32
-rw-r--r--source/blender/blenkernel/intern/mesh_mirror.c50
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc62
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c21
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c34
-rw-r--r--source/blender/blenkernel/intern/mesh_tangent.c21
-rw-r--r--source/blender/blenkernel/intern/mesh_tessellate.c22
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c55
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.cc3
-rw-r--r--source/blender/blenkernel/intern/modifier.c83
-rw-r--r--source/blender/blenkernel/intern/movieclip.c25
-rw-r--r--source/blender/blenkernel/intern/multires.c15
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c4
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.h123
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_util.c7
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_vertcos.c1
-rw-r--r--source/blender/blenkernel/intern/nla.c212
-rw-r--r--source/blender/blenkernel/intern/node.cc261
-rw-r--r--source/blender/blenkernel/intern/object.cc451
-rw-r--r--source/blender/blenkernel/intern/object_deform.c84
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc55
-rw-r--r--source/blender/blenkernel/intern/object_update.c19
-rw-r--r--source/blender/blenkernel/intern/ocean.c12
-rw-r--r--source/blender/blenkernel/intern/ocean_spectrum.c17
-rw-r--r--source/blender/blenkernel/intern/packedFile.c21
-rw-r--r--source/blender/blenkernel/intern/paint.c39
-rw-r--r--source/blender/blenkernel/intern/paint_toolslots.c4
-rw-r--r--source/blender/blenkernel/intern/particle.c59
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c7
-rw-r--r--source/blender/blenkernel/intern/particle_system.c22
-rw-r--r--source/blender/blenkernel/intern/pbvh.c16
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c6
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h9
-rw-r--r--source/blender/blenkernel/intern/pointcache.c93
-rw-r--r--source/blender/blenkernel/intern/pointcloud.cc5
-rw-r--r--source/blender/blenkernel/intern/preferences.c10
-rw-r--r--source/blender/blenkernel/intern/report.c5
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c25
-rw-r--r--source/blender/blenkernel/intern/scene.c113
-rw-r--r--source/blender/blenkernel/intern/screen.c75
-rw-r--r--source/blender/blenkernel/intern/shader_fx.c14
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c80
-rw-r--r--source/blender/blenkernel/intern/simulation.cc2
-rw-r--r--source/blender/blenkernel/intern/softbody.c19
-rw-r--r--source/blender/blenkernel/intern/sound.c26
-rw-r--r--source/blender/blenkernel/intern/speaker.c2
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc35
-rw-r--r--source/blender/blenkernel/intern/spline_bezier.cc63
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc3
-rw-r--r--source/blender/blenkernel/intern/spline_poly.cc9
-rw-r--r--source/blender/blenkernel/intern/studiolight.c6
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c5
-rw-r--r--source/blender/blenkernel/intern/text.c52
-rw-r--r--source/blender/blenkernel/intern/texture.c9
-rw-r--r--source/blender/blenkernel/intern/tracking.c121
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_detect.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_plane_tracker.c1
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c6
-rw-r--r--source/blender/blenkernel/intern/tracking_solver.c22
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c36
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c17
-rw-r--r--source/blender/blenkernel/intern/type_conversions.cc364
-rw-r--r--source/blender/blenkernel/intern/undo_system.c146
-rw-r--r--source/blender/blenkernel/intern/unit.c17
-rw-r--r--source/blender/blenkernel/intern/vfont.c23
-rw-r--r--source/blender/blenkernel/intern/vfontdata_freetype.c8
-rw-r--r--source/blender/blenkernel/intern/volume.cc17
-rw-r--r--source/blender/blenkernel/intern/workspace.c46
-rw-r--r--source/blender/blenkernel/intern/world.c2
-rw-r--r--source/blender/blenkernel/intern/writeavi.c1
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c26
-rw-r--r--source/blender/blenkernel/nla_private.h33
-rw-r--r--source/blender/blenkernel/tracking_private.h38
311 files changed, 13667 insertions, 9168 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index c95190d2c83..0fff6d27031 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -242,8 +242,17 @@ struct DerivedMesh {
void (*release)(DerivedMesh *dm);
};
+/**
+ * Utility function to initialize a #DerivedMesh's function pointers to
+ * the default implementation (for those functions which have a default).
+ */
void DM_init_funcs(DerivedMesh *dm);
+/**
+ * Utility function to initialize a #DerivedMesh for the desired number
+ * of vertices, edges and faces (doesn't allocate memory for them, just
+ * sets up the custom data layers)>
+ */
void DM_init(DerivedMesh *dm,
DerivedMeshType type,
int numVerts,
@@ -252,6 +261,10 @@ void DM_init(DerivedMesh *dm,
int numLoops,
int numPolys);
+/**
+ * Utility function to initialize a DerivedMesh for the desired number
+ * of vertices, edges and faces, with a layer setup copied from source
+ */
void DM_from_template_ex(DerivedMesh *dm,
DerivedMesh *source,
DerivedMeshType type,
@@ -276,43 +289,59 @@ void DM_from_template(DerivedMesh *dm,
*/
bool DM_release(DerivedMesh *dm);
+/**
+ * set the #CD_FLAG_NOCOPY flag in custom data layers where the mask is
+ * zero for the layer type, so only layer types specified by the mask
+ * will be copied
+ */
void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask);
-/* adds a vertex/edge/face custom data layer to a DerivedMesh, optionally
+/* Adds a vertex/edge/face custom data layer to a DerivedMesh, optionally
* backed by an external data array
* alloctype defines how the layer is allocated or copied, and how it is
- * freed, see BKE_customdata.h for the different options
- */
+ * freed, see BKE_customdata.h for the different options. */
+
void DM_add_vert_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_edge_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_tessface_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_poly_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
-/* custom data access functions
- * return pointer to data from first layer which matches type
- * if they return NULL for valid indices, data doesn't exist
- * note these return pointers - any change modifies the internals of the mesh
- */
+/* -------------------------------------------------------------------- */
+/** \name Custom Data Access Functions
+ *
+ * \return pointer to data from first layer which matches type
+ * if they return NULL for valid indices, data doesn't exist.
+ * \note these return pointers - any change modifies the internals of the mesh.
+ * \{ */
+
void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type);
void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type);
void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type);
void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
-/* custom data layer access functions
- * return pointer to first data layer which matches type (a flat array)
- * if they return NULL, data doesn't exist
- * note these return pointers - any change modifies the internals of the mesh
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom Data Layer Access Functions
+ *
+ * \return pointer to first data layer which matches type (a flat array)
+ * if they return NULL, data doesn't exist.
+ * \note these return pointers - any change modifies the internals of the mesh.
+ * \{ */
+
void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_poly_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_loop_data_layer(struct DerivedMesh *dm, int type);
-/* custom data copy functions
+/** \} */
+
+/**
+ * Custom data copy functions
* copy count elements from source_index in source to dest_index in dest
- * these copy all layers for which the CD_FLAG_NOCOPY flag is not set
+ * these copy all layers for which the CD_FLAG_NOCOPY flag is not set.
*/
void DM_copy_vert_data(struct DerivedMesh *source,
struct DerivedMesh *dest,
@@ -320,13 +349,26 @@ void DM_copy_vert_data(struct DerivedMesh *source,
int dest_index,
int count);
-/* Sets up mpolys for a DM based on face iterators in source. */
+/**
+ * Sets up mpolys for a DM based on face iterators in source.
+ */
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
void DM_ensure_normals(DerivedMesh *dm);
+/**
+ * Ensure the array is large enough.
+ *
+ * \note This function must always be thread-protected by caller.
+ * It should only be used by internal code.
+ */
void DM_ensure_looptri_data(DerivedMesh *dm);
+/**
+ * Interpolates vertex data from the vertices indexed by `src_indices` in the
+ * source mesh using the given weights and stores the result in the vertex
+ * indexed by `dest_index` in the `dest` mesh.
+ */
void DM_interp_vert_data(struct DerivedMesh *source,
struct DerivedMesh *dest,
int *src_indices,
@@ -336,7 +378,9 @@ void DM_interp_vert_data(struct DerivedMesh *source,
void mesh_get_mapped_verts_coords(struct Mesh *me_eval, float (*r_cos)[3], const int totcos);
-/* same as above but won't use render settings */
+/**
+ * Same as above but won't use render settings.
+ */
struct Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *,
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 763e540fdd9..ea8ee3f93b1 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -79,50 +79,86 @@ typedef enum eAction_TransformFlags {
ACT_TRANS_ALL = (ACT_TRANS_ONLY | ACT_TRANS_PROP),
} eAction_TransformFlags;
-/* Return flags indicating which transforms the given object/posechannel has
+/**
+ * Return flags indicating which transforms the given object/posechannel has
* - if 'curves' is provided, a list of links to these curves are also returned
- * whose nodes WILL NEED FREEING
+ * whose nodes WILL NEED FREEING.
*/
short action_get_item_transforms(struct bAction *act,
struct Object *ob,
struct bPoseChannel *pchan,
ListBase *curves);
-/* Some kind of bounding box operation on the action */
+/**
+ * Calculate the extents of given action.
+ */
void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers);
-/* Does action have any motion data at all? */
+/* Retrieve the intended playback frame range, using the manually set range if available,
+ * or falling back to scanning F-Curves for their first & last frames otherwise. */
+void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end);
+
+/**
+ * Check if the given action has any keyframes.
+ */
bool action_has_motion(const struct bAction *act);
+/**
+ * Is the action configured as cyclic.
+ */
+bool BKE_action_is_cyclic(const struct bAction *act);
+
/* Action Groups API ----------------- */
-/* Get the active action-group for an Action */
+/**
+ * Get the active action-group for an Action.
+ */
struct bActionGroup *get_active_actiongroup(struct bAction *act);
-/* Make the given Action Group the active one */
+/**
+ * Make the given Action-Group the active one.
+ */
void set_active_action_group(struct bAction *act, struct bActionGroup *agrp, short select);
-/* Sync colors used for action/bone group with theme settings */
+/**
+ * Sync colors used for action/bone group with theme settings.
+ */
void action_group_colors_sync(struct bActionGroup *grp, const struct bActionGroup *ref_grp);
-/* Add a new action group with the given name to the action */
+/**
+ * Add a new action group with the given name to the action>
+ */
struct bActionGroup *action_groups_add_new(struct bAction *act, const char name[]);
-/* Add given channel into (active) group */
+/**
+ * Add given channel into (active) group
+ * - assumes that channel is not linked to anything anymore
+ * - always adds at the end of the group
+ */
void action_groups_add_channel(struct bAction *act,
struct bActionGroup *agrp,
struct FCurve *fcurve);
-/* Remove the given channel from all groups */
+/**
+ * Remove the given channel from all groups.
+ */
void action_groups_remove_channel(struct bAction *act, struct FCurve *fcu);
-/* Reconstruct group channel pointers. */
+/**
+ * Reconstruct group channel pointers.
+ * Assumes that the groups referred to by the FCurves are already in act->groups.
+ * Reorders the main channel list to match group order.
+ */
void BKE_action_groups_reconstruct(struct bAction *act);
-/* Find a group with the given name */
+/**
+ * Find a group with the given name.
+ */
struct bActionGroup *BKE_action_group_find_name(struct bAction *act, const char name[]);
-/* Clear all 'temp' flags on all groups */
+/**
+ * Clear all 'temp' flags on all groups.
+ */
void action_groups_clear_tempflags(struct bAction *act);
/**
@@ -139,21 +175,47 @@ bool BKE_action_has_single_frame(const struct bAction *act);
/* Pose API ----------------- */
void BKE_pose_channel_free(struct bPoseChannel *pchan);
+/**
+ * Deallocates a pose channel.
+ * Does not free the pose channel itself.
+ */
void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user);
+/**
+ * Clears the runtime cache of a pose channel without free.
+ */
void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime);
+/**
+ * Reset all non-persistent fields.
+ */
void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime);
+/**
+ * Deallocates runtime cache of a pose channel
+ */
void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime);
+/**
+ * Deallocates runtime cache of a pose channel's B-Bone shape.
+ */
void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime);
void BKE_pose_channels_free(struct bPose *pose);
+/**
+ * Removes and deallocates all channels from a pose.
+ * Does not free the pose itself.
+ */
void BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_user);
+/**
+ * Removes the hash for quick lookup of channels, must be done when adding/removing channels.
+ */
void BKE_pose_channels_hash_ensure(struct bPose *pose);
void BKE_pose_channels_hash_free(struct bPose *pose);
+/**
+ * Selectively remove pose channels.
+ */
void BKE_pose_channels_remove(struct Object *ob,
bool (*filter_fn)(const char *bone_name, void *user_data),
void *user_data);
@@ -161,18 +223,63 @@ void BKE_pose_channels_remove(struct Object *ob,
void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user);
void BKE_pose_free_data(struct bPose *pose);
void BKE_pose_free(struct bPose *pose);
+/**
+ * Removes and deallocates all data from a pose, and also frees the pose.
+ */
void BKE_pose_free_ex(struct bPose *pose, bool do_id_user);
+/**
+ * Allocate a new pose on the heap, and copy the src pose and its channels
+ * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
+ *
+ * \param dst: Should be freed already, makes entire duplicate.
+ */
void BKE_pose_copy_data_ex(struct bPose **dst,
const struct bPose *src,
const int flag,
const bool copy_constraints);
void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints);
+/**
+ * Copy the internal members of each pose channel including constraints
+ * and ID-Props, used when duplicating bones in edit-mode.
+ * (unlike copy_pose_channel_data which only does posing-related stuff).
+ *
+ * \note use when copying bones in edit-mode (on returned value from #BKE_pose_channel_ensure)
+ */
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
void BKE_pose_channel_session_uuid_generate(struct bPoseChannel *pchan);
+/**
+ * Return a pointer to the pose channel of the given name
+ * from this pose.
+ */
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
+/**
+ * Find the active pose-channel for an object
+ * (we can't just use pose, as layer info is in armature)
+ *
+ * \note #Object, not #bPose is used here, as we need layer info from Armature.
+ */
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
+/**
+ * Use this when detecting the "other selected bone",
+ * when we have multiple armatures in pose mode.
+ *
+ * In this case the active-selected is an obvious choice when finding the target for a
+ * constraint for eg. however from the users perspective the active pose bone of the
+ * active object is the _real_ active bone, so any other non-active selected bone
+ * is a candidate for being the other selected bone, see: T58447.
+ */
struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob);
+/**
+ * Looks to see if the channel with the given name already exists
+ * in this pose - if not a new one is allocated and initialized.
+ *
+ * \note Use with care, not on Armature poses but for temporal ones.
+ * \note (currently used for action constraints and in rebuild_pose).
+ */
struct bPoseChannel *BKE_pose_channel_ensure(struct bPose *pose, const char *name);
+/**
+ * \see #ED_armature_ebone_get_mirrored (edit-mode, matching function)
+ */
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name);
void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose);
@@ -181,37 +288,60 @@ void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose);
bool BKE_pose_channels_is_valid(const struct bPose *pose);
#endif
-/* sets constraint flags */
+/**
+ * Checks for IK constraint, Spline IK, and also for Follow-Path constraint.
+ * can do more constraints flags later. pose should be entirely OK.
+ */
void BKE_pose_update_constraint_flags(struct bPose *pose);
-/* tag constraint flags for update */
+/**
+ * Tag constraint flags for update.
+ */
void BKE_pose_tag_update_constraint_flags(struct bPose *pose);
-/* return the name of structure pointed by pose->ikparam */
+/**
+ * Return the name of structure pointed by `pose->ikparam`.
+ */
const char *BKE_pose_ikparam_get_name(struct bPose *pose);
-/* allocate and initialize pose->ikparam according to pose->iksolver */
+/**
+ * Allocate and initialize `pose->ikparam` according to `pose->iksolver`.
+ */
void BKE_pose_ikparam_init(struct bPose *pose);
-/* initialize a bItasc structure with default value */
+/**
+ * Initialize a #bItasc structure with default value.
+ */
void BKE_pose_itasc_init(struct bItasc *itasc);
-/* Checks if a bone is part of an IK chain or not */
+/**
+ * Checks if a bone is part of an IK chain or not.
+ */
bool BKE_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
/* Bone Groups API --------------------- */
-/* Adds a new bone-group */
+/**
+ * Adds a new bone-group (name may be NULL).
+ */
struct bActionGroup *BKE_pose_add_group(struct bPose *pose, const char *name);
-/* Remove a bone-group */
+/**
+ * Remove the given bone-group (expects 'virtual' index (+1 one, used by active_group etc.))
+ * index might be invalid ( < 1), in which case it will be find from grp.
+ */
void BKE_pose_remove_group(struct bPose *pose, struct bActionGroup *grp, const int index);
-/* Remove the matching bone-group from its index */
+/**
+ * Remove the indexed bone-group (expects 'virtual' index (+1 one, used by active_group etc.)).
+ */
void BKE_pose_remove_group_index(struct bPose *pose, const int index);
/* Assorted Evaluation ----------------- */
-/* Used for the Action Constraint */
+/**
+ * For the calculation of the effects of an Action at the given frame on an object
+ * This is currently only used for the Action Constraint
+ */
void what_does_obaction(struct Object *ob,
struct Object *workob,
struct bPose *pose,
@@ -222,11 +352,18 @@ void what_does_obaction(struct Object *ob,
/* for proxy */
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,
const struct bPoseChannel *pchanfrom);
+/**
+ * Both poses should be in sync.
+ */
bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
-/* Clear transforms. */
+/**
+ * Zero the pose transforms for the entire pose or only for selected bones.
+ */
void BKE_pose_rest(struct bPose *pose, bool selected_bones_only);
-/* Tag pose for recalc. Also tag all related data to be recalc. */
+/**
+ * Tag pose for recalculation. Also tag all related data to be recalculated.
+ */
void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose);
void BKE_pose_blend_write(struct BlendWriter *writer, struct bPose *pose, struct bArmature *arm);
diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h
index 14ab9f21424..a65efbd707c 100644
--- a/source/blender/blenkernel/BKE_anim_data.h
+++ b/source/blender/blenkernel/BKE_anim_data.h
@@ -43,43 +43,81 @@ struct bAction;
/* ************************************* */
/* AnimData API */
-/* Check if the given ID-block can have AnimData */
+/**
+ * Check if the given ID-block can have AnimData.
+ */
bool id_type_can_have_animdata(const short id_type);
bool id_can_have_animdata(const struct ID *id);
-/* Get AnimData from the given ID-block */
+/**
+ * Get #AnimData from the given ID-block.
+ */
struct AnimData *BKE_animdata_from_id(struct ID *id);
-/* Ensure AnimData is present in the ID-block (when supported). */
+/**
+ * Ensure #AnimData exists in the given ID-block (when supported).
+ */
struct AnimData *BKE_animdata_ensure_id(struct ID *id);
-/* Set active action used by AnimData from the given ID-block */
+/**
+ * Set active action used by AnimData from the given ID-block.
+ *
+ * Called when user tries to change the active action of an #AnimData block
+ * (via RNA, Outliner, etc.)
+ *
+ * \param reports: Can be NULL.
+ * \param id: The owner of the animation data
+ * \param act: The Action to set, or NULL to clear.
+ *
+ * \return true when the action was successfully updated, false otherwise.
+ */
bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act);
bool BKE_animdata_action_editable(const struct AnimData *adt);
-/* Ensure that the action's idroot is set correctly given the ID type of the owner.
- * Return true if it is, false if it was already set to an incompatible type. */
+/**
+ * Ensure that the action's idroot is set correctly given the ID type of the owner.
+ * Return true if it is, false if it was already set to an incompatible type.
+ */
bool BKE_animdata_action_ensure_idroot(const struct ID *owner, struct bAction *action);
-/* Free AnimData */
+/**
+ * Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer.
+ */
void BKE_animdata_free(struct ID *id, const bool do_id_user);
-/* Return true if the ID-block has non-empty AnimData. */
+/**
+ * Return true if the ID-block has non-empty AnimData.
+ */
bool BKE_animdata_id_is_animated(const struct ID *id);
+/**
+ * Callback used by lib_query to walk over all ID usages
+ * (mimics `foreach_id` callback of #IDTypeInfo structure).
+ */
void BKE_animdata_foreach_id(struct AnimData *adt, struct LibraryForeachIDData *data);
-/* Copy AnimData */
+/**
+ * Make a copy of the given AnimData - to be used when copying data-blocks.
+ * \param flag: Control ID pointers management,
+ * see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_lib_id.h
+ * \return The copied animdata.
+ */
struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, const int flag);
-/* Copy AnimData */
+/**
+ * \param flag: Control ID pointers management,
+ * see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_lib_id.h
+ * \return true is successfully copied.
+ */
bool BKE_animdata_copy_id(struct Main *bmain,
struct ID *id_to,
struct ID *id_from,
const int flag);
-/* Copy AnimData Actions */
+/**
+ * Copy AnimData Actions.
+ */
void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id);
void BKE_animdata_duplicate_id_action(struct Main *bmain,
@@ -98,6 +136,9 @@ typedef enum eAnimData_MergeCopy_Modes {
ADT_MERGECOPY_SRC_REF = 2,
} eAnimData_MergeCopy_Modes;
+/**
+ * Merge copies of the data from the src AnimData into the destination AnimData.
+ */
void BKE_animdata_merge_copy(struct Main *bmain,
struct ID *dst_id,
struct ID *src_id,
diff --git a/source/blender/blenkernel/BKE_anim_path.h b/source/blender/blenkernel/BKE_anim_path.h
index 9db63080fd9..6bc09eb35ed 100644
--- a/source/blender/blenkernel/BKE_anim_path.h
+++ b/source/blender/blenkernel/BKE_anim_path.h
@@ -35,12 +35,21 @@ struct Object;
int BKE_anim_path_get_array_size(const struct CurveCache *curve_cache);
float BKE_anim_path_get_length(const struct CurveCache *curve_cache);
-/* This function populates the 'ob->runtime.curve_cache->anim_path_accum_length' data.
+/**
+ * This function populates the 'ob->runtime.curve_cache->anim_path_accum_length' data.
* You should never have to call this manually as it should already have been called by
* 'BKE_displist_make_curveTypes'. Do not call this manually unless you know what you are doing.
*/
void BKE_anim_path_calc_data(struct Object *ob);
+/**
+ * Calculate the deformation implied by the curve path at a given parametric position,
+ * and returns whether this operation succeeded.
+ *
+ * \param ctime: Time is normalized range <0-1>.
+ *
+ * \return success.
+ */
bool BKE_where_on_path(const struct Object *ob,
float ctime,
float r_vec[4],
diff --git a/source/blender/blenkernel/BKE_anim_visualization.h b/source/blender/blenkernel/BKE_anim_visualization.h
index 4e86abeed8d..3b8c91b7fd2 100644
--- a/source/blender/blenkernel/BKE_anim_visualization.h
+++ b/source/blender/blenkernel/BKE_anim_visualization.h
@@ -38,13 +38,34 @@ struct bPoseChannel;
/* ---------------------------------------------------- */
/* Animation Visualization */
+/**
+ * Initialize the default settings for animation visualization.
+ */
void animviz_settings_init(struct bAnimVizSettings *avs);
+/**
+ * Make a copy of motion-path data, so that viewing with copy on write works.
+ */
struct bMotionPath *animviz_copy_motionpath(const struct bMotionPath *mpath_src);
+/**
+ * Free the given motion path's cache.
+ */
void animviz_free_motionpath_cache(struct bMotionPath *mpath);
+/**
+ * Free the given motion path instance and its data.
+ * \note this frees the motion path given!
+ */
void animviz_free_motionpath(struct bMotionPath *mpath);
+/**
+ * Setup motion paths for the given data.
+ * \note Only used when explicitly calculating paths on bones which may/may not be consider already
+ *
+ * \param scene: Current scene (for frame ranges, etc.)
+ * \param ob: Object to add paths for (must be provided)
+ * \param pchan: Posechannel to add paths for (optional; if not provided, object-paths are assumed)
+ */
struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports,
struct Scene *scene,
struct Object *ob,
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 07da9d75e59..6197cb93c95 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -69,12 +69,17 @@ AnimationEvalContext BKE_animsys_eval_context_construct_at(
/* ************************************* */
/* KeyingSets API */
-/* Used to create a new 'custom' KeyingSet for the user,
- * that will be automatically added to the stack */
+/**
+ * Used to create a new 'custom' KeyingSet for the user,
+ * that will be automatically added to the stack.
+ */
struct KeyingSet *BKE_keyingset_add(
struct ListBase *list, const char idname[], const char name[], short flag, short keyingflag);
-/* Add a path to a KeyingSet */
+/**
+ * Add a path to a KeyingSet. Nothing is returned for now.
+ * Checks are performed to ensure that destination is appropriate for the KeyingSet in question
+ */
struct KS_Path *BKE_keyingset_add_path(struct KeyingSet *ks,
struct ID *id,
const char group_name[],
@@ -83,7 +88,10 @@ struct KS_Path *BKE_keyingset_add_path(struct KeyingSet *ks,
short flag,
short groupmode);
-/* Find the destination matching the criteria given */
+/**
+ * Find the destination matching the criteria given.
+ * TODO: do we want some method to perform partial matches too?
+ */
struct KS_Path *BKE_keyingset_find_path(struct KeyingSet *ks,
struct ID *id,
const char group_name[],
@@ -208,11 +216,32 @@ void BKE_fcurves_id_cb(struct ID *id, ID_FCurve_Edit_Callback func, void *user_d
typedef struct NlaKeyframingContext NlaKeyframingContext;
+/**
+ * Prepare data necessary to compute correct keyframe values for NLA strips
+ * with non-Replace mode or influence different from 1.
+ *
+ * \param cache: List used to cache contexts for reuse when keying
+ * multiple channels in one operation.
+ * \param ptr: RNA pointer to the Object with the animation.
+ * \return Keyframing context, or NULL if not necessary.
+ */
struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
struct ListBase *cache,
struct PointerRNA *ptr,
struct AnimData *adt,
const struct AnimationEvalContext *anim_eval_context);
+/**
+ * Apply correction from the NLA context to the values about to be keyframed.
+ *
+ * \param context: Context to use (may be NULL).
+ * \param prop_ptr: Property about to be keyframed.
+ * \param[in,out] values: Array of property values to adjust.
+ * \param count: Number of values in the array.
+ * \param index: Index of the element about to be updated, or -1.
+ * \param[out] r_force_all: Set to true if all channels must be inserted. May be NULL.
+ * \return False if correction fails due to a division by zero,
+ * or null r_force_all when all channels are required.
+ */
bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
struct PointerRNA *prop_ptr,
struct PropertyRNA *prop,
@@ -220,6 +249,9 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
int count,
int index,
bool *r_force_all);
+/**
+ * Free all cached contexts from the list.
+ */
void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache);
/* ************************************* */
@@ -240,16 +272,32 @@ bool BKE_animsys_rna_path_resolve(struct PointerRNA *ptr,
const int array_index,
struct PathResolvedRNA *r_result);
bool BKE_animsys_read_from_rna_path(struct PathResolvedRNA *anim_rna, float *r_value);
+/**
+ * Write the given value to a setting using RNA, and return success.
+ */
bool BKE_animsys_write_to_rna_path(struct PathResolvedRNA *anim_rna, const float value);
-/* Evaluation loop for evaluating animation data. */
+/**
+ * Evaluation loop for evaluation animation data
+ *
+ * This assumes that the animation-data provided belongs to the ID block in question,
+ * and that the flags for which parts of the animation-data settings need to be recalculated
+ * have been set already by the depsgraph. Now, we use the recalculate.
+ */
void BKE_animsys_evaluate_animdata(struct ID *id,
struct AnimData *adt,
const struct AnimationEvalContext *anim_eval_context,
eAnimData_Recalc recalc,
const bool flush_to_original);
-/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */
+/**
+ * Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only
+ *
+ * This will evaluate only the animation info available in the animation data-blocks
+ * encountered. In order to enforce the system by which some settings controlled by a
+ * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a
+ * standard 'root') block are overridden by a larger 'user'
+ */
void BKE_animsys_evaluate_all_animation(struct Main *main,
struct Depsgraph *depsgraph,
float ctime);
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index 65485058dd7..dd589282bdd 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -17,6 +17,9 @@
/** \file
* \ingroup bke
+ *
+ * \note on naming: typical _get() suffix is omitted here,
+ * since its the main purpose of the API.
*/
#include <stddef.h>
@@ -29,54 +32,139 @@ extern "C" {
struct ListBase;
+/**
+ * Sanity check to ensure correct API use in debug mode.
+ *
+ * Run this once the first level of arguments has been passed so we can be sure
+ * `--env-system-datafiles`, and other `--env-*` arguments has been passed.
+ *
+ * Without this any callers to this module that run early on,
+ * will miss out on changes from parsing arguments.
+ */
void BKE_appdir_init(void);
void BKE_appdir_exit(void);
-/* note on naming: typical _get() suffix is omitted here,
- * since its the main purpose of the API. */
+/**
+ * Get the folder that's the "natural" starting point for browsing files on an OS.
+ * - Unix: `$HOME`
+ * - Windows: `%userprofile%/Documents`
+ *
+ * \note On Windows `Users/{MyUserName}/Documents` is used as it's the default location to save
+ * documents.
+ */
const char *BKE_appdir_folder_default(void) ATTR_WARN_UNUSED_RESULT;
const char *BKE_appdir_folder_root(void) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
const char *BKE_appdir_folder_default_or_root(void) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
+/**
+ * Get the user's home directory, i.e.
+ * - Unix: `$HOME`
+ * - Windows: `%userprofile%`
+ */
const char *BKE_appdir_folder_home(void);
+/**
+ * Get the user's document directory, i.e.
+ * - Linux: `$HOME/Documents`
+ * - Windows: `%userprofile%/Documents`
+ *
+ * If this can't be found using OS queries (via Ghost), try manually finding it.
+ *
+ * \returns True if the path is valid and points to an existing directory.
+ */
bool BKE_appdir_folder_documents(char *dir);
+/**
+ * Get the user's cache directory, i.e.
+ * - Linux: `$HOME/.cache/blender/`
+ * - Windows: `%USERPROFILE%\AppData\Local\Blender Foundation\Blender\`
+ * - MacOS: `/Library/Caches/Blender`
+ *
+ * \returns True if the path is valid. It doesn't create or checks format
+ * if the `blender` folder exists. It does check if the parent of the path exists.
+ */
bool BKE_appdir_folder_caches(char *r_path, size_t path_len);
+/**
+ * Get a folder out of the \a folder_id presets for paths.
+ *
+ * \param subfolder: The name of a directory to check for,
+ * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir.
+ * \return The path if found, NULL string if not.
+ */
bool BKE_appdir_folder_id_ex(const int folder_id,
const char *subfolder,
char *path,
size_t path_len);
const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder);
+/**
+ * Returns the path to a folder in the user area, creating it if it doesn't exist.
+ */
const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder);
+/**
+ * Returns the path to a folder in the user area without checking that it actually exists first.
+ */
const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
+/**
+ * Returns the path of the top-level version-specific local, user or system directory.
+ * If check_is_dir, then the result will be NULL if the directory doesn't exist.
+ */
const char *BKE_appdir_folder_id_version(const int folder_id,
const int version,
const bool check_is_dir);
+/**
+ * Check if this is an install with user files kept together
+ * with the Blender executable and its installation files.
+ */
bool BKE_appdir_app_is_portable_install(void);
+/**
+ * Return true if templates exist
+ */
bool BKE_appdir_app_template_any(void);
bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len);
bool BKE_appdir_app_template_has_userpref(const char *app_template);
void BKE_appdir_app_templates(struct ListBase *templates);
-/* Initialize path to program executable */
+/**
+ * Initialize path to program executable.
+ */
void BKE_appdir_program_path_init(const char *argv0);
+/**
+ * Path to executable
+ */
const char *BKE_appdir_program_path(void);
+/**
+ * Path to directory of executable
+ */
const char *BKE_appdir_program_dir(void);
-/* Return OS fonts directory. */
+/**
+ * Gets a good default directory for fonts.
+ */
bool BKE_appdir_font_folder_default(char *dir);
-/* find python executable */
+/**
+ * Find Python executable.
+ */
bool BKE_appdir_program_python_search(char *fullpath,
const size_t fullpath_len,
const int version_major,
const int version_minor);
-/* Initialize path to temporary directory. */
+/**
+ * Initialize path to temporary directory.
+ */
void BKE_tempdir_init(const char *userdir);
+/**
+ * Path to persistent temporary directory (with trailing slash)
+ */
const char *BKE_tempdir_base(void);
+/**
+ * Path to temporary directory (with trailing slash)
+ */
const char *BKE_tempdir_session(void);
+/**
+ * Delete content of this instance's temp dir.
+ */
void BKE_tempdir_session_purge(void);
/* folder_id */
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index e13475fd78c..fcba7d9d365 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -166,8 +166,20 @@ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
bool BKE_pose_minmax(
struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select);
+/**
+ * Finds the best possible extension to the name on a particular axis.
+ * (For renaming, check for unique names afterwards)
+ * \param strip_number: removes number extensions (TODO: not used).
+ * \param axis: The axis to name on.
+ * \param head: The head co-ordinate of the bone on the specified axis.
+ * \param tail: The tail co-ordinate of the bone on the specified axis.
+ */
bool bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail);
+/**
+ * Walk the list until the bone is found (slow!),
+ * use #BKE_armature_bone_from_name_map for multiple lookups.
+ */
struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name);
void BKE_armature_bone_hash_make(struct bArmature *arm);
@@ -177,40 +189,87 @@ bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag);
void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmature *arm);
+/**
+ * Using `vec` with dist to bone `b1 - b2`.
+ */
float distfactor_to_bone(
const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist);
+/**
+ * Updates vectors and matrices on rest-position level, only needed
+ * after editing armature itself, now only on reading file.
+ */
void BKE_armature_where_is(struct bArmature *arm);
+/**
+ * Recursive part, calculates rest-position of entire tree of children.
+ * \note Used when exiting edit-mode too.
+ */
void BKE_armature_where_is_bone(struct Bone *bone,
const struct Bone *bone_parent,
const bool use_recursion);
+/**
+ * Clear pointers of object's pose
+ * (needed in remap case, since we cannot always wait for a complete pose rebuild).
+ */
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
+/**
+ * Update the links for the B-Bone handles from Bone data.
+ */
void BKE_pchan_rebuild_bbone_handles(struct bPose *pose, struct bPoseChannel *pchan);
void BKE_pose_channels_clear_with_null_bone(struct bPose *pose, const bool do_id_user);
+/**
+ * Only after leave edit-mode, duplicating, validating older files, library syncing.
+ *
+ * \note pose->flag is set for it.
+ *
+ * \param bmain: May be NULL, only used to tag depsgraph as being dirty.
+ */
void BKE_pose_rebuild(struct Main *bmain,
struct Object *ob,
struct bArmature *arm,
const bool do_id_user);
+/**
+ * Ensures object's pose is rebuilt if needed.
+ *
+ * \param bmain: May be NULL, only used to tag depsgraph as being dirty.
+ */
void BKE_pose_ensure(struct Main *bmain,
struct Object *ob,
struct bArmature *arm,
const bool do_id_user);
+/**
+ * \note This is the only function adding poses.
+ * \note This only reads anim data from channels, and writes to channels.
+ */
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
+/**
+ * The main armature solver, does all constraints excluding IK.
+ *
+ * \param pchan: pose-channel - validated, as having bone and parent pointer.
+ * \param do_extra: when zero skips loc/size/rot, constraints and strip modifiers.
+ */
void BKE_pose_where_is_bone(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan,
float ctime,
bool do_extra);
+/**
+ * Calculate tail of pose-channel.
+ */
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
-/* Evaluate the action and apply it to the pose. If any pose bones are selected, only FCurves that
- * relate to those bones are evaluated. */
+/**
+ * Evaluate the action and apply it to the pose. If any pose bones are selected, only FCurves that
+ * relate to those bones are evaluated.
+ */
void BKE_pose_apply_action_selected_bones(struct Object *ob,
struct bAction *action,
struct AnimationEvalContext *anim_eval_context);
-/* Evaluate the action and apply it to the pose. Ignore selection state of the bones. */
+/**
+ * Evaluate the action and apply it to the pose. Ignore selection state of the bones.
+ */
void BKE_pose_apply_action_all_bones(struct Object *ob,
struct bAction *action,
struct AnimationEvalContext *anim_eval_context);
@@ -221,24 +280,63 @@ void BKE_pose_apply_action_blend(struct Object *ob,
float blend_factor);
void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3]);
+
+/**
+ * Calculates the rest matrix of a bone based on its vector and a roll around that vector.
+ */
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3]);
+/**
+ * Computes vector and roll based on a rotation.
+ * "mat" must contain only a rotation, and no scaling.
+ */
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll);
+/**
+ * Computes roll around the vector that best approximates the matrix.
+ * If `vec` is the Y vector from purely rotational `mat`, result should be exact.
+ */
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll);
/* Common Conversions Between Co-ordinate Spaces */
+
+/**
+ * Convert World-Space Matrix to Pose-Space Matrix.
+ */
void BKE_armature_mat_world_to_pose(struct Object *ob,
const float inmat[4][4],
float outmat[4][4]);
+/**
+ * Convert World-Space Location to Pose-Space Location
+ * \note this cannot be used to convert to pose-space location of the supplied
+ * pose-channel into its local space (i.e. 'visual'-keyframing).
+ */
void BKE_armature_loc_world_to_pose(struct Object *ob, const float inloc[3], float outloc[3]);
+/**
+ * Convert Pose-Space Matrix to Bone-Space Matrix.
+ * \note this cannot be used to convert to pose-space transforms of the supplied
+ * pose-channel into its local space (i.e. 'visual'-keyframing).
+ */
void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4]);
+/**
+ * Convert Pose-Space Location to Bone-Space Location
+ * \note this cannot be used to convert to pose-space location of the supplied
+ * pose-channel into its local space (i.e. 'visual'-keyframing).
+ */
void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan,
const float inloc[3],
float outloc[3]);
+/**
+ * Convert Bone-Space Matrix to Pose-Space Matrix.
+ */
void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4]);
+/**
+ * Remove rest-position effects from pose-transform for obtaining
+ * 'visual' transformation of pose-channel.
+ * (used by the Visual-Keyframing stuff).
+ */
void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
float pose_mat[4][4],
float arm_mat[4][4]);
@@ -249,13 +347,34 @@ void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph,
const float inmat[4][4],
float outmat[4][4]);
+/**
+ * Same as #BKE_object_mat3_to_rot().
+ */
void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, const float mat[3][3], bool use_compat);
+/**
+ * Same as #BKE_object_rot_to_mat3().
+ */
void BKE_pchan_rot_to_mat3(const struct bPoseChannel *pchan, float r_mat[3][3]);
+/**
+ * Apply a 4x4 matrix to the pose bone,
+ * similar to #BKE_object_apply_mat4().
+ */
void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, const float mat[4][4], bool use_compat);
+/**
+ * Convert the loc/rot/size to \a r_chanmat (typically #bPoseChannel.chan_mat).
+ */
void BKE_pchan_to_mat4(const struct bPoseChannel *pchan, float r_chanmat[4][4]);
+
+/**
+ * Convert the loc/rot/size to mat4 (`pchan.chan_mat`),
+ * used in `constraint.c` too.
+ */
void BKE_pchan_calc_mat(struct bPoseChannel *pchan);
-/* Simple helper, computes the offset bone matrix. */
+/**
+ * Simple helper, computes the offset bone matrix:
+ * `offs_bone = yoffs(b-1) + root(b) + bonemat(b)`.
+ */
void BKE_bone_offset_matrix_get(const struct Bone *bone, float offs_bone[4][4]);
/* Transformation inherited from the parent bone. These matrices apply the effects of
@@ -277,9 +396,38 @@ void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt,
const float inmat[4][4],
float outmat[4][4]);
-/* Get the current parent transformation for the given pose bone. */
+/**
+ * Get the current parent transformation for the given pose bone.
+ *
+ * Construct the matrices (rot/scale and loc)
+ * to apply the PoseChannels into the armature (object) space.
+ * I.e. (roughly) the `pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b)` in the
+ * `pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b)`
+ * ...function.
+ *
+ * This allows to get the transformations of a bone in its object space,
+ * *before* constraints (and IK) get applied (used by pose evaluation code).
+ * And reverse: to find pchan transformations needed to place a bone at a given loc/rot/scale
+ * in object space (used by interactive transform, and snapping code).
+ *
+ * Note that, with the HINGE/NO_SCALE/NO_LOCAL_LOCATION options, the location matrix
+ * will differ from the rotation/scale matrix...
+ *
+ * \note This cannot be used to convert to pose-space transforms of the supplied
+ * pose-channel into its local space (i.e. 'visual'-keyframing).
+ * (NOTE(@mont29): I don't understand that, so I keep it :p).
+ */
void BKE_bone_parent_transform_calc_from_pchan(const struct bPoseChannel *pchan,
struct BoneParentTransform *r_bpt);
+/**
+ * Compute the parent transform using data decoupled from specific data structures.
+ *
+ * \param bone_flag: #Bone.flag containing settings.
+ * \param offs_bone: delta from parent to current arm_mat (or just arm_mat if no parent).
+ * \param parent_arm_mat: arm_mat of parent, or NULL.
+ * \param parent_pose_mat: pose_mat of parent, or NULL.
+ * \param r_bpt: OUTPUT parent transform.
+ */
void BKE_bone_parent_transform_calc_from_matrices(int bone_flag,
int inherit_scale_mode,
const float offs_bone[4][4],
@@ -287,7 +435,13 @@ void BKE_bone_parent_transform_calc_from_matrices(int bone_flag,
const float parent_pose_mat[4][4],
struct BoneParentTransform *r_bpt);
-/* Rotation Mode Conversions - Used for PoseChannels + Objects... */
+/**
+ * Rotation Mode Conversions - Used for Pose-Channels + Objects.
+ *
+ * Called from RNA when rotation mode changes
+ * - the result should be that the rotations given in the provided pointers have had conversions
+ * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed.
+ */
void BKE_rotMode_change_values(
float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode);
@@ -320,18 +474,31 @@ typedef struct BBoneSplineParameters {
float curve_in_x, curve_in_z, curve_out_x, curve_out_z;
} BBoneSplineParameters;
+/**
+ * Get "next" and "prev" bones - these are used for handle calculations.
+ */
void BKE_pchan_bbone_handles_get(struct bPoseChannel *pchan,
struct bPoseChannel **r_prev,
struct bPoseChannel **r_next);
+/**
+ * Compute B-Bone spline parameters for the given channel.
+ */
void BKE_pchan_bbone_spline_params_get(struct bPoseChannel *pchan,
const bool rest,
struct BBoneSplineParameters *r_param);
+/**
+ * Fills the array with the desired amount of bone->segments elements.
+ * This calculation is done within unit bone space.
+ */
void BKE_pchan_bbone_spline_setup(struct bPoseChannel *pchan,
const bool rest,
const bool for_deform,
Mat4 *result_array);
+/**
+ * Computes the bezier handle vectors and rolls coming from custom handles.
+ */
void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param,
float h1[3],
float *r_roll1,
@@ -339,14 +506,28 @@ void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param,
float *r_roll2,
bool ease,
bool offsets);
+/**
+ * Fills the array with the desired amount of `bone->segments` elements.
+ * This calculation is done within unit bone space.
+ */
int BKE_pchan_bbone_spline_compute(struct BBoneSplineParameters *param,
const bool for_deform,
Mat4 *result_array);
+/**
+ * Compute and cache the B-Bone shape in the channel runtime struct.
+ */
void BKE_pchan_bbone_segments_cache_compute(struct bPoseChannel *pchan);
+/**
+ * Copy cached B-Bone segments from one channel to another.
+ */
void BKE_pchan_bbone_segments_cache_copy(struct bPoseChannel *pchan,
struct bPoseChannel *pchan_from);
+/**
+ * Calculate index and blend factor for the two B-Bone segment nodes
+ * affecting the point at 0 <= pos <= 1.
+ */
void BKE_pchan_bbone_deform_segment_index(const struct bPoseChannel *pchan,
float pos,
int *r_index,
diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h
index 722d142b56c..58c50fb736f 100644
--- a/source/blender/blenkernel/BKE_asset.h
+++ b/source/blender/blenkernel/BKE_asset.h
@@ -57,6 +57,9 @@ struct AssetTagEnsureResult {
};
struct AssetTag *BKE_asset_metadata_tag_add(struct AssetMetaData *asset_data, const char *name);
+/**
+ * Make sure there is a tag with name \a name, create one if needed.
+ */
struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(struct AssetMetaData *asset_data,
const char *name);
void BKE_asset_metadata_tag_remove(struct AssetMetaData *asset_data, struct AssetTag *tag);
diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index 3478eebbeb4..ecc839050b7 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -98,6 +98,15 @@ class AssetCatalogService {
bool write_to_disk(const CatalogFilePath &blend_file_path);
/**
+ * Ensure that the next call to #on_blend_save_post() will choose a new location for the CDF
+ * suitable for the location of the blend file (regardless of where the current catalogs come
+ * from), and that catalogs will be merged with already-existing ones in that location.
+ *
+ * Use this for a "Save as..." that has to write the catalogs to the new blend file location,
+ * instead of updating the previously read CDF. */
+ void prepare_to_merge_on_write();
+
+ /**
* Merge on-disk changes into the in-memory asset catalogs.
* This should be called before writing the asset catalogs to disk.
*
@@ -238,6 +247,11 @@ class AssetCatalogService {
*/
void create_missing_catalogs();
+ /**
+ * For every catalog, mark it as "dirty".
+ */
+ void tag_all_catalogs_as_unsaved_changes();
+
/* For access by subclasses, as those will not be marked as friend by #AssetCatalogCollection. */
AssetCatalogDefinitionFile *get_catalog_definition_file();
OwningAssetCatalogMap &get_catalogs();
@@ -363,6 +377,9 @@ class AssetCatalogDefinitionFile {
/* For now this is the only version of the catalog definition files that is supported.
* Later versioning code may be added to handle older files. */
const static int SUPPORTED_VERSION;
+ /* String that's matched in the catalog definition file to know that the line is the version
+ * declaration. It has to start with a space to ensure it won't match any hypothetical future
+ * field that starts with "VERSION". */
const static std::string VERSION_MARKER;
const static std::string HEADER;
diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh
index 47f62b52a0f..fd30813a506 100644
--- a/source/blender/blenkernel/BKE_attribute_access.hh
+++ b/source/blender/blenkernel/BKE_attribute_access.hh
@@ -155,6 +155,10 @@ using fn::GVMutableArray;
const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types);
+/**
+ * Domains with a higher "information density" have a higher priority,
+ * in order to choose a domain that will not lose data through domain conversion.
+ */
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains);
/**
@@ -345,8 +349,15 @@ class CustomDataAttributes {
void reallocate(const int size);
+ void clear();
+
std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
+ /**
+ * Return a virtual array for a stored attribute, or a single value virtual array with the
+ * default value if the attribute doesn't exist. If no default value is provided, the default
+ * value for the type will be used.
+ */
blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
const void *default_value) const;
@@ -514,19 +525,3 @@ template<typename T> inline MutableSpan<T> OutputAttribute::as_span()
/** \} */
} // namespace blender::bke
-
-/* -------------------------------------------------------------------- */
-/** \name External Template Instantiations
- *
- * Defined in `intern/extern_implementations.cc`.
- * \{ */
-
-namespace blender::bke {
-extern template class OutputAttribute_Typed<float>;
-extern template class OutputAttribute_Typed<int>;
-extern template class OutputAttribute_Typed<float3>;
-extern template class OutputAttribute_Typed<bool>;
-extern template class OutputAttribute_Typed<ColorGeometry4f>;
-} // namespace blender::bke
-
-/** \} */
diff --git a/source/blender/blenkernel/BKE_autoexec.h b/source/blender/blenkernel/BKE_autoexec.h
index 84d83ae5d30..55bb3e8877f 100644
--- a/source/blender/blenkernel/BKE_autoexec.h
+++ b/source/blender/blenkernel/BKE_autoexec.h
@@ -23,6 +23,10 @@
extern "C" {
#endif
+/**
+ * \param path: The path to check against.
+ * \return Success
+ */
bool BKE_autoexec_match(const char *path);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 813472715fa..8c0512edb1d 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -29,6 +29,9 @@ extern "C" {
struct UserDef;
+/**
+ * Only to be called on exit Blender.
+ */
void BKE_blender_free(void);
void BKE_blender_globals_init(void);
@@ -38,11 +41,19 @@ void BKE_blender_userdef_data_swap(struct UserDef *userdef_a, struct UserDef *us
void BKE_blender_userdef_data_set(struct UserDef *userdef);
void BKE_blender_userdef_data_set_and_free(struct UserDef *userdef);
+/**
+ * Write U from userdef.
+ * This function defines which settings a template will override for the user preferences.
+ */
void BKE_blender_userdef_app_template_data_swap(struct UserDef *userdef_a,
struct UserDef *userdef_b);
void BKE_blender_userdef_app_template_data_set(struct UserDef *userdef);
void BKE_blender_userdef_app_template_data_set_and_free(struct UserDef *userdef);
+/**
+ * When loading a new userdef from file,
+ * or when exiting Blender.
+ */
void BKE_blender_userdef_data_free(struct UserDef *userdef, bool clear_fonts);
/* Blenders' own atexit (avoids leaking) */
diff --git a/source/blender/blenkernel/BKE_blender_copybuffer.h b/source/blender/blenkernel/BKE_blender_copybuffer.h
index 4dd7145e66d..abfb37ef959 100644
--- a/source/blender/blenkernel/BKE_blender_copybuffer.h
+++ b/source/blender/blenkernel/BKE_blender_copybuffer.h
@@ -30,16 +30,54 @@ struct Main;
struct ReportList;
struct bContext;
-/* copybuffer (wrapper for BKE_blendfile_write_partial) */
+/* Copy-buffer (wrapper for BKE_blendfile_write_partial). */
+
+/**
+ * Initialize a copy operation.
+ */
void BKE_copybuffer_copy_begin(struct Main *bmain_src);
+/**
+ * Mark an ID to be copied. Should only be called after a call to #BKE_copybuffer_copy_begin.
+ */
void BKE_copybuffer_copy_tag_ID(struct ID *id);
+/**
+ * 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_copy_end(struct Main *bmain_src,
const char *filename,
struct ReportList *reports);
+/**
+ * Paste data-blocks 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(struct Main *bmain_dst,
const char *libname,
struct ReportList *reports,
const uint64_t id_types_mask);
+/**
+ * Paste data-blocks 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(struct bContext *C,
const char *libname,
const int flag,
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 966d6c95421..d0ab8be9a29 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 3
+#define BLENDER_FILE_SUBVERSION 5
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index 3e0a343a766..b3211b1dbbc 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -33,6 +33,14 @@ struct ReportList;
struct UserDef;
struct bContext;
+/**
+ * Shared setup function that makes the data from `bfd` into the current blend file,
+ * replacing the contents of #G.main.
+ * This uses the bfd #BKE_blendfile_read and similarly named functions.
+ *
+ * This is done in a separate step so the caller may perform actions after it is known the file
+ * loaded correctly but before the file replaces the existing blend file contents.
+ */
void BKE_blendfile_read_setup_ex(struct bContext *C,
struct BlendFileData *bfd,
const struct BlendFileReadParams *params,
@@ -46,28 +54,56 @@ void BKE_blendfile_read_setup(struct bContext *C,
const struct BlendFileReadParams *params,
struct BlendFileReadReport *reports);
+/**
+ * \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
+ */
struct BlendFileData *BKE_blendfile_read(const char *filepath,
const struct BlendFileReadParams *params,
struct BlendFileReadReport *reports);
+/**
+ * \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
+ */
struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
struct ReportList *reports);
+/**
+ * \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
+ * \note `memfile` is the undo buffer.
+ */
struct BlendFileData *BKE_blendfile_read_from_memfile(struct Main *bmain,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
struct ReportList *reports);
+/**
+ * Utility to make a file 'empty' used for startup to optionally give an empty file.
+ * Handy for tests.
+ */
void BKE_blendfile_read_make_empty(struct bContext *C);
+/**
+ * Only read the #UserDef from a .blend.
+ */
struct UserDef *BKE_blendfile_userdef_read(const char *filepath, struct ReportList *reports);
struct UserDef *BKE_blendfile_userdef_read_from_memory(const void *filebuf,
int filelength,
struct ReportList *reports);
struct UserDef *BKE_blendfile_userdef_from_defaults(void);
+/**
+ * Only write the #UserDef in a `.blend`.
+ * \return success.
+ */
bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
+/**
+ * Only write the #UserDef in a `.blend`, merging with the existing blend file.
+ * \return success.
+ *
+ * \note In the future we should re-evaluate user preferences,
+ * possibly splitting out system/hardware specific preferences.
+ */
bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports);
bool BKE_blendfile_userdef_write_all(struct ReportList *reports);
@@ -81,9 +117,14 @@ bool BKE_blendfile_workspace_config_write(struct Main *bmain,
struct ReportList *reports);
void BKE_blendfile_workspace_config_data_free(struct WorkspaceConfigFileData *workspace_config);
-/* partial blend file writing */
+/* Partial blend file writing. */
+
void BKE_blendfile_write_partial_tag_ID(struct ID *id, bool set);
void BKE_blendfile_write_partial_begin(struct Main *bmain_src);
+/**
+ * \param remap_mode: Choose the kind of path remapping or none #eBLO_WritePathRemap.
+ * \return Success.
+ */
bool BKE_blendfile_write_partial(struct Main *bmain_src,
const char *filepath,
const int write_flags,
diff --git a/source/blender/blenkernel/BKE_blendfile_link_append.h b/source/blender/blenkernel/BKE_blendfile_link_append.h
new file mode 100644
index 00000000000..aaa31352316
--- /dev/null
+++ b/source/blender/blenkernel/BKE_blendfile_link_append.h
@@ -0,0 +1,222 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct BlendHandle;
+struct ID;
+struct Library;
+struct LibraryLink_Params;
+struct Main;
+struct ReportList;
+struct Scene;
+struct ViewLayer;
+struct View3D;
+
+typedef struct BlendfileLinkAppendContext BlendfileLinkAppendContext;
+typedef struct BlendfileLinkAppendContextItem BlendfileLinkAppendContextItem;
+
+/**
+ * Allocate and initialize a new context to link/append data-blocks.
+ */
+BlendfileLinkAppendContext *BKE_blendfile_link_append_context_new(
+ struct LibraryLink_Params *params);
+/**
+ * Free a link/append context.
+ */
+void BKE_blendfile_link_append_context_free(struct BlendfileLinkAppendContext *lapp_context);
+/**
+ * Set or clear flags in given \a lapp_context.
+ *
+ * \param flag: A combination of:
+ * - #eFileSel_Params_Flag from `DNA_space_types.h` &
+ * - #eBLOLibLinkFlags * from `BLO_readfile.h`.
+ * \param do_set: Set the given \a flag if true, clear it otherwise.
+ */
+void BKE_blendfile_link_append_context_flag_set(struct BlendfileLinkAppendContext *lapp_context,
+ const int flag,
+ const bool do_set);
+
+/**
+ * Store reference to a Blender's embedded memfile into the context.
+ *
+ * \note This is required since embedded startup blender file is handled in `ED` module, which
+ * cannot be linked in BKE code.
+ */
+void BKE_blendfile_link_append_context_embedded_blendfile_set(
+ struct BlendfileLinkAppendContext *lapp_context,
+ const void *blendfile_mem,
+ int blendfile_memsize);
+/** Clear reference to Blender's embedded startup file into the context. */
+void BKE_blendfile_link_append_context_embedded_blendfile_clear(
+ struct BlendfileLinkAppendContext *lapp_context);
+
+/**
+ * Add a new source library to search for items to be linked to the given link/append context.
+ *
+ * \param libname: the absolute path to the library blend file.
+ * \param blo_handle: the blend file handle of the library, NULL is not available. Note that this
+ * is only borrowed for linking purpose, no releasing or other management will
+ * be performed by #BKE_blendfile_link_append code on it.
+ *
+ * \note *Never* call #BKE_blendfile_link_append_context_library_add()
+ * after having added some items.
+ */
+void BKE_blendfile_link_append_context_library_add(struct BlendfileLinkAppendContext *lapp_context,
+ const char *libname,
+ struct BlendHandle *blo_handle);
+/**
+ * Add a new item (data-block name and `idcode`) to be searched and linked/appended from libraries
+ * associated to the given context.
+ *
+ * \param userdata: an opaque user-data pointer stored in generated link/append item.
+ *
+ * TODO: Add a more friendly version of this that combines it with the call to
+ * #BKE_blendfile_link_append_context_item_library_index_enable to enable the added item for all
+ * added library sources.
+ */
+struct BlendfileLinkAppendContextItem *BKE_blendfile_link_append_context_item_add(
+ struct BlendfileLinkAppendContext *lapp_context,
+ const char *idname,
+ const short idcode,
+ void *userdata);
+
+#define BLENDFILE_LINK_APPEND_INVALID -1
+/**
+ * Search for all ID matching given `id_types_filter` in given `library_index`, and add them to
+ * the list of items to process.
+ *
+ * \note #BKE_blendfile_link_append_context_library_add should never be called on the same
+ *`lapp_context` after this function.
+ *
+ * \param id_types_filter: A set of `FILTER_ID` bitflags, the types of IDs to add to the items
+ * list.
+ * \param library_index: The index of the library to look into, in given `lapp_context`.
+ *
+ * \return The number of items found and added to the list, or `BLENDFILE_LINK_APPEND_INVALID` if
+ * it could not open the .blend file.
+ */
+int BKE_blendfile_link_append_context_item_idtypes_from_library_add(
+ struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports,
+ const uint64_t id_types_filter,
+ const int library_index);
+
+/**
+ * Enable search of the given \a item into the library stored at given index in the link/append
+ * context.
+ */
+void BKE_blendfile_link_append_context_item_library_index_enable(
+ struct BlendfileLinkAppendContext *lapp_context,
+ struct BlendfileLinkAppendContextItem *item,
+ const int library_index);
+/**
+ * Check if given link/append context is empty (has no items to process) or not.
+ */
+bool BKE_blendfile_link_append_context_is_empty(struct BlendfileLinkAppendContext *lapp_context);
+
+void *BKE_blendfile_link_append_context_item_userdata_get(
+ struct BlendfileLinkAppendContext *lapp_context, struct BlendfileLinkAppendContextItem *item);
+struct ID *BKE_blendfile_link_append_context_item_newid_get(
+ struct BlendfileLinkAppendContext *lapp_context, struct BlendfileLinkAppendContextItem *item);
+short BKE_blendfile_link_append_context_item_idcode_get(
+ struct BlendfileLinkAppendContext *lapp_context, struct BlendfileLinkAppendContextItem *item);
+
+typedef enum eBlendfileLinkAppendForeachItemFlag {
+ /** Loop over directly linked items (i.e. those explicitly defined by user code). */
+ BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_DIRECT = 1 << 0,
+ /** Loop over indirectly linked items (i.e. those defined by internal code, as dependencies of
+ * direct ones).
+ *
+ * IMPORTANT: Those 'indirect' items currently may not cover **all** indirectly linked data.
+ * See comments in #foreach_libblock_link_append_callback. */
+ BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_INDIRECT = 1 << 0,
+} eBlendfileLinkAppendForeachItemFlag;
+/**
+ * Callback called by #BKE_blendfile_link_append_context_item_foreach over each (or a subset of
+ * each) of the items in given #BlendfileLinkAppendContext.
+ *
+ * \param userdata: An opaque void pointer passed to the `callback_function`.
+ *
+ * \return `true` if iteration should continue, `false` otherwise.
+ */
+typedef bool (*BKE_BlendfileLinkAppendContexteItemFunction)(
+ struct BlendfileLinkAppendContext *lapp_context,
+ struct BlendfileLinkAppendContextItem *item,
+ void *userdata);
+/**
+ * Iterate over all (or a subset) of the items listed in given #BlendfileLinkAppendContext,
+ * and call the `callback_function` on them.
+ *
+ * \param flag: Control which type of items to process (see
+ * #eBlendfileLinkAppendForeachItemFlag enum flags).
+ * \param userdata: An opaque void pointer passed to the `callback_function`.
+ */
+void BKE_blendfile_link_append_context_item_foreach(
+ struct BlendfileLinkAppendContext *lapp_context,
+ BKE_BlendfileLinkAppendContexteItemFunction callback_function,
+ const eBlendfileLinkAppendForeachItemFlag flag,
+ void *userdata);
+
+/**
+ * Perform append operation, using modern ID usage looper to detect which ID should be kept
+ * linked, made local, duplicated as local, re-used from local etc.
+ *
+ * The IDs processed by this functions are the one that have been linked by a previous call to
+ * #BKE_blendfile_link on the same `lapp_context`.
+ */
+void BKE_blendfile_append(struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports);
+/**
+ * Perform linking operation on all items added to given `lapp_context`.
+ */
+void BKE_blendfile_link(struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports);
+
+/**
+ * Try to relocate all linked IDs added to `lapp_context`, belonging to the given `library`.
+ *
+ * This function searches for matching IDs (type and name) in all libraries added to the given
+ * `lapp_context`.
+ *
+ * Typical usages include:
+ * - Relocating a library:
+ * - Add the new target library path to `lapp_context`.
+ * - Add all IDs from the library to relocate to `lapp_context`
+ * - Mark the new target library to be considered for each ID.
+ * - Call this function.
+ *
+ * - Searching for (e.g.missing) linked IDs in a set or sub-set of libraries:
+ * - Add all potential library sources paths to `lapp_context`.
+ * - Add all IDs to search for to `lapp_context`.
+ * - Mark which libraries should be considered for each ID.
+ * - Call this function.
+ */
+void BKE_blendfile_library_relocate(struct BlendfileLinkAppendContext *lapp_context,
+ struct ReportList *reports,
+ struct Library *library,
+ const bool do_reload);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h
index 71a4d35767f..a9c8ad6422f 100644
--- a/source/blender/blenkernel/BKE_boids.h
+++ b/source/blender/blenkernel/BKE_boids.h
@@ -51,7 +51,13 @@ typedef struct BoidBrainData {
} BoidBrainData;
void boids_precalc_rules(struct ParticleSettings *part, float cfra);
+/**
+ * Determines the velocity the boid wants to have.
+ */
void boid_brain(BoidBrainData *bbd, int p, struct ParticleData *pa);
+/**
+ * Tries to realize the wanted velocity taking all constraints into account.
+ */
void boid_body(BoidBrainData *bbd, struct ParticleData *pa);
void boid_default_settings(struct BoidSettings *boids);
struct BoidRule *boid_new_rule(int type);
diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h
index 3ec5409ca7f..bae151f6a72 100644
--- a/source/blender/blenkernel/BKE_bpath.h
+++ b/source/blender/blenkernel/BKE_bpath.h
@@ -16,10 +16,14 @@
/** \file
* \ingroup bke
- * \attention Based on ghash, difference is ghash is not a fixed size,
- * so for BPath we don't need to malloc
+ *
+ * \warning All paths manipulated by this API are assumed to be either constant char buffers of
+ * `FILE_MAX` size, or allocated char buffers not bigger than `FILE_MAX`.
*/
+/* TODO: Make this module handle a bit more safely string length, instead of assuming buffers are
+ * FILE_MAX length etc. */
+
#pragma once
#ifdef __cplusplus
@@ -31,66 +35,181 @@ struct ListBase;
struct Main;
struct ReportList;
-/* Function that does something with an ID's file path. Should return 1 if the
- * path has changed, and in that case, should write the result to pathOut. */
-typedef bool (*BPathVisitor)(void *userdata, char *path_dst, const char *path_src);
-/* Executes 'visit' for each path associated with 'id'. */
-void BKE_bpath_traverse_id(struct Main *bmain,
- struct ID *id,
- BPathVisitor visit_cb,
- const int flag,
- void *bpath_user_data);
-void BKE_bpath_traverse_id_list(struct Main *bmain,
- struct ListBase *lb,
- BPathVisitor visit_cb,
- const int flag,
- void *bpath_user_data);
-void BKE_bpath_traverse_main(struct Main *bmain,
- BPathVisitor visit_cb,
- const int flag,
- void *bpath_user_data);
-bool BKE_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src);
-
-/* Functions for temp backup/restore of paths, path count must NOT change */
-void *BKE_bpath_list_backup(struct Main *bmain, const int flag);
-void BKE_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle);
-void BKE_bpath_list_free(void *ls_handle);
-
-enum {
- /* convert paths to absolute */
- BKE_BPATH_TRAVERSE_ABS = (1 << 0),
- /* skip library paths */
- BKE_BPATH_TRAVERSE_SKIP_LIBRARY = (1 << 1),
- /* skip packed data */
- BKE_BPATH_TRAVERSE_SKIP_PACKED = (1 << 2),
- /* skip paths where a single dir is used with an array of files, eg.
- * sequence strip images and pointcache. in this case only use the first
- * file, this is needed for directory manipulation functions which might
- * otherwise modify the same directory multiple times */
- BKE_BPATH_TRAVERSE_SKIP_MULTIFILE = (1 << 3),
- /* reload data (when the path is edited) */
- BKE_BPATH_TRAVERSE_RELOAD_EDITED = (1 << 4),
-};
-
-/* high level funcs */
-
-/* creates a text file with missing files if there are any */
+/** \name Core `foreach_path` API.
+ * \{ */
+
+typedef enum eBPathForeachFlag {
+ /** Flags controlling the behavior of the generic BPath API. */
+
+ /** Ensures the `absolute_base_path` member of #BPathForeachPathData is initialized properly with
+ * the path of the current .blend file. This can be used by the callbacks to convert relative
+ * paths to absolute ones. */
+ BKE_BPATH_FOREACH_PATH_ABSOLUTE = (1 << 0),
+ /** Skip paths of linked IDs. */
+ BKE_BPATH_FOREACH_PATH_SKIP_LINKED = (1 << 1),
+ /** Skip paths when their matching data is packed. */
+ BKE_BPATH_FOREACH_PATH_SKIP_PACKED = (1 << 2),
+ /* Skip weak reference paths. Those paths are typically 'nice to have' extra information, but are
+ * not used as actual source of data by the current .blend file.
+ *
+ * NOTE: Currently this only concerns the weak reference to a library file stored in
+ * `ID::library_weak_reference`. */
+ BKE_BPATH_TRAVERSE_SKIP_WEAK_REFERENCES = (1 << 5),
+
+ /** Flags not affecting the generic BPath API. Those may be used by specific IDTypeInfo
+ * `foreach_path` implementations and/or callbacks to implement specific behaviors. */
+
+ /** Skip paths where a single dir is used with an array of files, eg. sequence strip images or
+ * point-caches. In this case only use the first file path is processed.
+ *
+ * This is needed for directory manipulation callbacks which might otherwise modify the same
+ * directory multiple times. */
+ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE = (1 << 8),
+ /** Reload data (when the path is edited).
+ * \note Only used by Image IDType currently. */
+ BKE_BPATH_FOREACH_PATH_RELOAD_EDITED = (1 << 9),
+} eBPathForeachFlag;
+
+struct BPathForeachPathData;
+
+/** Callback used to iterate over an ID's file paths.
+ *
+ * \note `path`s parameters should be considered as having a maximal `FILE_MAX` string length.
+ *
+ * \return `true` if the path has been changed, and in that case, result should be written into
+ * `r_path_dst`. */
+typedef bool (*BPathForeachPathFunctionCallback)(struct BPathForeachPathData *bpath_data,
+ char *r_path_dst,
+ const char *path_src);
+
+/** Storage for common data needed across the BPath 'foreach_path' code. */
+typedef struct BPathForeachPathData {
+ struct Main *bmain;
+
+ BPathForeachPathFunctionCallback callback_function;
+ eBPathForeachFlag flag;
+
+ void *user_data;
+
+ /* 'Private' data, caller don't need to set those. */
+
+ /** The root to use as base for relative paths. Only set if `BKE_BPATH_FOREACH_PATH_ABSOLUTE`
+ * flag is set, NULL otherwise. */
+ const char *absolute_base_path;
+} BPathForeachPathData;
+
+/** Run `bpath_data.callback_function` on all paths contained in `id`. */
+void BKE_bpath_foreach_path_id(BPathForeachPathData *bpath_data, struct ID *id);
+
+/** Run `bpath_data.callback_function` on all paths of all IDs in `bmain`. */
+void BKE_bpath_foreach_path_main(BPathForeachPathData *bpath_data);
+
+/** \} */
+
+/** \name Helpers to handle common cases from `IDTypeInfo`'s `foreach_path` functions.
+ * \{ */
+
+/* TODO: Investigate using macros around those calls to check a bit better about actual
+ * strings/buffers length (e,g, with static asserts). */
+
+/**
+ * Run the callback on a path, replacing the content of the string as needed.
+ *
+ * \param path: A fixed, FILE_MAX-sized char buffer.
+ *
+ * \return true is \a path was modified, false otherwise.
+ */
+bool BKE_bpath_foreach_path_fixed_process(struct BPathForeachPathData *bpath_data, char *path);
+
+/**
+ * Run the callback on a (directory + file) path, replacing the content of the two strings as
+ * needed.
+ *
+ * \param path_dir: A fixed, FILE_MAXDIR-sized char buffer.
+ * \param path_file: A fixed, FILE_MAXFILE-sized char buffer.
+ *
+ * \return true is \a path_dir and/or \a path_file were modified, false otherwise.
+ */
+bool BKE_bpath_foreach_path_dirfile_fixed_process(struct BPathForeachPathData *bpath_data,
+ char *path_dir,
+ char *path_file);
+
+/**
+ * Run the callback on a path, replacing the content of the string as needed.
+ *
+ * \param path: A pointer to a MEM-allocated string. If modified, it will be freed and replaced by
+ * a new allocated string.
+ * \note path is expected to be FILE_MAX size or smaller.
+ *
+ * \return true is \a path was modified and re-allocated, false otherwise.
+ */
+bool BKE_bpath_foreach_path_allocated_process(struct BPathForeachPathData *bpath_data,
+ char **path);
+
+/** \} */
+
+/** \name High level features.
+ * \{ */
+
+/** Check for missing files. */
void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports);
+
+/** Recursively search into given search directory, for all file paths of all IDs in given \a
+ * bmain, and replace existing paths as needed.
+ *
+ * \note The search will happen into the whole search directory tree recursively (with a limit of
+ * MAX_DIR_RECURSE), if several files are found matching a searched filename, the biggest one will
+ * be used. This is so that things like thumbnails don't get selected instead of the actual image
+ * e.g.
+ *
+ * \param searchpath: The root directory in which the new filepaths should be searched for.
+ * \param find_all: If `true`, also search for files which current path is still valid, if `false`
+ * skip those still valid paths.
+ * */
void BKE_bpath_missing_files_find(struct Main *bmain,
const char *searchpath,
struct ReportList *reports,
const bool find_all);
+
+/** Rebase all relative file paths in given \a bmain from \a basedir_src to \a basedir_dst. */
void BKE_bpath_relative_rebase(struct Main *bmain,
const char *basedir_src,
const char *basedir_dst,
struct ReportList *reports);
+
+/** Make all absolute file paths in given \a bmain relative to given \a basedir. */
void BKE_bpath_relative_convert(struct Main *bmain,
const char *basedir,
struct ReportList *reports);
+
+/** Make all relative file paths in given \a bmain absolute, using given \a basedir as root. */
void BKE_bpath_absolute_convert(struct Main *bmain,
const char *basedir,
struct ReportList *reports);
+/** Temp backup of paths from all IDs in given \a bmain.
+ *
+ * \return An opaque handle to pass to #BKE_bpath_list_restore and #BKE_bpath_list_free.
+ */
+void *BKE_bpath_list_backup(struct Main *bmain, const eBPathForeachFlag flag);
+
+/** Restore the temp backup of paths from \a path_list_handle into all IDs in given \a bmain.
+ *
+ * \note This function assumes that the data in given Main did not change (no
+ * addition/deletion/re-ordering of IDs, or their file paths) since the call to
+ * #BKE_bpath_list_backup that generated the given \a path_list_handle. */
+void BKE_bpath_list_restore(struct Main *bmain,
+ const eBPathForeachFlag flag,
+ void *path_list_handle);
+
+/** Free the temp backup of paths in \a path_list_handle.
+ *
+ * \note This function assumes that the path list has already been restored with a call to
+ * #BKE_bpath_list_restore, and is therefore empty. */
+void BKE_bpath_list_free(void *path_list_handle);
+
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 452a08bc9c8..a0f3733588a 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -39,49 +39,93 @@ struct UnifiedPaintSettings;
// enum eCurveMappingPreset;
-/* globals for brush execution */
+/* Globals for brush execution. */
+
void BKE_brush_system_init(void);
void BKE_brush_system_exit(void);
-/* datablock functions */
+/* Data-block functions. */
+
+/**
+ * \note Resulting brush will have two users: one as a fake user,
+ * another is assumed to be used by the caller.
+ */
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, const eObjectMode ob_mode);
+/**
+ * Add a new gp-brush.
+ */
struct Brush *BKE_brush_add_gpencil(struct Main *bmain,
struct ToolSettings *ts,
const char *name,
eObjectMode mode);
+/**
+ * Delete a Brush.
+ */
bool BKE_brush_delete(struct Main *bmain, struct Brush *brush);
+/**
+ * Add grease pencil settings.
+ */
void BKE_brush_init_gpencil_settings(struct Brush *brush);
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode);
void BKE_brush_sculpt_reset(struct Brush *brush);
+/**
+ * Create a set of grease pencil Drawing presets.
+ */
void BKE_brush_gpencil_paint_presets(struct Main *bmain,
struct ToolSettings *ts,
const bool reset);
+/**
+ * Create a set of grease pencil Vertex Paint presets.
+ */
void BKE_brush_gpencil_vertex_presets(struct Main *bmain,
struct ToolSettings *ts,
const bool reset);
+/**
+ * Create a set of grease pencil Sculpt Paint presets.
+ */
void BKE_brush_gpencil_sculpt_presets(struct Main *bmain,
struct ToolSettings *ts,
const bool reset);
+/**
+ * Create a set of grease pencil Weight Paint presets.
+ */
void BKE_brush_gpencil_weight_presets(struct Main *bmain,
struct ToolSettings *ts,
const bool reset);
void BKE_gpencil_brush_preset_set(struct Main *bmain, struct Brush *brush, const short type);
-/* jitter */
void BKE_brush_jitter_pos(const struct Scene *scene,
struct Brush *brush,
const float pos[2],
float jitterpos[2]);
void BKE_brush_randomize_texture_coords(struct UnifiedPaintSettings *ups, bool mask);
-/* brush curve */
+/* Brush curve. */
+
+/**
+ * Library Operations
+ */
void BKE_brush_curve_preset(struct Brush *b, enum eCurveMappingPreset preset);
-float BKE_brush_curve_strength_clamped(struct Brush *br, float p, const float len);
+/**
+ * Uses the brush curve control to find a strength value between 0 and 1.
+ */
+float BKE_brush_curve_strength_clamped(const struct Brush *br, float p, const float len);
+/**
+ * Uses the brush curve control to find a strength value.
+ */
float BKE_brush_curve_strength(const struct Brush *br, float p, const float len);
-/* sampling */
+/* Sampling. */
+
+/**
+ * Generic texture sampler for 3D painting systems.
+ * point has to be either in region space mouse coordinates,
+ * or 3d world coordinates for 3D mapping.
+ *
+ * RGBA outputs straight alpha.
+ */
float BKE_brush_sample_tex_3d(const struct Scene *scene,
const struct Brush *br,
const float point[3],
@@ -94,15 +138,18 @@ float BKE_brush_sample_masktex(const struct Scene *scene,
const int thread,
struct ImagePool *pool);
-/* texture */
+/* Texture. */
+
unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool use_secondary);
-/* radial control */
+/**
+ * Radial control.
+ */
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br,
bool secondary,
bool display_gradient);
-/* unified strength size and color */
+/* Unified strength size and color. */
const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush);
const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush);
@@ -127,12 +174,16 @@ bool BKE_brush_use_size_pressure(const struct Brush *brush);
bool BKE_brush_sculpt_has_secondary_color(const struct Brush *brush);
-/* scale unprojected radius to reflect a change in the brush's 2D size */
+/**
+ * Scale unprojected radius to reflect a change in the brush's 2D size.
+ */
void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
int new_brush_size,
int old_brush_size);
-/* scale brush size to reflect a change in the brush's unprojected radius */
+/**
+ * Scale brush size to reflect a change in the brush's unprojected radius.
+ */
void BKE_brush_scale_size(int *r_brush_size,
float new_unprojected_radius,
float old_unprojected_radius);
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index bb95985ef4c..45c3a8ec159 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -48,7 +48,7 @@ struct BVHCache;
typedef struct BVHTreeFromEditMesh {
struct BVHTree *tree;
- /** Default callbacks to bvh nearest and ray-cast. */
+ /** Default callbacks to BVH nearest and ray-cast. */
BVHTree_NearestPointCallback nearest_callback;
BVHTree_RayCastCallback raycast_callback;
@@ -65,7 +65,7 @@ typedef struct BVHTreeFromEditMesh {
typedef struct BVHTreeFromMesh {
struct BVHTree *tree;
- /** Default callbacks to bvh nearest and ray-cast. */
+ /** Default callbacks to BVH nearest and ray-cast. */
BVHTree_NearestPointCallback nearest_callback;
BVHTree_RayCastCallback raycast_callback;
@@ -105,7 +105,7 @@ typedef enum BVHCacheType {
} BVHCacheType;
/**
- * Builds a bvh tree where nodes are the relevant elements of the given mesh.
+ * Builds a BVH tree where nodes are the relevant elements of the given mesh.
* Configures #BVHTreeFromMesh.
*
* The tree is build in mesh space coordinates, this means special care must be made on queries
@@ -113,11 +113,14 @@ typedef enum BVHCacheType {
* Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it
* becomes possible to reuse a #BVHTree.
*
- * free_bvhtree_from_mesh should be called when the tree is no longer needed.
+ * #free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
+/**
+ * Builds a BVH-tree where nodes are the vertices of the given `em`.
+ */
BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const BLI_bitmap *mask,
@@ -129,11 +132,18 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
struct BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex);
+/**
+ * Builds a BVH-tree where nodes are the given vertices (NOTE: does not copy given `vert`!).
+ * \param vert_allocated: if true, vert freeing will be done when freeing data.
+ * \param verts_mask: if not null, true elements give which vert to add to BVH-tree.
+ * \param verts_num_active: if >= 0, number of active verts to add to BVH-tree
+ * (else will be computed from mask).
+ */
BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const int verts_num,
const bool vert_allocated,
- const BLI_bitmap *mask,
+ const BLI_bitmap *verts_mask,
int verts_num_active,
float epsilon,
int tree_type,
@@ -145,6 +155,9 @@ BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
+/**
+ * Builds a BVH-tree where nodes are the edges of the given `em`.
+ */
BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const BLI_bitmap *edges_mask,
@@ -156,6 +169,14 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
struct BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex);
+/**
+ * Builds a BVH-tree where nodes are the given edges.
+ * \param vert, vert_allocated: if true, elem freeing will be done when freeing data.
+ * \param edge, edge_allocated: if true, elem freeing will be done when freeing data.
+ * \param edges_mask: if not null, true elements give which vert to add to BVH-tree.
+ * \param edges_num_active: if >= 0, number of active edges to add to BVH-tree
+ * (else will be computed from mask).
+ */
BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const bool vert_allocated,
@@ -171,13 +192,22 @@ BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
struct BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex);
+/**
+ * Builds a BVH-tree where nodes are the given tessellated faces
+ * (NOTE: does not copy given mfaces!).
+ * \param vert_allocated: if true, vert freeing will be done when freeing data.
+ * \param face_allocated: if true, face freeing will be done when freeing data.
+ * \param faces_mask: if not null, true elements give which faces to add to BVH-tree.
+ * \param faces_num_active: if >= 0, number of active faces to add to BVH-tree
+ * (else will be computed from mask).
+ */
BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const bool vert_allocated,
const struct MFace *face,
const int numFaces,
const bool face_allocated,
- const BLI_bitmap *mask,
+ const BLI_bitmap *faces_mask,
int faces_num_active,
float epsilon,
int tree_type,
@@ -189,6 +219,9 @@ BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
BVHTree *bvhtree_from_editmesh_looptri(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
+/**
+ * Builds a BVH-tree where nodes are the `looptri` faces of the given `bm`.
+ */
BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const BLI_bitmap *mask,
@@ -200,6 +233,11 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
struct BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex);
+/**
+ * Builds a BVH-tree where nodes are the looptri faces of the given mesh.
+ *
+ * \note for edit-mesh this is currently a duplicate of #bvhtree_from_mesh_faces_ex
+ */
BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const bool vert_allocated,
@@ -217,11 +255,20 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
struct BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex);
+/**
+ * Builds or queries a BVH-cache for the cache BVH-tree of the request type.
+ *
+ * \note This function only fills a cache, and therefore the mesh argument can
+ * be considered logically const. Concurrent access is protected by a mutex.
+ */
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
const struct Mesh *mesh,
const BVHCacheType bvh_cache_type,
const int tree_type);
+/**
+ * Builds or queries a BVH-cache for the cache BVH-tree of the request type.
+ */
BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const int tree_type,
@@ -230,9 +277,12 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
ThreadMutex *mesh_eval_mutex);
/**
- * Frees data allocated by a call to bvhtree_from_mesh_*.
+ * Frees data allocated by a call to `bvhtree_from_editmesh_*`.
*/
void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data);
+/**
+ * Frees data allocated by a call to `bvhtree_from_mesh_*`.
+ */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
/**
@@ -272,6 +322,9 @@ void free_bvhtree_from_pointcloud(struct BVHTreeFromPointCloud *data);
bool bvhcache_has_tree(const struct BVHCache *bvh_cache, const BVHTree *tree);
struct BVHCache *bvhcache_init(void);
+/**
+ * Frees a BVH-cache.
+ */
void bvhcache_free(struct BVHCache *bvh_cache);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 836597f95da..ac621bfdcb9 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -61,6 +61,12 @@ void BKE_cachefile_reader_open(struct CacheFile *cache_file,
const char *object_path);
void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader **reader);
+/**
+ * Determine whether the #CacheFile should use a render engine procedural. If so, data is not read
+ * from the file and bounding boxes are used to represent the objects in the Scene.
+ * Render engines will receive the bounding box as a placeholder but can instead
+ * load the data directly if they support it.
+ */
bool BKE_cache_file_uses_render_procedural(const struct CacheFile *cache_file,
struct Scene *scene,
const int dag_eval_mode);
diff --git a/source/blender/blenkernel/BKE_callbacks.h b/source/blender/blenkernel/BKE_callbacks.h
index 7c518f33c89..c125b081b49 100644
--- a/source/blender/blenkernel/BKE_callbacks.h
+++ b/source/blender/blenkernel/BKE_callbacks.h
@@ -133,6 +133,9 @@ void BKE_callback_add(bCallbackFuncStore *funcstore, eCbEvent evt);
void BKE_callback_remove(bCallbackFuncStore *funcstore, eCbEvent evt);
void BKE_callback_global_init(void);
+/**
+ * Call on application exit.
+ */
void BKE_callback_global_finalize(void);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index b42fcbe7808..45bfef82302 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -37,22 +37,26 @@ struct Scene;
struct View3D;
struct rctf;
-/* Camera Datablock */
+/* Camera Data-block */
void *BKE_camera_add(struct Main *bmain, const char *name);
/* Camera Usage */
+/**
+ * Get the camera's DOF value, takes the DOF object into account.
+ */
float BKE_camera_object_dof_distance(struct Object *ob);
int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey);
float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y);
-/* Camera Parameters:
+/**
+ * Camera Parameters:
*
* Intermediate struct for storing camera parameters from various sources,
- * to unify computation of viewplane, window matrix, ... */
-
+ * to unify computation of view-plane, window matrix, ... etc.
+ */
typedef struct CameraParams {
/* lens */
bool is_ortho;
@@ -84,7 +88,7 @@ typedef struct CameraParams {
float winmat[4][4];
} CameraParams;
-/* values for CameraParams.zoom, need to be taken into account for some operations */
+/* Values for CameraParams.zoom, need to be taken into account for some operations. */
#define CAMERA_PARAM_ZOOM_INIT_CAMOB 1.0f
#define CAMERA_PARAM_ZOOM_INIT_PERSP 2.0f
@@ -97,6 +101,9 @@ void BKE_camera_params_from_view3d(CameraParams *params,
void BKE_camera_params_compute_viewplane(
CameraParams *params, int winx, int winy, float aspx, float aspy);
+/**
+ * View-plane is assumed to be already computed.
+ */
void BKE_camera_params_compute_matrix(CameraParams *params);
/* Camera View Frame */
@@ -114,6 +121,11 @@ void BKE_camera_view_frame(const struct Scene *scene,
const struct Camera *camera,
float r_vec[4][3]);
+/**
+ * \param r_scale: only valid/useful for orthographic cameras.
+ *
+ * \note Don't move the camera, just yield the fit location.
+ */
bool BKE_camera_view_frame_fit_to_scene(struct Depsgraph *depsgraph,
const struct Scene *scene,
struct Object *camera_ob,
@@ -128,9 +140,15 @@ bool BKE_camera_view_frame_fit_to_coords(const struct Depsgraph *depsgraph,
/* Camera multi-view API */
+/**
+ * Returns the camera to be used for render.
+ */
struct Object *BKE_camera_multiview_render(const struct Scene *scene,
struct Object *camera,
const char *viewname);
+/**
+ * The view matrix is used by the viewport drawing, it is basically the inverted model matrix.
+ */
void BKE_camera_multiview_view_matrix(const struct RenderData *rd,
const struct Object *camera,
const bool is_left,
@@ -158,6 +176,7 @@ bool BKE_camera_multiview_spherical_stereo(const struct RenderData *rd,
const struct Object *camera);
/* Camera background image API */
+
struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam);
void BKE_camera_background_image_remove(struct Camera *cam, struct CameraBGImage *bgpic);
void BKE_camera_background_image_clear(struct Camera *cam);
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index dbf285feb92..ee73b926886 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -235,7 +235,9 @@ int cloth_bvh_collision(struct Depsgraph *depsgraph,
/* cloth.c */
/* Needed for modifier.c */
+/** Frees all. */
void cloth_free_modifier_extern(struct ClothModifierData *clmd);
+/** Frees all. */
void cloth_free_modifier(struct ClothModifierData *clmd);
void clothModifier_do(struct ClothModifierData *clmd,
struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 2c7143be60e..46c1fe0d33d 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -54,20 +54,51 @@ typedef struct CollectionParent {
/* Collections */
+/**
+ * Add a collection to a collection ListBase and synchronize all render layers
+ * The ListBase is NULL when the collection is to be added to the master collection
+ */
struct Collection *BKE_collection_add(struct Main *bmain,
struct Collection *parent,
const char *name);
+/**
+ * Add \a collection_dst to all scene collections that reference object \a ob_src is in.
+ * Used to replace an instance object with a collection (library override operator).
+ *
+ * Logic is very similar to #BKE_collection_object_add_from().
+ */
void BKE_collection_add_from_object(struct Main *bmain,
struct Scene *scene,
const struct Object *ob_src,
struct Collection *collection_dst);
+/**
+ * Add \a collection_dst to all scene collections that reference collection \a collection_src is
+ * in.
+ *
+ * Logic is very similar to #BKE_collection_object_add_from().
+ */
void BKE_collection_add_from_collection(struct Main *bmain,
struct Scene *scene,
struct Collection *collection_src,
struct Collection *collection_dst);
+/**
+ * Free (or release) any data used by this collection (does not free the collection itself).
+ */
void BKE_collection_free_data(struct Collection *collection);
+/**
+ * Remove a collection, optionally removing its child objects or moving
+ * them to parent collections.
+ */
bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy);
+/**
+ * Make a deep copy (aka duplicate) of the given collection and all of its children, recursively.
+ *
+ * \warning This functions will clear all \a bmain #ID.idnew pointers, unless \a
+ * #LIB_ID_DUPLICATE_IS_SUBPROCESS duplicate option is passed on, in which case caller is
+ * responsible to reconstruct collection dependencies information's
+ * (i.e. call #BKE_main_collection_sync).
+ */
struct Collection *BKE_collection_duplicate(struct Main *bmain,
struct Collection *parent,
struct Collection *collection,
@@ -91,28 +122,60 @@ struct Collection *BKE_collection_object_find(struct Main *bmain,
struct Object *ob);
bool BKE_collection_is_empty(const struct Collection *collection);
+/**
+ * Add object to collection
+ */
bool BKE_collection_object_add(struct Main *bmain,
struct Collection *collection,
struct Object *ob);
+/**
+ * Add \a ob_dst to all scene collections that reference object \a ob_src is in.
+ * Used for copying objects.
+ *
+ * Logic is very similar to #BKE_collection_add_from_object()
+ */
void BKE_collection_object_add_from(struct Main *bmain,
struct Scene *scene,
struct Object *ob_src,
struct Object *ob_dst);
+/**
+ * Remove object from collection.
+ */
bool BKE_collection_object_remove(struct Main *bmain,
struct Collection *collection,
struct Object *object,
const bool free_us);
+/**
+ * Move object from a collection into another
+ *
+ * If source collection is NULL move it from all the existing collections.
+ */
void BKE_collection_object_move(struct Main *bmain,
struct Scene *scene,
struct Collection *collection_dst,
struct Collection *collection_src,
struct Object *ob);
+/**
+ * Remove object from all collections of scene
+ */
bool BKE_scene_collections_object_remove(struct Main *bmain,
struct Scene *scene,
struct Object *object,
const bool free_us);
void BKE_collections_object_remove_nulls(struct Main *bmain);
+/**
+ * Remove all NULL children from parent collections of changed \a collection.
+ * This is used for library remapping, where these pointers have been set to NULL.
+ * Otherwise this should never happen.
+ *
+ * \note caller must ensure #BKE_main_collection_sync_remap() is called afterwards!
+ *
+ * \param parent_collection: The collection owning the pointers that were remapped. May be \a NULL,
+ * in which case whole \a bmain database of collections is checked.
+ * \param child_collection: The collection that was remapped to another pointer. May be \a NULL,
+ * in which case whole \a bmain database of collections is checked.
+ */
void BKE_collections_child_remove_nulls(struct Main *bmain,
struct Collection *parent_collection,
struct Collection *child_collection);
@@ -136,9 +199,24 @@ struct Base *BKE_collection_or_layer_objects(const struct ViewLayer *view_layer,
/* Editing. */
+/**
+ * Return Scene Collection for a given index.
+ *
+ * The index is calculated from top to bottom counting the children before the siblings.
+ */
struct Collection *BKE_collection_from_index(struct Scene *scene, const int index);
+/**
+ * The automatic/fallback name of a new collection.
+ */
void BKE_collection_new_name_get(struct Collection *collection_parent, char *rname);
+/**
+ * The name to show in the interface.
+ */
const char *BKE_collection_ui_name_get(struct Collection *collection);
+/**
+ * Select all the objects in this Collection (and its nested collections) for this ViewLayer.
+ * Return true if any object was selected.
+ */
bool BKE_collection_objects_select(struct ViewLayer *view_layer,
struct Collection *collection,
bool deselect);
@@ -162,13 +240,36 @@ bool BKE_collection_move(struct Main *bmain,
bool relative_after,
struct Collection *collection);
+/**
+ * Find potential cycles in collections.
+ *
+ * \param new_ancestor: the potential new owner of given \a collection,
+ * or the collection to check if the later is NULL.
+ * \param collection: the collection we want to add to \a new_ancestor,
+ * may be NULL if we just want to ensure \a new_ancestor does not already have cycles.
+ * \return true if a cycle is found.
+ */
bool BKE_collection_cycle_find(struct Collection *new_ancestor, struct Collection *collection);
+/**
+ * Find and fix potential cycles in collections.
+ *
+ * \param collection: The collection to check for existing cycles.
+ * \return true if cycles are found and fixed.
+ */
bool BKE_collection_cycles_fix(struct Main *bmain, struct Collection *collection);
bool BKE_collection_has_collection(const struct Collection *parent,
const struct Collection *collection);
+/**
+ * Rebuild parent relationships from child ones, for all children of given \a collection.
+ *
+ * \note Given collection is assumed to already have valid parents.
+ */
void BKE_collection_parent_relations_rebuild(struct Collection *collection);
+/**
+ * Rebuild parent relationships from child ones, for all collections in given \a bmain.
+ */
void BKE_main_collections_parent_relations_rebuild(struct Main *bmain);
/* .blend file I/O */
@@ -224,6 +325,10 @@ typedef void (*BKE_scene_collections_Cb)(struct Collection *ob, void *data);
/* Iteration over collections in scene. */
+/**
+ * Only use this in non-performance critical situations
+ * (it iterates over all scene collections twice)
+ */
void BKE_scene_collections_iterator_begin(struct BLI_Iterator *iter, void *data_in);
void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter);
void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter);
@@ -232,6 +337,13 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
+/**
+ * Generate a new #GSet (or extend given `objects_gset` if not NULL) with all objects referenced by
+ * all collections of given `scene`.
+ *
+ * \note This will include objects without a base currently
+ * (because they would belong to excluded collections only e.g.).
+ */
struct GSet *BKE_scene_objects_as_gset(struct Scene *scene, struct GSet *objects_gset);
#define FOREACH_SCENE_COLLECTION_BEGIN(scene, _instance) \
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 2c21b7355d6..71929d1797c 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -116,8 +116,11 @@ void bvhtree_update_from_mvert(struct BVHTree *bvhtree,
/////////////////////////////////////////////////
-/* move Collision modifier object inter-frame with step = [0,1]
- * defined in collisions.c */
+/**
+ * Move Collision modifier object inter-frame with step = [0,1]
+ *
+ * \param step: is limited from 0 (frame start position) to 1 (frame end position).
+ */
void collision_move_object(struct CollisionModifierData *collmd,
const float step,
const float prevstep,
@@ -135,6 +138,11 @@ typedef struct CollisionRelation {
struct Object *ob;
} CollisionRelation;
+/**
+ * Create list of collision relations in the collection or entire scene.
+ * This is used by the depsgraph to build relations, as well as faster
+ * lookup of colliders during evaluation.
+ */
struct ListBase *BKE_collision_relations_create(struct Depsgraph *depsgraph,
struct Collection *collection,
unsigned int modifier_type);
@@ -142,6 +150,10 @@ void BKE_collision_relations_free(struct ListBase *relations);
/* Collision object lists for physics simulation evaluation. */
+/**
+ * Create effective list of colliders from relations built beforehand.
+ * Self will be excluded.
+ */
struct Object **BKE_collision_objects_create(struct Depsgraph *depsgraph,
struct Object *self,
struct Collection *collection,
@@ -155,6 +167,10 @@ typedef struct ColliderCache {
struct CollisionModifierData *collmd;
} ColliderCache;
+/**
+ * Create effective list of colliders from relations built beforehand.
+ * Self will be excluded.
+ */
struct ListBase *BKE_collider_cache_create(struct Depsgraph *depsgraph,
struct Object *self,
struct Collection *collection);
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 109947cece4..17fb48cdd27 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -59,40 +59,85 @@ enum {
CURVEMAP_SLOPE_POS_NEG = 2,
};
+/**
+ * Reset the view for current curve.
+ */
void BKE_curvemapping_reset_view(struct CurveMapping *cumap);
void BKE_curvemap_reset(struct CurveMap *cuma, const struct rctf *clipr, int preset, int slope);
+/**
+ * Removes with flag set.
+ */
void BKE_curvemap_remove(struct CurveMap *cuma, const short flag);
+/**
+ * Remove specified point.
+ */
bool BKE_curvemap_remove_point(struct CurveMap *cuma, struct CurveMapPoint *cmp);
struct CurveMapPoint *BKE_curvemap_insert(struct CurveMap *cuma, float x, float y);
+/**
+ * \param type: #eBezTriple_Handle
+ */
void BKE_curvemap_handle_set(struct CurveMap *cuma, int type);
+/**
+ * \note only does current curvemap!.
+ */
void BKE_curvemapping_changed(struct CurveMapping *cumap, const bool rem_doubles);
void BKE_curvemapping_changed_all(struct CurveMapping *cumap);
-/* call before _all_ evaluation functions */
+/**
+ * Call before _all_ evaluation functions.
+ */
void BKE_curvemapping_init(struct CurveMapping *cumap);
-/* keep these (const CurveMap) - to help with thread safety */
-/* single curve, no table check */
+/**
+ * Keep these `const CurveMap` - to help with thread safety.
+ * \note Single curve, no table check.
+ * \note Table should be verified.
+ */
float BKE_curvemap_evaluateF(const struct CurveMapping *cumap,
const struct CurveMap *cuma,
float value);
-/* single curve, with table check */
+/**
+ * Single curve, with table check.
+ * Works with curve 'cur'.
+ */
float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value);
+/**
+ * Vector case.
+ */
void BKE_curvemapping_evaluate3F(const struct CurveMapping *cumap,
float vecout[3],
const float vecin[3]);
+/**
+ * RGB case, no black/white points, no pre-multiply.
+ */
void BKE_curvemapping_evaluateRGBF(const struct CurveMapping *cumap,
float vecout[3],
const float vecin[3]);
+/**
+ * Byte version of #BKE_curvemapping_evaluateRGBF.
+ */
void BKE_curvemapping_evaluate_premulRGB(const struct CurveMapping *cumap,
unsigned char vecout_byte[3],
const unsigned char vecin_byte[3]);
+/**
+ * Same as #BKE_curvemapping_evaluate_premulRGBF
+ * but black/bwmul are passed as args for the compositor
+ * where they can change per pixel.
+ *
+ * Use in conjunction with #BKE_curvemapping_set_black_white_ex
+ *
+ * \param black: Use instead of cumap->black
+ * \param bwmul: Use instead of cumap->bwmul
+ */
void BKE_curvemapping_evaluate_premulRGBF_ex(const struct CurveMapping *cumap,
float vecout[3],
const float vecin[3],
const float black[3],
const float bwmul[3]);
+/**
+ * RGB with black/white points and pre-multiply. tables are checked.
+ */
void BKE_curvemapping_evaluate_premulRGBF(const struct CurveMapping *cumap,
float vecout[3],
const float vecin[3]);
@@ -100,12 +145,18 @@ bool BKE_curvemapping_RGBA_does_something(const struct CurveMapping *cumap);
void BKE_curvemapping_table_F(const struct CurveMapping *cumap, float **array, int *size);
void BKE_curvemapping_table_RGBA(const struct CurveMapping *cumap, float **array, int *size);
-/* non-const, these modify the curve */
-void BKE_curvemapping_premultiply(struct CurveMapping *cumap, int restore);
+/**
+ * Call when you do images etc, needs restore too. also verifies tables.
+ * non-const (these modify the curve).
+ */
+void BKE_curvemapping_premultiply(struct CurveMapping *cumap, bool restore);
void BKE_curvemapping_blend_write(struct BlendWriter *writer, const struct CurveMapping *cumap);
void BKE_curvemapping_curves_blend_write(struct BlendWriter *writer,
const struct CurveMapping *cumap);
+/**
+ * \note `cumap` itself has been read already.
+ */
void BKE_curvemapping_blend_read(struct BlendDataReader *reader, struct CurveMapping *cumap);
void BKE_histogram_update_sample_line(struct Histogram *hist,
@@ -123,16 +174,20 @@ void BKE_color_managed_display_settings_init(struct ColorManagedDisplaySettings
void BKE_color_managed_display_settings_copy(struct ColorManagedDisplaySettings *new_settings,
const struct ColorManagedDisplaySettings *settings);
-/* Initialize view settings to be best suitable for render type of viewing.
+/**
+ * Initialize view settings to be best suitable for render type of viewing.
* This will use default view transform from the OCIO configuration if none
- * is specified. */
+ * is specified.
+ */
void BKE_color_managed_view_settings_init_render(
struct ColorManagedViewSettings *settings,
const struct ColorManagedDisplaySettings *display_settings,
const char *view_transform);
-/* Initialize view settings which are best suitable for viewing non-render
- * images. For example,s movie clips while tracking. */
+/**
+ * Initialize view settings which are best suitable for viewing non-render images.
+ * For example,s movie clips while tracking.
+ */
void BKE_color_managed_view_settings_init_default(
struct ColorManagedViewSettings *settings,
const struct ColorManagedDisplaySettings *display_settings);
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 784b395dfa5..1f59efbb0f3 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -45,7 +45,7 @@ extern "C" {
typedef struct bConstraintOb {
/** to get evaluated armature. */
struct Depsgraph *depsgraph;
- /** for system time, part of deglobalization, code nicer later with local time (ton) */
+ /** for system time, part of de-globalization, code nicer later with local time (ton) */
struct Scene *scene;
/** if pchan, then armature that it comes from, otherwise constraint owner */
struct Object *ob;
@@ -61,7 +61,7 @@ typedef struct bConstraintOb {
/** type of owner. */
short type;
- /** rotation order for constraint owner (as defined in eEulerRotationOrders in BLI_math.h) */
+ /** rotation order for constraint owner (as defined in #eEulerRotationOrders in BLI_math.h) */
short rotOrder;
} bConstraintOb;
@@ -76,7 +76,7 @@ typedef void (*ConstraintIDFunc)(struct bConstraint *con,
/* ....... */
/**
- * Constraint Type-Info (shorthand in code = cti):
+ * Constraint Type-Info (shorthand in code = `cti`):
* This struct provides function pointers for runtime, so that functions can be
* written more generally (with fewer/no special exceptions for various constraints).
*
@@ -138,49 +138,107 @@ typedef struct bConstraintTypeInfo {
} bConstraintTypeInfo;
/* Function Prototypes for bConstraintTypeInfo's */
+
+/**
+ * This function should always be used to get the appropriate type-info, as it
+ * has checks which prevent segfaults in some weird cases.
+ */
const bConstraintTypeInfo *BKE_constraint_typeinfo_get(struct bConstraint *con);
+/**
+ * This function should be used for getting the appropriate type-info when only
+ * a constraint type is known.
+ */
const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type);
/* ---------------------------------------------------------------------------- */
/* Constraint function prototypes */
+
+/**
+ * Find the first available, non-duplicate name for a given constraint.
+ */
void BKE_constraint_unique_name(struct bConstraint *con, struct ListBase *list);
+/**
+ * Allocate and duplicate a single constraint, outside of any object/pose context.
+ */
struct bConstraint *BKE_constraint_duplicate_ex(struct bConstraint *src,
const int flag,
const bool do_extern);
+/**
+ * Add a copy of the given constraint for the given bone.
+ */
struct bConstraint *BKE_constraint_copy_for_pose(struct Object *ob,
struct bPoseChannel *pchan,
struct bConstraint *src);
+/**
+ * Add a copy of the given constraint for the given object.
+ */
struct bConstraint *BKE_constraint_copy_for_object(struct Object *ob, struct bConstraint *src);
void BKE_constraints_free(struct ListBase *list);
+/**
+ * Free all constraints from a constraint-stack.
+ */
void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user);
void BKE_constraints_copy(struct ListBase *dst, const struct ListBase *src, bool do_extern);
+/**
+ * Duplicate all of the constraints in a constraint stack.
+ */
void BKE_constraints_copy_ex(struct ListBase *dst,
const struct ListBase *src,
const int flag,
bool do_extern);
+/**
+ * Run the given callback on all ID-blocks in list of constraints.
+ */
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, void *userdata);
void BKE_constraint_free_data(struct bConstraint *con);
+/**
+ * Free data of a specific constraint if it has any info.
+ * Be sure to run #BIK_clear_data() when freeing an IK constraint,
+ * unless #DAG_relations_tag_update is called.
+ */
void BKE_constraint_free_data_ex(struct bConstraint *con, bool do_id_user);
bool BKE_constraint_target_uses_bbone(struct bConstraint *con, struct bConstraintTarget *ct);
/* Constraint API function prototypes */
+
+/**
+ * Finds the 'active' constraint in a constraint stack.
+ */
struct bConstraint *BKE_constraints_active_get(struct ListBase *list);
+/**
+ * Set the given constraint as the active one (clearing all the others).
+ */
void BKE_constraints_active_set(ListBase *list, struct bConstraint *con);
struct bConstraint *BKE_constraints_find_name(struct ListBase *list, const char *name);
+/**
+ * Finds the constraint that owns the given target within the object.
+ */
struct bConstraint *BKE_constraint_find_from_target(struct Object *ob,
struct bConstraintTarget *tgt,
struct bPoseChannel **r_pchan);
+/**
+ * Check whether given constraint is not local (i.e. from linked data) when the object is a library
+ * override.
+ *
+ * \param con: May be NULL, in which case we consider it as a non-local constraint case.
+ */
bool BKE_constraint_is_nonlocal_in_liboverride(const struct Object *ob,
const struct bConstraint *con);
+/**
+ * Add new constraint for the given object.
+ */
struct bConstraint *BKE_constraint_add_for_object(struct Object *ob, const char *name, short type);
+/**
+ * Add new constraint for the given bone.
+ */
struct bConstraint *BKE_constraint_add_for_pose(struct Object *ob,
struct bPoseChannel *pchan,
const char *name,
@@ -190,8 +248,14 @@ bool BKE_constraint_remove_ex(ListBase *list,
struct Object *ob,
struct bConstraint *con,
bool clear_dep);
+/**
+ * Remove the specified constraint from the given constraint stack.
+ */
bool BKE_constraint_remove(ListBase *list, struct bConstraint *con);
+/**
+ * Apply the specified constraint in the given constraint stack.
+ */
bool BKE_constraint_apply_for_object(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
@@ -217,17 +281,38 @@ bool BKE_constraint_apply_and_remove_for_pose(struct Depsgraph *depsgraph,
void BKE_constraint_panel_expand(struct bConstraint *con);
/* Constraints + Proxies function prototypes */
+
+/**
+ * Rescue all constraints tagged as being #CONSTRAINT_PROXY_LOCAL
+ * (i.e. added to bone that's proxy-synced in this file).
+ */
void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *src);
+/**
+ * Returns if the owner of the constraint is proxy-protected.
+ */
bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan);
/* Constraint Evaluation function prototypes */
+
+/**
+ * This function MEM_calloc's a #bConstraintOb struct,
+ * that will need to be freed after evaluation.
+ */
struct bConstraintOb *BKE_constraints_make_evalob(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
void *subdata,
short datatype);
+/**
+ * Cleanup after constraint evaluation.
+ */
void BKE_constraints_clear_evalob(struct bConstraintOb *cob);
+/**
+ * This function is responsible for the correct transformations/conversions
+ * of a matrix from one space to another for constraint evaluation.
+ * For now, this is only implemented for objects and pose-channels.
+ */
void BKE_constraint_mat_convertspace(struct Object *ob,
struct bPoseChannel *pchan,
struct bConstraintOb *cob,
@@ -236,6 +321,14 @@ void BKE_constraint_mat_convertspace(struct Object *ob,
short to,
const bool keep_scale);
+/**
+ * This function is a relic from the prior implementations of the constraints system, when all
+ * constraints either had one or no targets. It used to be called during the main constraint
+ * solving loop, but is now only used for the remaining cases for a few constraints.
+ *
+ * None of the actual calculations of the matrices should be done here! Also, this function is
+ * not to be used by any new constraints, particularly any that have multiple targets.
+ */
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
struct Scene *scene,
struct bConstraint *con,
@@ -244,12 +337,22 @@ void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
void *ownerdata,
float mat[4][4],
float ctime);
+/**
+ * Get the list of targets required for solving a constraint.
+ */
void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph,
struct bConstraint *con,
struct bConstraintOb *ob,
struct ListBase *targets,
float ctime);
void BKE_constraint_custom_object_space_get(float r_mat[4][4], struct bConstraint *con);
+/**
+ * This function is called whenever constraints need to be evaluated. Currently, all
+ * constraints that can be evaluated are every time this gets run.
+ *
+ * #BKE_constraints_make_evalob and #BKE_constraints_clear_evalob should be called before and
+ * after running this function, to sort out cob.
+ */
void BKE_constraints_solve(struct Depsgraph *depsgraph,
struct ListBase *conlist,
struct bConstraintOb *cob,
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index b0705ff411f..ac864c7f82c 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -247,6 +247,12 @@ PointerRNA CTX_data_pointer_get_type_silent(const bContext *C,
const char *member,
StructRNA *type);
ListBase CTX_data_collection_get(const bContext *C, const char *member);
+/**
+ * \param C: Context.
+ * \param use_store: Use 'C->wm.store'.
+ * \param use_rna: Use Include the properties from 'RNA_Context'.
+ * \param use_all: Don't skip values (currently only "scene").
+ */
ListBase CTX_data_dir_get_ex(const bContext *C,
const bool use_store,
const bool use_rna,
@@ -297,6 +303,13 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
+/**
+ * This is tricky. Sometimes the user overrides the render_layer
+ * but not the scene_collection. In this case what to do?
+ *
+ * If the scene_collection is linked to the #ViewLayer we use it.
+ * Otherwise we fallback to the active one of the #ViewLayer.
+ */
struct LayerCollection *CTX_data_layer_collection(const bContext *C);
struct Collection *CTX_data_collection(const bContext *C);
struct ViewLayer *CTX_data_view_layer(const bContext *C);
@@ -367,28 +380,34 @@ struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid);
bool CTX_wm_interface_locked(const bContext *C);
-/* Gets pointer to the dependency graph.
+/**
+ * Gets pointer to the dependency graph.
* If it doesn't exist yet, it will be allocated.
*
* The result dependency graph is NOT guaranteed to be up-to-date neither from relation nor from
* evaluated data points of view.
*
- * NOTE: Can not be used if access to a fully evaluated datablock is needed. */
+ * \note Can not be used if access to a fully evaluated data-block is needed.
+ */
struct Depsgraph *CTX_data_depsgraph_pointer(const bContext *C);
-/* Get dependency graph which is expected to be fully evaluated.
+/**
+ * Get dependency graph which is expected to be fully evaluated.
*
* In the release builds it is the same as CTX_data_depsgraph_pointer(). In the debug builds extra
* sanity checks are done. Additionally, this provides more semantic meaning to what is exactly
- * expected to happen. */
+ * expected to happen.
+ */
struct Depsgraph *CTX_data_expect_evaluated_depsgraph(const bContext *C);
-/* Gets fully updated and evaluated dependency graph.
+/**
+ * Gets fully updated and evaluated dependency graph.
*
* All the relations and evaluated objects are guaranteed to be up to date.
*
- * NOTE: Will be expensive if there are relations or objects tagged for update.
- * NOTE: If there are pending updates depsgraph hooks will be invoked. */
+ * \note Will be expensive if there are relations or objects tagged for update.
+ * \note If there are pending updates depsgraph hooks will be invoked.
+ */
struct Depsgraph *CTX_data_ensure_evaluated_depsgraph(const bContext *C);
/* Will Return NULL if depsgraph is not allocated yet.
diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h
index b95be70379f..f5266ed7a10 100644
--- a/source/blender/blenkernel/BKE_crazyspace.h
+++ b/source/blender/blenkernel/BKE_crazyspace.h
@@ -33,6 +33,10 @@ struct Object;
struct Scene;
/* crazyspace.c */
+
+/**
+ * Disable subdivision-surface temporal, get mapped coordinates, and enable it.
+ */
float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph,
struct Object *obedit))[3];
void BKE_crazyspace_set_quats_editmesh(struct BMEditMesh *em,
@@ -44,6 +48,10 @@ void BKE_crazyspace_set_quats_mesh(struct Mesh *me,
float (*origcos)[3],
float (*mappedcos)[3],
float (*quats)[4]);
+/**
+ * Returns an array of deform matrices for crazy-space correction,
+ * and the number of modifiers left.
+ */
int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph,
struct Scene *,
struct Object *,
diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h
index e98a9b2b1fd..329046ad494 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.h
+++ b/source/blender/blenkernel/BKE_cryptomatte.h
@@ -55,6 +55,9 @@ uint32_t BKE_cryptomatte_asset_hash(struct CryptomatteSession *session,
const char *layer_name,
const struct Object *object);
float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash);
+/**
+ * Find an ID in the given main that matches the given encoded float.
+ */
bool BKE_cryptomatte_find_name(const struct CryptomatteSession *session,
const float encoded_hash,
char *r_name,
diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh
index 9e205d01765..08536ecccbd 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.hh
+++ b/source/blender/blenkernel/BKE_cryptomatte.hh
@@ -37,7 +37,8 @@ struct ID;
namespace blender::bke::cryptomatte {
-/* Format to a cryptomatte meta data key.
+/**
+ * Format to a cryptomatte meta data key.
*
* Cryptomatte stores meta data. The keys are formatted containing a hash that
* is generated from its layer name.
@@ -48,7 +49,8 @@ namespace blender::bke::cryptomatte {
std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name,
const StringRefNull key_name);
-/* Extract the cryptomatte layer name from the given `render_pass_name`.
+/**
+ * Extract the cryptomatte layer name from the given `render_pass_name`.
*
* Cryptomatte passes are formatted with a trailing number for storing multiple samples that belong
* to the same cryptomatte layer. This function would remove the trailing numbers to determine the
@@ -59,7 +61,7 @@ std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name,
* A render_pass_name could be 'View Layer.CryptoMaterial02'. The cryptomatte layer would be 'View
* Layer.CryptoMaterial'.
*
- * NOTE: The return type is a sub-string of `render_pass_name` and therefore cannot outlive the
+ * \note The return type is a sub-string of `render_pass_name` and therefore cannot outlive the
* `render_pass_name` internal data.
*/
StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name);
@@ -72,6 +74,18 @@ struct CryptomatteHash {
static CryptomatteHash from_hex_encoded(blender::StringRef hex_encoded);
std::string hex_encoded() const;
+ /**
+ Convert a cryptomatte hash to a float.
+ *
+ * Cryptomatte hashes are stored in float textures and images. The conversion is taken from the
+ * cryptomatte specification. See Floating point conversion section in
+ * https://github.com/Psyop/Cryptomatte/blob/master/specification/cryptomatte_specification.pdf.
+ *
+ * The conversion uses as many 32 bit floating point values as possible to minimize hash
+ * collisions. Unfortunately not all 32 bits can be used as NaN and Inf can be problematic.
+ *
+ * Note that this conversion assumes to be running on a L-endian system.
+ */
float float_encoded() const;
};
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 5e474c0c5ac..713ee8cac01 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -75,8 +75,8 @@ typedef struct CVKeyIndex {
#define SEGMENTSV(nu) (((nu)->flagv & CU_NURB_CYCLIC) ? (nu)->pntsv : (nu)->pntsv - 1)
#define CU_DO_RADIUS(cu, nu) \
- ((((cu)->flag & (CU_PATH_RADIUS | CU_3D)) || (cu)->bevobj || (cu)->ext1 != 0.0f || \
- (cu)->ext2 != 0.0f) ? \
+ ((((cu)->flag & (CU_PATH_RADIUS | CU_3D)) || (cu)->bevobj || (cu)->extrude != 0.0f || \
+ (cu)->bevel_radius != 0.0f) ? \
1 : \
0)
@@ -86,6 +86,9 @@ typedef struct CVKeyIndex {
#define CU_DO_2DFILL(cu) (CU_IS_2D(cu) && (((cu)->flag & (CU_FRONT | CU_BACK)) != 0))
/* ** Curve ** */
+/**
+ * Frees edit-curve entirely.
+ */
void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu, const short curve_type);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
@@ -98,6 +101,8 @@ struct BoundBox *BKE_curve_boundbox_get(struct Object *ob);
void BKE_curve_texspace_calc(struct Curve *cu);
void BKE_curve_texspace_ensure(struct Curve *cu);
+/* Basic vertex data functions. */
+
bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
@@ -119,14 +124,26 @@ void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsig
void BKE_curve_smooth_flag_set(struct Curve *cu, const bool use_smooth);
+/**
+ * \return edit-nurbs or normal nurbs list.
+ */
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
const ListBase *BKE_curve_nurbs_get_for_read(const struct Curve *cu);
int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert);
void BKE_curve_nurb_active_set(struct Curve *cu, const struct Nurb *nu);
struct Nurb *BKE_curve_nurb_active_get(struct Curve *cu);
+/**
+ * Get active vert for curve.
+ */
void *BKE_curve_vert_active_get(struct Curve *cu);
+/**
+ * Set active nurb and active vert for curve.
+ */
void BKE_curve_nurb_vert_active_set(struct Curve *cu, const struct Nurb *nu, const void *vert);
+/**
+ * Get points to the active nurb and active vert for curve.
+ */
bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert);
void BKE_curve_nurb_vert_active_validate(struct Curve *cu);
@@ -152,6 +169,9 @@ void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, const float *key)
void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv);
void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
void BKE_curve_editNurb_free(struct Curve *cu);
+/**
+ * Get list of nurbs from edit-nurbs structure.
+ */
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
const struct ListBase *BKE_curve_editNurbs_get_for_read(const struct Curve *cu);
@@ -159,8 +179,14 @@ void BKE_curve_bevelList_free(struct ListBase *bev);
void BKE_curve_bevelList_make(struct Object *ob, const struct ListBase *nurbs, bool for_render);
ListBase BKE_curve_bevel_make(const struct Curve *curve);
+/**
+ * Forward differencing method for bezier curve.
+ */
void BKE_curve_forward_diff_bezier(
float q0, float q1, float q2, float q3, float *p, int it, int stride);
+/**
+ * Forward differencing method for first derivative of cubic bezier curve.
+ */
void BKE_curve_forward_diff_tangent_bezier(
float q0, float q1, float q2, float q3, float *p, int it, int stride);
@@ -168,6 +194,10 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu,
const struct TextBox *tb,
struct rctf *r_rect);
+/**
+ * This function is almost the same as #BKE_fcurve_correct_bezpart,
+ * but doesn't allow as large a tangent.
+ */
void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2]);
/* ** Nurbs ** */
@@ -179,6 +209,15 @@ int BKE_nurbList_verts_count_without_handles(const struct ListBase *nurb);
void BKE_nurbList_free(struct ListBase *lb);
void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2);
+/**
+ * \param code:
+ * - 1 (#HD_AUTO): set auto-handle.
+ * - 2 (#HD_VECT): set vector-handle.
+ * - 3 (#HD_ALIGN) it toggle, vector-handles become #HD_FREE.
+ *
+ * - 5: Set align, like 3 but no toggle.
+ * - 6: Clear align (setting #HD_FREE), like 3 but no toggle.
+ */
void BKE_nurbList_handles_set(struct ListBase *editnurb, const char code);
void BKE_nurbList_handles_recalculate(struct ListBase *editnurb,
const bool calc_length,
@@ -186,18 +225,36 @@ void BKE_nurbList_handles_recalculate(struct ListBase *editnurb,
void BKE_nurbList_handles_autocalc(ListBase *editnurb, uint8_t flag);
void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set);
+/**
+ * Set \a flag for every point that already has \a from_flag set.
+ */
bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, uint8_t from_flag, uint8_t flag);
void BKE_nurb_free(struct Nurb *nu);
struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu);
+/**
+ * Copy the nurb but allow for different number of points (to be copied after this).
+ */
struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
void BKE_nurb_project_2d(struct Nurb *nu);
+/**
+ * if use_radius is truth, minmax will take points' radius into account,
+ * which will make bound-box closer to beveled curve.
+ */
void BKE_nurb_minmax(const struct Nurb *nu, bool use_radius, float min[3], float max[3]);
float BKE_nurb_calc_length(const struct Nurb *nu, int resolution);
+/**
+ * \param coord_array: has to be `(3 * 4 * resolu * resolv)` in size, and zero-ed.
+ */
void BKE_nurb_makeFaces(
const struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv);
+/**
+ * \param coord_array: Has to be `(3 * 4 * pntsu * resolu)` in size and zero-ed
+ * \param tilt_array: set when non-NULL
+ * \param radius_array: set when non-NULL
+ */
void BKE_nurb_makeCurve(const struct Nurb *nu,
float *coord_array,
float *tilt_array,
@@ -206,10 +263,19 @@ void BKE_nurb_makeCurve(const struct Nurb *nu,
int resolu,
int stride);
+/**
+ * Calculate the length for arrays filled in by #BKE_curve_calc_coords_axis.
+ */
unsigned int BKE_curve_calc_coords_axis_len(const unsigned int bezt_array_len,
const unsigned int resolu,
const bool is_cyclic,
const bool use_cyclic_duplicate_endpoint);
+/**
+ * Calculate an array for the entire curve (cyclic or non-cyclic).
+ * \note Call for each axis.
+ *
+ * \param use_cyclic_duplicate_endpoint: Duplicate values at the beginning & end of the array.
+ */
void BKE_curve_calc_coords_axis(const struct BezTriple *bezt_array,
const unsigned int bezt_array_len,
const unsigned int resolu,
@@ -232,11 +298,17 @@ bool BKE_nurb_order_clamp_u(struct Nurb *nu);
bool BKE_nurb_order_clamp_v(struct Nurb *nu);
void BKE_nurb_direction_switch(struct Nurb *nu);
+/**
+ * \note caller must ensure active vertex remains valid.
+ */
bool BKE_nurb_type_convert(struct Nurb *nu,
const short type,
const bool use_handles,
const char **r_err_msg);
+/**
+ * Be sure to call #BKE_nurb_knot_calc_u / #BKE_nurb_knot_calc_v after this.
+ */
void BKE_nurb_points_add(struct Nurb *nu, int number);
void BKE_nurb_bezierPoints_add(struct Nurb *nu, int number);
@@ -254,17 +326,31 @@ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_p
void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3]);
void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, struct BPoint *bp, float r_plane[3]);
+/**
+ * Recalculate the handles of a nurb bezier-triple. Acts based on handle selection with `SELECT`
+ * flag. To use a different flag, use #BKE_nurb_handle_calc_ex().
+ */
void BKE_nurb_handle_calc(struct BezTriple *bezt,
struct BezTriple *prev,
struct BezTriple *next,
const bool is_fcurve,
const char smoothing);
+/**
+ * Variant of #BKE_nurb_handle_calc() that allows calculating based on a different select flag.
+ *
+ * \param handle_sel_flag: The flag (bezt.f1/2/3) value to use to determine selection.
+ * Usually #SELECT, but may want to use a different one at times
+ * (if caller does not operate on selection).
+ */
void BKE_nurb_handle_calc_ex(struct BezTriple *bezt,
struct BezTriple *prev,
struct BezTriple *next,
const eBezTriple_Flag__Alias handle_sel_flag,
const bool is_fcurve,
const char smoothing);
+/**
+ * Similar to #BKE_nurb_handle_calc but for curves and figures out the previous and next for us.
+ */
void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
@@ -272,6 +358,18 @@ void BKE_nurb_handle_smooth_fcurve(struct BezTriple *bezt, int total, bool cycli
void BKE_nurb_handles_calc(struct Nurb *nu);
void BKE_nurb_handles_autocalc(struct Nurb *nu, uint8_t flag);
+/**
+ * Update selected handle types to ensure valid state, e.g. deduce "Auto" types to concrete ones.
+ * Thereby \a sel_flag defines what qualifies as selected.
+ * Use when something has changed handle positions.
+ *
+ * The caller needs to recalculate handles.
+ *
+ * \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
+ * but may want to use a different one at times (if caller does not operate on * selection).
+ * \param use_handle: Check selection state of individual handles, otherwise always update both
+ * handles if the key is selected.
+ */
void BKE_nurb_bezt_handle_test(struct BezTriple *bezt,
const eBezTriple_Flag__Alias sel_flag,
const bool use_handle,
@@ -337,6 +435,12 @@ void BKE_curve_deform_coords_with_editmesh(const struct Object *ob_curve,
const short defaxis,
struct BMEditMesh *em_target);
+/**
+ * \param orco: Input vec and orco = local coord in curve space
+ * orco is original not-animated or deformed reference point.
+ *
+ * The result written to `vec` and `r_mat`.
+ */
void BKE_curve_deform_co(const struct Object *ob_curve,
const struct Object *ob_target,
const float orco[3],
diff --git a/source/blender/blenkernel/BKE_curve_to_mesh.hh b/source/blender/blenkernel/BKE_curve_to_mesh.hh
index fb077425336..cf5c8b87ede 100644
--- a/source/blender/blenkernel/BKE_curve_to_mesh.hh
+++ b/source/blender/blenkernel/BKE_curve_to_mesh.hh
@@ -25,7 +25,21 @@ struct CurveEval;
namespace blender::bke {
+/**
+ * Extrude all splines in the profile curve along the path of every spline in the curve input.
+ * Transfer curve attributes to the mesh.
+ *
+ * \note Normal calculation is by far the slowest part of calculations relating to the result mesh.
+ * Although it would be a sensible decision to use the better topology information available while
+ * generating the mesh to also generate the normals, that work may wasted if the output mesh is
+ * changed anyway in a way that affects the normals. So currently this code uses the safer /
+ * simpler solution of deferring normal calculation to the rest of Blender.
+ */
Mesh *curve_to_mesh_sweep(const CurveEval &curve, const CurveEval &profile, bool fill_caps);
+/**
+ * Create a loose-edge mesh based on the evaluated path of the curve's splines.
+ * Transfer curve attributes to the mesh.
+ */
Mesh *curve_to_wire_mesh(const CurveEval &curve);
} // namespace blender::bke
diff --git a/source/blender/blenkernel/BKE_curveprofile.h b/source/blender/blenkernel/BKE_curveprofile.h
index 5a948f0d844..ee8bf99a216 100644
--- a/source/blender/blenkernel/BKE_curveprofile.h
+++ b/source/blender/blenkernel/BKE_curveprofile.h
@@ -34,8 +34,15 @@ struct BlendWriter;
struct CurveProfile;
struct CurveProfilePoint;
+/**
+ * Sets the default settings and clip range for the profile widget.
+ * Does not generate either table.
+ */
void BKE_curveprofile_set_defaults(struct CurveProfile *profile);
+/**
+ * Returns a pointer to a newly allocated curve profile, using the given preset.
+ */
struct CurveProfile *BKE_curveprofile_add(eCurveProfilePresets preset);
void BKE_curveprofile_free_data(struct CurveProfile *profile);
@@ -46,32 +53,90 @@ void BKE_curveprofile_copy_data(struct CurveProfile *target, const struct CurveP
struct CurveProfile *BKE_curveprofile_copy(const struct CurveProfile *profile);
+/**
+ * Move a point's handle, accounting for the alignment of handles with the #HD_ALIGN type.
+ *
+ * \param handle_1: Whether to move the 1st or 2nd control point.
+ * \param delta: The *relative* change in the handle's position.
+ * \note Requires #BKE_curveprofile_update call after.
+ * \return Whether the handle moved from its start position.
+ */
bool BKE_curveprofile_move_handle(struct CurveProfilePoint *point,
const bool handle_1,
const bool snap,
const float delta[2]);
+/**
+ * Moves a control point, accounting for clipping and snapping, and moving free handles.
+ *
+ * \param snap: Whether to snap the point to the grid
+ * \param delta: The *relative* change of the point's location.
+ * \return Whether the point moved from its start position.
+ * \note Requires #BKE_curveprofile_update call after.
+ */
bool BKE_curveprofile_move_point(struct CurveProfile *profile,
struct CurveProfilePoint *point,
const bool snap,
const float delta[2]);
+/**
+ * Removes a specific point from the path of control points.
+ * \note Requires #BKE_curveprofile_update call after.
+ */
bool BKE_curveprofile_remove_point(struct CurveProfile *profile, struct CurveProfilePoint *point);
+/**
+ * Removes every point in the widget with the supplied flag set, except for the first and last.
+ *
+ * \param flag: #CurveProfilePoint.flag.
+ *
+ * \note Requires #BKE_curveprofile_update call after.
+ */
void BKE_curveprofile_remove_by_flag(struct CurveProfile *profile, const short flag);
+/**
+ * Adds a new point at the specified location. The choice for which points to place the new vertex
+ * between is made by checking which control point line segment is closest to the new point and
+ * placing the new vertex in between that segment's points.
+ *
+ * \note Requires #BKE_curveprofile_update call after.
+ */
struct CurveProfilePoint *BKE_curveprofile_insert(struct CurveProfile *profile, float x, float y);
+/**
+ * Sets the handle type of the selected control points.
+ * \param type_1, type_2: Handle type for the first handle. HD_VECT, HD_AUTO, HD_FREE, or HD_ALIGN.
+ * \note Requires #BKE_curveprofile_update call after.
+ */
void BKE_curveprofile_selected_handle_set(struct CurveProfile *profile, int type_1, int type_2);
+/**
+ * Flips the profile across the diagonal so that its orientation is reversed.
+ *
+ * \note Requires #BKE_curveprofile_update call after.
+ */
void BKE_curveprofile_reverse(struct CurveProfile *profile);
+/**
+ * Reset the view to the clipping rectangle.
+ */
void BKE_curveprofile_reset_view(struct CurveProfile *profile);
+/**
+ * Resets the profile to the current preset.
+ *
+ * \note Requires #BKE_curveprofile_update call after.
+ */
void BKE_curveprofile_reset(struct CurveProfile *profile);
int BKE_curveprofile_table_size(const struct CurveProfile *profile);
+/**
+ * Refreshes the higher resolution table sampled from the input points. A call to this or
+ * #BKE_curveprofile_update is needed before evaluation functions that use the table.
+ * Also sets the number of segments used for the display preview of the locations
+ * of the sampled points.
+ */
void BKE_curveprofile_init(struct CurveProfile *profile, short segments_len);
/* Called for a complete update of the widget after modifications */
@@ -80,15 +145,31 @@ enum {
PROF_UPDATE_REMOVE_DOUBLES = (1 << 0),
PROF_UPDATE_CLIP = (1 << 1),
};
+/**
+ * Should be called after the widget is changed. Does profile and remove double checks and more
+ * importantly, recreates the display / evaluation and segments tables.
+ * \param update_flags: Bit-field with fields defined in header file.
+ * Controls removing doubles and clipping.
+ */
void BKE_curveprofile_update(struct CurveProfile *profile, const int update_flags);
-/* Length portion is the fraction of the total path length where we want the location */
+/**
+ * Does a single evaluation along the profile's path.
+ * Travels down (length_portion * path) length and returns the position at that point.
+ * Where length portion is the fraction of the total path length where we want the location.
+ *
+ * \param length_portion: The portion (0 to 1) of the path's full length to sample at.
+ * \note Requires #BKE_curveprofile_init or #BKE_curveprofile_update call before to fill table.
+ */
void BKE_curveprofile_evaluate_length_portion(const struct CurveProfile *profile,
float length_portion,
float *x_out,
float *y_out);
void BKE_curveprofile_blend_write(struct BlendWriter *writer, const struct CurveProfile *profile);
+/**
+ * Expects that the curve profile itself has been read already.
+ */
void BKE_curveprofile_blend_read(struct BlendDataReader *reader, struct CurveProfile *profile);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 0732f1e5190..68d29235469 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -86,8 +86,14 @@ typedef void (*cd_interp)(
typedef void (*cd_copy)(const void *source, void *dest, int count);
typedef bool (*cd_validate)(void *item, const uint totitems, const bool do_fixes);
+/**
+ * Update mask_dst with layers defined in mask_src (equivalent to a bit-wise OR).
+ */
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
const CustomData_MeshMasks *mask_src);
+/**
+ * Return True if all layers set in \a mask_required are also set in \a mask_ref
+ */
bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
const CustomData_MeshMasks *mask_required);
@@ -99,39 +105,50 @@ bool CustomData_layer_has_math(const struct CustomData *data, int layer_n);
bool CustomData_layer_has_interp(const struct CustomData *data, int layer_n);
/**
- * Checks if any of the customdata layers has math.
+ * Checks if any of the custom-data layers has math.
*/
bool CustomData_has_math(const struct CustomData *data);
bool CustomData_has_interp(const struct CustomData *data);
+/**
+ * A non bmesh version would have to check `layer->data`.
+ */
bool CustomData_bmesh_has_free(const struct CustomData *data);
/**
- * Checks if any of the customdata layers is referenced.
+ * Checks if any of the custom-data layers is referenced.
*/
bool CustomData_has_referenced(const struct CustomData *data);
-/* Copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
+/**
+ * Copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* another, while not overwriting anything else (e.g. flags). probably only
- * implemented for mloopuv/mloopcol, for now. */
+ * implemented for mloopuv/mloopcol, for now.
+ */
void CustomData_data_copy_value(int type, const void *source, void *dest);
-/* Same as above, but doing advanced mixing.
- * Only available for a few types of data (like colors...). */
+/**
+ * Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into
+ * another, while not overwriting anything else (e.g. flags).
+ */
void CustomData_data_mix_value(
int type, const void *source, void *dest, const int mixmode, const float mixfactor);
-/* compares if data1 is equal to data2. type is a valid CustomData type
- * enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare
- * the data, if it exists, otherwise memcmp is used. */
+/**
+ * Compares if data1 is equal to data2. type is a valid CustomData type
+ * enum (e.g. #CD_MLOOPUV). the layer type's equal function is used to compare
+ * the data, if it exists, otherwise #memcmp is used.
+ */
bool CustomData_data_equals(int type, const void *data1, const void *data2);
void CustomData_data_initminmax(int type, void *min, void *max);
void CustomData_data_dominmax(int type, const void *data, void *min, void *max);
void CustomData_data_multiply(int type, void *data, float fac);
void CustomData_data_add(int type, void *data1, const void *data2);
-/* initializes a CustomData object with the same layer setup as source.
- * mask is a bitfield where (mask & (1 << (layer type))) indicates
- * if a layer should be copied or not. alloctype must be one of the above. */
+/**
+ * Initializes a CustomData object with the same layer setup as source.
+ * mask is a bitfield where `(mask & (1 << (layer type)))` indicates
+ * if a layer should be copied or not. alloctype must be one of the above.
+ */
void CustomData_copy(const struct CustomData *source,
struct CustomData *dest,
CustomDataMask mask,
@@ -141,25 +158,30 @@ void CustomData_copy(const struct CustomData *source,
/* BMESH_TODO, not really a public function but readfile.c needs it */
void CustomData_update_typemap(struct CustomData *data);
-/* same as the above, except that this will preserve existing layers, and only
- * add the layers that were not there yet */
+/**
+ * Same as the above, except that this will preserve existing layers, and only
+ * add the layers that were not there yet.
+ */
bool CustomData_merge(const struct CustomData *source,
struct CustomData *dest,
CustomDataMask mask,
eCDAllocType alloctype,
int totelem);
-/* Reallocate custom data to a new element count.
+/**
+ * Reallocate custom data to a new element count.
* Only affects on data layers which are owned by the CustomData itself,
* referenced data is kept unchanged,
*
- * NOTE: Take care of referenced layers by yourself!
+ * \note Take care of referenced layers by yourself!
*/
void CustomData_realloc(struct CustomData *data, int totelem);
-/* bmesh version of CustomData_merge; merges the layouts of source and dest,
- * then goes through the mesh and makes sure all the customdata blocks are
- * consistent with the new layout. */
+/**
+ * BMesh version of CustomData_merge; merges the layouts of source and `dest`,
+ * then goes through the mesh and makes sure all the custom-data blocks are
+ * consistent with the new layout.
+ */
bool CustomData_bmesh_merge(const struct CustomData *source,
struct CustomData *dest,
CustomDataMask mask,
@@ -167,7 +189,9 @@ bool CustomData_bmesh_merge(const struct CustomData *source,
struct BMesh *bm,
const char htype);
-/** NULL's all members and resets the typemap. */
+/**
+ * NULL's all members and resets the #CustomData.typemap.
+ */
void CustomData_reset(struct CustomData *data);
/**
@@ -175,19 +199,26 @@ void CustomData_reset(struct CustomData *data);
*/
void CustomData_free(struct CustomData *data, int totelem);
-/* same as above, but only frees layers which matches the given mask. */
+/**
+ * Same as above, but only frees layers which matches the given mask.
+ */
void CustomData_free_typemask(struct CustomData *data, int totelem, CustomDataMask mask);
-/* frees all layers with CD_FLAG_TEMPORARY */
+/**
+ * Frees all layers with #CD_FLAG_TEMPORARY.
+ */
void CustomData_free_temporary(struct CustomData *data, int totelem);
-/* adds a data layer of the given type to the CustomData object, optionally
+/**
+ * Adds a data layer of the given type to the #CustomData object, optionally
* backed by an external data array. the different allocation types are
* defined above. returns the data of the layer.
*/
void *CustomData_add_layer(
struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem);
-/* Same as above but accepts a name. */
+/**
+ * Same as above but accepts a name.
+ */
void *CustomData_add_layer_named(struct CustomData *data,
int type,
eCDAllocType alloctype,
@@ -201,32 +232,42 @@ void *CustomData_add_layer_anonymous(struct CustomData *data,
int totelem,
const struct AnonymousAttributeID *anonymous_id);
-/* frees the active or first data layer with the give type.
+/**
+ * Frees the active or first data layer with the give type.
* returns 1 on success, 0 if no layer with the given type is found
*
- * in editmode, use EDBM_data_layer_free instead of this function
+ * In edit-mode, use #EDBM_data_layer_free instead of this function.
*/
bool CustomData_free_layer(struct CustomData *data, int type, int totelem, int index);
-/* frees the layer index with the give type.
- * returns 1 on success, 0 if no layer with the given type is found
+/**
+ * Frees the layer index with the give type.
+ * returns 1 on success, 0 if no layer with the given type is found.
*
- * in editmode, use EDBM_data_layer_free instead of this function
+ * In edit-mode, use #EDBM_data_layer_free instead of this function.
*/
bool CustomData_free_layer_active(struct CustomData *data, int type, int totelem);
-/* same as above, but free all layers with type */
+/**
+ * Same as above, but free all layers with type.
+ */
void CustomData_free_layers(struct CustomData *data, int type, int totelem);
-/* returns 1 if a layer with the specified type exists */
+/**
+ * Returns true if a layer with the specified type exists.
+ */
bool CustomData_has_layer(const struct CustomData *data, int type);
-/* returns the number of layers with this type */
+/**
+ * Returns the number of layers with this type.
+ */
int CustomData_number_of_layers(const struct CustomData *data, int type);
int CustomData_number_of_layers_typemask(const struct CustomData *data, CustomDataMask mask);
-/* duplicate data of a layer with flag NOFREE, and remove that flag.
- * returns the layer data */
+/**
+ * Duplicate data of a layer with flag NOFREE, and remove that flag.
+ * \return the layer data.
+ */
void *CustomData_duplicate_referenced_layer(struct CustomData *data,
const int type,
const int totelem);
@@ -245,19 +286,21 @@ void *CustomData_duplicate_referenced_layer_anonymous(
const int totelem);
bool CustomData_is_referenced_layer(struct CustomData *data, int type);
-/* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers. */
+/**
+ * Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers.
+ */
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem);
-/* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
- * zero for the layer type, so only layer types specified by the mask
- * will be copied
+/**
+ * Set the #CD_FLAG_NOCOPY flag in custom data layers where the mask is
+ * zero for the layer type, so only layer types specified by the mask will be copied
*/
void CustomData_set_only_copy(const struct CustomData *data, CustomDataMask mask);
-/* copies data from one CustomData object to another
+/**
+ * Copies data from one CustomData object to another
* objects need not be compatible, each source layer is copied to the
- * first dest layer of correct type (if there is none, the layer is skipped)
- * return 1 on success, 0 on failure
+ * first dest layer of correct type (if there is none, the layer is skipped).
*/
void CustomData_copy_data(const struct CustomData *source,
struct CustomData *dest,
@@ -287,7 +330,9 @@ void CustomData_bmesh_copy_data_exclude_by_type(const struct CustomData *source,
void **dest_block,
const CustomDataMask mask_exclude);
-/* Copies data of a single layer of a given type. */
+/**
+ * Copies data of a single layer of a given type.
+ */
void CustomData_copy_layer_type_data(const struct CustomData *source,
struct CustomData *destination,
int type,
@@ -295,22 +340,22 @@ void CustomData_copy_layer_type_data(const struct CustomData *source,
int destination_index,
int count);
-/* frees data in a CustomData object
- * return 1 on success, 0 on failure
+/**
+ * Frees data in a #CustomData object.
*/
void CustomData_free_elem(struct CustomData *data, int index, int count);
-/* interpolates data from one CustomData object to another
- * objects need not be compatible, each source layer is interpolated to the
- * first dest layer of correct type (if there is none, the layer is skipped)
- * if weights == NULL or sub_weights == NULL, they default to all 1's
+/**
+ * Interpolate given custom data source items into a single destination one.
*
- * src_indices gives the source elements to interpolate from
- * weights gives the weight for each source element
- * sub_weights is an array of matrices of weights for sub-elements (matrices
- * should be source->subElems * source->subElems in size)
- * count gives the number of source elements to interpolate from
- * dest_index gives the dest element to write the interpolated value to
+ * \param src_indices: Indices of every source items to interpolate into the destination one.
+ * \param weights: The weight to apply to each source value individually. If NULL, they will be
+ * averaged.
+ * \param sub_weights: The weights of sub-items, only used to affect each corners of a
+ * tessellated face data (should always be and array of four values).
+ * \param count: The number of source items to interpolate.
+ * \param dest_index: Index of the destination item, in which to put the result of the
+ * interpolation.
*/
void CustomData_interp(const struct CustomData *source,
struct CustomData *dest,
@@ -319,6 +364,10 @@ void CustomData_interp(const struct CustomData *source,
const float *sub_weights,
int count,
int dest_index);
+/**
+ * \note src_blocks_ofs & dst_block_ofs
+ * must be pointers to the data, offset by layer->offset already.
+ */
void CustomData_bmesh_interp_n(struct CustomData *data,
const void **src_blocks,
const float *weights,
@@ -333,30 +382,45 @@ void CustomData_bmesh_interp(struct CustomData *data,
int count,
void *dst_block);
-/* swaps the data in the element corners, to new corners with indices as
- * specified in corner_indices. for edges this is an array of length 2, for
- * faces an array of length 4 */
+/**
+ * Swap data inside each item, for all layers.
+ * This only applies to item types that may store several sub-item data
+ * (e.g. corner data [UVs, VCol, ...] of tessellated faces).
+ *
+ * \param corner_indices: A mapping 'new_index -> old_index' of sub-item data.
+ */
void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices);
+/**
+ * Swap two items of given custom data, in all available layers.
+ */
void CustomData_swap(struct CustomData *data, const int index_a, const int index_b);
-/* gets a pointer to the data element at index from the first layer of type
- * returns NULL if there is no layer of type
+/**
+ * Gets a pointer to the data element at index from the first layer of type.
+ * \return NULL if there is no layer of type.
*/
void *CustomData_get(const struct CustomData *data, int index, int type);
void *CustomData_get_n(const struct CustomData *data, int type, int index, int n);
+
+/* BMesh Custom Data Functions.
+ * Should replace edit-mesh ones with these as well, due to more efficient memory alloc. */
+
void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type);
void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n);
-/* gets the layer at physical index n, with no type checking.
+/**
+ * Gets from the layer at physical index `n`,
+ * \note doesn't check type.
*/
void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
bool CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name);
const char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
-/* gets a pointer to the active or first layer of type
- * returns NULL if there is no layer of type
+/**
+ * Gets a pointer to the active or first layer of type.
+ * \return NULL if there is no layer of type.
*/
void *CustomData_get_layer(const struct CustomData *data, int type);
void *CustomData_get_layer_n(const struct CustomData *data, int type, int n);
@@ -377,9 +441,9 @@ int CustomData_get_render_layer(const struct CustomData *data, int type);
int CustomData_get_clone_layer(const struct CustomData *data, int type);
int CustomData_get_stencil_layer(const struct CustomData *data, int type);
-/* copies the data from source to the data element at index in the first
- * layer of type
- * no effect if there is no layer of type
+/**
+ * Copies the data from source to the data element at index in the first layer of type
+ * no effect if there is no layer of type.
*/
void CustomData_set(const struct CustomData *data, int index, int type, const void *source);
@@ -390,42 +454,63 @@ void CustomData_bmesh_set(const struct CustomData *data,
void CustomData_bmesh_set_n(
struct CustomData *data, void *block, int type, int n, const void *source);
-/* sets the data of the block at physical layer n. no real type checking
- * is performed.
+/**
+ * Sets the data of the block at physical layer n.
+ * no real type checking is performed.
*/
void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n, const void *source);
-/* set the pointer of to the first layer of type. the old data is not freed.
- * returns the value of ptr if the layer is found, NULL otherwise
+/**
+ * Set the pointer of to the first layer of type. the old data is not freed.
+ * returns the value of `ptr` if the layer is found, NULL otherwise.
*/
void *CustomData_set_layer(const struct CustomData *data, int type, void *ptr);
void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr);
-/* sets the nth layer of type as active */
+/**
+ * Sets the nth layer of type as active.
+ */
void CustomData_set_layer_active(struct CustomData *data, int type, int n);
void CustomData_set_layer_render(struct CustomData *data, int type, int n);
void CustomData_set_layer_clone(struct CustomData *data, int type, int n);
void CustomData_set_layer_stencil(struct CustomData *data, int type, int n);
-/* same as above but works with an index from CustomData_get_layer_index */
+/**
+ * For using with an index from #CustomData_get_active_layer_index and
+ * #CustomData_get_render_layer_index.
+ */
void CustomData_set_layer_active_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_render_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_clone_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_stencil_index(struct CustomData *data, int type, int n);
-/* adds flag to the layer flags */
+/**
+ * Adds flag to the layer flags.
+ */
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag);
void CustomData_clear_layer_flag(struct CustomData *data, int type, int flag);
void CustomData_bmesh_set_default(struct CustomData *data, void **block);
void CustomData_bmesh_free_block(struct CustomData *data, void **block);
+/**
+ * Same as #CustomData_bmesh_free_block but zero the memory rather than freeing.
+ */
void CustomData_bmesh_free_block_data(struct CustomData *data, void *block);
+/**
+ * A selective version of #CustomData_bmesh_free_block_data.
+ */
void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data,
void *block,
const CustomDataMask mask_exclude);
-/* copy custom data to/from layers as in mesh/derivedmesh, to editmesh
- * blocks of data. the CustomData's must not be compatible */
+/**
+ * Copy custom data to/from layers as in mesh/derived-mesh, to edit-mesh
+ * blocks of data. the CustomData's must not be compatible.
+ *
+ * \param use_default_init: initializes data which can't be copied,
+ * typically you'll want to use this if the BM_xxx create function
+ * is called with BM_CREATE_SKIP_CD flag
+ */
void CustomData_to_bmesh_block(const struct CustomData *source,
struct CustomData *dest,
int src_index,
@@ -436,17 +521,34 @@ void CustomData_from_bmesh_block(const struct CustomData *source,
void *src_block,
int dest_index);
-/* query info over types */
+/**
+ * Query info over types.
+ */
void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num);
int CustomData_sizeof(int type);
-/* get the name of a layer type */
+/**
+ * Get the name of a layer type.
+ */
const char *CustomData_layertype_name(int type);
+/**
+ * Can only ever be one of these.
+ */
bool CustomData_layertype_is_singleton(int type);
+/**
+ * Has dynamically allocated members.
+ * This is useful to know if operations such as #memcmp are
+ * valid when comparing data from two layers.
+ */
bool CustomData_layertype_is_dynamic(int type);
+/**
+ * \return Maximum number of layers of given \a type, -1 means 'no limit'.
+ */
int CustomData_layertype_layers_max(const int type);
-/* make sure the name of layer at index is unique */
+/**
+ * Make sure the name of layer at index is unique.
+ */
void CustomData_set_layer_unique_name(struct CustomData *data, int index);
void CustomData_validate_layer_name(const struct CustomData *data,
@@ -454,23 +556,45 @@ void CustomData_validate_layer_name(const struct CustomData *data,
const char *name,
char *outname);
-/* for file reading compatibility, returns false if the layer was freed,
- * only after this test passes, layer->data should be assigned */
+/**
+ * For file reading compatibility, returns false if the layer was freed,
+ * only after this test passes, `layer->data` should be assigned.
+ */
bool CustomData_verify_versions(struct CustomData *data, int index);
-/* BMesh specific custom-data stuff. */
+/* BMesh specific custom-data stuff.
+ *
+ * Needed to convert to/from different face representation (for versioning). */
+
void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int totloop);
void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int total);
void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata);
+/**
+ * Update active indices for active/render/clone/stencil custom data layers
+ * based on indices from fdata layers
+ * used by do_versions in `readfile.c` when creating pdata and ldata for pre-bmesh
+ * meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files.
+ */
void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata,
struct CustomData *ldata);
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype);
#ifndef NDEBUG
+/**
+ * Debug check, used to assert when we expect layers to be in/out of sync.
+ *
+ * \param fallback: Use when there are no layers to handle,
+ * since callers may expect success or failure.
+ */
bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback);
#endif
-/* Layer data validation. */
+/**
+ * Validate and fix data of \a layer,
+ * if possible (needs relevant callback in layer's type to be defined).
+ *
+ * \return True if some errors were found.
+ */
bool CustomData_layer_validate(struct CustomDataLayer *layer,
const uint totitems,
const bool do_fixes);
@@ -587,16 +711,41 @@ typedef struct CustomDataTransferLayerMap {
cd_datatransfer_interp interp;
} CustomDataTransferLayerMap;
-/* Those functions assume src_n and dst_n layers of given type exist in resp. src and dst. */
+/**
+ * Those functions assume src_n and dst_n layers of given type exist in resp. src and dst.
+ */
void CustomData_data_transfer(const struct MeshPairRemap *me_remap,
const CustomDataTransferLayerMap *laymap);
/* .blend file I/O */
+
+/**
+ * Prepare given custom data for file writing.
+ *
+ * \param data: the custom-data to tweak for .blend file writing (modified in place).
+ * \param r_write_layers: contains a reduced set of layers to be written to file,
+ * use it with #writestruct_at_address()
+ * (caller must free it if != \a write_layers_buff).
+ *
+ * \param write_layers_buff: An optional buffer for r_write_layers (to avoid allocating it).
+ * \param write_layers_size: The size of pre-allocated \a write_layer_buff.
+ *
+ * \warning After this funcion has ran, given custom data is no more valid from Blender POV
+ * (its `totlayer` is invalid). This function shall always be called with localized data
+ * (as it is in write_meshes()).
+ *
+ * \note `data->typemap` is not updated here, since it is always rebuilt on file read anyway.
+ * This means written `typemap` does not match written layers (as returned by \a r_write_layers).
+ * Trivial to fix is ever needed.
+ */
void CustomData_blend_write_prepare(struct CustomData *data,
struct CustomDataLayer **r_write_layers,
struct CustomDataLayer *write_layers_buff,
size_t write_layers_size);
+/**
+ * \param layers: The layers argument assigned by #CustomData_blend_write_prepare.
+ */
void CustomData_blend_write(struct BlendWriter *writer,
struct CustomData *data,
CustomDataLayer *layers,
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index a2544e43c3d..a4218ec564b 100644
--- a/source/blender/blenkernel/BKE_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -65,6 +65,10 @@ enum {
void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types,
struct CustomData_MeshMasks *r_data_masks);
+/**
+ * Check what can do each layer type
+ * (if it is actually handled by transfer-data, if it supports advanced mixing.
+ */
bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types,
bool *r_advanced_mixing,
bool *r_threshold);
@@ -122,6 +126,12 @@ enum {
#endif
};
+/**
+ * Transfer data *layout* of selected types from source to destination object.
+ * By default, it only creates new data layers if needed on \a ob_dst.
+ * If \a use_delete is true, it will also delete data layers on \a ob_dst that do not match those
+ * from \a ob_src, to get (as much as possible) exact copy of source data layout.
+ */
void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_src,
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index f4221d57428..9870d43b5c2 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -44,20 +44,36 @@ const struct ListBase *BKE_object_defgroup_list(const struct Object *ob);
struct ListBase *BKE_object_defgroup_list_mutable(struct Object *ob);
int BKE_object_defgroup_count(const struct Object *ob);
+/**
+ * \note For historical reasons, the index starts at 1 rather than 0.
+ */
int BKE_object_defgroup_active_index_get(const struct Object *ob);
+/**
+ * \note For historical reasons, the index starts at 1 rather than 0.
+ */
void BKE_object_defgroup_active_index_set(struct Object *ob, const int new_index);
const struct ListBase *BKE_id_defgroup_list_get(const struct ID *id);
struct ListBase *BKE_id_defgroup_list_get_mutable(struct ID *id);
int BKE_id_defgroup_name_index(const struct ID *id, const char *name);
+bool BKE_id_defgroup_name_find(const struct ID *id,
+ const char *name,
+ int *r_index,
+ struct bDeformGroup **r_group);
struct bDeformGroup *BKE_object_defgroup_new(struct Object *ob, const char *name);
void BKE_defgroup_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
struct bDeformGroup *BKE_defgroup_duplicate(const struct bDeformGroup *ingroup);
struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, const char *name);
+/**
+ * \note caller must free.
+ */
int *BKE_object_defgroup_flip_map(const struct Object *ob,
int *flip_map_len,
const bool use_default);
+/**
+ * \note caller must free.
+ */
int *BKE_object_defgroup_flip_map_single(const struct Object *ob,
int *flip_map_len,
const bool use_default,
@@ -67,11 +83,33 @@ int BKE_object_defgroup_name_index(const struct Object *ob, const char *name);
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
struct MDeformWeight *BKE_defvert_find_index(const struct MDeformVert *dv, const int defgroup);
+/**
+ * Ensures that `dv` has a deform weight entry for the specified defweight group.
+ *
+ * \note this function is mirrored in editmesh_tools.c, for use for edit-vertices.
+ */
struct MDeformWeight *BKE_defvert_ensure_index(struct MDeformVert *dv, const int defgroup);
+/**
+ * Adds the given vertex to the specified vertex group, with given weight.
+ *
+ * \warning this does NOT check for existing, assume caller already knows its not there.
+ */
void BKE_defvert_add_index_notest(struct MDeformVert *dv, int defgroup, const float weight);
+/**
+ * Removes the given vertex from the vertex group.
+ *
+ * \warning This function frees the given #MDeformWeight, do not use it afterward!
+ */
void BKE_defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw);
void BKE_defvert_clear(struct MDeformVert *dvert);
+/**
+ * \return The first group index shared by both deform verts
+ * or -1 if none are found.
+ */
int BKE_defvert_find_shared(const struct MDeformVert *dvert_a, const struct MDeformVert *dvert_b);
+/**
+ * \return true if has no weights.
+ */
bool BKE_defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_tot);
void BKE_defvert_array_free_elems(struct MDeformVert *dvert, int totvert);
@@ -79,14 +117,32 @@ void BKE_defvert_array_free(struct MDeformVert *dvert, int totvert);
void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert);
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup);
+/**
+ * Take care with this the rationale is:
+ * - if the object has no vertex group. act like vertex group isn't set and return 1.0.
+ * - if the vertex group exists but the 'defgroup' isn't found on this vertex, _still_ return 0.0.
+ *
+ * This is a bit confusing, just saves some checks from the caller.
+ */
float BKE_defvert_array_find_weight_safe(const struct MDeformVert *dvert,
const int index,
const int defgroup);
+/**
+ * \return The total weight in all groups marked in the selection mask.
+ */
float BKE_defvert_total_selected_weight(const struct MDeformVert *dv,
int defbase_tot,
const bool *defbase_sel);
+/**
+ * \return The representative weight of a multi-paint group, used for
+ * viewport colors and actual painting.
+ *
+ * Result equal to sum of weights with auto normalize, and average otherwise.
+ * Value is not clamped, since painting relies on multiplication being always
+ * commutative with the collective weight function.
+ */
float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv,
int defbase_tot,
const bool *defbase_sel,
@@ -96,9 +152,19 @@ float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv,
/* This much unlocked weight is considered equivalent to none. */
#define VERTEX_WEIGHT_LOCK_EPSILON 1e-6f
+/**
+ * Computes the display weight for the lock relative weight paint mode.
+ *
+ * \return weight divided by 1-locked_weight with division by zero check
+ */
float BKE_defvert_calc_lock_relative_weight(float weight,
float locked_weight,
float unlocked_weight);
+/**
+ * Computes the display weight for the lock relative weight paint mode, using weight data.
+ *
+ * \return weight divided by unlocked, or 1-locked_weight with division by zero check.
+ */
float BKE_defvert_lock_relative_weight(float weight,
const struct MDeformVert *dv,
int defbase_tot,
@@ -106,41 +172,75 @@ float BKE_defvert_lock_relative_weight(float weight,
const bool *defbase_unlocked);
void BKE_defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src);
+/**
+ * Overwrite weights filtered by vgroup_subset.
+ * - do nothing if neither are set.
+ * - add destination weight if needed
+ */
void BKE_defvert_copy_subset(struct MDeformVert *dvert_dst,
const struct MDeformVert *dvert_src,
const bool *vgroup_subset,
const int vgroup_tot);
+/**
+ * Overwrite weights filtered by vgroup_subset and with mirroring specified by the flip map
+ * - do nothing if neither are set.
+ * - add destination weight if needed
+ */
void BKE_defvert_mirror_subset(struct MDeformVert *dvert_dst,
const struct MDeformVert *dvert_src,
const bool *vgroup_subset,
const int vgroup_tot,
const int *flip_map,
const int flip_map_len);
+/**
+ * Copy an index from one #MDeformVert to another.
+ * - do nothing if neither are set.
+ * - add destination weight if needed.
+ */
void BKE_defvert_copy_index(struct MDeformVert *dvert_dst,
const int defgroup_dst,
const struct MDeformVert *dvert_src,
const int defgroup_src);
+/**
+ * Only sync over matching weights, don't add or remove groups
+ * warning, loop within loop.
+ */
void BKE_defvert_sync(struct MDeformVert *dvert_dst,
const struct MDeformVert *dvert_src,
const bool use_ensure);
+/**
+ * be sure all flip_map values are valid
+ */
void BKE_defvert_sync_mapped(struct MDeformVert *dvert_dst,
const struct MDeformVert *dvert_src,
const int *flip_map,
const int flip_map_len,
const bool use_ensure);
+/**
+ * be sure all flip_map values are valid
+ */
void BKE_defvert_remap(struct MDeformVert *dvert, const int *map, const int map_len);
void BKE_defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
void BKE_defvert_flip_merged(struct MDeformVert *dvert,
const int *flip_map,
const int flip_map_len);
void BKE_defvert_normalize(struct MDeformVert *dvert);
+/**
+ * Same as #BKE_defvert_normalize but takes a bool array.
+ */
void BKE_defvert_normalize_subset(struct MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot);
+/**
+ * Same as BKE_defvert_normalize() if the locked vgroup is not a member of the subset
+ */
void BKE_defvert_normalize_lock_single(struct MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
const uint def_nr_lock);
+/**
+ * Same as BKE_defvert_normalize() if no locked vgroup is a member of the subset
+ */
void BKE_defvert_normalize_lock_map(struct MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
@@ -149,11 +249,16 @@ void BKE_defvert_normalize_lock_map(struct MDeformVert *dvert,
/* Utilities to 'extract' a given vgroup into a simple float array,
* for verts, but also edges/polys/loops. */
+
void BKE_defvert_extract_vgroup_to_vertweights(struct MDeformVert *dvert,
const int defgroup,
const int num_verts,
float *r_weights,
const bool invert_vgroup);
+/**
+ * The following three make basic interpolation,
+ * using temp vert_weights array to avoid looking up same weight several times.
+ */
void BKE_defvert_extract_vgroup_to_edgeweights(struct MDeformVert *dvert,
const int defgroup,
const int num_verts,
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 8fb596a8096..db1217465d7 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -98,6 +98,12 @@ void BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
bool BKE_displist_surfindex_get(
const struct DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
+/**
+ * \param normal_proj: Optional normal that's used to project the scan-fill verts into 2D coords.
+ * Pass this along if known since it saves time calculating the normal.
+ * This is also used to initialize #DispList.nors (one normal per display list).
+ * \param flip_normal: Flip the normal (same as passing \a normal_proj negated).
+ */
void BKE_displist_fill(const struct ListBase *dispbase,
struct ListBase *to,
const float normal_proj[3],
diff --git a/source/blender/blenkernel/BKE_duplilist.h b/source/blender/blenkernel/BKE_duplilist.h
index 989b68f4ccb..5eff84b8c9e 100644
--- a/source/blender/blenkernel/BKE_duplilist.h
+++ b/source/blender/blenkernel/BKE_duplilist.h
@@ -36,6 +36,9 @@ struct ID;
/* ---------------------------------------------------- */
/* Dupli-Geometry */
+/**
+ * \return a #ListBase of #DupliObject.
+ */
struct ListBase *object_duplilist(struct Depsgraph *depsgraph,
struct Scene *sce,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index 31f48be2c27..4b34a9490c4 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -64,41 +64,79 @@ typedef struct PaintWavePoint {
short state;
} PaintWavePoint;
+/**
+ * Modifier call. Processes dynamic paint modifier step.
+ */
struct Mesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd,
struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct Mesh *me);
+/**
+ * Free whole dynamic-paint modifier.
+ */
void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd);
void dynamicPaint_Modifier_free_runtime(struct DynamicPaintRuntime *runtime);
void dynamicPaint_Modifier_copy(const struct DynamicPaintModifierData *pmd,
struct DynamicPaintModifierData *tpmd,
int flag);
+/**
+ * Initialize modifier data.
+ */
bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene);
+/**
+ * Creates a new surface and adds it to the list
+ * If scene is null, frame range of 1-250 is used
+ * A pointer to this surface is returned.
+ */
struct DynamicPaintSurface *dynamicPaint_createNewSurface(
struct DynamicPaintCanvasSettings *canvas, struct Scene *scene);
+/**
+ * Clears surface data back to zero.
+ */
void dynamicPaint_clearSurface(const struct Scene *scene, struct DynamicPaintSurface *surface);
+/**
+ * Completely (re)initializes surface (only for point cache types).
+ */
bool dynamicPaint_resetSurface(const struct Scene *scene, struct DynamicPaintSurface *surface);
void dynamicPaint_freeSurface(const struct DynamicPaintModifierData *pmd,
struct DynamicPaintSurface *surface);
+/**
+ * Free canvas data.
+ */
void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd);
+/* Free brush data */
void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd);
void dynamicPaint_freeSurfaceData(struct DynamicPaintSurface *surface);
+/**
+ * Update cache frame range.
+ */
void dynamicPaint_cacheUpdateFrames(struct DynamicPaintSurface *surface);
bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface,
struct Object *ob,
int output);
+/**
+ * Change surface data to defaults on new type.
+ */
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface);
void dynamicPaintSurface_setUniqueName(struct DynamicPaintSurface *surface, const char *basename);
+/**
+ * Get currently active surface (in user interface).
+ */
struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings *canvas);
-/* image sequence baking */
+/**
+ * Image sequence baking.
+ */
int dynamicPaint_createUVSurface(struct Scene *scene,
struct DynamicPaintSurface *surface,
float *progress,
short *do_update);
+/**
+ * Calculate a single frame and included sub-frames for surface.
+ */
int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface,
struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 2c24b1a5487..32cc5961e4a 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -102,12 +102,29 @@ void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMPartialUpda
void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em,
struct BMPartialUpdate *bmpinfo);
+/**
+ * Performing the face normal calculation at the same time as tessellation
+ * gives a reasonable performance boost (approx ~20% faster).
+ */
void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em);
+/**
+ * \note The caller is responsible for ensuring triangulation data,
+ * typically by calling #BKE_editmesh_looptri_calc.
+ */
BMEditMesh *BKE_editmesh_create(BMesh *bm);
BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
+/**
+ * \brief Return the #BMEditMesh for a given object
+ *
+ * \note this function assumes this is a mesh object,
+ * don't add NULL data check here. caller must do that
+ */
BMEditMesh *BKE_editmesh_from_object(struct Object *ob);
void BKE_editmesh_free_derived_caches(BMEditMesh *em);
+/**
+ * \note Does not free the #BMEditMesh struct itself.
+ */
void BKE_editmesh_free_data(BMEditMesh *em);
float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
@@ -124,6 +141,9 @@ const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph
bool *r_is_alloc))[3];
void BKE_editmesh_lnorspace_update(BMEditMesh *em, struct Mesh *me);
+/**
+ * If auto-smooth not already set, set it.
+ */
void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, struct Mesh *me);
struct BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em);
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 69d1b4819f8..fc274b4ffd1 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -78,7 +78,9 @@ struct BMFace *BKE_bmbvh_ray_cast_filter(BMBVHTree *tree,
BMBVHTree_FaceFilter filter_cb,
void *filter_userdata);
-/* find a vert closest to co in a sphere of radius dist_max */
+/**
+ * Find a vert closest to co in a sphere of radius dist_max.
+ */
struct BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *tree,
const float co[3],
const float dist_max);
@@ -86,10 +88,16 @@ struct BMFace *BKE_bmbvh_find_face_closest(BMBVHTree *tree,
const float co[3],
const float dist_max);
+/**
+ * Overlap indices reference the looptri's.
+ */
struct BVHTreeOverlap *BKE_bmbvh_overlap(const BMBVHTree *bmtree_a,
const BMBVHTree *bmtree_b,
unsigned int *r_overlap_tot);
+/**
+ * Overlap indices reference the looptri's.
+ */
struct BVHTreeOverlap *BKE_bmbvh_overlap_self(const BMBVHTree *bmtree,
unsigned int *r_overlap_tot);
diff --git a/source/blender/blenkernel/BKE_editmesh_tangent.h b/source/blender/blenkernel/BKE_editmesh_tangent.h
index 0e3f063ae44..b76db11348e 100644
--- a/source/blender/blenkernel/BKE_editmesh_tangent.h
+++ b/source/blender/blenkernel/BKE_editmesh_tangent.h
@@ -24,6 +24,13 @@
extern "C" {
#endif
+/**
+ * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
+ *
+ * \note This function is not so normal, its using #BMesh.ldata as input,
+ * but output's to #Mesh.ldata.
+ * This is done because #CD_TANGENT is cache data used only for drawing.
+ */
void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 3a964ddb1aa..f33ca2f03d1 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -113,16 +113,27 @@ struct PartDeflect *BKE_partdeflect_new(int type);
struct PartDeflect *BKE_partdeflect_copy(const struct PartDeflect *pd_src);
void BKE_partdeflect_free(struct PartDeflect *pd);
+/**
+ * Create list of effector relations in the collection or entire scene.
+ * This is used by the depsgraph to build relations, as well as faster
+ * lookup of effectors during evaluation.
+ */
struct ListBase *BKE_effector_relations_create(struct Depsgraph *depsgraph,
struct ViewLayer *view_layer,
struct Collection *collection);
void BKE_effector_relations_free(struct ListBase *lb);
+/**
+ * Create effective list of effectors from relations built beforehand.
+ */
struct ListBase *BKE_effectors_create(struct Depsgraph *depsgraph,
struct Object *ob_src,
struct ParticleSystem *psys_src,
struct EffectorWeights *weights,
bool use_rotation);
+/**
+ * Generic force/speed system, now used for particles, soft-bodies & dynamic-paint.
+ */
void BKE_effectors_apply(struct ListBase *effectors,
struct ListBase *colliders,
struct EffectorWeights *weights,
@@ -146,15 +157,15 @@ float effector_falloff(struct EffectorCache *eff,
struct EffectorData *efd,
struct EffectedPoint *point,
struct EffectorWeights *weights);
-int closest_point_on_surface(struct SurfaceModifierData *surmd,
- const float co[3],
- float surface_co[3],
- float surface_nor[3],
- float surface_vel[3]);
-int get_effector_data(struct EffectorCache *eff,
- struct EffectorData *efd,
- struct EffectedPoint *point,
- int real_velocity);
+bool closest_point_on_surface(struct SurfaceModifierData *surmd,
+ const float co[3],
+ float surface_co[3],
+ float surface_nor[3],
+ float surface_vel[3]);
+bool get_effector_data(struct EffectorCache *eff,
+ struct EffectorData *efd,
+ struct EffectedPoint *point,
+ int real_velocity);
/* required for particle_system.c */
#if 0
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index f494c2e30cc..1537d14ab01 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -133,20 +133,56 @@ typedef enum eFMI_Requirement_Flags {
} eFMI_Requirement_Flags;
/* Function Prototypes for FModifierTypeInfo's */
+
+/**
+ * This function should always be used to get the appropriate type-info,
+ * as it has checks which prevent segfaults in some weird cases.
+ */
const FModifierTypeInfo *fmodifier_get_typeinfo(const struct FModifier *fcm);
+/**
+ * This function should be used for getting the appropriate type-info when only
+ * a F-Curve modifier type is known.
+ */
const FModifierTypeInfo *get_fmodifier_typeinfo(const int type);
/* ---------------------- */
+/**
+ * Add a new F-Curve Modifier to the given F-Curve of a certain type.
+ */
struct FModifier *add_fmodifier(ListBase *modifiers, int type, struct FCurve *owner_fcu);
+/**
+ * Make a copy of the specified F-Modifier.
+ */
struct FModifier *copy_fmodifier(const struct FModifier *src);
+/**
+ * Duplicate all of the F-Modifiers in the Modifier stacks.
+ */
void copy_fmodifiers(ListBase *dst, const ListBase *src);
+/**
+ * Remove and free the given F-Modifier from the given stack.
+ */
bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
+/**
+ * Remove all of a given F-Curve's modifiers.
+ */
void free_fmodifiers(ListBase *modifiers);
+/**
+ * Find the active F-Modifier.
+ */
struct FModifier *find_active_fmodifier(ListBase *modifiers);
+/**
+ * Set the active F-Modifier.
+ */
void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm);
+/**
+ * Do we have any modifiers which match certain criteria.
+ *
+ * \param mtype: Type of modifier (if 0, doesn't matter).
+ * \param acttype: Type of action to perform (if -1, doesn't matter).
+ */
bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype);
typedef struct FModifiersStackStorage {
@@ -156,17 +192,38 @@ typedef struct FModifiersStackStorage {
} FModifiersStackStorage;
uint evaluate_fmodifiers_storage_size_per_modifier(ListBase *modifiers);
+/**
+ * Evaluate time modifications imposed by some F-Curve Modifiers.
+ *
+ * - This step acts as an optimization to prevent the F-Curve stack being evaluated
+ * several times by modifiers requesting the time be modified, as the final result
+ * would have required using the modified time
+ * - Modifiers only ever receive the unmodified time, as subsequent modifiers should be
+ * working on the 'global' result of the modified curve, not some localized segment,
+ * so \a evaltime gets set to whatever the last time-modifying modifier likes.
+ * - We start from the end of the stack, as only the last one matters for now.
+ *
+ * \param fcu: Can be NULL.
+ */
float evaluate_time_fmodifiers(FModifiersStackStorage *storage,
ListBase *modifiers,
struct FCurve *fcu,
float cvalue,
float evaltime);
+/**
+ * Evaluates the given set of F-Curve Modifiers using the given data
+ * Should only be called after evaluate_time_fmodifiers() has been called.
+ */
void evaluate_value_fmodifiers(FModifiersStackStorage *storage,
ListBase *modifiers,
struct FCurve *fcu,
float *cvalue,
float evaltime);
+/**
+ * Bake modifiers for given F-Curve to curve sample data, in the frame range defined
+ * by start and end (inclusive).
+ */
void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array,
@@ -182,30 +239,64 @@ int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array,
/* -------- Data Management -------- */
struct FCurve *BKE_fcurve_create(void);
+/**
+ * Frees the F-Curve itself too, so make sure #BLI_remlink is called before calling this.
+ */
void BKE_fcurve_free(struct FCurve *fcu);
+/**
+ * Duplicate a F-Curve.
+ */
struct FCurve *BKE_fcurve_copy(const struct FCurve *fcu);
-
+/**
+ * Frees a list of F-Curves.
+ */
void BKE_fcurves_free(ListBase *list);
+/**
+ * Duplicate a list of F-Curves.
+ */
void BKE_fcurves_copy(ListBase *dst, ListBase *src);
+/**
+ * Callback used by lib_query to walk over all ID usages
+ * (mimics `foreach_id` callback of #IDTypeInfo structure).
+ */
void BKE_fcurve_foreach_id(struct FCurve *fcu, struct LibraryForeachIDData *data);
-/* find matching F-Curve in the given list of F-Curves */
+/**
+ * Find the F-Curve affecting the given RNA-access path + index,
+ * in the list of F-Curves provided.
+ */
struct FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_index);
+/**
+ * Quick way to loop over all f-curves of a given 'path'.
+ */
struct FCurve *BKE_fcurve_iter_step(struct FCurve *fcu_iter, const char rna_path[]);
-/* high level function to get an fcurve from C without having the rna */
+/**
+ * High level function to get an f-curve from C without having the RNA.
+ */
struct FCurve *id_data_find_fcurve(
ID *id, void *data, struct StructRNA *type, const char *prop_name, int index, bool *r_driven);
-/* Get list of LinkData's containing pointers to the F-Curves which control the types of data
- * indicated
- * e.g. numMatches = BKE_fcurves_filter(matches, &act->curves, "pose.bones[", "MyFancyBone");
+/**
+ * Get list of LinkData's containing pointers to the F-curves
+ * which control the types of data indicated.
+ * e.g. `numMatches = BKE_fcurves_filter(matches, &act->curves, "pose.bones[", "MyFancyBone");`
+ *
+ * Lists:
+ * \param dst: list of LinkData's matching the criteria returned.
+ * List must be freed after use, and is assumed to be empty when passed.
+ * \param src: list of F-Curves to search through
+ * Filters:
+ * \param dataPrefix: i.e. `pose.bones[` or `nodes[`.
+ * \param dataName: name of entity within "" immediately following the prefix.
*/
int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName);
-/* Find an f-curve based on an rna property. */
+/**
+ * Find an f-curve based on an rna property.
+ */
struct FCurve *BKE_fcurve_find_by_rna(struct PointerRNA *ptr,
struct PropertyRNA *prop,
int rnaindex,
@@ -213,8 +304,10 @@ struct FCurve *BKE_fcurve_find_by_rna(struct PointerRNA *ptr,
struct bAction **r_action,
bool *r_driven,
bool *r_special);
-/* Same as above, but takes a context data,
- * temp hack needed for complex paths like texture ones. */
+/**
+ * Same as above, but takes a context data,
+ * temp hack needed for complex paths like texture ones.
+ */
struct FCurve *BKE_fcurve_find_by_rna_context_ui(struct bContext *C,
struct PointerRNA *ptr,
struct PropertyRNA *prop,
@@ -224,7 +317,8 @@ struct FCurve *BKE_fcurve_find_by_rna_context_ui(struct bContext *C,
bool *r_driven,
bool *r_special);
-/* Binary search algorithm for finding where to 'insert' BezTriple with given frame number.
+/**
+ * Binary search algorithm for finding where to 'insert' #BezTriple with given frame number.
* Returns the index to insert at (data already at that index will be offset if replace is 0)
*/
int BKE_fcurve_bezt_binarysearch_index(const struct BezTriple array[],
@@ -233,23 +327,35 @@ int BKE_fcurve_bezt_binarysearch_index(const struct BezTriple array[],
bool *r_replace);
/* fcurve_cache.c */
-/* Cached f-curve look-ups, use when this needs to be done many times. */
+
+/**
+ * Cached f-curve look-ups, use when this needs to be done many times.
+ */
struct FCurvePathCache;
struct FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list);
void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache);
struct FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
const char rna_path[],
const int array_index);
+/**
+ * Fill in an array of F-Curve, leave NULL when not found.
+ *
+ * \return The number of F-Curves found.
+ */
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
const char *rna_path,
struct FCurve **fcurve_result,
int fcurve_result_len);
-/* get the time extents for F-Curve */
+/**
+ * Calculate the extents of F-Curve's keyframes.
+ */
bool BKE_fcurve_calc_range(
struct FCurve *fcu, float *min, float *max, const bool do_sel_only, const bool do_min_length);
-/* get the bounding-box extents for F-Curve */
+/**
+ * Calculate the extents of F-Curve's data.
+ */
bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
float *xmin,
float *xmax,
@@ -258,6 +364,14 @@ bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
const bool do_sel_only,
const bool include_handles);
+/**
+ * Return an array of keyed frames, rounded to `interval`.
+ *
+ * \param interval: Set to 1.0 to round to whole keyframes, 0.5 for in-between key-frames, etc.
+ *
+ * \note An interval of zero could be supported (this implies no rounding at all),
+ * however this risks very small differences in float values being treated as separate keyframes.
+ */
float *BKE_fcurves_calc_keyed_frames_ex(struct FCurve **fcurve_array,
const int fcurve_array_len,
const float interval,
@@ -266,23 +380,42 @@ float *BKE_fcurves_calc_keyed_frames(struct FCurve **fcurve_array,
const int fcurve_array_len,
int *r_frames_len);
+/**
+ * Set the index that stores the FCurve's active keyframe, assuming that \a active_bezt
+ * is already part of `fcu->bezt`. If NULL, set active keyframe index to "none."
+ */
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt);
+/**
+ * Get the active keyframe index, with sanity checks for point bounds.
+ */
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu);
-/* Move the indexed keyframe to the given value, and move the handles with it to ensure the slope
- * remains the same. */
+/**
+ * Move the indexed keyframe to the given value,
+ * and move the handles with it to ensure the slope remains the same.
+ */
void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, float new_value);
/* .............. */
-/* Are keyframes on F-Curve of any use (to final result, and to show in editors)? */
+/**
+ * Are keyframes on F-Curve of any use (to final result, and to show in editors)?
+ * Usability of keyframes refers to whether they should be displayed,
+ * and also whether they will have any influence on the final result.
+ */
bool BKE_fcurve_are_keyframes_usable(struct FCurve *fcu);
-/* Can keyframes be added to F-Curve? */
+/**
+ * Can keyframes be added to F-Curve?
+ * Keyframes can only be added if they are already visible.
+ */
bool BKE_fcurve_is_keyframable(struct FCurve *fcu);
bool BKE_fcurve_is_protected(struct FCurve *fcu);
-/* The curve is an infinite cycle via Cycles modifier */
+/**
+ * Checks if the F-Curve has a Cycles modifier with simple settings
+ * that warrant transition smoothing.
+ */
bool BKE_fcurve_is_cyclic(struct FCurve *fcu);
/* Type of infinite cycle for a curve. */
@@ -294,9 +427,19 @@ typedef enum eFCU_Cycle_Type {
FCU_CYCLE_OFFSET,
} eFCU_Cycle_Type;
+/**
+ * Checks if the F-Curve has a Cycles modifier, and returns the type of the cycle behavior.
+ */
eFCU_Cycle_Type BKE_fcurve_get_cycle_type(struct FCurve *fcu);
-/* Recompute handles to neatly subdivide the prev-next range at bezt. */
+/**
+ * Recompute bezier handles of all three given BezTriples, so that `bezt` can be inserted between
+ * `prev` and `next` without changing the resulting curve shape.
+ *
+ * \param r_pdelta: return Y difference between `bezt` and the original curve value at its X
+ * position.
+ * \return Whether the split was successful.
+ */
bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt,
struct BezTriple *prev,
struct BezTriple *next,
@@ -304,12 +447,50 @@ bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt,
/* -------- Curve Sanity -------- */
+/**
+ * This function recalculates the handles of an F-Curve. Acts based on selection with `SELECT`
+ * flag. To use a different flag, use #calchandles_fcurve_ex().
+ *
+ * If the BezTriples have been rearranged, sort them first before using this.
+ */
void calchandles_fcurve(struct FCurve *fcu);
+/**
+ * Variant of #calchandles_fcurve() that allows calculating based on a different select flag.
+ *
+ * \param handle_sel_flag: The flag (bezt.f1/2/3) value to use to determine selection.
+ * Usually `SELECT`, but may want to use a different one at times
+ * (if caller does not operate on selection).
+ */
void calchandles_fcurve_ex(struct FCurve *fcu, eBezTriple_Flag handle_sel_flag);
+/**
+ * Update handles, making sure the handle-types are valid (e.g. correctly deduced from an "Auto"
+ * type), and recalculating their position vectors.
+ * Use when something has changed handle positions.
+ *
+ * \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
+ * but may want to use a different one at times (if caller does not operate on selection).
+ * \param use_handle: Check selection state of individual handles, otherwise always update both
+ * handles if the key is selected.
+ */
void testhandles_fcurve(struct FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_handle);
+/**
+ * This function sorts BezTriples so that they are arranged in chronological order,
+ * as tools working on F-Curves expect that the BezTriples are in order.
+ */
void sort_time_fcurve(struct FCurve *fcu);
+/**
+ * This function tests if any BezTriples are out of order, thus requiring a sort.
+ */
bool test_time_fcurve(struct FCurve *fcu);
+/**
+ * The length of each handle is not allowed to be more
+ * than the horizontal distance between (v1-v4).
+ * This is to prevent curve loops.
+ *
+ * This function is very similar to BKE_curve_correct_bezpart(), but allows a steeper tangent for
+ * more snappy animations. This is not desired for other areas in which curves are used, though.
+ */
void BKE_fcurve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2]);
/* -------- Evaluation -------- */
@@ -321,8 +502,14 @@ float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna,
struct FCurve *fcu,
struct ChannelDriver *driver_orig,
const struct AnimationEvalContext *anim_eval_context);
+/**
+ * Checks if the curve has valid keys, drivers or modifiers that produce an actual curve.
+ */
bool BKE_fcurve_is_empty(struct FCurve *fcu);
-/* evaluate fcurve and store value */
+/**
+ * Calculate the value of the given F-Curve at the given frame,
+ * and store it's value in #FCurve.curval.
+ */
float calculate_fcurve(struct PathResolvedRNA *anim_rna,
struct FCurve *fcu,
const struct AnimationEvalContext *anim_eval_context);
@@ -331,26 +518,34 @@ float calculate_fcurve(struct PathResolvedRNA *anim_rna,
/* -------- Defines -------- */
-/* Basic signature for F-Curve sample-creation function
- * - fcu: the F-Curve being operated on
- * - data: pointer to some specific data that may be used by one of the callbacks
+/**
+ * Basic signature for F-Curve sample-creation function.
+ *
+ * \param fcu: the F-Curve being operated on.
+ * \param data: pointer to some specific data that may be used by one of the callbacks.
*/
typedef float (*FcuSampleFunc)(struct FCurve *fcu, void *data, float evaltime);
/* ----- Sampling Callbacks ------ */
-/* Basic sampling callback which acts as a wrapper for evaluate_fcurve() */
+/**
+ * Basic sampling callback which acts as a wrapper for #evaluate_fcurve()
+ * 'data' arg here is unneeded here.
+ */
float fcurve_samplingcb_evalcurve(struct FCurve *fcu, void *data, float evaltime);
/* -------- Main Methods -------- */
-/* Main API function for creating a set of sampled curve data, given some callback function
+/**
+ * Main API function for creating a set of sampled curve data, given some callback function
* used to retrieve the values to store.
*/
void fcurve_store_samples(
struct FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb);
-/* Convert baked/sampled fcurves into bezt/regular fcurves. */
+/**
+ * Convert baked/sampled f-curves into bezt/regular f-curves.
+ */
void fcurve_samples_to_keyframes(struct FCurve *fcu, const int start, const int end);
/* ************* F-Curve .blend file API ******************** */
diff --git a/source/blender/blenkernel/BKE_fcurve_driver.h b/source/blender/blenkernel/BKE_fcurve_driver.h
index 5b4da4a78a4..18676dfcb38 100644
--- a/source/blender/blenkernel/BKE_fcurve_driver.h
+++ b/source/blender/blenkernel/BKE_fcurve_driver.h
@@ -66,34 +66,85 @@ struct PropertyRNA;
/* ---------------------- */
+/**
+ * This frees the driver itself.
+ */
void fcurve_free_driver(struct FCurve *fcu);
+/**
+ * This makes a copy of the given driver.
+ */
struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
+/**
+ * Copy driver variables from src_vars list to dst_vars list.
+ */
void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars);
+/**
+ * Compute channel values for a rotational Transform Channel driver variable.
+ */
void BKE_driver_target_matrix_to_rot_channels(
float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]);
+/**
+ * Perform actual freeing driver variable and remove it from the given list.
+ */
void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar);
+/**
+ * Free the driver variable and do extra updates.
+ */
void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar);
+/**
+ * Change the type of driver variable.
+ */
void driver_change_variable_type(struct DriverVar *dvar, int type);
+/**
+ * Validate driver variable name (after being renamed).
+ *
+ */
void driver_variable_name_validate(struct DriverVar *dvar);
+/**
+ * Add a new driver variable.
+ */
struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
+/**
+ * Evaluate a Driver Variable to get a value that contributes to the final.
+ */
float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar);
+/**
+ * Same as 'dtar_get_prop_val'. but get the RNA property.
+ */
bool driver_get_variable_property(struct ChannelDriver *driver,
struct DriverTarget *dtar,
struct PointerRNA *r_ptr,
struct PropertyRNA **r_prop,
int *r_index);
+/**
+ * Check if the expression in the driver conforms to the simple subset.
+ */
bool BKE_driver_has_simple_expression(struct ChannelDriver *driver);
+/**
+ * Check if the expression in the driver may depend on the current frame.
+ */
bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver);
+/**
+ * Reset cached compiled expression data.
+ */
void BKE_driver_invalidate_expression(struct ChannelDriver *driver,
bool expr_changed,
bool varname_changed);
+/**
+ * Evaluate an Channel-Driver to get a 'time' value to use
+ * instead of `anim_eval_context->eval_time`.
+ *
+ * - `anim_eval_context->eval_time` is the frame at which F-Curve is being evaluated.
+ * - Has to return a float value.
+ * - \a driver_orig is where we cache Python expressions, in case of COW
+ */
float evaluate_driver(struct PathResolvedRNA *anim_rna,
struct ChannelDriver *driver,
struct ChannelDriver *driver_orig,
diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h
index 33ff6943514..7bafcf00ce8 100644
--- a/source/blender/blenkernel/BKE_fluid.h
+++ b/source/blender/blenkernel/BKE_fluid.h
@@ -64,6 +64,10 @@ void BKE_fluid_cache_free_all(struct FluidDomainSettings *fds, struct Object *ob
void BKE_fluid_cache_free(struct FluidDomainSettings *fds, struct Object *ob, int cache_map);
void BKE_fluid_cache_new_name_for_current_session(int maxlen, char *r_name);
+/**
+ * Get fluid velocity and density at given coordinates.
+ * \returns fluid density or -1.0f if outside domain.
+ */
float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3]);
int BKE_fluid_get_data_flags(struct FluidDomainSettings *fds);
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
index 5e29665d728..ee3517f5b43 100644
--- a/source/blender/blenkernel/BKE_freestyle.h
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -47,6 +47,10 @@ void BKE_freestyle_config_copy(struct FreestyleConfig *new_config,
struct FreestyleModuleConfig *BKE_freestyle_module_add(struct FreestyleConfig *config);
bool BKE_freestyle_module_delete(struct FreestyleConfig *config,
struct FreestyleModuleConfig *module_conf);
+/**
+ * Reinsert \a module_conf offset by \a direction from current position.
+ * \return if position of \a module_conf changed.
+ */
bool BKE_freestyle_module_move(struct FreestyleConfig *config,
struct FreestyleModuleConfig *module_conf,
int direction);
diff --git a/source/blender/blenkernel/BKE_geometry_set.h b/source/blender/blenkernel/BKE_geometry_set.h
index 17cdb9d6a42..2d6218f1036 100644
--- a/source/blender/blenkernel/BKE_geometry_set.h
+++ b/source/blender/blenkernel/BKE_geometry_set.h
@@ -39,6 +39,8 @@ typedef enum GeometryComponentType {
GEO_COMPONENT_TYPE_CURVE = 4,
} GeometryComponentType;
+#define GEO_COMPONENT_TYPE_ENUM_SIZE 5
+
void BKE_geometry_set_free(struct GeometrySet *geometry_set);
bool BKE_object_has_geometry_set_instances(const struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 35e66908d54..79f29e0954e 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -62,7 +62,9 @@ class ComponentAttributeProviders;
class GeometryComponent;
/**
- * This is the base class for specialized geometry component types.
+ * This is the base class for specialized geometry component types. A geometry component handles
+ * a user count to allow avoiding duplication when it is wrapped with #UserCounter. It also handles
+ * the attribute API, which generalizes storing and modifying generic information on a geometry.
*/
class GeometryComponent {
private:
@@ -150,6 +152,10 @@ class GeometryComponent {
const AttributeInit &initializer);
blender::Set<blender::bke::AttributeIDRef> attribute_ids() const;
+ /**
+ * \return False if the callback explicitly returned false at any point, otherwise true,
+ * meaning the callback made it all the way through.
+ */
bool attribute_foreach(const AttributeForeachCallback callback) const;
virtual bool is_empty() const;
@@ -252,19 +258,33 @@ template<typename T>
inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryComponent, T>;
/**
- * A geometry set contains zero or more geometry components. There is at most one component of each
- * type. Individual components might be shared between multiple geometries. Shared components are
- * copied automatically when write access is requested.
+ * A geometry set is a container for multiple kinds of geometry. It does not own geometry directly
+ * itself, instead geometry is owned by multiple #GeometryComponents, and the geometry set
+ * increases the user count of each component, so they avoid losing the data. This means
+ * individual components might be shared between multiple geometries and other code. Shared
+ * components are copied automatically when write access is requested.
+ *
+ * The components usually do not store data directly, but keep a reference to a data
+ * structure defined elsewhere. There is at most one component of each type:
+ * - #MeshComponent
+ * - #CurveComponent
+ * - #PointCloudComponent
+ * - #InstancesComponent
+ * - #VolumeComponent
*
* Copying a geometry set is a relatively cheap operation, because it does not copy the referenced
- * geometry components.
+ * geometry components, so #GeometrySet can often be passed or moved by value.
*/
struct GeometrySet {
private:
using GeometryComponentPtr = blender::UserCounter<class GeometryComponent>;
- blender::Map<GeometryComponentType, GeometryComponentPtr> components_;
+ /* Indexed by #GeometryComponentType. */
+ std::array<GeometryComponentPtr, GEO_COMPONENT_TYPE_ENUM_SIZE> components_;
public:
+ /**
+ * The methods are defaulted here so that they are not instantiated in every translation unit.
+ */
GeometrySet();
GeometrySet(const GeometrySet &other);
GeometrySet(GeometrySet &&other);
@@ -272,6 +292,10 @@ struct GeometrySet {
GeometrySet &operator=(const GeometrySet &other);
GeometrySet &operator=(GeometrySet &&other);
+ /**
+ * This method can only be used when the geometry set is mutable. It returns a mutable geometry
+ * component of the given type.
+ */
GeometryComponent &get_component_for_write(GeometryComponentType component_type);
template<typename Component> Component &get_component_for_write()
{
@@ -279,6 +303,9 @@ struct GeometrySet {
return static_cast<Component &>(this->get_component_for_write(Component::static_type));
}
+ /**
+ * Get the component of the given type. Might return null if the component does not exist yet.
+ */
const GeometryComponent *get_component_for_read(GeometryComponentType component_type) const;
template<typename Component> const Component *get_component_for_read() const
{
@@ -300,19 +327,33 @@ struct GeometrySet {
return this->remove(Component::static_type);
}
+ /**
+ * Remove all geometry components with types that are not in the provided list.
+ */
void keep_only(const blender::Span<GeometryComponentType> component_types);
void add(const GeometryComponent &component);
+ /**
+ * Get all geometry components in this geometry set for read-only access.
+ */
blender::Vector<const GeometryComponent *> get_components_for_read() const;
void compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const;
friend std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set);
+ /**
+ * Remove all geometry components from the geometry set.
+ */
void clear();
bool owns_direct_data() const;
+ /**
+ * Make sure that the geometry can be cached. This does not ensure ownership of object/collection
+ * instances. This is necessary because sometimes components only have read-only or editing
+ * access to their data, which might be freed later if this geometry set outlasts the data.
+ */
void ensure_owns_direct_data();
using AttributeForeachCallback =
@@ -335,46 +376,119 @@ struct GeometrySet {
using ForeachSubGeometryCallback = blender::FunctionRef<void(GeometrySet &geometry_set)>;
+ /**
+ * Modify every (recursive) instance separately. This is often more efficient than realizing all
+ * instances just to change the same thing on all of them.
+ */
void modify_geometry_sets(ForeachSubGeometryCallback callback);
/* Utility methods for creation. */
+ /**
+ * Create a new geometry set that only contains the given mesh.
+ */
static GeometrySet create_with_mesh(
Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Create a new geometry set that only contains the given point cloud.
+ */
static GeometrySet create_with_pointcloud(
PointCloud *pointcloud, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Create a new geometry set that only contains the given curve.
+ */
static GeometrySet create_with_curve(
CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/* Utility methods for access. */
+ /**
+ * Returns true when the geometry set has a mesh component that has a mesh.
+ */
bool has_mesh() const;
+ /**
+ * Returns true when the geometry set has a point cloud component that has a point cloud.
+ */
bool has_pointcloud() const;
+ /**
+ * Returns true when the geometry set has an instances component that has at least one instance.
+ */
bool has_instances() const;
+ /**
+ * Returns true when the geometry set has a volume component that has a volume.
+ */
bool has_volume() const;
+ /**
+ * Returns true when the geometry set has a curve component that has a curve.
+ */
bool has_curve() const;
+ /**
+ * Returns true when the geometry set has any data that is not an instance.
+ */
bool has_realized_data() const;
+ /**
+ * Return true if the geometry set has any component that isn't empty.
+ */
bool is_empty() const;
+ /**
+ * Returns a read-only mesh or null.
+ */
const Mesh *get_mesh_for_read() const;
+ /**
+ * Returns a read-only point cloud of null.
+ */
const PointCloud *get_pointcloud_for_read() const;
+ /**
+ * Returns a read-only volume or null.
+ */
const Volume *get_volume_for_read() const;
+ /**
+ * Returns a read-only curve or null.
+ */
const CurveEval *get_curve_for_read() const;
+ /**
+ * Returns a mutable mesh or null. No ownership is transferred.
+ */
Mesh *get_mesh_for_write();
+ /**
+ * Returns a mutable point cloud or null. No ownership is transferred.
+ */
PointCloud *get_pointcloud_for_write();
+ /**
+ * Returns a mutable volume or null. No ownership is transferred.
+ */
Volume *get_volume_for_write();
+ /**
+ * Returns a mutable curve or null. No ownership is transferred.
+ */
CurveEval *get_curve_for_write();
/* Utility methods for replacement. */
+ /**
+ * Clear the existing mesh and replace it with the given one.
+ */
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Clear the existing point cloud and replace with the given one.
+ */
void replace_pointcloud(PointCloud *pointcloud,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Clear the existing volume and replace with the given one.
+ */
void replace_volume(Volume *volume,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Clear the existing curve and replace it with the given one.
+ */
void replace_curve(CurveEval *curve,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
private:
- /* Utility to retrieve a mutable component without creating it. */
+ /**
+ * Retrieve the pointer to a component without creating it if it does not exist,
+ * unlike #get_component_for_write.
+ */
GeometryComponent *get_component_ptr(GeometryComponentType type);
template<typename Component> Component *get_component_ptr()
{
@@ -383,7 +497,13 @@ struct GeometrySet {
}
};
-/** A geometry component that can store a mesh. */
+/**
+ * A geometry component that can store a mesh, storing the #Mesh data structure.
+ *
+ * Attributes are stored in the mesh itself, on any of the four attribute domains. Generic
+ * attributes are stored in contiguous arrays, but often built-in attributes are stored in an
+ * array of structs fashion for historical reasons, requiring more complex attribute access.
+ */
class MeshComponent : public GeometryComponent {
private:
Mesh *mesh_ = nullptr;
@@ -396,10 +516,25 @@ class MeshComponent : public GeometryComponent {
void clear();
bool has_mesh() const;
+ /**
+ * Clear the component and replace it with the new mesh.
+ */
void replace(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Return the mesh and clear the component. The caller takes over responsibility for freeing the
+ * mesh (if the component was responsible before).
+ */
Mesh *release();
+ /**
+ * Get the mesh from this component. This method can be used by multiple threads at the same
+ * time. Therefore, the returned mesh should not be modified. No ownership is transferred.
+ */
const Mesh *get_for_read() const;
+ /**
+ * Get the mesh from this component. This method can only be used when the component is mutable,
+ * i.e. it is not shared. The returned mesh can be modified. No ownership is transferred.
+ */
Mesh *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
@@ -420,7 +555,16 @@ class MeshComponent : public GeometryComponent {
const AttributeDomain to_domain) const final;
};
-/** A geometry component that stores a point cloud. */
+/**
+ * A geometry component that stores a point cloud, corresponding to the #PointCloud data structure.
+ * While a point cloud is technically a subset of a mesh in some respects, it is useful because of
+ * its simplicity, partly on a conceptual level for the user, but also in the code, though partly
+ * for historical reasons. Point clouds can also be rendered in special ways, based on the built-in
+ * `radius` attribute.
+ *
+ * Attributes on point clouds are all stored in contiguous arrays in its #CustomData,
+ * which makes them efficient to process, relative to some legacy built-in mesh attributes.
+ */
class PointCloudComponent : public GeometryComponent {
private:
PointCloud *pointcloud_ = nullptr;
@@ -433,11 +577,28 @@ class PointCloudComponent : public GeometryComponent {
void clear();
bool has_pointcloud() const;
+ /**
+ * Clear the component and replace it with the new point cloud.
+ */
void replace(PointCloud *pointcloud,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Return the point cloud and clear the component. The caller takes over responsibility for
+ * freeing the point cloud (if the component was responsible before).
+ */
PointCloud *release();
+ /**
+ * Get the point cloud from this component. This method can be used by multiple threads at the
+ * same time. Therefore, the returned point cloud should not be modified. No ownership is
+ * transferred.
+ */
const PointCloud *get_for_read() const;
+ /**
+ * Get the point cloud from this component. This method can only be used when the component is
+ * mutable, i.e. it is not shared. The returned point cloud can be modified. No ownership is
+ * transferred.
+ */
PointCloud *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
@@ -453,7 +614,13 @@ class PointCloudComponent : public GeometryComponent {
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
};
-/** A geometry component that stores curve data, in other words, a group of splines. */
+/**
+ * A geometry component that stores curve data, in other words, a group of splines.
+ * Curves are stored differently than other geometry components, because the data structure used
+ * here does not correspond exactly to the #Curve DNA data structure. A #CurveEval is stored here
+ * instead, though the component does give access to a #Curve for interfacing with render engines
+ * and other areas of Blender that expect to use a data-block with an #ID.
+ */
class CurveComponent : public GeometryComponent {
private:
CurveEval *curve_ = nullptr;
@@ -475,6 +642,9 @@ class CurveComponent : public GeometryComponent {
void clear();
bool has_curve() const;
+ /**
+ * Clear the component and replace it with the new curve.
+ */
void replace(CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
CurveEval *release();
@@ -488,6 +658,10 @@ class CurveComponent : public GeometryComponent {
bool owns_direct_data() const override;
void ensure_owns_direct_data() override;
+ /**
+ * Create empty curve data used for rendering the spline's wire edges.
+ * \note See comment on #curve_for_render_ for further explanation.
+ */
const Curve *get_curve_for_render() const;
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_CURVE;
@@ -501,6 +675,10 @@ class CurveComponent : public GeometryComponent {
const AttributeDomain to_domain) const final;
};
+/**
+ * Holds a reference to conceptually unique geometry or a pointer to object/collection data
+ * that is is instanced with a transform in #InstancesComponent.
+ */
class InstanceReference {
public:
enum class Type {
@@ -623,7 +801,19 @@ class InstanceReference {
}
};
-/** A geometry component that stores instances. */
+/**
+ * A geometry component that stores instances. The instance data can be any type described by
+ * #InstanceReference. Geometry instances can even contain instances themselves, for nested
+ * instancing. Each instance has an index into an array of unique instance data, and a transform.
+ * The component can also store generic attributes for each instance.
+ *
+ * The component works differently from other geometry components in that it stores
+ * data about instancing directly, rather than owning a pointer to a separate data structure.
+ *
+ * This component is not responsible for handling the interface to a render engine, or other
+ * areas that work with all visible geometry, that is handled by the dependency graph iterator
+ * (see `DEG_depsgraph_query.h`).
+ */
class InstancesComponent : public GeometryComponent {
private:
/**
@@ -636,18 +826,11 @@ class InstancesComponent : public GeometryComponent {
blender::Vector<int> instance_reference_handles_;
/** Transformation of the instances. */
blender::Vector<blender::float4x4> instance_transforms_;
- /**
- * IDs of the instances. They are used for consistency over multiple frames for things like
- * motion blur. Proper stable ID data that actually helps when rendering can only be generated
- * in some situations, so this vector is allowed to be empty, in which case the index of each
- * instance will be used for the final ID.
- */
- blender::Vector<int> instance_ids_;
- /* These almost unique ids are generated based on `ids_`, which might not contain unique ids at
- * all. They are *almost* unique, because under certain very unlikely circumstances, they are not
- * unique. Code using these ids should not crash when they are not unique but can generally
- * expect them to be unique. */
+ /* These almost unique ids are generated based on the `id` attribute, which might not contain
+ * unique ids at all. They are *almost* unique, because under certain very unlikely
+ * circumstances, they are not unique. Code using these ids should not crash when they are not
+ * unique but can generally expect them to be unique. */
mutable std::mutex almost_unique_ids_mutex_;
mutable blender::Array<int> almost_unique_ids_;
@@ -661,26 +844,47 @@ class InstancesComponent : public GeometryComponent {
void clear();
void reserve(int min_capacity);
+ /**
+ * Resize the transform, handles, and attributes to the specified capacity.
+ *
+ * \note This function should be used carefully, only when it's guaranteed
+ * that the data will be filled.
+ */
void resize(int capacity);
+ /**
+ * Returns a handle for the given reference.
+ * If the reference exists already, the handle of the existing reference is returned.
+ * Otherwise a new handle is added.
+ */
int add_reference(const InstanceReference &reference);
+ /**
+ * Add a reference to the instance reference with an index specified by the #instance_handle
+ * argument. For adding many instances, using #resize and accessing the transform array directly
+ * is preferred.
+ */
void add_instance(int instance_handle, const blender::float4x4 &transform);
blender::Span<InstanceReference> references() const;
void remove_unused_references();
+ /**
+ * If references have a collection or object type, convert them into geometry instances
+ * recursively. After that, the geometry sets can be edited. There may still be instances of
+ * other types of they can't be converted to geometry sets.
+ */
void ensure_geometry_instances();
+ /**
+ * With write access to the instances component, the data in the instanced geometry sets can be
+ * changed. This is a function on the component rather than each reference to ensure `const`
+ * correctness for that reason.
+ */
GeometrySet &geometry_set_from_reference(const int reference_index);
blender::Span<int> instance_reference_handles() const;
blender::MutableSpan<int> instance_reference_handles();
blender::MutableSpan<blender::float4x4> instance_transforms();
blender::Span<blender::float4x4> instance_transforms() const;
- blender::MutableSpan<int> instance_ids();
- blender::Span<int> instance_ids() const;
-
- blender::MutableSpan<int> instance_ids_ensure();
- void instance_ids_clear();
int instances_amount() const;
int references_amount() const;
@@ -706,7 +910,11 @@ class InstancesComponent : public GeometryComponent {
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
};
-/** A geometry component that stores volume grids. */
+/**
+ * A geometry component that stores volume grids, corresponding to the #Volume data structure.
+ * This component does not implement an attribute API, partly because storage of sparse volume
+ * information in grids is much more complicated than it is for other types
+ */
class VolumeComponent : public GeometryComponent {
private:
Volume *volume_ = nullptr;
@@ -719,10 +927,26 @@ class VolumeComponent : public GeometryComponent {
void clear();
bool has_volume() const;
+ /**
+ * Clear the component and replace it with the new volume.
+ */
void replace(Volume *volume, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ /**
+ * Return the volume and clear the component. The caller takes over responsibility for freeing
+ * the volume (if the component was responsible before).
+ */
Volume *release();
+ /**
+ * Get the volume from this component. This method can be used by multiple threads at the same
+ * time. Therefore, the returned volume should not be modified. No ownership is transferred.
+ */
const Volume *get_for_read() const;
+ /**
+ * Get the volume from this component. This method can only be used when the component is
+ * mutable, i.e. it is not shared. The returned volume can be modified. No ownership is
+ * transferred.
+ */
Volume *get_for_write();
bool owns_direct_data() const override;
@@ -755,13 +979,26 @@ class GeometryComponentFieldContext : public fn::FieldContext {
}
};
-class AttributeFieldInput : public fn::FieldInput {
+class GeometryFieldInput : public fn::FieldInput {
+ public:
+ using fn::FieldInput::FieldInput;
+
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const override;
+
+ virtual GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask mask) const = 0;
+};
+
+class AttributeFieldInput : public GeometryFieldInput {
private:
std::string name_;
public:
AttributeFieldInput(std::string name, const CPPType &type)
- : fn::FieldInput(type, name), name_(std::move(name))
+ : GeometryFieldInput(type, name), name_(std::move(name))
{
category_ = Category::NamedAttribute;
}
@@ -778,9 +1015,9 @@ class AttributeFieldInput : public fn::FieldInput {
return name_;
}
- GVArray get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask mask) const override;
std::string socket_inspection_name() const override;
@@ -788,16 +1025,16 @@ class AttributeFieldInput : public fn::FieldInput {
bool is_equal_to(const fn::FieldNode &other) const override;
};
-class IDAttributeFieldInput : public fn::FieldInput {
+class IDAttributeFieldInput : public GeometryFieldInput {
public:
- IDAttributeFieldInput() : fn::FieldInput(CPPType::get<int>())
+ IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>())
{
category_ = Category::Generated;
}
- GVArray get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask mask) const override;
std::string socket_inspection_name() const override;
@@ -805,7 +1042,7 @@ class IDAttributeFieldInput : public fn::FieldInput {
bool is_equal_to(const fn::FieldNode &other) const override;
};
-class AnonymousAttributeFieldInput : public fn::FieldInput {
+class AnonymousAttributeFieldInput : public GeometryFieldInput {
private:
/**
* A strong reference is required to make sure that the referenced attribute is not removed
@@ -818,7 +1055,7 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id,
const CPPType &type,
std::string producer_name)
- : fn::FieldInput(type, anonymous_id.debug_name()),
+ : GeometryFieldInput(type, anonymous_id.debug_name()),
anonymous_id_(std::move(anonymous_id)),
producer_name_(producer_name)
{
@@ -834,9 +1071,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
return fn::Field<T>{field_input};
}
- GVArray get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask mask) const override;
std::string socket_inspection_name() const override;
diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index e5b28e4fbab..98120b07f2d 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -20,6 +20,9 @@
namespace blender::bke {
+/**
+ * \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
+ */
GeometrySet object_get_evaluated_geometry_set(const Object &object);
/**
@@ -41,11 +44,19 @@ struct GeometryInstanceGroup {
Vector<float4x4> transforms;
};
+/**
+ * Return flattened vector of the geometry component's recursive instances. I.e. all collection
+ * instances and object instances will be expanded into the instances of their geometry components.
+ * Even the instances in those geometry components' will be included.
+ *
+ * \note For convenience (to avoid duplication in the caller), the returned vector also contains
+ * the argument geometry set.
+ *
+ * \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
+ */
void geometry_set_gather_instances(const GeometrySet &geometry_set,
Vector<GeometryInstanceGroup> &r_instance_groups);
-GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
-
/**
* Add information about all the attributes on every component of the type. The resulting info
* will contain the highest complexity data type and the highest priority domain among every
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index d6cabbc1236..ecf2e1f32a0 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -37,35 +37,61 @@ struct Main;
typedef struct Global {
- /** Active pointers. */
+ /**
+ * Data for the current active blend file.
+ *
+ * Note that `CTX_data_main(C)` should be used where possible.
+ * Otherwise access via #G_MAIN.
+ */
struct Main *main;
- /** Strings: last saved */
- char ima[1024], lib[1024]; /* 1024 = FILE_MAX */
-
- /** When set: `G_MAIN->name` contains valid relative base path. */
- bool relbase_valid;
- bool save_over;
+ /** Last saved location for images. */
+ char ima[1024]; /* 1024 = FILE_MAX */
+ /** Last used location for library link/append. */
+ char lib[1024];
- /** Strings of recent opened files. */
+ /**
+ * Strings of recently opened files to show in the file menu.
+ * A list of #RecentFile read from #BLENDER_HISTORY_FILE.
+ */
struct ListBase recent_files;
- /** Has escape been pressed or Ctrl+C pressed in background mode, used for render quit. */
+ /**
+ * Set when Escape been pressed or `Ctrl-C` pressed in background mode.
+ * Used for render quit and some other background tasks such as baking.
+ */
bool is_break;
+ /**
+ * Blender is running without any Windows or OpenGLES context.
+ * Typically set by the `--background` command-line argument.
+ *
+ * Also enabled when build defines `WITH_PYTHON_MODULE` or `WITH_HEADLESS` are set
+ * (which use background mode by definition).
+ */
bool background;
+
+ /**
+ * Skip reading the startup file and user preferences.
+ * Also disable saving the preferences on exit (see #G_FLAG_USERPREF_NO_SAVE_ON_EXIT),
+ * see via the command line argument: `--factory-startup`.
+ */
bool factory_startup;
+ /**
+ * Set when the user is interactively moving (transforming) content.
+ * see: #G_TRANSFORM_OBJ and related flags.
+ */
short moving;
- /** To indicate render is busy, prevent render-window events etc. */
+ /** To indicate render is busy, prevent render-window events, animation playback etc. */
bool is_rendering;
/**
* Debug value, can be set from the UI and python, used for testing nonstandard features.
* DO NOT abuse it with generic checks like `if (G.debug_value > 0)`. Do not use it as bitflags.
* Only precise specific values should be checked for, to avoid unpredictable side-effects.
- * Please document here the value(s) you are using (or a range of values reserved to some area).
+ * Please document here the value(s) you are using (or a range of values reserved to some area):
* * -16384 and below: Reserved for python (add-ons) usage.
* * -1: Disable faster motion paths computation (since 08/2018).
* * 1 - 30: EEVEE debug/stats values (01/2018).
@@ -82,24 +108,50 @@ typedef struct Global {
*/
short debug_value;
- /** Saved to the blend file as #FileGlobal.globalf,
- * however this is now only used for runtime options. */
+ /**
+ * Saved to the blend file as #FileGlobal.globalf
+ *
+ * \note Currently this is only used for runtime options, adding flags to #G_FLAG_ALL_READFILE
+ * will cause them to be written and read to files.
+ */
int f;
struct {
- /** Logging vars (different loggers may use). */
+ /**
+ * Logging vars (different loggers may use).
+ * Set via `--log-level` command line argument.
+ */
int level;
- /** FILE handle or use stderr (we own this so close when done). */
+ /**
+ * FILE handle or use `stderr` (we own this so close when done).
+ * Set via `--log-file` command line argument.
+ */
void *file;
} log;
- /** debug flag, #G_DEBUG, #G_DEBUG_PYTHON & friends, set python or command line args */
+ /**
+ * Debug flag, #G_DEBUG, #G_DEBUG_PYTHON & friends, set via:
+ * - Command line arguments: `--debug`, `--debug-memory` ... etc.
+ * - Python API: `bpy.app.debug`, `bpy.app.debug_memory` ... etc.
+ */
int debug;
- /** This variable is written to / read from #FileGlobal.fileflags */
+ /**
+ * Control behavior of file reading/writing.
+ *
+ * This variable is written to / read from #FileGlobal.fileflags.
+ * See: #G_FILE_COMPRESS and related flags.
+ */
int fileflags;
- /** Message to use when auto execution fails. */
+ /**
+ * Message to show when loading a `.blend` file attempts to execute
+ * a Python script or driver-expression when doing so is disallowed.
+ *
+ * Set when `(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL) == 0`,
+ * so users can be alerted to the reason why the file may not be behaving as expected.
+ * Typically Python drivers.
+ */
char autoexec_fail[200];
} Global;
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index b58317f4815..a483d482bd5 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -86,65 +86,185 @@ struct bGPdata;
/* ------------ Grease-Pencil API ------------------ */
+/* clean vertex groups weights */
void BKE_gpencil_free_point_weights(struct MDeformVert *dvert);
void BKE_gpencil_free_stroke_weights(struct bGPDstroke *gps);
void BKE_gpencil_free_stroke_editcurve(struct bGPDstroke *gps);
+/* free stroke, doesn't unlink from any listbase */
void BKE_gpencil_free_stroke(struct bGPDstroke *gps);
+/* Free strokes belonging to a gp-frame */
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf);
+/* Free all of a gp-layer's frames */
void BKE_gpencil_free_frames(struct bGPDlayer *gpl);
+/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
void BKE_gpencil_free_layers(struct ListBase *list);
+/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
void BKE_gpencil_free_data(struct bGPdata *gpd, bool free_all);
+/**
+ * Delete grease pencil evaluated data
+ * \param gpd_eval: Grease pencil data-block
+ */
void BKE_gpencil_eval_delete(struct bGPdata *gpd_eval);
void BKE_gpencil_free_layer_masks(struct bGPDlayer *gpl);
+/**
+ * Tag data-block for depsgraph update.
+ * Wrapper to avoid include Depsgraph tag functions in other modules.
+ * \param gpd: Grease pencil data-block.
+ */
void BKE_gpencil_tag(struct bGPdata *gpd);
void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
void BKE_gpencil_batch_cache_free(struct bGPdata *gpd);
+/**
+ * Ensure selection status of stroke is in sync with its points.
+ * \param gps: Grease pencil stroke
+ */
void BKE_gpencil_stroke_sync_selection(struct bGPdata *gpd, struct bGPDstroke *gps);
void BKE_gpencil_curve_sync_selection(struct bGPdata *gpd, struct bGPDstroke *gps);
+/* Assign unique stroke ID for selection. */
void BKE_gpencil_stroke_select_index_set(struct bGPdata *gpd, struct bGPDstroke *gps);
+/* Reset unique stroke ID for selection. */
void BKE_gpencil_stroke_select_index_reset(struct bGPDstroke *gps);
+/**
+ * Add a new gp-frame to the given layer.
+ * \param gpl: Grease pencil layer
+ * \param cframe: Frame number
+ * \return Pointer to new frame
+ */
struct bGPDframe *BKE_gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe);
+/**
+ * Add a copy of the active gp-frame to the given layer.
+ * \param gpl: Grease pencil layer
+ * \param cframe: Frame number
+ * \return Pointer to new frame
+ */
struct bGPDframe *BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe);
+/**
+ * Add a new gp-layer and make it the active layer.
+ * \param gpd: Grease pencil data-block
+ * \param name: Name of the layer
+ * \param setactive: Set as active
+ * \param add_to_header: Used to force the layer added at header
+ * \return Pointer to new layer
+ */
struct bGPDlayer *BKE_gpencil_layer_addnew(struct bGPdata *gpd,
const char *name,
const bool setactive,
const bool add_to_header);
+/**
+ * Add a new grease pencil data-block.
+ * \param bmain: Main pointer
+ * \param name: Name of the datablock
+ * \return Pointer to new data-block
+ */
struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[]);
+/**
+ * Make a copy of a given gpencil frame.
+ * \param gpf_src: Source grease pencil frame
+ * \return Pointer to new frame
+ */
struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src,
const bool dup_strokes);
+/**
+ * Make a copy of a given gpencil layer.
+ * \param gpl_src: Source grease pencil layer
+ * \return Pointer to new layer
+ */
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src,
const bool dup_frames,
const bool dup_strokes);
+/**
+ * Make a copy of a given gpencil layer settings.
+ */
void BKE_gpencil_layer_copy_settings(const struct bGPDlayer *gpl_src, struct bGPDlayer *gpl_dst);
+/**
+ * Make a copy of strokes between gpencil frames.
+ * \param gpf_src: Source grease pencil frame
+ * \param gpf_dst: Destination grease pencil frame
+ */
void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
+/* Create a hash with the list of selected frame number. */
void BKE_gpencil_frame_selected_hash(struct bGPdata *gpd, struct GHash *r_list);
+/* Make a copy of a given gpencil stroke editcurve */
struct bGPDcurve *BKE_gpencil_stroke_curve_duplicate(struct bGPDcurve *gpc_src);
+/**
+ * Make a copy of a given grease-pencil stroke.
+ * \param gps_src: Source grease pencil strokes.
+ * \param dup_points: Duplicate points data.
+ * \param dup_curve: Duplicate curve data.
+ * \return Pointer to new stroke.
+ */
struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src,
const bool dup_points,
const bool dup_curve);
+/**
+ * Make a copy of a given gpencil data-block.
+ *
+ * XXX: Should this be deprecated?
+ */
struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain,
const struct bGPdata *gpd,
bool internal_copy);
+/**
+ * Delete the last stroke of the given frame.
+ * \param gpl: Grease pencil layer
+ * \param gpf: Grease pencil frame
+ */
void BKE_gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
/* materials */
+/**
+ * Reassign strokes using a material.
+ * \param gpd: Grease pencil data-block
+ * \param totcol: Total materials
+ * \param index: Index of the material
+ */
void BKE_gpencil_material_index_reassign(struct bGPdata *gpd, int totcol, int index);
+/**
+ * Remove strokes using a material.
+ * \param gpd: Grease pencil data-block
+ * \param index: Index of the material
+ * \return True if removed
+ */
bool BKE_gpencil_material_index_used(struct bGPdata *gpd, int index);
+/**
+ * Remap material
+ * \param gpd: Grease pencil data-block
+ * \param remap: Remap index
+ * \param remap_len: Remap length
+ */
void BKE_gpencil_material_remap(struct bGPdata *gpd,
const unsigned int *remap,
unsigned int remap_len);
+/**
+ * Load a table with material conversion index for merged materials.
+ * \param ob: Grease pencil object.
+ * \param hue_threshold: Threshold for Hue.
+ * \param sat_threshold: Threshold for Saturation.
+ * \param val_threshold: Threshold for Value.
+ * \param r_mat_table: return material table.
+ * \return True if done.
+ */
bool BKE_gpencil_merge_materials_table_get(struct Object *ob,
const float hue_threshold,
const float sat_threshold,
const float val_threshold,
struct GHash *r_mat_table);
+/**
+ * Merge similar materials
+ * \param ob: Grease pencil object
+ * \param hue_threshold: Threshold for Hue
+ * \param sat_threshold: Threshold for Saturation
+ * \param val_threshold: Threshold for Value
+ * \param r_removed: Number of materials removed
+ * \return True if done
+ */
bool BKE_gpencil_merge_materials(struct Object *ob,
const float hue_threshold,
const float sat_threshold,
@@ -152,12 +272,42 @@ bool BKE_gpencil_merge_materials(struct Object *ob,
int *r_removed);
/* statistics functions */
+/**
+ * Calc grease pencil statistics functions.
+ * \param gpd: Grease pencil data-block
+ */
void BKE_gpencil_stats_update(struct bGPdata *gpd);
+/**
+ * Create a new stroke, with pre-allocated data buffers.
+ * \param mat_idx: Index of the material
+ * \param totpoints: Total points
+ * \param thickness: Stroke thickness
+ * \return Pointer to new stroke
+ */
struct bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness);
+/**
+ * Create a new stroke and add to frame.
+ * \param gpf: Grease pencil frame
+ * \param mat_idx: Material index
+ * \param totpoints: Total points
+ * \param thickness: Stroke thickness
+ * \param insert_at_head: Add to the head of the strokes list
+ * \return Pointer to new stroke
+ */
struct bGPDstroke *BKE_gpencil_stroke_add(
struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head);
+/**
+ * Add a stroke and copy the temporary drawing color value
+ * from one of the existing stroke.
+ * \param gpf: Grease pencil frame
+ * \param existing: Stroke with the style to copy
+ * \param mat_idx: Material index
+ * \param totpoints: Total points
+ * \param thickness: Stroke thickness
+ * \return Pointer to new stroke
+ */
struct bGPDstroke *BKE_gpencil_stroke_add_existing_style(struct bGPDframe *gpf,
struct bGPDstroke *existing,
int mat_idx,
@@ -170,6 +320,11 @@ struct bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points);
#define GPENCIL_ALPHA_OPACITY_THRESH 0.001f
#define GPENCIL_STRENGTH_MIN 0.003f
+/**
+ * Check if the given layer is able to be edited or not.
+ * \param gpl: Grease pencil layer
+ * \return True if layer is editable
+ */
bool BKE_gpencil_layer_is_editable(const struct bGPDlayer *gpl);
/* How gpencil_layer_getframe() should behave when there
@@ -185,28 +340,121 @@ typedef enum eGP_GetFrame_Mode {
GP_GETFRAME_ADD_COPY = 2,
} eGP_GetFrame_Mode;
+/**
+ * Get the appropriate gp-frame from a given layer
+ * - this sets the layer's actframe var (if allowed to)
+ * - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
+ *
+ * \param gpl: Grease pencil layer
+ * \param cframe: Frame number
+ * \param addnew: Add option
+ * \return Pointer to new frame
+ */
struct bGPDframe *BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl,
int cframe,
eGP_GetFrame_Mode addnew);
+/**
+ * Look up the gp-frame on the requested frame number, but don't add a new one.
+ * \param gpl: Grease pencil layer
+ * \param cframe: Frame number
+ * \return Pointer to frame
+ */
struct bGPDframe *BKE_gpencil_layer_frame_find(struct bGPDlayer *gpl, int cframe);
+/**
+ * Delete the given frame from a layer.
+ * \param gpl: Grease pencil layer
+ * \param gpf: Grease pencil frame
+ * \return True if delete was done
+ */
bool BKE_gpencil_layer_frame_delete(struct bGPDlayer *gpl, struct bGPDframe *gpf);
+/**
+ * Get layer by name
+ * \param gpd: Grease pencil data-block
+ * \param name: Layer name
+ * \return Pointer to layer
+ */
struct bGPDlayer *BKE_gpencil_layer_named_get(struct bGPdata *gpd, const char *name);
+/**
+ * Get the active grease pencil layer for editing.
+ * \param gpd: Grease pencil data-block
+ * \return Pointer to layer
+ */
struct bGPDlayer *BKE_gpencil_layer_active_get(struct bGPdata *gpd);
+/**
+ * Set active grease pencil layer.
+ * \param gpd: Grease pencil data-block
+ * \param active: Grease pencil layer to set as active
+ */
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active);
+/**
+ * Delete grease pencil layer.
+ * \param gpd: Grease pencil data-block
+ * \param gpl: Grease pencil layer
+ */
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
+/**
+ * Set locked layers for autolock mode.
+ * \param gpd: Grease pencil data-block
+ * \param unlock: Unlock flag
+ */
void BKE_gpencil_layer_autolock_set(struct bGPdata *gpd, const bool unlock);
+/**
+ * Add grease pencil mask layer.
+ * \param gpl: Grease pencil layer
+ * \param name: Name of the mask
+ * \return Pointer to new mask layer
+ */
struct bGPDlayer_Mask *BKE_gpencil_layer_mask_add(struct bGPDlayer *gpl, const char *name);
+/**
+ * Remove grease pencil mask layer.
+ * \param gpl: Grease pencil layer
+ * \param mask: Grease pencil mask layer
+ */
void BKE_gpencil_layer_mask_remove(struct bGPDlayer *gpl, struct bGPDlayer_Mask *mask);
+/**
+ * Remove any reference to mask layer.
+ * \param gpd: Grease pencil data-block
+ * \param name: Name of the mask layer
+ */
void BKE_gpencil_layer_mask_remove_ref(struct bGPdata *gpd, const char *name);
+/**
+ * Get mask layer by name.
+ * \param gpl: Grease pencil layer
+ * \param name: Mask name
+ * \return Pointer to mask layer
+ */
struct bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(struct bGPDlayer *gpl, const char *name);
+/**
+ * Sort grease pencil mask layers.
+ * \param gpd: Grease pencil data-block
+ * \param gpl: Grease pencil layer
+ */
void BKE_gpencil_layer_mask_sort(struct bGPdata *gpd, struct bGPDlayer *gpl);
+/**
+ * Sort all grease pencil mask layer.
+ * \param gpd: Grease pencil data-block
+ */
void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd);
+/**
+ * Make a copy of a given gpencil mask layers.
+ */
void BKE_gpencil_layer_mask_copy(const struct bGPDlayer *gpl_src, struct bGPDlayer *gpl_dst);
+/**
+ * Clean any invalid mask layer.
+ */
void BKE_gpencil_layer_mask_cleanup(struct bGPdata *gpd, struct bGPDlayer *gpl);
+/**
+ * Clean any invalid mask layer for all layers.
+ */
void BKE_gpencil_layer_mask_cleanup_all_layers(struct bGPdata *gpd);
+/**
+ * Sort grease pencil frames.
+ * \param gpl: Grease pencil layer
+ * \param r_has_duplicate_frames: Duplicated frames flag
+ */
void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames);
struct bGPDlayer *BKE_gpencil_layer_get_by_name(struct bGPdata *gpd,
@@ -214,14 +462,43 @@ struct bGPDlayer *BKE_gpencil_layer_get_by_name(struct bGPdata *gpd,
int first_if_not_found);
/* Brush */
+/**
+ * Get grease pencil material from brush.
+ * \param brush: Brush
+ * \return Pointer to material
+ */
struct Material *BKE_gpencil_brush_material_get(struct Brush *brush);
+/**
+ * Set grease pencil brush material.
+ * \param brush: Brush
+ * \param material: Material
+ */
void BKE_gpencil_brush_material_set(struct Brush *brush, struct Material *material);
/* Object */
+/**
+ * Get active color, and add all default settings if we don't find anything.
+ * \param ob: Grease pencil object
+ * \return Material pointer
+ */
struct Material *BKE_gpencil_object_material_ensure_active(struct Object *ob);
+/**
+ * Adds the pinned material to the object if necessary.
+ * \param bmain: Main pointer
+ * \param ob: Grease pencil object
+ * \param brush: Brush
+ * \return Pointer to material
+ */
struct Material *BKE_gpencil_object_material_ensure_from_brush(struct Main *bmain,
struct Object *ob,
struct Brush *brush);
+/**
+ * Assigns the material to object (if not already present) and returns its index (mat_nr).
+ * \param bmain: Main pointer
+ * \param ob: Grease pencil object
+ * \param material: Material
+ * \return Index of the material
+ */
int BKE_gpencil_object_material_ensure(struct Main *bmain,
struct Object *ob,
struct Material *material);
@@ -230,41 +507,140 @@ struct Material *BKE_gpencil_object_material_ensure_by_name(struct Main *bmain,
const char *name,
int *r_index);
+/**
+ * Creates a new grease-pencil material and assigns it to object.
+ * \param bmain: Main pointer
+ * \param ob: Grease pencil object
+ * \param name: Material name
+ * \param r_index: value is set to zero based index of the new material if \a r_index is not NULL.
+ * \return Material pointer.
+ */
struct Material *BKE_gpencil_object_material_new(struct Main *bmain,
struct Object *ob,
const char *name,
int *r_index);
+/**
+ * Get material index (0-based like mat_nr not actcol).
+ * \param ob: Grease pencil object
+ * \param ma: Material
+ * \return Index of the material
+ */
int BKE_gpencil_object_material_index_get(struct Object *ob, struct Material *ma);
int BKE_gpencil_object_material_index_get_by_name(struct Object *ob, const char *name);
+/**
+ * Returns the material for a brush with respect to its pinned state.
+ * \param ob: Grease pencil object
+ * \param brush: Brush
+ * \return Material pointer
+ */
struct Material *BKE_gpencil_object_material_from_brush_get(struct Object *ob,
struct Brush *brush);
+/**
+ * Returns the material index for a brush with respect to its pinned state.
+ * \param ob: Grease pencil object
+ * \param brush: Brush
+ * \return Material index.
+ */
int BKE_gpencil_object_material_get_index_from_brush(struct Object *ob, struct Brush *brush);
+/**
+ * Guaranteed to return a material assigned to object. Returns never NULL.
+ * \param bmain: Main pointer
+ * \param ob: Grease pencil object
+ * \return Material pointer.
+ */
struct Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(
struct Main *bmain, struct Object *ob, struct ToolSettings *ts);
+/**
+ * Guaranteed to return a material assigned to object. Returns never NULL.
+ * \param bmain: Main pointer
+ * \param ob: Grease pencil object.
+ * \param brush: Brush
+ * \return Material pointer
+ */
struct Material *BKE_gpencil_object_material_ensure_from_active_input_brush(struct Main *bmain,
struct Object *ob,
struct Brush *brush);
+/**
+ * Guaranteed to return a material assigned to object. Returns never NULL.
+ * Only use this for materials unrelated to user input.
+ * \param ob: Grease pencil object
+ * \return Material pointer
+ */
struct Material *BKE_gpencil_object_material_ensure_from_active_input_material(struct Object *ob);
+/**
+ * Check if stroke has any point selected
+ * \param gps: Grease pencil stroke
+ * \return True if selected
+ */
bool BKE_gpencil_stroke_select_check(const struct bGPDstroke *gps);
/* vertex groups */
+/**
+ * Ensure stroke has vertex group.
+ * \param gps: Grease pencil stroke
+ */
void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps);
+/**
+ * Remove a vertex group.
+ * \param ob: Grease pencil object
+ * \param defgroup: deform group
+ */
void BKE_gpencil_vgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
+/**
+ * Make a copy of a given gpencil weights.
+ * \param gps_src: Source grease pencil stroke
+ * \param gps_dst: Destination grease pencil stroke
+ */
void BKE_gpencil_stroke_weights_duplicate(struct bGPDstroke *gps_src, struct bGPDstroke *gps_dst);
/* Set active frame by layer. */
+/**
+ * Set current grease pencil active frame.
+ * \param depsgraph: Current depsgraph
+ * \param gpd: Grease pencil data-block.
+ */
void BKE_gpencil_frame_active_set(struct Depsgraph *depsgraph, struct bGPdata *gpd);
+/**
+ * Get range of selected frames in layer.
+ * Always the active frame is considered as selected, so if no more selected the range
+ * will be equal to the current active frame.
+ * \param gpl: Layer.
+ * \param r_initframe: Number of first selected frame.
+ * \param r_endframe: Number of last selected frame.
+ */
void BKE_gpencil_frame_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe);
+/**
+ * Get Falloff factor base on frame range
+ * \param gpf: Frame.
+ * \param actnum: Number of active frame in layer.
+ * \param f_init: Number of first selected frame.
+ * \param f_end: Number of last selected frame.
+ * \param cur_falloff: Curve with falloff factors.
+ */
float BKE_gpencil_multiframe_falloff_calc(
struct bGPDframe *gpf, int actnum, int f_init, int f_end, struct CurveMapping *cur_falloff);
+/**
+ * Create a default palette.
+ * \param bmain: Main pointer
+ * \param scene: Scene
+ */
void BKE_gpencil_palette_ensure(struct Main *bmain, struct Scene *scene);
+/**
+ * Create grease pencil strokes from image
+ * \param sima: Image
+ * \param gpd: Grease pencil data-block
+ * \param gpf: Grease pencil frame
+ * \param size: Size
+ * \param mask: Mask
+ * \return True if done
+ */
bool BKE_gpencil_from_image(struct SpaceImage *sima,
struct bGPdata *gpd,
struct bGPDframe *gpf,
@@ -272,7 +648,9 @@ bool BKE_gpencil_from_image(struct SpaceImage *sima,
const bool mask);
/* Iterators */
-/* frame & stroke are NULL if it is a layer callback. */
+/**
+ * Frame & stroke are NULL if it is a layer callback.
+ */
typedef void (*gpIterCb)(struct bGPDlayer *layer,
struct bGPDframe *frame,
struct bGPDstroke *stroke,
@@ -294,17 +672,45 @@ void BKE_gpencil_visible_stroke_advanced_iter(struct ViewLayer *view_layer,
extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd);
extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
+/**
+ * Update original pointers in evaluated frame.
+ * \param gpf_orig: Original grease-pencil frame.
+ * \param gpf_eval: Evaluated grease pencil frame.
+ */
void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
const struct bGPDframe *gpf_eval);
+/**
+ * Update pointers of eval data to original data to keep references.
+ * \param ob_orig: Original grease pencil object
+ * \param ob_eval: Evaluated grease pencil object
+ */
void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval);
+/**
+ * Get parent matrix, including layer parenting.
+ * \param depsgraph: Depsgraph
+ * \param obact: Grease pencil object
+ * \param gpl: Grease pencil layer
+ * \param diff_mat: Result parent matrix
+ */
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph,
struct Object *obact,
struct bGPDlayer *gpl,
float diff_mat[4][4]);
+/**
+ * Update parent matrix and local transforms.
+ * \param depsgraph: Depsgraph
+ * \param ob: Grease pencil object
+ */
void BKE_gpencil_update_layer_transforms(const struct Depsgraph *depsgraph, struct Object *ob);
+/**
+ * Find material by name prefix.
+ * \param ob: Object pointer
+ * \param name_prefix: Prefix name of the material
+ * \return Index
+ */
int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char *name_prefix);
void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd);
diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h
index 9cbe67af9c1..044e2ff2336 100644
--- a/source/blender/blenkernel/BKE_gpencil_curve.h
+++ b/source/blender/blenkernel/BKE_gpencil_curve.h
@@ -35,6 +35,17 @@ struct bGPDlayer;
struct bGPDstroke;
struct bGPdata;
+/**
+ * Convert a curve object to grease pencil stroke.
+ *
+ * \param bmain: Main thread pointer
+ * \param scene: Original scene.
+ * \param ob_gp: Grease pencil object to add strokes.
+ * \param ob_cu: Curve to convert.
+ * \param use_collections: Create layers using collection names.
+ * \param scale_thickness: Scale thickness factor.
+ * \param sample: Sample distance, zero to disable.
+ */
void BKE_gpencil_convert_curve(struct Main *bmain,
struct Scene *scene,
struct Object *ob_gp,
@@ -43,24 +54,42 @@ void BKE_gpencil_convert_curve(struct Main *bmain,
const float scale_thickness,
const float sample);
+/**
+ * Creates a bGPDcurve by doing a cubic curve fitting on the grease pencil stroke points.
+ */
struct bGPDcurve *BKE_gpencil_stroke_editcurve_generate(struct bGPDstroke *gps,
const float error_threshold,
const float corner_angle,
const float stroke_radius);
+/**
+ * Updates the edit-curve for a stroke. Frees the old curve if one exists and generates a new one.
+ */
void BKE_gpencil_stroke_editcurve_update(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDstroke *gps);
+/**
+ * Sync the selection from stroke to edit-curve.
+ */
void BKE_gpencil_editcurve_stroke_sync_selection(struct bGPdata *gpd,
struct bGPDstroke *gps,
struct bGPDcurve *gpc);
+/**
+ * Sync the selection from edit-curve to stroke.
+ */
void BKE_gpencil_stroke_editcurve_sync_selection(struct bGPdata *gpd,
struct bGPDstroke *gps,
struct bGPDcurve *gpc);
void BKE_gpencil_strokes_selected_update_editcurve(struct bGPdata *gpd);
void BKE_gpencil_strokes_selected_sync_selection_editcurve(struct bGPdata *gpd);
+/**
+ * Recalculate stroke points with the edit-curve of the stroke.
+ */
void BKE_gpencil_stroke_update_geometry_from_editcurve(struct bGPDstroke *gps,
const uint resolution,
const bool is_adaptive);
+/**
+ * Recalculate the handles of the edit curve of a grease pencil stroke.
+ */
void BKE_gpencil_editcurve_recalculate_handles(struct bGPDstroke *gps);
void BKE_gpencil_editcurve_subdivide(struct bGPDstroke *gps, const int cuts);
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index 41b1bba10ba..4b9671c7881 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -38,38 +38,130 @@ struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
-/* Object boundbox. */
+/* Object bound-box. */
+
+/**
+ * Get min/max bounds of all strokes in grease pencil data-block.
+ * \param gpd: Grease pencil data-block
+ * \param r_min: Result minimum coordinates
+ * \param r_max: Result maximum coordinates
+ * \return True if it was possible to calculate
+ */
bool BKE_gpencil_data_minmax(const struct bGPdata *gpd, float r_min[3], float r_max[3]);
+/**
+ * Get min/max coordinate bounds for single stroke.
+ * \param gps: Grease pencil stroke
+ * \param use_select: Include only selected points
+ * \param r_min: Result minimum coordinates
+ * \param r_max: Result maximum coordinates
+ * \return True if it was possible to calculate
+ */
bool BKE_gpencil_stroke_minmax(const struct bGPDstroke *gps,
const bool use_select,
float r_min[3],
float r_max[3]);
+/**
+ * Get grease pencil object bounding box.
+ * \param ob: Grease pencil object
+ * \return Bounding box
+ */
struct BoundBox *BKE_gpencil_boundbox_get(struct Object *ob);
+/**
+ * Compute center of bounding box.
+ * \param gpd: Grease pencil data-block
+ * \param r_centroid: Location of the center
+ */
void BKE_gpencil_centroid_3d(struct bGPdata *gpd, float r_centroid[3]);
+/**
+ * Compute stroke bounding box.
+ * \param gps: Grease pencil Stroke
+ */
void BKE_gpencil_stroke_boundingbox_calc(struct bGPDstroke *gps);
-/* stroke geometry utilities */
+/* Stroke geometry utilities. */
+
+/**
+ * Calculate stroke normals.
+ * \param gps: Grease pencil stroke
+ * \param r_normal: Return Normal vector normalized
+ */
void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
+/**
+ * Reduce a series of points to a simplified version,
+ * but maintains the general shape of the series.
+ *
+ * Ramer - Douglas - Peucker algorithm
+ * by http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+ * \param gpd: Grease pencil data-block
+ * \param gps: Grease pencil stroke
+ * \param epsilon: Epsilon value to define precision of the algorithm
+ */
void BKE_gpencil_stroke_simplify_adaptive(struct bGPdata *gpd,
struct bGPDstroke *gps,
float epsilon);
+/**
+ * Simplify alternate vertex of stroke except extremes.
+ * \param gpd: Grease pencil data-block
+ * \param gps: Grease pencil stroke
+ */
void BKE_gpencil_stroke_simplify_fixed(struct bGPdata *gpd, struct bGPDstroke *gps);
+/**
+ * Subdivide a stroke
+ * \param gpd: Grease pencil data-block
+ * \param gps: Stroke
+ * \param level: Level of subdivision
+ * \param type: Type of subdivision
+ */
void BKE_gpencil_stroke_subdivide(struct bGPdata *gpd,
struct bGPDstroke *gps,
int level,
int type);
+/**
+ * Trim stroke to the first intersection or loop.
+ * \param gps: Stroke data
+ */
bool BKE_gpencil_stroke_trim(struct bGPdata *gpd, struct bGPDstroke *gps);
+/**
+ * Reduce a series of points when the distance is below a threshold.
+ * Special case for first and last points (both are kept) for other points,
+ * the merge point always is at first point.
+ *
+ * \param gpd: Grease pencil data-block.
+ * \param gpf: Grease Pencil frame.
+ * \param gps: Grease Pencil stroke.
+ * \param threshold: Distance between points.
+ * \param use_unselected: Set to true to analyze all stroke and not only selected points.
+ */
void BKE_gpencil_stroke_merge_distance(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const float threshold,
const bool use_unselected);
+/**
+ * Get points of stroke always flat to view not affected
+ * by camera view or view position.
+ * \param points: Array of grease pencil points (3D)
+ * \param totpoints: Total of points
+ * \param points2d: Result array of 2D points
+ * \param r_direction: Return Concave (-1), Convex (1), or Auto-detect (0)
+ */
void BKE_gpencil_stroke_2d_flat(const struct bGPDspoint *points,
int totpoints,
float (*points2d)[2],
int *r_direction);
+/**
+ * Get points of stroke always flat to view not affected by camera view or view position
+ * using another stroke as reference.
+ * \param ref_points: Array of reference points (3D)
+ * \param ref_totpoints: Total reference points
+ * \param points: Array of points to flat (3D)
+ * \param totpoints: Total points
+ * \param points2d: Result array of 2D points
+ * \param scale: Scale factor
+ * \param r_direction: Return Concave (-1), Convex (1), or Auto-detect (0)
+ */
void BKE_gpencil_stroke_2d_flat_ref(const struct bGPDspoint *ref_points,
int ref_totpoints,
const struct bGPDspoint *points,
@@ -77,10 +169,28 @@ void BKE_gpencil_stroke_2d_flat_ref(const struct bGPDspoint *ref_points,
float (*points2d)[2],
const float scale,
int *r_direction);
+/**
+ * Triangulate stroke to generate data for filling areas.
+ * \param gps: Grease pencil stroke
+ */
void BKE_gpencil_stroke_fill_triangulate(struct bGPDstroke *gps);
+/**
+ * Recalc all internal geometry data for the stroke
+ * \param gpd: Grease pencil data-block
+ * \param gps: Grease pencil stroke
+ */
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps);
+/**
+ * Update Stroke UV data.
+ * \param gps: Grease pencil stroke
+ */
void BKE_gpencil_stroke_uv_update(struct bGPDstroke *gps);
+/**
+ * Apply grease pencil Transforms.
+ * \param gpd: Grease pencil data-block
+ * \param mat: Transformation matrix
+ */
void BKE_gpencil_transform(struct bGPdata *gpd, const float mat[4][4]);
typedef struct GPencilPointCoordinates {
@@ -90,27 +200,93 @@ typedef struct GPencilPointCoordinates {
float pressure;
} GPencilPointCoordinates;
+/**
+ * \note Used for "move only origins" in object_data_transform.c.
+ */
int BKE_gpencil_stroke_point_count(const struct bGPdata *gpd);
+/**
+ * \note Used for "move only origins" in object_data_transform.c.
+ */
void BKE_gpencil_point_coords_get(struct bGPdata *gpd, GPencilPointCoordinates *elem_data);
+/**
+ * \note Used for "move only origins" in object_data_transform.c.
+ */
void BKE_gpencil_point_coords_apply(struct bGPdata *gpd, const GPencilPointCoordinates *elem_data);
+/**
+ * \note Used for "move only origins" in object_data_transform.c.
+ */
void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd,
const GPencilPointCoordinates *elem_data,
const float mat[4][4]);
+/**
+ * Resample a stroke
+ * \param gpd: Grease pencil data-block
+ * \param gps: Stroke to sample
+ * \param dist: Distance of one segment
+ */
bool BKE_gpencil_stroke_sample(struct bGPdata *gpd,
struct bGPDstroke *gps,
const float dist,
const bool select);
-bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps, int i, float inf);
+/**
+ * Apply smooth position to stroke point.
+ * \param gps: Stroke to smooth
+ * \param i: Point index
+ * \param inf: Amount of smoothing to apply
+ * \param smooth_caps: Apply smooth to stroke extremes
+ */
+bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps,
+ int i,
+ float inf,
+ const bool smooth_caps);
+/**
+ * Apply smooth strength to stroke point.
+ * \param gps: Stroke to smooth
+ * \param point_index: Point index
+ * \param influence: Amount of smoothing to apply
+ */
bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps, int point_index, float influence);
+/**
+ * Apply smooth for thickness to stroke point (use pressure).
+ * \param gps: Stroke to smooth
+ * \param point_index: Point index
+ * \param influence: Amount of smoothing to apply
+ */
bool BKE_gpencil_stroke_smooth_thickness(struct bGPDstroke *gps, int point_index, float influence);
+/**
+ * Apply smooth for UV rotation to stroke point (use pressure).
+ * \param gps: Stroke to smooth
+ * \param point_index: Point index
+ * \param influence: Amount of smoothing to apply
+ */
bool BKE_gpencil_stroke_smooth_uv(struct bGPDstroke *gps, int point_index, float influence);
+/**
+ * Close grease pencil stroke.
+ * \param gps: Stroke to close
+ */
bool BKE_gpencil_stroke_close(struct bGPDstroke *gps);
+/**
+ * Dissolve points in stroke.
+ * \param gpd: Grease pencil data-block
+ * \param gpf: Grease pencil frame
+ * \param gps: Grease pencil stroke
+ * \param tag: Type of tag for point
+ */
void BKE_gpencil_dissolve_points(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const short tag);
+/**
+ * Backbone stretch similar to Freestyle.
+ * \param gps: Stroke to sample.
+ * \param dist: Length of the added section.
+ * \param overshoot_fac: Relative length of the curve which is used to determine the extension.
+ * \param mode: Affect to Start, End or Both extremes (0->Both, 1->Start, 2->End).
+ * \param follow_curvature: True for approximating curvature of given overshoot.
+ * \param extra_point_count: When follow_curvature is true, use this amount of extra points.
+ */
bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps,
const float dist,
const float overshoot_fac,
@@ -120,9 +296,20 @@ bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps,
const float segment_influence,
const float max_angle,
const bool invert_curvature);
+/**
+ * Trim stroke to needed segments.
+ * \param gps: Target stroke.
+ * \param index_from: the index of the first point to be used in the trimmed result.
+ * \param index_to: the index of the last point to be used in the trimmed result.
+ */
bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps,
const int index_from,
const int index_to);
+/**
+ * Split the given stroke into several new strokes, partitioning
+ * it based on whether the stroke points have a particular flag
+ * is set (e.g. #GP_SPOINT_SELECT in most cases, but not always).
+ */
struct bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
@@ -138,33 +325,84 @@ void BKE_gpencil_curve_delete_tagged_points(struct bGPdata *gpd,
struct bGPDcurve *gpc,
int tag_flags);
+/**
+ * Flip stroke.
+ */
void BKE_gpencil_stroke_flip(struct bGPDstroke *gps);
+/**
+ * Split stroke.
+ * \param gpd: Grease pencil data-block.
+ * \param gpf: Grease pencil frame.
+ * \param gps: Grease pencil original stroke.
+ * \param before_index: Position of the point to split.
+ * \param remaining_gps: Secondary stroke after split.
+ * \return True if the split was done
+ */
bool BKE_gpencil_stroke_split(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const int before_index,
struct bGPDstroke **remaining_gps);
+/**
+ * Shrink the stroke by length.
+ * \param gps: Stroke to shrink
+ * \param dist: delta length
+ * \param mode: 1->Start, 2->End
+ */
bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, const float dist, const short mode);
+/**
+ * Calculate grease pencil stroke length.
+ * \param gps: Grease pencil stroke.
+ * \param use_3d: Set to true to use 3D points.
+ * \return Length of the stroke.
+ */
float BKE_gpencil_stroke_length(const struct bGPDstroke *gps, bool use_3d);
+/** Calculate grease pencil stroke length between points. */
float BKE_gpencil_stroke_segment_length(const struct bGPDstroke *gps,
const int start_index,
const int end_index,
bool use_3d);
+/**
+ * Set a random color to stroke using vertex color.
+ * \param gps: Stroke
+ */
void BKE_gpencil_stroke_set_random_color(struct bGPDstroke *gps);
+/**
+ * Join two strokes using the shortest distance (reorder stroke if necessary).
+ */
void BKE_gpencil_stroke_join(struct bGPDstroke *gps_a,
struct bGPDstroke *gps_b,
const bool leave_gaps,
const bool fit_thickness,
const bool smooth);
+/**
+ * Copy the stroke of the frame to all frames selected (except current).
+ */
void BKE_gpencil_stroke_copy_to_keyframes(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const bool tail);
+/**
+ * Convert a mesh object to grease pencil stroke.
+ *
+ * \param bmain: Main thread pointer.
+ * \param depsgraph: Original depsgraph.
+ * \param scene: Original scene.
+ * \param ob_gp: Grease pencil object to add strokes.
+ * \param ob_mesh: Mesh to convert.
+ * \param angle: Limit angle to consider a edge-loop ends.
+ * \param thickness: Thickness of the strokes.
+ * \param offset: Offset along the normals.
+ * \param matrix: Transformation matrix.
+ * \param frame_offset: Destination frame number offset.
+ * \param use_seams: Only export seam edges.
+ * \param use_faces: Export faces as filled strokes.
+ */
bool BKE_gpencil_convert_mesh(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Scene *scene,
@@ -179,24 +417,56 @@ bool BKE_gpencil_convert_mesh(struct Main *bmain,
const bool use_faces,
const bool use_vgroups);
+/**
+ * Subdivide the grease pencil stroke so the number of points is target_number.
+ * Does not change the shape of the stroke. The new points will be distributed as
+ * uniformly as possible by repeatedly subdividing the current longest edge.
+ *
+ * \param gps: The stroke to be up-sampled.
+ * \param target_number: The number of points the up-sampled stroke should have.
+ * \param select: Select/Deselect the stroke.
+ */
void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd,
struct bGPDstroke *gps,
const uint32_t target_number,
const bool select);
+/**
+ * Stroke to view space
+ * Transforms a stroke to view space.
+ * This allows for manipulations in 2D but also easy conversion back to 3D.
+ * \note also takes care of parent space transform.
+ */
void BKE_gpencil_stroke_to_view_space(struct RegionView3D *rv3d,
struct bGPDstroke *gps,
const float diff_mat[4][4]);
+/**
+ * Stroke from view space
+ * Transforms a stroke from view space back to world space.
+ * Inverse of #BKE_gpencil_stroke_to_view_space
+ * \note also takes care of parent space transform.
+ */
void BKE_gpencil_stroke_from_view_space(struct RegionView3D *rv3d,
struct bGPDstroke *gps,
const float diff_mat[4][4]);
+/**
+ * Calculates the perimeter of a stroke projected from the view and returns it as a new stroke.
+ * \param subdivisions: Number of subdivisions for the start and end caps.
+ * \return: bGPDstroke pointer to stroke perimeter.
+ */
struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
struct bGPdata *gpd,
const struct bGPDlayer *gpl,
struct bGPDstroke *gps,
const int subdivisions,
const float diff_mat[4][4]);
+/**
+ * Get average pressure.
+ */
float BKE_gpencil_stroke_average_pressure_get(struct bGPDstroke *gps);
+/**
+ * Check if the thickness of the stroke is constant.
+ */
bool BKE_gpencil_stroke_is_pressure_constant(struct bGPDstroke *gps);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index 33524e47473..5fc0abf6a2c 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -249,36 +249,114 @@ typedef struct GpencilModifierTypeInfo {
#define GPENCIL_MODIFIER_TYPE_PANEL_PREFIX "MOD_PT_gpencil_"
-/* Initialize modifier's global data (type info and some common global storage). */
+/**
+ * Initialize modifier's global data (type info and some common global storage).
+ */
void BKE_gpencil_modifier_init(void);
+/**
+ * Get the idname of the modifier type's panel, which was defined in the #panelRegister callback.
+ *
+ * \param type: Type of modifier.
+ * \param r_idname: ID name.
+ */
void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname);
void BKE_gpencil_modifier_panel_expand(struct GpencilModifierData *md);
+/**
+ * Get grease pencil modifier information.
+ * \param type: Type of modifier.
+ * \return Pointer to type
+ */
const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type);
+/**
+ * Create new grease pencil modifier.
+ * \param type: Type of modifier.
+ * \return New modifier pointer.
+ */
struct GpencilModifierData *BKE_gpencil_modifier_new(int type);
+/**
+ * Free grease pencil modifier data
+ * \param md: Modifier data.
+ * \param flag: Flags.
+ */
void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, const int flag);
+/**
+ * Free grease pencil modifier data
+ * \param md: Modifier data.
+ */
void BKE_gpencil_modifier_free(struct GpencilModifierData *md);
+/* check unique name */
bool BKE_gpencil_modifier_unique_name(struct ListBase *modifiers, struct GpencilModifierData *gmd);
+/**
+ * Check if grease pencil modifier depends on time.
+ * \param md: Modifier data.
+ * \return True if depends on time.
+ */
bool BKE_gpencil_modifier_depends_ontime(struct GpencilModifierData *md);
struct GpencilModifierData *BKE_gpencil_modifiers_findby_type(struct Object *ob,
GpencilModifierType type);
+/**
+ * Find grease pencil modifier by name.
+ * \param ob: Grease pencil object.
+ * \param name: Name to find.
+ * \return Pointer to modifier.
+ */
struct GpencilModifierData *BKE_gpencil_modifiers_findby_name(struct Object *ob, const char *name);
+/**
+ * Generic grease pencil modifier copy data.
+ * \param md_src: Source modifier data.
+ * \param md_dst: Target modifier data.
+ */
void BKE_gpencil_modifier_copydata_generic(const struct GpencilModifierData *md_src,
struct GpencilModifierData *md_dst);
+/**
+ * Copy grease pencil modifier data.
+ * \param md: Source modifier data.
+ * \param target: Target modifier data.
+ */
void BKE_gpencil_modifier_copydata(struct GpencilModifierData *md,
struct GpencilModifierData *target);
+/**
+ * Copy grease pencil modifier data.
+ * \param md: Source modifier data.
+ * \param target: Target modifier data.
+ * \param flag: Flags.
+ */
void BKE_gpencil_modifier_copydata_ex(struct GpencilModifierData *md,
struct GpencilModifierData *target,
const int flag);
+/**
+ * Set grease pencil modifier error.
+ * \param md: Modifier data.
+ * \param format: Format.
+ */
void BKE_gpencil_modifier_set_error(struct GpencilModifierData *md, const char *format, ...)
ATTR_PRINTF_FORMAT(2, 3);
+/**
+ * Link grease pencil modifier related IDs.
+ * \param ob: Grease pencil object.
+ * \param walk: Walk option.
+ * \param userData: User data.
+ */
void BKE_gpencil_modifiers_foreach_ID_link(struct Object *ob,
GreasePencilIDWalkFunc walk,
void *userData);
+/**
+ * Link grease pencil modifier related Texts.
+ * \param ob: Grease pencil object.
+ * \param walk: Walk option.
+ * \param userData: User data.
+ */
void BKE_gpencil_modifiers_foreach_tex_link(struct Object *ob,
GreasePencilTexWalkFunc walk,
void *userData);
+/**
+ * Check whether given modifier is not local (i.e. from linked data) when the object is a library
+ * override.
+ *
+ * \param gmd: May be NULL, in which case we consider it as a non-local modifier case.
+ */
bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const struct Object *ob,
const struct GpencilModifierData *gmd);
@@ -287,11 +365,30 @@ typedef struct GpencilVirtualModifierData {
LatticeGpencilModifierData lmd;
} GpencilVirtualModifierData;
+/**
+ * This is to include things that are not modifiers in the evaluation of the modifier stack,
+ * for example parenting to an armature or lattice without having a real modifier.
+ */
struct GpencilModifierData *BKE_gpencil_modifiers_get_virtual_modifierlist(
const struct Object *ob, struct GpencilVirtualModifierData *data);
+/**
+ * Check if object has grease pencil Geometry modifiers.
+ * \param ob: Grease pencil object.
+ * \return True if exist.
+ */
bool BKE_gpencil_has_geometry_modifiers(struct Object *ob);
+/**
+ * Check if object has grease pencil Time modifiers.
+ * \param ob: Grease pencil object.
+ * \return True if exist.
+ */
bool BKE_gpencil_has_time_modifiers(struct Object *ob);
+/**
+ * Check if object has grease pencil transform stroke modifiers.
+ * \param ob: Grease pencil object.
+ * \return True if exist.
+ */
bool BKE_gpencil_has_transform_modifiers(struct Object *ob);
/* Stores the maximum calculation range in the whole modifier stack for line art so the cache can
@@ -310,21 +407,44 @@ void BKE_gpencil_set_lineart_modifier_limits(struct GpencilModifierData *md,
bool BKE_gpencil_is_first_lineart_in_stack(const struct Object *ob,
const struct GpencilModifierData *md);
-void BKE_gpencil_lattice_init(struct Object *ob);
-void BKE_gpencil_lattice_clear(struct Object *ob);
+void BKE_gpencil_cache_data_init(struct Depsgraph *depsgraph, struct Object *ob);
+void BKE_gpencil_cache_data_clear(struct Object *ob);
+/**
+ * Calculate grease-pencil modifiers.
+ * \param depsgraph: Current depsgraph.
+ * \param scene: Current scene.
+ * \param ob: Grease pencil object.
+ */
void BKE_gpencil_modifiers_calc(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
+/**
+ * Prepare grease pencil eval data for modifiers
+ * \param depsgraph: Current depsgraph.
+ * \param scene: Current scene.
+ * \param ob: Grease pencil object.
+ */
void BKE_gpencil_prepare_eval_data(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
+/**
+ * Get the current frame re-timed with time modifiers.
+ * \param depsgraph: Current depsgraph.
+ * \param scene: Current scene.
+ * \param ob: Grease pencil object.
+ * \param gpl: Grease pencil layer.
+ * \return New frame number.
+ */
struct bGPDframe *BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct bGPDlayer *gpl);
+/**
+ * Get Time modifier frame number.
+ */
int BKE_gpencil_time_modifier_cfra(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 28a6f837f61..c96a37e0d09 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -97,76 +97,135 @@ enum eIconSizes;
void BKE_icons_init(int first_dyn_id);
-/* return icon id for library object or create new icon if not found */
+/**
+ * Return icon id for library object or create new icon if not found.
+ */
int BKE_icon_id_ensure(struct ID *id);
-/* return icon id for Grease Pencil layer (color preview) or create new icon if not found */
+/**
+ * Return icon id for Grease Pencil layer (color preview) or create new icon if not found.
+ */
int BKE_icon_gplayer_color_ensure(struct bGPDlayer *gpl);
+/**
+ * Return icon id of given preview, or create new icon if not found.
+ */
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
+/**
+ * Create an icon as owner or \a ibuf. The icon-ID is not stored in \a ibuf,
+ * it needs to be stored separately.
+ * \note Transforms ownership of \a ibuf to the newly created icon.
+ */
int BKE_icon_imbuf_create(struct ImBuf *ibuf) ATTR_WARN_UNUSED_RESULT;
struct ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) ATTR_WARN_UNUSED_RESULT;
-/* retrieve icon for id */
+/**
+ * Retrieve icon for id.
+ */
struct Icon *BKE_icon_get(const int icon_id);
-/* set icon for id if not already defined */
-/* used for inserting the internal icons */
+/**
+ * Set icon for id if not already defined.
+ * Used for inserting the internal icons.
+ */
void BKE_icon_set(const int icon_id, struct Icon *icon);
-/* remove icon and free data if library object becomes invalid */
+/**
+ * Remove icon and free data if library object becomes invalid.
+ */
void BKE_icon_id_delete(struct ID *id);
+/**
+ * Remove icon and free data.
+ */
bool BKE_icon_delete(const int icon_id);
bool BKE_icon_delete_unmanaged(const int icon_id);
-/* report changes - icon needs to be recalculated */
+/**
+ * Report changes - icon needs to be recalculated.
+ */
void BKE_icon_changed(const int icon_id);
-/* free all icons */
+/**
+ * Free all icons.
+ */
void BKE_icons_free(void);
-/* free all icons marked for deferred deletion */
+/**
+ * Free all icons marked for deferred deletion.
+ */
void BKE_icons_deferred_free(void);
-/* free the preview image for use in list */
+/**
+ * Free the preview image for use in list.
+ */
void BKE_previewimg_freefunc(void *link);
-/* free the preview image */
+/**
+ * Free the preview image.
+ */
void BKE_previewimg_free(struct PreviewImage **prv);
-/* clear the preview image or icon, but does not free it */
+/**
+ * Clear the preview image or icon, but does not free it.
+ */
void BKE_previewimg_clear(struct PreviewImage *prv);
-/* clear the preview image or icon at a specific size */
+/**
+ * Clear the preview image or icon at a specific size.
+ */
void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size);
-/* get the preview from any pointer */
+/**
+ * Get the preview from any pointer.
+ */
struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id);
struct PreviewImage *BKE_previewimg_id_get(const struct ID *id);
bool BKE_previewimg_id_supports_jobs(const struct ID *id);
-/* Trigger deferred loading of a custom image file into the preview buffer. */
+/**
+ * Trigger deferred loading of a custom image file into the preview buffer.
+ */
void BKE_previewimg_id_custom_set(struct ID *id, const char *path);
-/* free the preview image belonging to the id */
+/**
+ * Free the preview image belonging to the id.
+ */
void BKE_previewimg_id_free(struct ID *id);
-/* create a new preview image */
+/**
+ * Create a new preview image.
+ */
struct PreviewImage *BKE_previewimg_create(void);
-/* create a copy of the preview image */
+/**
+ * Create a copy of the preview image.
+ */
struct PreviewImage *BKE_previewimg_copy(const struct PreviewImage *prv);
+/**
+ * Duplicate preview image from \a id and clear icon_id,
+ * to be used by data-block copy functions.
+ */
void BKE_previewimg_id_copy(struct ID *new_id, const struct ID *old_id);
-/* retrieve existing or create new preview image */
+/**
+ * Retrieve existing or create new preview image.
+ */
struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id);
+/**
+ * Handle deferred (lazy) loading/generation of preview image, if needed.
+ * For now, only used with file thumbnails.
+ */
void BKE_previewimg_ensure(struct PreviewImage *prv, const int size);
+/**
+ * Create an #ImBuf holding a copy of the preview image buffer in \a prv.
+ * \note The returned image buffer has to be free'd (#IMB_freeImBuf()).
+ */
struct ImBuf *BKE_previewimg_to_imbuf(struct PreviewImage *prv, const int size);
void BKE_previewimg_finish(struct PreviewImage *prv, const int size);
@@ -174,8 +233,15 @@ bool BKE_previewimg_is_finished(const struct PreviewImage *prv, const int size);
struct PreviewImage *BKE_previewimg_cached_get(const char *name);
+/**
+ * Generate an empty #PreviewImage, if not yet existing.
+ */
struct PreviewImage *BKE_previewimg_cached_ensure(const char *name);
+/**
+ * Generate a #PreviewImage from given file path, using thumbnails management, if not yet existing.
+ * Does not actually generate the preview, #BKE_previewimg_ensure() must be called for that.
+ */
struct PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name,
const char *path,
const int source,
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index c28ac63388b..1fb3636e9fd 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -56,11 +56,17 @@ typedef union IDPropertyTemplate {
/* ----------- Property Array Type ---------- */
+/**
+ * \note as a start to move away from the stupid #IDP_New function,
+ * this type has its own allocation function.
+ */
struct IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
struct IDProperty *IDP_CopyIDPArray(const struct IDProperty *array,
const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-/* shallow copies item */
+/**
+ * Shallow copies item.
+ */
void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
@@ -68,11 +74,20 @@ void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item);
void IDP_ResizeIDPArray(struct IDProperty *prop, int len);
/* ----------- Numeric Array Type ----------- */
-/* This function works for strings too! */
+
+/**
+ * This function works for strings too!
+ */
void IDP_ResizeArray(struct IDProperty *prop, int newlen);
void IDP_FreeArray(struct IDProperty *prop);
/* ---------- String Type ------------ */
+/**
+ * \param st: The string to assign.
+ * \param name: The property name.
+ * \param maxlen: The size of the new string (including the \0 terminator).
+ * \return The new string property.
+ */
struct IDProperty *IDP_NewString(const char *st,
const char *name,
int maxlen) ATTR_WARN_UNUSED_RESULT
@@ -91,38 +106,90 @@ void IDP_AssignID(struct IDProperty *prop, struct ID *id, const int flag);
/*-------- Group Functions -------*/
-/** Sync values from one group to another, only where they match */
+/**
+ * Sync values from one group to another when values name and types match,
+ * copy the values, else ignore.
+ *
+ * \note Use for syncing proxies.
+ */
void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
void IDP_SyncGroupTypes(struct IDProperty *dest,
const struct IDProperty *src,
const bool do_arraylen) ATTR_NONNULL();
+/**
+ * Replaces all properties with the same name in a destination group from a source group.
+ */
void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
+/**
+ * Checks if a property with the same name as prop exists, and if so replaces it.
+ * Use this to preserve order!
+ */
void IDP_ReplaceInGroup_ex(struct IDProperty *group,
struct IDProperty *prop,
struct IDProperty *prop_exist);
+/**
+ * If a property is missing in \a dest, add it.
+ * Do it recursively.
+ */
void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, const bool do_overwrite)
ATTR_NONNULL();
+/**
+ * If a property is missing in \a dest, add it.
+ * Do it recursively.
+ */
void IDP_MergeGroup_ex(struct IDProperty *dest,
const struct IDProperty *src,
const bool do_overwrite,
const int flag) ATTR_NONNULL();
+/**
+ * This function has a sanity check to make sure ID properties with the same name don't
+ * get added to the group.
+ *
+ * The sanity check just means the property is not added to the group if another property
+ * exists with the same name; the client code using ID properties then needs to detect this
+ * (the function that adds new properties to groups, #IDP_AddToGroup,
+ * returns false if a property can't be added to the group, and true if it can)
+ * and free the property.
+ */
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
+/**
+ * This is the same as IDP_AddToGroup, only you pass an item
+ * in the group list to be inserted after.
+ */
bool IDP_InsertToGroup(struct IDProperty *group,
struct IDProperty *previous,
struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */);
+/**
+ * \note this does not free the property!
+ *
+ * To free the property, you have to do:
+ * #IDP_FreeProperty(prop);
+ */
void IDP_RemoveFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
+/**
+ * Removes the property from the group and frees it.
+ */
void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
struct IDProperty *IDP_GetPropertyFromGroup(const struct IDProperty *prop,
const char *name) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Same as above but ensure type match.
+ */
struct IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop,
const char *name,
const char type) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
/*-------- Main Functions --------*/
+/**
+ * Get the Group property that contains the id properties for ID id.
+ *
+ * \param create_if_needed: Set to create the group property and attach it to id if it doesn't
+ * exist; otherwise the function will return NULL if there's no Group property attached to the ID.
+ */
struct IDProperty *IDP_GetProperties(struct ID *id,
const bool create_if_needed) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
@@ -130,8 +197,15 @@ struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNU
ATTR_NONNULL();
struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop,
const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Copy content from source #IDProperty into destination one,
+ * freeing destination property's content first.
+ */
void IDP_CopyPropertyContent(struct IDProperty *dst, struct IDProperty *src) ATTR_NONNULL();
+/**
+ * \param is_strict: When false treat missing items as a match.
+ */
bool IDP_EqualsProperties_ex(struct IDProperty *prop1,
struct IDProperty *prop2,
const bool is_strict) ATTR_WARN_UNUSED_RESULT;
@@ -139,10 +213,41 @@ bool IDP_EqualsProperties_ex(struct IDProperty *prop1,
bool IDP_EqualsProperties(struct IDProperty *prop1,
struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
+/**
+ * Allocate a new ID.
+ *
+ * This function takes three arguments: the ID property type, a union which defines
+ * its initial value, and a name.
+ *
+ * The union is simple to use; see the top of BKE_idprop.h for its definition.
+ * An example of using this function:
+ *
+ * \code{.c}
+ * IDPropertyTemplate val;
+ * IDProperty *group, *idgroup, *color;
+ * group = IDP_New(IDP_GROUP, val, "group1"); // groups don't need a template.
+ *
+ * val.array.len = 4
+ * val.array.type = IDP_FLOAT;
+ * color = IDP_New(IDP_ARRAY, val, "color1");
+ *
+ * idgroup = IDP_GetProperties(some_id, 1);
+ * IDP_AddToGroup(idgroup, color);
+ * IDP_AddToGroup(idgroup, group);
+ * \endcode
+ *
+ * Note that you MUST either attach the id property to an id property group with
+ * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
+ * a memory leak.
+ */
struct IDProperty *IDP_New(const char type,
const IDPropertyTemplate *val,
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
+ * But it does not free the actual #IDProperty struct itself.
+ */
void IDP_FreePropertyContent_ex(struct IDProperty *prop, const bool do_id_user);
void IDP_FreePropertyContent(struct IDProperty *prop);
void IDP_FreeProperty_ex(struct IDProperty *prop, const bool do_id_user);
@@ -184,16 +289,35 @@ void IDP_Reset(struct IDProperty *prop, const struct IDProperty *reference);
# define IDP_Id(prop) ((ID *)(prop)->data.pointer)
#endif
+/**
+ * Return an int from an #IDProperty with a compatible type. This should be avoided, but
+ * it's sometimes necessary, for example when legacy files have incorrect property types.
+ */
int IDP_coerce_to_int_or_zero(const struct IDProperty *prop);
+/**
+ * Return a float from an #IDProperty with a compatible type. This should be avoided, but
+ * it's sometimes necessary, for example when legacy files have incorrect property types.
+ */
float IDP_coerce_to_float_or_zero(const struct IDProperty *prop);
+/**
+ * Return a double from an #IDProperty with a compatible type. This should be avoided, but
+ * it's sometimes necessary, for example when legacy files have incorrect property types.
+ */
double IDP_coerce_to_double_or_zero(const struct IDProperty *prop);
/**
- * Call a callback for each idproperty in the hierarchy under given root one (included).
- *
+ * Call a callback for each #IDproperty in the hierarchy under given root one (included).
*/
typedef void (*IDPForeachPropertyCallback)(struct IDProperty *id_property, void *user_data);
+/**
+ * Loop through all ID properties in hierarchy of given \a id_property_root included.
+ *
+ * \note Container types (groups and arrays) are processed after applying the callback on them.
+ *
+ * \param type_filter: If not 0, only apply callback on properties of matching types, see
+ * IDP_TYPE_FILTER_ enum in DNA_ID.h.
+ */
void IDP_foreach_property(struct IDProperty *id_property_root,
const int type_filter,
IDPForeachPropertyCallback callback,
@@ -230,6 +354,11 @@ typedef enum eIDPropertyUIDataType {
bool IDP_ui_data_supported(const struct IDProperty *prop);
eIDPropertyUIDataType IDP_ui_data_type(const struct IDProperty *prop);
void IDP_ui_data_free(struct IDProperty *prop);
+/**
+ * Free allocated pointers in the UI data that isn't shared with the UI data in the `other`
+ * argument. Useful for returning early on failure when updating UI data in place, or when
+ * replacing a subset of the UI data's allocated pointers.
+ */
void IDP_ui_data_free_unique_contents(struct IDPropertyUIData *ui_data,
eIDPropertyUIDataType type,
const struct IDPropertyUIData *other);
diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h
index d33c24f2c75..8cd5d2a2361 100644
--- a/source/blender/blenkernel/BKE_idtype.h
+++ b/source/blender/blenkernel/BKE_idtype.h
@@ -35,6 +35,7 @@ struct BlendDataReader;
struct BlendExpander;
struct BlendLibReader;
struct BlendWriter;
+struct BPathForeachPathData;
struct ID;
struct LibraryForeachIDData;
struct Main;
@@ -81,7 +82,7 @@ typedef void (*IDTypeCopyDataFunction)(struct Main *bmain,
typedef void (*IDTypeFreeDataFunction)(struct ID *id);
-/** \param flag: See BKE_lib_id.h's LIB_ID_MAKELOCAL_... flags. */
+/** \param flags: See BKE_lib_id.h's LIB_ID_MAKELOCAL_... flags. */
typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const int flags);
typedef void (*IDTypeForeachIDFunction)(struct ID *id, struct LibraryForeachIDData *data);
@@ -100,6 +101,8 @@ typedef void (*IDTypeForeachCacheFunction)(struct ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data);
+typedef void (*IDTypeForeachPathFunction)(struct ID *id, struct BPathForeachPathData *bpath_data);
+
typedef struct ID *(*IDTypeEmbeddedOwnerGetFunction)(struct Main *bmain, struct ID *id);
typedef void (*IDTypeBlendWriteFunction)(struct BlendWriter *writer,
@@ -149,11 +152,12 @@ typedef struct IDTypeInfo {
/** Generic info flags about that data-block type. */
uint32_t flags;
- /* ********** ID management callbacks ********** */
+ /**
+ * Information and callbacks for assets, based on the type of asset.
+ */
+ struct AssetTypeInfo *asset_type_info;
- /* TODO: Note about callbacks: Ideally we could also handle here `BKE_lib_query`'s behavior, as
- * well as read/write of files. However, this is a bit more involved than basic ID management
- * callbacks, so we'll check on this later. */
+ /* ********** ID management callbacks ********** */
/**
* Initialize a new, empty calloc'ed data-block. May be NULL if there is nothing to do.
@@ -189,6 +193,11 @@ typedef struct IDTypeInfo {
IDTypeForeachCacheFunction foreach_cache;
/**
+ * Iterator over all file paths of given ID.
+ */
+ IDTypeForeachPathFunction foreach_path;
+
+ /**
* For embedded IDs, return their owner ID.
*/
IDTypeEmbeddedOwnerGetFunction owner_get;
@@ -228,11 +237,6 @@ typedef struct IDTypeInfo {
* \note Currently needed for some update operation on point caches.
*/
IDTypeLibOverrideApplyPost lib_override_apply_post;
-
- /**
- * Callbacks for assets, based on the type of asset.
- */
- struct AssetTypeInfo *asset_type_info;
} IDTypeInfo;
/* ********** Declaration of each IDTypeInfo. ********** */
@@ -279,6 +283,7 @@ extern IDTypeInfo IDType_ID_PT;
extern IDTypeInfo IDType_ID_VO;
extern IDTypeInfo IDType_ID_SIM;
+/** Empty shell mostly, but needed for read code. */
extern IDTypeInfo IDType_ID_LINK_PLACEHOLDER;
/* ********** Helpers/Utils API. ********** */
@@ -290,32 +295,101 @@ void BKE_idtype_init(void);
const struct IDTypeInfo *BKE_idtype_get_info_from_idcode(const short id_code);
const struct IDTypeInfo *BKE_idtype_get_info_from_id(const struct ID *id);
+/**
+ * Convert an \a idcode into a name.
+ *
+ * \param idcode: The code to convert.
+ * \return A static string representing the name of the code.
+ */
const char *BKE_idtype_idcode_to_name(const short idcode);
+/**
+ * Convert an \a idcode into a name (plural).
+ *
+ * \param idcode: The code to convert.
+ * \return A static string representing the name of the code.
+ */
const char *BKE_idtype_idcode_to_name_plural(const short idcode);
+/**
+ * Convert an \a idcode into its translations' context.
+ *
+ * \param idcode: The code to convert.
+ * \return A static string representing the i18n context of the code.
+ */
const char *BKE_idtype_idcode_to_translation_context(const short idcode);
+/**
+ * Return if the ID code is a valid ID code.
+ *
+ * \param idcode: The code to check.
+ * \return Boolean, 0 when invalid.
+ */
bool BKE_idtype_idcode_is_valid(const short idcode);
+/**
+ * Check if an ID type is linkable.
+ *
+ * \param idcode: The IDType code to check.
+ * \return Boolean, false when non linkable, true otherwise.
+ */
bool BKE_idtype_idcode_is_linkable(const short idcode);
+/**
+ * Check if an ID type is only appendable.
+ *
+ * \param idcode: The IDType code to check.
+ * \return Boolean, false when also linkable, true when only appendable.
+ */
bool BKE_idtype_idcode_is_only_appendable(const short idcode);
+/**
+ * Check if an ID type can try to reuse and existing matching local one when being appended again.
+ *
+ * \param idcode: The IDType code to check.
+ * \return Boolean, false when it cannot be re-used, true otherwise.
+ */
bool BKE_idtype_idcode_append_is_reusable(const short idcode);
/* Macro currently, since any linkable IDtype should be localizable. */
#define BKE_idtype_idcode_is_localizable BKE_idtype_idcode_is_linkable
+/**
+ * Convert an ID-type name into an \a idcode (ie. #ID_SCE)
+ *
+ * \param idtype_name: The ID-type's "user visible name" to convert.
+ * \return The \a idcode for the name, or 0 if invalid.
+ */
short BKE_idtype_idcode_from_name(const char *idtype_name);
+/**
+ * Convert an \a idcode into an \a idfilter (e.g. #ID_OB -> #FILTER_ID_OB).
+ */
uint64_t BKE_idtype_idcode_to_idfilter(const short idcode);
+/**
+ * Convert an \a idfilter into an \a idcode (e.g. #FILTER_ID_OB -> #ID_OB).
+ */
short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter);
+/**
+ * Convert an \a idcode into an index (e.g. #ID_OB -> #INDEX_ID_OB).
+ */
int BKE_idtype_idcode_to_index(const short idcode);
+/**
+ * Get an \a idcode from an index (e.g. #INDEX_ID_OB -> #ID_OB).
+ */
short BKE_idtype_idcode_from_index(const int index);
+/**
+ * Return an ID code and steps the index forward 1.
+ *
+ * \param index: start as 0.
+ * \return the code, 0 when all codes have been returned.
+ */
short BKE_idtype_idcode_iter_step(int *index);
/* Some helpers/wrappers around callbacks defined in #IDTypeInfo, dealing e.g. with embedded IDs.
* XXX Ideally those would rather belong to #BKE_lib_id, but using callback function pointers makes
* this hard to do properly if we want to avoid headers includes in headers. */
+/**
+ * Wrapper around #IDTypeInfo foreach_cache that also handles embedded IDs.
+ */
void BKE_idtype_id_foreach_cache(struct ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 77f1d197844..4db6da4b3ea 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -50,9 +50,16 @@ struct anim;
void BKE_image_free_packedfiles(struct Image *image);
void BKE_image_free_views(struct Image *image);
void BKE_image_free_buffers(struct Image *image);
+/**
+ * Simply free the image data from memory,
+ * on display the image can load again (except for render buffers).
+ */
void BKE_image_free_buffers_ex(struct Image *image, bool do_lock);
void BKE_image_free_gputextures(struct Image *ima);
-/* call from library */
+/**
+ * Free (or release) any data used by this image (does not free the image itself).
+ * \note Call from library.
+ */
void BKE_image_free_data(struct Image *image);
typedef void(StampCallback)(void *data, const char *propname, char *propvalue, int len);
@@ -66,6 +73,9 @@ void BKE_render_result_stamp_info(struct Scene *scene,
* The caller is responsible for freeing the allocated memory.
*/
struct StampData *BKE_stamp_info_from_scene_static(const struct Scene *scene);
+/**
+ * Check whether the given metadata field name translates to a known field of a stamp.
+ */
bool BKE_stamp_is_known_field(const char *field_name);
void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_stamp_info_from_imbuf(struct RenderResult *rr, struct ImBuf *ibuf);
@@ -90,8 +100,15 @@ int BKE_imbuf_write_stamp(struct Scene *scene,
struct ImBuf *ibuf,
const char *name,
const struct ImageFormatData *imf);
+/**
+ * \note imf->planes is ignored here, its assumed the image channels are already set.
+ */
void BKE_imbuf_write_prepare(struct ImBuf *ibuf, const struct ImageFormatData *imf);
int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, const struct ImageFormatData *imf);
+/**
+ * Same as #BKE_imbuf_write() but crappy workaround not to permanently modify _some_,
+ * values in the imbuf.
+ */
int BKE_imbuf_write_as(struct ImBuf *ibuf,
const char *name,
struct ImageFormatData *imf,
@@ -125,11 +142,18 @@ bool BKE_imtype_requires_linear_float(const char imtype);
char BKE_imtype_valid_channels(const char imtype, bool write_file);
char BKE_imtype_valid_depths(const char imtype);
+/**
+ * String is from command line `--render-format` argument,
+ * keep in sync with `creator_args.c` help info.
+ */
char BKE_imtype_from_arg(const char *arg);
void BKE_imformat_defaults(struct ImageFormatData *im_format);
void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const struct ImBuf *imbuf);
+/**
+ * Used by sequencer too.
+ */
struct anim *openanim(const char *name,
int flags,
int streamindex,
@@ -164,11 +188,18 @@ struct RenderResult;
#define IMA_CHAN_FLAG_RGB 2
#define IMA_CHAN_FLAG_ALPHA 4
-/* checks whether there's an image buffer for given image and user */
+/**
+ * Checks whether there's an image buffer for given image and user.
+ */
bool BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser);
-/* same as above, but can be used to retrieve images being rendered in
- * a thread safe way, always call both acquire and release */
+/**
+ * Return image buffer for given image and user:
+ * - will lock render result if image type is render result and lock is not NULL
+ * - will return NULL if image is NULL or image type is render or composite result and lock is NULL
+ *
+ * References the result, #BKE_image_release_ibuf should be used to de-reference.
+ */
struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock);
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock);
@@ -179,17 +210,28 @@ struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima,
struct ImagePool *pool);
void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool);
-/* set an alpha mode based on file extension */
+/**
+ * Set an alpha mode based on file extension.
+ */
char BKE_image_alpha_mode_from_extension_ex(const char *filepath);
void BKE_image_alpha_mode_from_extension(struct Image *image);
-/* returns a new image or NULL if it can't load */
+/**
+ * Returns a new image or NULL if it can't load.
+ */
struct Image *BKE_image_load(struct Main *bmain, const char *filepath);
-/* returns existing Image when filename/type is same (frame optional) */
+/**
+ * Returns existing Image when filename/type is same.
+ *
+ * Checks if image was already loaded, then returns same image otherwise creates new
+ * (does not load ibuf itself).
+ */
struct Image *BKE_image_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
struct Image *BKE_image_load_exists(struct Main *bmain, const char *filepath);
-/* adds image, adds ibuf, generates color or pattern */
+/**
+ * Adds new image block, creates ImBuf and initializes color.
+ */
struct Image *BKE_image_add_generated(struct Main *bmain,
unsigned int width,
unsigned int height,
@@ -201,10 +243,15 @@ struct Image *BKE_image_add_generated(struct Main *bmain,
const bool stereo3d,
const bool is_data,
const bool tiled);
-/* adds image from imbuf, owns imbuf */
+/**
+ * Create an image from ibuf. The reference-count of ibuf is increased,
+ * caller should take care to drop its reference by calling #IMB_freeImBuf if needed.
+ */
struct Image *BKE_image_add_from_imbuf(struct Main *bmain, struct ImBuf *ibuf, const char *name);
-/* for reload, refresh, pack */
+/**
+ * For reload, refresh, pack.
+ */
void BKE_imageuser_default(struct ImageUser *iuser);
void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser);
void BKE_image_signal(struct Main *bmain, struct Image *ima, struct ImageUser *iuser, int signal);
@@ -216,61 +263,100 @@ void BKE_image_walk_all_users(const struct Main *mainp,
struct ImageUser *iuser,
void *customdata));
-/* ensures an Image exists for viewing nodes or render */
+/**
+ * Ensures an Image exists for viewing nodes or render
+ * forces existence of 1 Image for render-output or nodes, returns Image.
+ *
+ * \param name: Only for default, when making new one.
+ */
struct Image *BKE_image_ensure_viewer(struct Main *bmain, int type, const char *name);
-/* ensures the view node cache is compatible with the scene views */
+/**
+ * Ensures the view node cache is compatible with the scene views.
+ * Reset the image cache and views when the Viewer Nodes views don't match the scene views.
+ */
void BKE_image_ensure_viewer_views(const struct RenderData *rd,
struct Image *ima,
struct ImageUser *iuser);
-/* called on frame change or before render */
+/**
+ * Called on frame change or before render.
+ */
void BKE_image_user_frame_calc(struct Image *ima, struct ImageUser *iuser, int cfra);
int BKE_image_user_frame_get(const struct ImageUser *iuser, int cfra, bool *r_is_in_range);
void BKE_image_user_file_path(struct ImageUser *iuser, struct Image *ima, char *path);
void BKE_image_editors_update_frame(const struct Main *bmain, int cfra);
-/* dependency graph update for image user users */
+/**
+ * Dependency graph update for image user users.
+ */
bool BKE_image_user_id_has_animation(struct ID *id);
void BKE_image_user_id_eval_animation(struct Depsgraph *depsgraph, struct ID *id);
-/* sets index offset for multilayer files */
+/**
+ * Sets index offset for multi-layer files and because rendered results use fake layer/passes,
+ * don't correct for wrong indices here.
+ */
struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser);
-/* sets index offset for multiview files */
+/**
+ * Sets index offset for multi-view files.
+ */
void BKE_image_multiview_index(struct Image *ima, struct ImageUser *iuser);
-/* for multilayer images as well as for render-viewer */
+/**
+ * For multi-layer images as well as for render-viewer
+ * and because rendered results use fake layer/passes, don't correct for wrong indices here.
+ */
bool BKE_image_is_multilayer(struct Image *ima);
bool BKE_image_is_multiview(struct Image *ima);
bool BKE_image_is_stereo(struct Image *ima);
struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima);
void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima);
-/* For multi-layer images as well as for single-layer. */
+/**
+ * For multi-layer images as well as for single-layer.
+ */
bool BKE_image_is_openexr(struct Image *ima);
-/* For multiple slot render, call this before render. */
+/**
+ * For multiple slot render, call this before render.
+ */
void BKE_image_backup_render(struct Scene *scene, struct Image *ima, bool free_current_slot);
-/* For single-layer OpenEXR saving */
+/**
+ * For single-layer OpenEXR saving.
+ */
bool BKE_image_save_openexr_multiview(struct Image *ima,
struct ImBuf *ibuf,
const char *filepath,
const int flags);
-/* goes over all textures that use images */
+/**
+ * Goes over all textures that use images.
+ */
void BKE_image_free_all_textures(struct Main *bmain);
-/* does one image! */
+/**
+ * Operates on one image only!
+ * \param except_frame: This is weak, only works for sequences without offset.
+ */
void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame);
-/* does all images with type MOVIE or SEQUENCE */
+/**
+ * Does all images with type MOVIE or SEQUENCE.
+ */
void BKE_image_all_free_anim_ibufs(struct Main *bmain, int cfra);
void BKE_image_free_all_gputextures(struct Main *bmain);
+/**
+ * Same as above but only free animated images.
+ */
void BKE_image_free_anim_gputextures(struct Main *bmain);
void BKE_image_free_old_gputextures(struct Main *bmain);
+/**
+ * Pack image to memory.
+ */
bool BKE_image_memorypack(struct Image *ima);
void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath);
void BKE_image_packfiles_from_mem(struct ReportList *reports,
@@ -278,22 +364,34 @@ void BKE_image_packfiles_from_mem(struct ReportList *reports,
char *data,
const size_t data_len);
-/* Prints memory statistics for images. */
+/**
+ * Prints memory statistics for images.
+ */
void BKE_image_print_memlist(struct Main *bmain);
-/* Merge source into dest, and free source. */
+/**
+ * Merge source into `dest`, and free `source`.
+ */
void BKE_image_merge(struct Main *bmain, struct Image *dest, struct Image *source);
-/* Scale the image. */
+/**
+ * Scale the image.
+ */
bool BKE_image_scale(struct Image *image, int width, int height);
-/* Check if texture has alpha (depth=32). */
+/**
+ * Check if texture has alpha (depth=32).
+ */
bool BKE_image_has_alpha(struct Image *image);
-/* Check if texture has GPU texture code. */
+/**
+ * Check if texture has GPU texture code.
+ */
bool BKE_image_has_opengl_texture(struct Image *ima);
-/* Get tile index for tiled images. */
+/**
+ * Get tile index for tiled images.
+ */
void BKE_image_get_tile_label(struct Image *ima,
struct ImageTile *tile,
char *label,
@@ -320,6 +418,9 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
const float uv[2],
float r_uv[2],
float r_ofs[2]);
+/**
+ * Return the tile_number for the closest UDIM tile.
+ */
int BKE_image_find_nearest_tile(const struct Image *image, const float co[2]);
void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *r_width, int *r_height);
@@ -327,6 +428,7 @@ void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float r
void BKE_image_get_aspect(struct Image *image, float *r_aspx, float *r_aspy);
/* image_gen.c */
+
void BKE_image_buf_fill_color(
unsigned char *rect, float *rect_float, int width, int height, const float color[4]);
void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height);
@@ -336,36 +438,64 @@ void BKE_image_buf_fill_checker_color(unsigned char *rect,
int height);
/* Cycles hookup */
+
unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, int tile);
float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int tile);
/* Image modifications */
+
bool BKE_image_is_dirty(struct Image *image);
void BKE_image_mark_dirty(struct Image *image, struct ImBuf *ibuf);
bool BKE_image_buffer_format_writable(struct ImBuf *ibuf);
+
bool BKE_image_is_dirty_writable(struct Image *image, bool *is_format_writable);
-/* Guess offset for the first frame in the sequence */
+/**
+ * Guess offset for the first frame in the sequence.
+ */
int BKE_image_sequence_guess_offset(struct Image *image);
bool BKE_image_has_anim(struct Image *image);
bool BKE_image_has_packedfile(const struct Image *image);
bool BKE_image_has_filepath(struct Image *ima);
+/**
+ * Checks the image buffer changes with time (not keyframed values).
+ */
bool BKE_image_is_animated(struct Image *image);
+/**
+ * Checks whether the image consists of multiple buffers.
+ */
bool BKE_image_has_multiple_ibufs(struct Image *image);
void BKE_image_file_format_set(struct Image *image,
int ftype,
const struct ImbFormatOptions *options);
bool BKE_image_has_loaded_ibuf(struct Image *image);
+/**
+ * References the result, #BKE_image_release_ibuf is to be called to de-reference.
+ * Use lock=NULL when calling #BKE_image_release_ibuf().
+ */
struct ImBuf *BKE_image_get_ibuf_with_name(struct Image *image, const char *name);
+/**
+ * References the result, #BKE_image_release_ibuf is to be called to de-reference.
+ * Use lock=NULL when calling #BKE_image_release_ibuf().
+ *
+ * TODO(sergey): This is actually "get first item from the cache", which is
+ * not so much predictable. But using first loaded image buffer
+ * was also malicious logic and all the areas which uses this
+ * function are to be re-considered.
+ */
struct ImBuf *BKE_image_get_first_ibuf(struct Image *image);
-/* Not to be use directly. */
+/**
+ * Not to be use directly.
+ */
struct GPUTexture *BKE_image_create_gpu_texture_from_ibuf(struct Image *image, struct ImBuf *ibuf);
-/* Get the #GPUTexture for a given `Image`.
+/**
+ * Get the #GPUTexture for a given `Image`.
*
* `iuser` and `ibuf` are mutual exclusive parameters. The caller can pass the `ibuf` when already
- * available. It is also required when requesting the #GPUTexture for a render result. */
+ * available. It is also required when requesting the #GPUTexture for a render result.
+ */
struct GPUTexture *BKE_image_get_gpu_texture(struct Image *image,
struct ImageUser *iuser,
struct ImBuf *ibuf);
@@ -375,14 +505,33 @@ struct GPUTexture *BKE_image_get_gpu_tiles(struct Image *image,
struct GPUTexture *BKE_image_get_gpu_tilemap(struct Image *image,
struct ImageUser *iuser,
struct ImBuf *ibuf);
+/**
+ * Is the alpha of the `GPUTexture` for a given image/ibuf premultiplied.
+ */
bool BKE_image_has_gpu_texture_premultiplied_alpha(struct Image *image, struct ImBuf *ibuf);
+/**
+ * Partial update of texture for texture painting.
+ * This is often much quicker than fully updating the texture for high resolution images.
+ */
void BKE_image_update_gputexture(
struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
+/**
+ * Mark areas on the #GPUTexture that needs to be updated. The areas are marked in chunks.
+ * The next time the #GPUTexture is used these tiles will be refreshes. This saves time
+ * when writing to the same place multiple times This happens for during foreground rendering.
+ */
void BKE_image_update_gputexture_delayed(
struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+/**
+ * Called on entering and exiting texture paint mode,
+ * temporary disabling/enabling mipmapping on all images for quick texture
+ * updates with glTexSubImage2D. images that didn't change don't have to be re-uploaded to OpenGL.
+ */
void BKE_image_paint_set_mipmap(struct Main *bmain, bool mipmap);
-/* Delayed free of OpenGL buffers by main thread */
+/**
+ * Delayed free of OpenGL buffers by main thread.
+ */
void BKE_image_free_unused_gpu_textures(void);
struct RenderSlot *BKE_image_add_renderslot(struct Image *ima, const char *name);
diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h
index f4871c83caf..5899db6c6ce 100644
--- a/source/blender/blenkernel/BKE_ipo.h
+++ b/source/blender/blenkernel/BKE_ipo.h
@@ -28,6 +28,19 @@ extern "C" {
struct Main;
+/**
+ * Called from #do_versions() in `readfile.c` to convert the old 'IPO/adrcode' system
+ * to the new 'Animato/RNA' system.
+ *
+ * The basic method used here, is to loop over data-blocks which have IPO-data,
+ * and add those IPO's to new AnimData blocks as Actions.
+ * Action/NLA data only works well for Objects, so these only need to be checked for there.
+ *
+ * Data that has been converted should be freed immediately, which means that it is immediately
+ * clear which data-blocks have yet to be converted, and also prevent freeing errors when we exit.
+ *
+ * \note Currently done after all file reading.
+ */
void do_versions_ipos_to_animato(struct Main *main);
/* --------------------- xxx stuff ------------------------ */
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index cb4fc607703..de069d6236f 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -36,21 +36,44 @@ struct Object;
extern "C" {
#endif
+/**
+ * Free (or release) any data used by this shapekey (does not free the key itself).
+ */
void BKE_key_free_data(struct Key *key);
void BKE_key_free_nolib(struct Key *key);
struct Key *BKE_key_add(struct Main *bmain, struct ID *id);
+/**
+ * Sort shape keys after a change.
+ * This assumes that at most one key was moved,
+ * which is a valid assumption for the places it's currently being called.
+ */
void BKE_key_sort(struct Key *key);
void key_curve_position_weights(float t, float data[4], int type);
+/**
+ * First derivative.
+ */
void key_curve_tangent_weights(float t, float data[4], int type);
+/**
+ * Second derivative.
+ */
void key_curve_normal_weights(float t, float data[4], int type);
+/**
+ * Returns key coordinates (+ tilt) when key applied, NULL otherwise.
+ */
float *BKE_key_evaluate_object_ex(struct Object *ob, int *r_totelem, float *arr, size_t arr_size);
float *BKE_key_evaluate_object(struct Object *ob, int *r_totelem);
+/**
+ * \param shape_index: The index to use or all (when -1).
+ */
int BKE_keyblock_element_count_from_shape(const struct Key *key, const int shape_index);
int BKE_keyblock_element_count(const struct Key *key);
+/**
+ * \param shape_index: The index to use or all (when -1).
+ */
size_t BKE_keyblock_element_calc_size_from_shape(const struct Key *key, const int shape_index);
size_t BKE_keyblock_element_calc_size(const struct Key *key);
@@ -60,18 +83,43 @@ struct Key **BKE_key_from_id_p(struct ID *id);
struct Key *BKE_key_from_id(struct ID *id);
struct Key **BKE_key_from_object_p(const struct Object *ob);
struct Key *BKE_key_from_object(const struct Object *ob);
+/**
+ * Only the active key-block.
+ */
struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
struct KeyBlock *BKE_keyblock_from_object_reference(struct Object *ob);
struct KeyBlock *BKE_keyblock_add(struct Key *key, const char *name);
+/**
+ * \note sorting is a problematic side effect in some cases,
+ * better only do this explicitly by having its own function,
+ *
+ * \param key: The key datablock to add to.
+ * \param name: Optional name for the new keyblock.
+ * \param do_force: always use ctime even for relative keys.
+ */
struct KeyBlock *BKE_keyblock_add_ctime(struct Key *key, const char *name, const bool do_force);
+/**
+ * Get the appropriate #KeyBlock given an index.
+ */
struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
+/**
+ * Get the appropriate #KeyBlock given a name to search for.
+ */
struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]);
+/**
+ * \brief copy shape-key attributes, but not key data or name/UID.
+ */
void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src);
+/**
+ * Get RNA-Path for 'value' setting of the given shape-key.
+ * \note the user needs to free the returned string once they're finish with it.
+ */
char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb);
/* conversion functions */
/* NOTE: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */
+
void BKE_keyblock_update_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt);
@@ -88,6 +136,15 @@ void BKE_keyblock_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct
void BKE_keyblock_update_from_mesh(struct Mesh *me, struct KeyBlock *kb);
void BKE_keyblock_convert_from_mesh(struct Mesh *me, struct Key *key, struct KeyBlock *kb);
void BKE_keyblock_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
+/**
+ * Computes normals (vertices, polygons and/or loops ones) of given mesh for given shape key.
+ *
+ * \param kb: the KeyBlock to use to compute normals.
+ * \param mesh: the Mesh to apply key-block to.
+ * \param r_vertnors: if non-NULL, an array of vectors, same length as number of vertices.
+ * \param r_polynors: if non-NULL, an array of vectors, same length as number of polygons.
+ * \param r_loopnors: if non-NULL, an array of vectors, same length as number of loops.
+ */
void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
struct Mesh *mesh,
float (*r_vertnors)[3],
@@ -107,28 +164,54 @@ void BKE_keyblock_update_from_offset(struct Object *ob,
const float (*ofs)[3]);
/* other management */
+
+/**
+ * Move shape key from org_index to new_index. Safe, clamps index to valid range,
+ * updates reference keys, the object's active shape index,
+ * the 'frame' value in case of absolute keys, etc.
+ * Note indices are expected in real values (not 'fake' shapenr +1 ones).
+ *
+ * \param org_index: if < 0, current object's active shape will be used as skey to move.
+ * \return true if something was done, else false.
+ */
bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index);
+/**
+ * Check if given key-block (as index) is used as basis by others in given key.
+ */
bool BKE_keyblock_is_basis(struct Key *key, const int index);
/* -------------------------------------------------------------------- */
/** \name Key-Block Data Access
* \{ */
+/**
+ * \param shape_index: The index to use or all (when -1).
+ */
void BKE_keyblock_data_get_from_shape(const struct Key *key,
float (*arr)[3],
const int shape_index);
void BKE_keyblock_data_get(const struct Key *key, float (*arr)[3]);
+/**
+ * Set the data to all key-blocks (or shape_index if != -1).
+ */
void BKE_keyblock_data_set_with_mat4(struct Key *key,
const int shape_index,
const float (*coords)[3],
const float mat[4][4]);
+/**
+ * Set the data for all key-blocks (or shape_index if != -1),
+ * transforming by \a mat.
+ */
void BKE_keyblock_curve_data_set_with_mat4(struct Key *key,
const struct ListBase *nurb,
const int shape_index,
const void *data,
const float mat[4][4]);
+/**
+ * Set the data for all key-blocks (or shape_index if != -1).
+ */
void BKE_keyblock_data_set(struct Key *key, const int shape_index, const void *data);
/** \} */
diff --git a/source/blender/blenkernel/BKE_keyconfig.h b/source/blender/blenkernel/BKE_keyconfig.h
index 1cacbf61976..132994ede3a 100644
--- a/source/blender/blenkernel/BKE_keyconfig.h
+++ b/source/blender/blenkernel/BKE_keyconfig.h
@@ -43,10 +43,12 @@ typedef struct wmKeyConfigPrefType_Runtime {
typedef struct wmKeyConfigPrefType_Runtime wmKeyConfigPrefType_Runtime;
#endif
-/* KeyConfig preferences (UserDef). */
+/* KeyConfig preferences (#UserDef). */
+
struct wmKeyConfigPref *BKE_keyconfig_pref_ensure(struct UserDef *userdef, const char *kc_idname);
/* KeyConfig preferences (RNA). */
+
struct wmKeyConfigPrefType_Runtime *BKE_keyconfig_pref_type_find(const char *idname, bool quiet);
void BKE_keyconfig_pref_type_add(struct wmKeyConfigPrefType_Runtime *kpt_rt);
void BKE_keyconfig_pref_type_remove(const struct wmKeyConfigPrefType_Runtime *kpt_rt);
@@ -55,6 +57,10 @@ void BKE_keyconfig_pref_type_init(void);
void BKE_keyconfig_pref_type_free(void);
/* Versioning. */
+
+/**
+ * Set select mouse, for versioning code.
+ */
void BKE_keyconfig_pref_set_select_mouse(struct UserDef *userdef, int value, bool override);
struct wmKeyConfigFilterItemParams {
@@ -67,6 +73,10 @@ void BKE_keyconfig_keymap_filter_item(struct wmKeyMap *keymap,
const struct wmKeyConfigFilterItemParams *params,
bool (*filter_fn)(struct wmKeyMapItem *kmi, void *user_data),
void *user_data);
+/**
+ * Filter & optionally remove key-map items,
+ * intended for versioning, but may be used in other situations too.
+ */
void BKE_keyconfig_pref_filter_items(struct UserDef *userdef,
const struct wmKeyConfigFilterItemParams *params,
bool (*filter_fn)(struct wmKeyMapItem *kmi, void *user_data),
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 02fa8b306d3..bf03e99bbc3 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -132,6 +132,7 @@ void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice,
const char *defgrp_name,
const float fac,
struct BMEditMesh *em_target);
+
/** \} */
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 08b44959096..b2fa464aedc 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -52,23 +52,57 @@ typedef enum eViewLayerCopyMethod {
VIEWLAYER_ADD_COPY = 2,
} eViewLayerCopyMethod;
+/**
+ * Returns the default view layer to view in work-spaces if there is
+ * none linked to the workspace yet.
+ */
struct ViewLayer *BKE_view_layer_default_view(const struct Scene *scene);
+/**
+ * Returns the default view layer to render if we need to render just one.
+ */
struct ViewLayer *BKE_view_layer_default_render(const struct Scene *scene);
+/**
+ * Returns view layer with matching name, or NULL if not found.
+ */
struct ViewLayer *BKE_view_layer_find(const struct Scene *scene, const char *layer_name);
+/**
+ * Add a new view layer by default, a view layer has the master collection.
+ */
struct ViewLayer *BKE_view_layer_add(struct Scene *scene,
const char *name,
struct ViewLayer *view_layer_source,
const int type);
/* DEPRECATED */
+/**
+ * This is a placeholder to know which areas of the code need to be addressed
+ * for the Workspace changes. Never use this, you should typically get the
+ * active layer from the context or window.
+ */
struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene);
void BKE_view_layer_free(struct ViewLayer *view_layer);
+/**
+ * Free (or release) any data used by this #ViewLayer.
+ */
void BKE_view_layer_free_ex(struct ViewLayer *view_layer, const bool do_id_user);
+/**
+ * Tag all the selected objects of a render-layer.
+ */
void BKE_view_layer_selected_objects_tag(struct ViewLayer *view_layer, const int tag);
+/**
+ * Fallback for when a Scene has no camera to use.
+ *
+ * \param view_layer: in general you want to use the same #ViewLayer that is used for depsgraph.
+ * If rendering you pass the scene active layer, when viewing in the viewport
+ * you want to get #ViewLayer from context.
+ */
struct Object *BKE_view_layer_camera_find(struct ViewLayer *view_layer);
+/**
+ * Find the #ViewLayer a #LayerCollection belongs to.
+ */
struct ViewLayer *BKE_view_layer_find_from_collection(const struct Scene *scene,
struct LayerCollection *lc);
struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob);
@@ -76,6 +110,11 @@ void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer);
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase);
+/**
+ * Only copy internal data of #ViewLayer from source to already allocated/initialized destination.
+ *
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
+ */
void BKE_view_layer_copy_data(struct Scene *scene_dst,
const struct Scene *scene_src,
struct ViewLayer *view_layer_dst,
@@ -87,15 +126,33 @@ void BKE_view_layer_rename(struct Main *bmain,
struct ViewLayer *view_layer,
const char *name);
+/**
+ * Get the active collection
+ */
struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer);
+/**
+ * Activate collection
+ */
bool BKE_layer_collection_activate(struct ViewLayer *view_layer, struct LayerCollection *lc);
+/**
+ * Activate first parent collection.
+ */
struct LayerCollection *BKE_layer_collection_activate_parent(struct ViewLayer *view_layer,
struct LayerCollection *lc);
+/**
+ * Get the total number of collections (including all the nested collections)
+ */
int BKE_layer_collection_count(const struct ViewLayer *view_layer);
+/**
+ * Get the collection for a given index.
+ */
struct LayerCollection *BKE_layer_collection_from_index(struct ViewLayer *view_layer,
const int index);
+/**
+ * \return -1 if not found.
+ */
int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct LayerCollection *lc);
void BKE_layer_collection_resync_forbid(void);
@@ -103,20 +160,43 @@ void BKE_layer_collection_resync_allow(void);
void BKE_main_collection_sync(const struct Main *bmain);
void BKE_scene_collection_sync(const struct Scene *scene);
+/**
+ * Update view layer collection tree from collections used in the scene.
+ * This is used when collections are removed or added, both while editing
+ * and on file loaded in case linked data changed or went missing.
+ */
void BKE_layer_collection_sync(const struct Scene *scene, struct ViewLayer *view_layer);
void BKE_layer_collection_local_sync(struct ViewLayer *view_layer, const struct View3D *v3d);
+/**
+ * Sync the local collection for all the 3D Viewports.
+ */
void BKE_layer_collection_local_sync_all(const struct Main *bmain);
void BKE_main_collection_sync_remap(const struct Main *bmain);
+/**
+ * Return the first matching #LayerCollection in the #ViewLayer for the Collection.
+ */
struct LayerCollection *BKE_layer_collection_first_from_scene_collection(
const struct ViewLayer *view_layer, const struct Collection *collection);
+/**
+ * See if view layer has the scene collection linked directly, or indirectly (nested).
+ */
bool BKE_view_layer_has_collection(const struct ViewLayer *view_layer,
const struct Collection *collection);
+/**
+ * See if the object is in any of the scene layers of the scene.
+ */
bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
-/* selection and hiding */
+/* Selection and hiding. */
+/**
+ * Select all the objects of this layer collection
+ *
+ * It also select the objects that are in nested collections.
+ * \note Recursive.
+ */
bool BKE_layer_collection_objects_select(struct ViewLayer *view_layer,
struct LayerCollection *lc,
bool deselect);
@@ -125,28 +205,54 @@ bool BKE_layer_collection_has_selected_objects(struct ViewLayer *view_layer,
bool BKE_layer_collection_has_layer_collection(struct LayerCollection *lc_parent,
struct LayerCollection *lc_child);
+/**
+ * Update after toggling visibility of an object base.
+ */
void BKE_base_set_visible(struct Scene *scene,
struct ViewLayer *view_layer,
struct Base *base,
bool extend);
bool BKE_base_is_visible(const struct View3D *v3d, const struct Base *base);
bool BKE_object_is_visible_in_viewport(const struct View3D *v3d, const struct Object *ob);
+/**
+ * Isolate the collection - hide all other collections but this one.
+ * Make sure to show all the direct parents and all children of the layer collection as well.
+ * When extending we simply show the collections and its direct family.
+ *
+ * If the collection or any of its parents is disabled, make it enabled.
+ * Don't change the children disable state though.
+ */
void BKE_layer_collection_isolate_global(struct Scene *scene,
struct ViewLayer *view_layer,
struct LayerCollection *lc,
bool extend);
+/**
+ * Isolate the collection locally
+ *
+ * Same as #BKE_layer_collection_isolate_local but for a viewport
+ */
void BKE_layer_collection_isolate_local(struct ViewLayer *view_layer,
const struct View3D *v3d,
struct LayerCollection *lc,
bool extend);
+/**
+ * Hide/show all the elements of a collection.
+ * Don't change the collection children enable/disable state,
+ * but it may change it for the collection itself.
+ */
void BKE_layer_collection_set_visible(struct ViewLayer *view_layer,
struct LayerCollection *lc,
const bool visible,
const bool hierarchy);
void BKE_layer_collection_set_flag(struct LayerCollection *lc, const int flag, const bool value);
-/* evaluation */
+/* Evaluation. */
+/**
+ * Applies object's restrict flags on top of flags coming from the collection
+ * and stores those in `base->flag`. #BASE_VISIBLE_DEPSGRAPH ignores viewport flags visibility
+ * (i.e., restriction and local collection).
+ */
void BKE_base_eval_flags(struct Base *base);
void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph,
@@ -380,6 +486,13 @@ struct Object **BKE_view_layer_array_selected_objects_params(
uint *r_len,
const struct ObjectsInViewLayerParams *params);
+/**
+ * Use this in rare cases we need to detect a pair of objects (active, selected).
+ * This returns the other non-active selected object.
+ *
+ * Returns NULL with it finds multiple other selected objects
+ * as behavior in this case would be random from the user perspective.
+ */
struct Object *BKE_view_layer_non_active_selected_object(struct ViewLayer *view_layer,
const struct View3D *v3d);
@@ -451,9 +564,20 @@ bool BKE_view_layer_filter_edit_mesh_has_edges(const struct Object *ob, void *us
struct ViewLayerAOV *BKE_view_layer_add_aov(struct ViewLayer *view_layer);
void BKE_view_layer_remove_aov(struct ViewLayer *view_layer, struct ViewLayerAOV *aov);
void BKE_view_layer_set_active_aov(struct ViewLayer *view_layer, struct ViewLayerAOV *aov);
+/**
+ * Update the naming and conflicts of the AOVs.
+ *
+ * Name must be unique between all AOVs.
+ * Conflicts with render passes will show a conflict icon. Reason is that switching a render
+ * engine or activating a render pass could lead to other conflicts that wouldn't be that clear
+ * for the user.
+ */
void BKE_view_layer_verify_aov(struct RenderEngine *engine,
struct Scene *scene,
struct ViewLayer *view_layer);
+/**
+ * Check if the given view layer has at least one valid AOV.
+ */
bool BKE_view_layer_has_valid_aov(struct ViewLayer *view_layer);
struct ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene,
struct ViewLayerAOV *view_layer_aov);
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index 359fb72534a..34339c4ff9f 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -62,21 +62,65 @@ struct PointerRNA;
struct PropertyRNA;
struct bContext;
+/**
+ * Get allocation size of a given data-block type and optionally allocation name.
+ */
size_t BKE_libblock_get_alloc_info(short type, const char **name);
+/**
+ * Allocates and returns memory of the right size for the specified block type,
+ * initialized to zero.
+ */
void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT;
+/**
+ * Allocates and returns a block of the specified type, with the specified name
+ * (adjusted as necessary to ensure uniqueness), and appended to the specified list.
+ * The user count is set to 1, all other content (apart from name and links) being
+ * initialized to zero.
+ */
void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag)
ATTR_WARN_UNUSED_RESULT;
+/**
+ * Initialize an ID of given type, such that it has valid 'empty' data.
+ * ID is assumed to be just calloc'ed.
+ */
void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
/* *** ID's session_uuid management. *** */
-/* When an ID's uuid is of that value, it is unset/invalid (e.g. for runtime IDs, etc.). */
+/**
+ * When an ID's uuid is of that value, it is unset/invalid (e.g. for runtime IDs, etc.).
+ */
#define MAIN_ID_SESSION_UUID_UNSET 0
+/**
+ * Generate a session-wise uuid for the given \a id.
+ *
+ * \note "session-wise" here means while editing a given .blend file. Once a new .blend file is
+ * loaded or created, undo history is cleared/reset, and so is the uuid counter.
+ */
void BKE_lib_libblock_session_uuid_ensure(struct ID *id);
+/**
+ * Re-generate a new session-wise uuid for the given \a id.
+ *
+ * \warning This has a few very specific use-cases, no other usage is expected currently:
+ * - To handle UI-related data-blocks that are kept across new file reading, when we do keep
+ * existing UI.
+ * - For IDs that are made local without needing any copying.
+ */
void BKE_lib_libblock_session_uuid_renew(struct ID *id);
+/**
+ * Generic helper to create a new empty data-block of given type in given \a bmain database.
+ *
+ * \param name: can be NULL, in which case we get default name for this ID type.
+ */
void *BKE_id_new(struct Main *bmain, const short type, const char *name);
+/**
+ * Generic helper to create a new temporary empty data-block of given type,
+ * *outside* of any Main database.
+ *
+ * \param name: can be NULL, in which case we get default name for this ID type.
+ */
void *BKE_id_new_nomain(const short type, const char *name);
/**
@@ -159,10 +203,20 @@ void BKE_libblock_copy_ex(struct Main *bmain,
const struct ID *id,
struct ID **r_newid,
const int orig_flag);
+/**
+ * Used everywhere in blenkernel.
+ */
void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Sets the name of a block to name, suitably adjusted for uniqueness.
+ */
void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
+/**
+ * Use after setting the ID's name
+ * When name exists: call 'new_id'
+ */
void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL();
struct ID *BKE_libblock_find_name(struct Main *bmain,
@@ -216,17 +270,70 @@ enum {
void BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL();
void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL();
+/**
+ * In most cases #BKE_id_free_ex handles this, when lower level functions are called directly
+ * this function will need to be called too, if Python has access to the data.
+ *
+ * ID data-blocks such as #Material.nodetree are not stored in #Main.
+ */
void BKE_libblock_free_data_py(struct ID *id);
+/**
+ * Complete ID freeing, extended version for corner cases.
+ * Can override default (and safe!) freeing process, to gain some speed up.
+ *
+ * At that point, given id is assumed to not be used by any other data-block already
+ * (might not be actually true, in case e.g. several inter-related IDs get freed together...).
+ * However, they might still be using (referencing) other IDs, this code takes care of it if
+ * #LIB_TAG_NO_USER_REFCOUNT is not defined.
+ *
+ * \param bmain: #Main database containing the freed #ID,
+ * can be NULL in case it's a temp ID outside of any #Main.
+ * \param idv: Pointer to ID to be freed.
+ * \param flag: Set of \a LIB_ID_FREE_... flags controlling/overriding usual freeing process,
+ * 0 to get default safe behavior.
+ * \param use_flag_from_idtag: Still use freeing info flags from given #ID datablock,
+ * even if some overriding ones are passed in \a flag parameter.
+ */
void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag);
+/**
+ * Complete ID freeing, should be usable in most cases (even for out-of-Main IDs).
+ *
+ * See #BKE_id_free_ex description for full details.
+ *
+ * \param bmain: Main database containing the freed ID,
+ * can be NULL in case it's a temp ID outside of any Main.
+ * \param idv: Pointer to ID to be freed.
+ */
void BKE_id_free(struct Main *bmain, void *idv);
+/**
+ * Not really a freeing function by itself,
+ * it decrements usercount of given id, and only frees it if it reaches 0.
+ */
void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
+/**
+ * Properly delete a single ID from given \a bmain database.
+ */
void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
+/**
+ * Properly delete all IDs tagged with \a LIB_TAG_DOIT, in given \a bmain database.
+ *
+ * This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
+ * (several times faster when deleting most of the IDs at once).
+ *
+ * \warning Considered experimental for now, seems to be working OK but this is
+ * risky code in a complicated area.
+ * \return Number of deleted datablocks.
+ */
size_t BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL();
+/**
+ * Add a 'NO_MAIN' data-block to given main (also sets usercounts of its IDs if needed).
+ */
void BKE_libblock_management_main_add(struct Main *bmain, void *idv);
+/** Remove a data-block from given main (set it to 'NO_MAIN' status). */
void BKE_libblock_management_main_remove(struct Main *bmain, void *idv);
void BKE_libblock_management_usercounts_set(struct Main *bmain, void *idv);
@@ -234,10 +341,23 @@ void BKE_libblock_management_usercounts_clear(struct Main *bmain, void *idv);
void id_lib_extern(struct ID *id);
void id_lib_indirect_weak_link(struct ID *id);
+/**
+ * Ensure we have a real user
+ *
+ * \note Now that we have flags, we could get rid of the 'fake_user' special case,
+ * flags are enough to ensure we always have a real user.
+ * However, #ID_REAL_USERS is used in several places outside of core lib.c,
+ * so think we can wait later to make this change.
+ */
void id_us_ensure_real(struct ID *id);
void id_us_clear_real(struct ID *id);
+/**
+ * Same as \a id_us_plus, but does not handle lib indirect -> extern.
+ * Only used by readfile.c so far, but simpler/safer to keep it here nonetheless.
+ */
void id_us_plus_no_lib(struct ID *id);
void id_us_plus(struct ID *id);
+/* decrements the user count for *id. */
void id_us_min(struct ID *id);
void id_fake_user_set(struct ID *id);
void id_fake_user_clear(struct ID *id);
@@ -262,66 +382,212 @@ enum {
LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING = 1 << 16,
};
+/**
+ * Generic 'make local' function, works for most of data-block types.
+ */
void BKE_lib_id_make_local_generic(struct Main *bmain, struct ID *id, const int flags);
+/**
+ * Calls the appropriate make_local method for the block, unless test is set.
+ *
+ * \note Always set #ID.newid pointer in case it gets duplicated.
+ *
+ * \param flags: Special flag used when making a whole library's content local,
+ * it needs specific handling.
+ * \return true is the ID has successfully been made local.
+ */
bool BKE_lib_id_make_local(struct Main *bmain, struct ID *id, const int flags);
+/**
+ * \note Does *not* set #ID.newid pointer.
+ */
bool id_single_user(struct bContext *C,
struct ID *id,
struct PointerRNA *ptr,
struct PropertyRNA *prop);
bool BKE_id_copy_is_allowed(const struct ID *id);
+/**
+ * Invokes the appropriate copy method for the block and returns the result in
+ * #ID.newid, unless test. Returns true if the block can be copied.
+ */
struct ID *BKE_id_copy(struct Main *bmain, const struct ID *id);
+/**
+ * Generic entry point for copying a data-block (new API).
+ *
+ * \note Copy is generally only affecting the given data-block
+ * (no ID used by copied one will be affected, besides user-count).
+ *
+ * There are exceptions though:
+ * - Embedded IDs (root node trees and master collections) are always copied with their owner.
+ * - If #LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated.
+ * - If #LIB_ID_COPY_SHAPEKEY is defined, shape-keys will be duplicated.
+ * - If #LIB_ID_CREATE_LOCAL is defined, root node trees will be deep-duplicated recursively.
+ *
+ * \note User-count of new copy is always set to 1.
+ *
+ * \param bmain: Main database, may be NULL only if LIB_ID_CREATE_NO_MAIN is specified.
+ * \param id: Source data-block.
+ * \param r_newid: Pointer to new (copied) ID pointer, may be NULL.
+ * Used to allow copying into already allocated memory.
+ * \param flag: Set of copy options, see `DNA_ID.h` enum for details
+ * (leave to zero for default, full copy).
+ * \return NULL when copying that ID type is not supported, the new copy otherwise.
+ */
struct ID *BKE_id_copy_ex(struct Main *bmain,
const struct ID *id,
struct ID **r_newid,
const int flag);
+/**
+ * Invokes the appropriate copy method for the block and returns the result in
+ * newid, unless test. Returns true if the block can be copied.
+ */
struct ID *BKE_id_copy_for_duplicate(struct Main *bmain,
struct ID *id,
const uint duplicate_flags,
const int copy_flags);
+/**
+ * Does a mere memory swap over the whole IDs data (including type-specific memory).
+ * \note Most internal ID data itself is not swapped (only IDProperties are).
+ *
+ * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to
+ * itself.
+ */
void BKE_lib_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
+/**
+ * Does a mere memory swap over the whole IDs data (including type-specific memory).
+ * \note All internal ID data itself is also swapped.
+ *
+ * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to
+ * itself.
+ */
void BKE_lib_id_swap_full(struct Main *bmain, struct ID *id_a, struct ID *id_b);
+/**
+ * Sort given \a id into given \a lb list, using case-insensitive comparison of the id names.
+ *
+ * \note All other IDs beside given one are assumed already properly sorted in the list.
+ *
+ * \param id_sorting_hint: Ignored if NULL. Otherwise, used to check if we can insert \a id
+ * immediately before or after that pointer. It must always be into given \a lb list.
+ */
void id_sort_by_name(struct ListBase *lb, struct ID *id, struct ID *id_sorting_hint);
+/**
+ * Expand ID usages of given id as 'extern' (and no more indirect) linked data.
+ * Used by ID copy/make_local functions.
+ */
void BKE_lib_id_expand_local(struct Main *bmain, struct ID *id, const int flags);
+/**
+ * Ensures given ID has a unique name in given listbase.
+ *
+ * Only for local IDs (linked ones already have a unique ID in their library).
+ *
+ * \param do_linked_data: if true, also ensure a unique name in case the given \a id is linked
+ * (otherwise, just ensure that it is properly sorted).
+ *
+ * \return true if a new name had to be created.
+ */
bool BKE_id_new_name_validate(struct ListBase *lb,
struct ID *id,
const char *name,
const bool do_linked_data) ATTR_NONNULL(1, 2);
+/**
+ * Pull an ID out of a library (make it local). Only call this for IDs that
+ * don't have other library users.
+ *
+ * \param flags: Same set of `LIB_ID_MAKELOCAL_` flags as passed to #BKE_lib_id_make_local.
+ */
void BKE_lib_id_clear_library_data(struct Main *bmain, struct ID *id, const int flags);
-/* Affect whole Main database. */
+/**
+ * Clear or set given tags for all ids of given type in `bmain` (runtime tags).
+ *
+ * \note Affect whole Main database.
+ */
void BKE_main_id_tag_idcode(struct Main *mainvar,
const short type,
const int tag,
const bool value);
+/**
+ * Clear or set given tags for all ids in listbase (runtime tags).
+ */
void BKE_main_id_tag_listbase(struct ListBase *lb, const int tag, const bool value);
+/**
+ * Clear or set given tags for all ids in bmain (runtime tags).
+ */
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value);
+/**
+ * Clear or set given flags for all ids in listbase (persistent flags).
+ */
void BKE_main_id_flag_listbase(struct ListBase *lb, const int flag, const bool value);
+/**
+ * Clear or set given flags for all ids in bmain (persistent flags).
+ */
void BKE_main_id_flag_all(struct Main *bmain, const int flag, const bool value);
+/**
+ * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.c`.
+ */
void BKE_main_id_newptr_and_tag_clear(struct Main *bmain);
void BKE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only);
void BKE_main_lib_objects_recalc_all(struct Main *bmain);
-/* Only for repairing files via versioning, avoid for general use. */
+/**
+ * Only for repairing files via versioning, avoid for general use.
+ */
void BKE_main_id_repair_duplicate_names_listbase(struct ListBase *lb);
#define MAX_ID_FULL_NAME (64 + 64 + 3 + 1) /* 64 is MAX_ID_NAME - 2 */
#define MAX_ID_FULL_NAME_UI (MAX_ID_FULL_NAME + 3) /* Adds 'keycode' two letters at beginning. */
+/**
+ * Generate full name of the data-block (without ID code, but with library if any).
+ *
+ * \note Result is unique to a given ID type in a given Main database.
+ *
+ * \param name: An allocated string of minimal length #MAX_ID_FULL_NAME,
+ * will be filled with generated string.
+ * \param separator_char: Character to use for separating name and library name.
+ * Can be 0 to use default (' ').
+ */
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id, char separator_char);
+/**
+ * Generate full name of the data-block (without ID code, but with library if any),
+ * with a 2 to 3 character prefix prepended indicating whether it comes from a library,
+ * is overriding, has a fake or no user, etc.
+ *
+ * \note Result is unique to a given ID type in a given Main database.
+ *
+ * \param name: An allocated string of minimal length #MAX_ID_FULL_NAME_UI,
+ * will be filled with generated string.
+ * \param separator_char: Character to use for separating name and library name.
+ * Can be 0 to use default (' ').
+ * \param r_prefix_len: The length of the prefix added.
+ */
void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI],
const struct ID *id,
const bool add_lib_hint,
char separator_char,
int *r_prefix_len);
+/**
+ * Generate a concatenation of ID name (including two-chars type code) and its lib name, if any.
+ *
+ * \return A unique allocated string key for any ID in the whole Main database.
+ */
char *BKE_id_to_unique_string_key(const struct ID *id);
+/**
+ * Make linked data-blocks local.
+ *
+ * \param bmain: Almost certainly global main.
+ * \param lib: If not NULL, only make local data-blocks from this library.
+ * \param untagged_only: If true, only make local data-blocks not tagged with
+ * #LIB_TAG_PRE_EXISTING.
+ * \param set_fake: If true, set fake user on all localized data-blocks
+ * (except group and objects ones).
+ */
void BKE_library_make_local(struct Main *bmain,
const struct Library *lib,
struct GHash *old_to_new_ids,
@@ -331,11 +597,22 @@ void BKE_library_make_local(struct Main *bmain,
void BKE_id_tag_set_atomic(struct ID *id, int tag);
void BKE_id_tag_clear_atomic(struct ID *id, int tag);
+/**
+ * Check that given ID pointer actually is in G_MAIN.
+ * Main intended use is for debug asserts in places we cannot easily get rid of #G_Main.
+ */
bool BKE_id_is_in_global_main(struct ID *id);
bool BKE_id_can_be_asset(const struct ID *id);
+/**
+ * Returns ordered list of data-blocks for display in the UI.
+ * Result is list of #LinkData of IDs that must be freed.
+ */
void BKE_id_ordered_list(struct ListBase *ordered_lb, const struct ListBase *lb);
+/**
+ * Reorder ID in the list, before or after the "relative" ID.
+ */
void BKE_id_reorder(const struct ListBase *lb, struct ID *id, struct ID *relative, bool after);
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id);
@@ -343,6 +620,12 @@ void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id);
#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->tag & LIB_TAG_DOIT))
/* lib_id_eval.c */
+
+/**
+ * Copy relatives parameters, from `id` to `id_cow`.
+ * Use handle the #ID_RECALC_PARAMETERS tag.
+ * \note Keep in sync with #ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW.
+ */
void BKE_id_eval_properties_copy(struct ID *id_cow, struct ID *id);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index b94a1b33606..1c30db7a714 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -57,35 +57,117 @@ struct ReportList;
struct Scene;
struct ViewLayer;
+/**
+ * Initialize empty overriding of \a reference_id by \a local_id.
+ */
struct IDOverrideLibrary *BKE_lib_override_library_init(struct ID *local_id,
struct ID *reference_id);
+/**
+ * Shallow or deep copy of a whole override from \a src_id to \a dst_id.
+ */
void BKE_lib_override_library_copy(struct ID *dst_id,
const struct ID *src_id,
const bool do_full_copy);
+/**
+ * Clear any overriding data from given \a override.
+ */
void BKE_lib_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user);
+/**
+ * Free given \a override.
+ */
void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user);
+/**
+ * Check if given ID has some override rules that actually indicate the user edited it.
+ */
bool BKE_lib_override_library_is_user_edited(struct ID *id);
+/**
+ * Create an overridden local copy of linked reference.
+ */
struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
struct ID *reference_id,
const bool do_tagged_remap);
+/**
+ * Create overridden local copies of all tagged data-blocks in given Main.
+ *
+ * \note Set `id->newid` of overridden libs with newly created overrides,
+ * caller is responsible to clean those pointers before/after usage as needed.
+ *
+ * \note By default, it will only remap newly created local overriding data-blocks between
+ * themselves, to avoid 'enforcing' those overrides into all other usages of the linked data in
+ * main. You can add more local IDs to be remapped to use new overriding ones by setting their
+ * LIB_TAG_DOIT tag.
+ *
+ * \param reference_library: the library from which the linked data being overridden come from
+ * (i.e. the library of the linked reference ID).
+ *
+ * \param do_no_main: Create the new override data outside of Main database.
+ * Used for resyncing of linked overrides.
+ *
+ * \return \a true on success, \a false otherwise.
+ */
bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
const struct Library *reference_library,
const bool do_no_main);
+/**
+ * Advanced 'smart' function to create fully functional overrides.
+ *
+ * \note Currently it only does special things if given \a id_root is an object or collection, more
+ * specific behaviors may be added in the future for other ID types.
+ *
+ * \note It will override all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at
+ * its beginning, so caller code can add extra data-blocks to be overridden as well.
+ *
+ * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
+ * which case \a scene's master collection children hierarchy is used instead).
+ * \param id_root: The root ID to create an override from.
+ * \param id_reference: Some reference ID used to do some post-processing after overrides have been
+ * created, may be NULL. Typically, the Empty object instantiating the linked collection we
+ * override, currently.
+ * \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
+ * \return true if override was successfully created.
+ */
bool BKE_lib_override_library_create(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
struct ID *id_root,
struct ID *id_reference,
struct ID **r_id_root_override);
+/**
+ * Create a library override template.
+ */
bool BKE_lib_override_library_template_create(struct ID *id);
+/**
+ * Convert a given proxy object into a library override.
+ *
+ * \note This is a thin wrapper around \a BKE_lib_override_library_create, only extra work is to
+ * actually convert the proxy itself into an override first.
+ *
+ * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
+ * which case \a scene's master collection children hierarchy is used instead).
+ * \return true if override was successfully created.
+ */
bool BKE_lib_override_library_proxy_convert(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
struct Object *ob_proxy);
+/**
+ * Convert all proxy objects into library overrides.
+ *
+ * \note Only affects local proxies, linked ones are not affected.
+ */
void BKE_lib_override_library_main_proxy_convert(struct Main *bmain,
struct BlendFileReadReport *reports);
+/**
+ * Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked
+ * data, from an existing override hierarchy.
+ *
+ * \param id_root: The root liboverride ID to resync from.
+ * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
+ * which case \a scene's master collection children hierarchy is used instead).
+ * \return true if override was successfully resynced.
+ */
bool BKE_lib_override_library_resync(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
@@ -94,26 +176,76 @@ bool BKE_lib_override_library_resync(struct Main *bmain,
const bool do_hierarchy_enforce,
const bool do_post_process,
struct BlendFileReadReport *reports);
+/**
+ * Detect and handle required resync of overrides data, when relations between reference linked IDs
+ * have changed.
+ *
+ * This is a fairly complex and costly operation, typically it should be called after
+ * #BKE_lib_override_library_main_update, which would already detect and tag a lot of cases.
+ *
+ * This function will first detect the remaining cases requiring a resync (namely, either when an
+ * existing linked ID that did not require to be overridden before now would be, or when new IDs
+ * are added to the hierarchy).
+ *
+ * Then it will handle the resync of necessary IDs (through calls to
+ * #BKE_lib_override_library_resync).
+ *
+ * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
+ * which case \a scene's master collection children hierarchy is used instead).
+ */
void BKE_lib_override_library_main_resync(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
struct BlendFileReadReport *reports);
+/**
+ * Advanced 'smart' function to delete library overrides (including their existing override
+ * hierarchy) and remap their usages to their linked reference IDs.
+ *
+ * \note All IDs tagged with #LIB_TAG_DOIT will be deleted.
+ *
+ * \param id_root: The root liboverride ID to delete.
+ */
void BKE_lib_override_library_delete(struct Main *bmain, struct ID *id_root);
+/**
+ * Make given ID fully local.
+ *
+ * \note Only differs from lower-level #BKE_lib_override_library_free in infamous embedded ID
+ * cases.
+ */
void BKE_lib_override_library_make_local(struct ID *id);
+/**
+ * Find override property from given RNA path, if it exists.
+ */
struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find(
struct IDOverrideLibrary *override, const char *rna_path);
+/**
+ * Find override property from given RNA path, or create it if it does not exist.
+ */
struct IDOverrideLibraryProperty *BKE_lib_override_library_property_get(
struct IDOverrideLibrary *override, const char *rna_path, bool *r_created);
+/**
+ * Remove and free given \a override_property from given ID \a override.
+ */
void BKE_lib_override_library_property_delete(struct IDOverrideLibrary *override,
struct IDOverrideLibraryProperty *override_property);
+/**
+ * Get the RNA-property matching the \a library_prop override property. Used for UI to query
+ * additional data about the overridden property (e.g. UI name).
+ *
+ * \param idpoin: Pointer to the override ID.
+ * \param library_prop: The library override property to find the matching RNA property for.
+ */
bool BKE_lib_override_rna_property_find(struct PointerRNA *idpoin,
const struct IDOverrideLibraryProperty *library_prop,
struct PointerRNA *r_override_poin,
struct PropertyRNA **r_override_prop);
+/**
+ * Find override property operation from given sub-item(s), if it exists.
+ */
struct IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_find(
struct IDOverrideLibraryProperty *override_property,
const char *subitem_refname,
@@ -122,6 +254,9 @@ struct IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_ope
const int subitem_locindex,
const bool strict,
bool *r_strict);
+/**
+ * Find override property operation from given sub-item(s), or create it if it does not exist.
+ */
struct IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_get(
struct IDOverrideLibraryProperty *override_property,
const short operation,
@@ -132,10 +267,16 @@ struct IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_ope
const bool strict,
bool *r_strict,
bool *r_created);
+/**
+ * Remove and free given \a override_property_operation from given ID \a override_property.
+ */
void BKE_lib_override_library_property_operation_delete(
struct IDOverrideLibraryProperty *override_property,
struct IDOverrideLibraryPropertyOperation *override_property_operation);
+/**
+ * Validate that required data for a given operation are available.
+ */
bool BKE_lib_override_library_property_operation_operands_validate(
struct IDOverrideLibraryPropertyOperation *override_property_operation,
struct PointerRNA *ptr_dst,
@@ -145,34 +286,107 @@ bool BKE_lib_override_library_property_operation_operands_validate(
struct PropertyRNA *prop_src,
struct PropertyRNA *prop_storage);
+/**
+ * Check against potential \a bmain.
+ */
void BKE_lib_override_library_validate(struct Main *bmain,
struct ID *id,
struct ReportList *reports);
+/**
+ * Check against potential \a bmain.
+ */
void BKE_lib_override_library_main_validate(struct Main *bmain, struct ReportList *reports);
+/**
+ * Check that status of local data-block is still valid against current reference one.
+ *
+ * It means that all overridable, but not overridden, properties' local values must be equal to
+ * reference ones. Clears #LIB_TAG_OVERRIDE_OK if they do not.
+ *
+ * This is typically used to detect whether some property has been changed in local and a new
+ * #IDOverrideProperty (of #IDOverridePropertyOperation) has to be added.
+ *
+ * \return true if status is OK, false otherwise. */
bool BKE_lib_override_library_status_check_local(struct Main *bmain, struct ID *local);
+/**
+ * Check that status of reference data-block is still valid against current local one.
+ *
+ * It means that all non-overridden properties' local values must be equal to reference ones.
+ * Clears LIB_TAG_OVERRIDE_OK if they do not.
+ *
+ * This is typically used to detect whether some reference has changed and local
+ * needs to be updated against it.
+ *
+ * \return true if status is OK, false otherwise. */
bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct ID *local);
+/**
+ * Compare local and reference data-blocks and create new override operations as needed,
+ * or reset to reference values if overriding is not allowed.
+ *
+ * \note Defining override operations is only mandatory before saving a `.blend` file on disk
+ * (not for undo!).
+ * Knowing that info at runtime is only useful for UI/UX feedback.
+ *
+ * \note This is by far the biggest operation (the more time-consuming) of the three so far,
+ * since it has to go over all properties in depth (all overridable ones at least).
+ * Generating differential values and applying overrides are much cheaper.
+ *
+ * \return true if any library operation was created.
+ */
bool BKE_lib_override_library_operations_create(struct Main *bmain, struct ID *local);
+/**
+ * Check all overrides from given \a bmain and create/update overriding operations as needed.
+ */
bool BKE_lib_override_library_main_operations_create(struct Main *bmain, const bool force_auto);
+/**
+ * Reset all overrides in given \a id_root, while preserving ID relations.
+ */
void BKE_lib_override_library_id_reset(struct Main *bmain, struct ID *id_root);
+/**
+ * Reset all overrides in given \a id_root and its dependencies, while preserving ID relations.
+ */
void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, struct ID *id_root);
+/**
+ * Set or clear given tag in all operations in that override property data.
+ */
void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property,
const short tag,
const bool do_set);
+/**
+ * Set or clear given tag in all properties and operations in that override data.
+ */
void BKE_lib_override_library_properties_tag(struct IDOverrideLibrary *override,
const short tag,
const bool do_set);
+/**
+ * Set or clear given tag in all properties and operations in that Main's ID override data.
+ */
void BKE_lib_override_library_main_tag(struct Main *bmain, const short tag, const bool do_set);
+/**
+ * Remove all tagged-as-unused properties and operations from that ID override data.
+ */
void BKE_lib_override_library_id_unused_cleanup(struct ID *local);
+/**
+ * Remove all tagged-as-unused properties and operations from that Main's ID override data.
+ */
void BKE_lib_override_library_main_unused_cleanup(struct Main *bmain);
+/**
+ * Update given override from its reference (re-applying overridden properties).
+ */
void BKE_lib_override_library_update(struct Main *bmain, struct ID *local);
+/**
+ * Update all overrides from given \a bmain.
+ */
void BKE_lib_override_library_main_update(struct Main *bmain);
+/**
+ * In case an ID is used by another liboverride ID, user may not be allowed to delete it.
+ */
bool BKE_lib_override_library_id_is_user_deletable(struct Main *bmain, struct ID *id);
/* Storage (.blend file writing) part. */
@@ -180,9 +394,22 @@ bool BKE_lib_override_library_id_is_user_deletable(struct Main *bmain, struct ID
/* For now, we just use a temp main list. */
typedef struct Main OverrideLibraryStorage;
+/**
+ * Initialize an override storage.
+ */
OverrideLibraryStorage *BKE_lib_override_library_operations_store_init(void);
+/**
+ * Generate suitable 'write' data (this only affects differential override operations).
+ *
+ * Note that \a local ID is no more modified by this call,
+ * all extra data are stored in its temp \a storage_id copy.
+ */
struct ID *BKE_lib_override_library_operations_store_start(
struct Main *bmain, OverrideLibraryStorage *override_storage, struct ID *local);
+/**
+ * Restore given ID modified by #BKE_lib_override_library_operations_store_start, to its
+ * original state.
+ */
void BKE_lib_override_library_operations_store_end(OverrideLibraryStorage *override_storage,
struct ID *local);
void BKE_lib_override_library_operations_store_finalize(OverrideLibraryStorage *override_storage);
diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h
index 30c742e3af6..91f72cc0762 100644
--- a/source/blender/blenkernel/BKE_lib_query.h
+++ b/source/blender/blenkernel/BKE_lib_query.h
@@ -143,6 +143,10 @@ enum {
typedef struct LibraryForeachIDData LibraryForeachIDData;
+/**
+ * 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(struct LibraryForeachIDData *data);
void BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data,
struct ID **id_pp,
@@ -181,25 +185,77 @@ int BKE_lib_query_foreachid_process_callback_flag_override(struct LibraryForeach
} \
((void)0)
+/**
+ * Process embedded ID pointers (root node-trees, 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(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. */
+/**
+ * Loop over all of the ID's this data-block links to.
+ */
void BKE_library_foreach_ID_link(
struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
+/**
+ * Re-usable function, use when replacing ID's.
+ */
void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cb_flag);
+/**
+ * Return the number of times given \a id_user uses/references \a id_used.
+ *
+ * \note This only checks for pointer references of an ID, shallow usages
+ * (like e.g. by RNA paths, as done for FCurves) are not detected at all.
+ *
+ * \param id_user: the ID which is supposed to use (reference) \a id_used.
+ * \param id_used: the ID which is supposed to be used (referenced) by \a id_user.
+ * \return the number of direct usages/references of \a id_used by \a id_user.
+ */
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
+/**
+ * Say whether given \a id_owner may use (in any way) a data-block of \a id_type_used.
+ *
+ * This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above,
+ * quite useful to reduce useless iterations in some cases.
+ */
bool BKE_library_id_can_use_idtype(struct ID *id_owner, const short id_type_used);
+/**
+ * Check whether given ID is used locally (i.e. by another non-linked ID).
+ */
bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv);
+/**
+ * Check whether given ID is used indirectly (i.e. by another linked ID).
+ */
bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
+/**
+ * Combine #BKE_library_ID_is_locally_used() and #BKE_library_ID_is_indirectly_used()
+ * in a single call.
+ */
void BKE_library_ID_test_usages(struct Main *bmain,
void *idv,
bool *is_used_local,
bool *is_used_linked);
+/**
+ * Tag all unused IDs (a.k.a 'orphaned').
+ *
+ * By default only tag IDs with `0` user count.
+ * If `do_tag_recursive` is set, it will check dependencies to detect all IDs that are not actually
+ * used in current file, including 'archipelagos` (i.e. set of IDs referencing each other in
+ * loops, but without any 'external' valid usages.
+ *
+ * Valid usages here are defined as ref-counting usages, which are not towards embedded or
+ * loop-back data.
+ *
+ * \param r_num_tagged: If non-NULL, must be a zero-initialized array of #INDEX_ID_MAX integers.
+ * Number of tagged-as-unused IDs is then set for each type, and as total in
+ * #INDEX_ID_NULL item.
+ */
void BKE_lib_query_unused_ids_tag(struct Main *bmain,
const int tag,
const bool do_local_ids,
@@ -207,7 +263,24 @@ void BKE_lib_query_unused_ids_tag(struct Main *bmain,
const bool do_tag_recursive,
int *r_num_tagged);
+/**
+ * Detect orphaned linked data blocks (i.e. linked data not used (directly or indirectly)
+ * in any way by any local data), including complex cases like 'linked archipelagoes', i.e.
+ * linked data-blocks that use each other in loops,
+ * which prevents their deletion by 'basic' usage checks.
+ *
+ * \param do_init_tag: if \a true, all linked data are checked, if \a false,
+ * only linked data-blocks already tagged with #LIB_TAG_DOIT are checked.
+ */
void BKE_library_unused_linked_data_set_tag(struct Main *bmain, const bool do_init_tag);
+/**
+ * Untag linked data blocks used by other untagged linked data-blocks.
+ * Used to detect data-blocks that we can forcefully make local
+ * (instead of copying them to later get rid of original):
+ * All data-blocks we want to make local are tagged by caller,
+ * after this function has ran caller knows data-blocks still tagged can directly be made local,
+ * since they are only used by other data-blocks that will also be made fully local.
+ */
void BKE_library_indirectly_used_data_tag_clear(struct Main *bmain);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index 5e154459a6c..9c8caa0266b 100644
--- a/source/blender/blenkernel/BKE_lib_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -97,8 +97,13 @@ enum {
ID_REMAP_FORCE_OBDATA_IN_EDITMODE = 1 << 9,
};
-/* NOTE: Requiring new_id to be non-null, this *may* not be the case ultimately,
- * but makes things simpler for now. */
+/**
+ * Replace all references in given Main to \a old_id by \a new_id
+ * (if \a new_id is NULL, it unlinks \a old_id).
+ *
+ * \note Requiring new_id to be non-null, this *may* not be the case ultimately,
+ * but makes things simpler for now.
+ */
void BKE_libblock_remap_locked(struct Main *bmain,
void *old_idv,
void *new_idv,
@@ -106,17 +111,39 @@ void BKE_libblock_remap_locked(struct Main *bmain,
void BKE_libblock_remap(struct Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
ATTR_NONNULL(1, 2);
+/**
+ * Unlink given \a id from given \a bmain
+ * (does not touch to indirect, i.e. library, usages of the ID).
+ *
+ * \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by
+ * #LIB_TAG_DOIT flag (quite obviously, 'non-NULL' usages can never be unlinked by this function).
+ */
void BKE_libblock_unlink(struct Main *bmain,
void *idv,
const bool do_flag_never_null,
const bool do_skip_indirect) ATTR_NONNULL();
+/**
+ * Similar to libblock_remap, but only affects IDs used by given \a idv ID.
+ *
+ * \param old_idv: Unlike BKE_libblock_remap, can be NULL,
+ * in which case all ID usages by given \a idv will be cleared.
+ */
void BKE_libblock_relink_ex(struct Main *bmain,
void *idv,
void *old_idv,
void *new_idv,
const short remap_flags) ATTR_NONNULL(1, 2);
+/**
+ * Remaps ID usages of given ID to their `id->newid` pointer if not None, and proceeds recursively
+ * in the dependency tree of IDs for all data-blocks tagged with `LIB_TAG_NEW`.
+ *
+ * \note `LIB_TAG_NEW` is cleared.
+ *
+ * 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(struct Main *bmain, struct ID *id, const int remap_flag)
ATTR_NONNULL();
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index 1236a96c8d9..eb17ff78688 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -80,6 +80,10 @@ int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle,
int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle,
LineStyleModifier *modifier);
+/**
+ * Reinsert \a modifier in modifier list with an offset of \a direction.
+ * \return if position of \a modifier has changed.
+ */
bool BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle,
LineStyleModifier *modifier,
int direction);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 9ded97e0003..41ef5e3f5ba 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -116,12 +116,14 @@ enum {
typedef struct Main {
struct Main *next, *prev;
- char name[1024]; /* 1024 = FILE_MAX */
+ /** The file-path of this blend file, an empty string indicates an unsaved file. */
+ char filepath[1024]; /* 1024 = FILE_MAX */
short versionfile, subversionfile; /* see BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION */
short minversionfile, minsubversionfile;
uint64_t build_commit_timestamp; /* commit's timestamp from buildinfo */
char build_hash[16]; /* hash from buildinfo */
- char recovered; /* indicate the main->name (file) is the recovered one */
+ /** Indicate the #Main.filepath (file) is the recovered one. */
+ char recovered;
/** All current ID's exist in the last memfile undo step. */
char is_memfile_undo_written;
/**
@@ -201,40 +203,99 @@ typedef struct Main {
struct Main *BKE_main_new(void);
void BKE_main_free(struct Main *mainvar);
+/**
+ * Check whether given `bmain` is empty or contains some IDs.
+ */
bool BKE_main_is_empty(struct Main *bmain);
void BKE_main_lock(struct Main *bmain);
void BKE_main_unlock(struct Main *bmain);
+/** Generate the mappings between used IDs and their users, and vice-versa. */
void BKE_main_relations_create(struct Main *bmain, const short flag);
void BKE_main_relations_free(struct Main *bmain);
+/** Set or clear given `tag` in all relation entries of given `bmain`. */
void BKE_main_relations_tag_set(struct Main *bmain,
const eMainIDRelationsEntryTags tag,
const bool value);
+/**
+ * Create a #GSet storing all IDs present in given \a bmain, by their pointers.
+ *
+ * \param gset: If not NULL, given GSet will be extended with IDs from given \a bmain,
+ * instead of creating a new one.
+ */
struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
-/*
- * Temporary runtime API to allow re-using local (already appended) IDs instead of appending a new
- * copy again.
- */
+/* Temporary runtime API to allow re-using local (already appended)
+ * IDs instead of appending a new copy again. */
+/**
+ * Generate a mapping between 'library path' of an ID
+ * (as a pair (relative blend file path, id name)), and a current local ID, if any.
+ *
+ * This uses the information stored in `ID.library_weak_reference`.
+ */
struct GHash *BKE_main_library_weak_reference_create(struct Main *bmain) ATTR_NONNULL();
+/**
+ * Destroy the data generated by #BKE_main_library_weak_reference_create.
+ */
void BKE_main_library_weak_reference_destroy(struct GHash *library_weak_reference_mapping)
ATTR_NONNULL();
+/**
+ * Search for a local ID matching the given linked ID reference.
+ *
+ * \param library_weak_reference_mapping: the mapping data generated by
+ * #BKE_main_library_weak_reference_create.
+ * \param library_filepath: the path of a blend file library (relative to current working one).
+ * \param library_id_name: the full ID name, including the leading two chars encoding the ID
+ * type.
+ */
struct ID *BKE_main_library_weak_reference_search_item(
struct GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name) ATTR_NONNULL();
+/**
+ * Add the given ID weak library reference to given local ID and the runtime mapping.
+ *
+ * \param library_weak_reference_mapping: the mapping data generated by
+ * #BKE_main_library_weak_reference_create.
+ * \param library_filepath: the path of a blend file library (relative to current working one).
+ * \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
+ * \param new_id: New local ID matching given weak reference.
+ */
void BKE_main_library_weak_reference_add_item(struct GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
struct ID *new_id) ATTR_NONNULL();
+/**
+ * Update the status of the given ID weak library reference in current local IDs and the runtime
+ * mapping.
+ *
+ * This effectively transfers the 'ownership' of the given weak reference from `old_id` to
+ * `new_id`.
+ *
+ * \param library_weak_reference_mapping: the mapping data generated by
+ * #BKE_main_library_weak_reference_create.
+ * \param library_filepath: the path of a blend file library (relative to current working one).
+ * \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
+ * \param old_id: Existing local ID matching given weak reference.
+ * \param new_id: New local ID matching given weak reference.
+ */
void BKE_main_library_weak_reference_update_item(struct GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
struct ID *old_id,
struct ID *new_id) ATTR_NONNULL();
+/**
+ * Remove the given ID weak library reference from the given local ID and the runtime mapping.
+ *
+ * \param library_weak_reference_mapping: the mapping data generated by
+ * #BKE_main_library_weak_reference_create.
+ * \param library_filepath: the path of a blend file library (relative to current working one).
+ * \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
+ * \param old_id: Existing local ID matching given weak reference.
+ */
void BKE_main_library_weak_reference_remove_item(struct GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
@@ -286,16 +347,57 @@ void BKE_main_library_weak_reference_remove_item(struct GHash *library_weak_refe
} \
((void)0)
+/**
+ * Generates a raw .blend file thumbnail data from given image.
+ *
+ * \param bmain: If not NULL, also store generated data in this Main.
+ * \param img: ImBuf image to generate thumbnail data from.
+ * \return The generated .blend file raw thumbnail data.
+ */
struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img);
+/**
+ * Generates an image from raw .blend file thumbnail \a data.
+ *
+ * \param bmain: Use this bmain->blen_thumb data if given \a data is NULL.
+ * \param data: Raw .blend file thumbnail data.
+ * \return An ImBuf from given data, or NULL if invalid.
+ */
struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data);
+/**
+ * Generates an empty (black) thumbnail for given Main.
+ */
void BKE_main_thumbnail_create(struct Main *bmain);
+/**
+ * Return file-path of given \a main.
+ */
const char *BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL();
+/**
+ * Return file-path of global main #G_MAIN.
+ *
+ * \warning Usage is not recommended,
+ * you should always try to get a valid Main pointer from context.
+ */
const char *BKE_main_blendfile_path_from_global(void);
+/**
+ * \return A pointer to the \a ListBase of given \a bmain for requested \a type ID type.
+ */
struct ListBase *which_libbase(struct Main *bmain, short type);
//#define INDEX_ID_MAX 41
+/**
+ * Put the pointers to all the #ListBase structs in given `bmain` into the `*lb[INDEX_ID_MAX]`
+ * array, and return the number of those for convenience.
+ *
+ * This is useful for generic traversal of all the blocks in a #Main (by traversing all the lists
+ * in turn), without worrying about block types.
+ *
+ * \param lb: Array of lists #INDEX_ID_MAX in length.
+ *
+ * \note The order of each ID type #ListBase in the array is determined by the `INDEX_ID_<IDTYPE>`
+ * enum definitions in `DNA_ID.h`. See also the #FOREACH_MAIN_ID_BEGIN macro in `BKE_main.h`
+ */
int set_listbasepointers(struct Main *main, struct ListBase *lb[]);
#define MAIN_VERSION_ATLEAST(main, ver, subver) \
diff --git a/source/blender/blenkernel/BKE_main_idmap.h b/source/blender/blenkernel/BKE_main_idmap.h
index ff69883f0fb..13ddcaa93ba 100644
--- a/source/blender/blenkernel/BKE_main_idmap.h
+++ b/source/blender/blenkernel/BKE_main_idmap.h
@@ -44,6 +44,17 @@ enum {
MAIN_IDMAP_TYPE_UUID = 1 << 1,
};
+/**
+ * Generate mapping from ID type/name to ID pointer for given \a bmain.
+ *
+ * \note When used during undo/redo, there is no guaranty that ID pointers from UI area are not
+ * pointing to freed memory (when some IDs have been deleted). To avoid crashes in those cases, one
+ * can provide the 'old' (aka current) Main database as reference. #BKE_main_idmap_lookup_id will
+ * then check that given ID does exist in \a old_bmain before trying to use it.
+ *
+ * \param create_valid_ids_set: If \a true, generate a reference to prevent freed memory accesses.
+ * \param old_bmain: If not NULL, its IDs will be added the valid references set.
+ */
struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
const bool create_valid_ids_set,
struct Main *old_bmain,
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 8e2f6e6f10c..2a2b080217c 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -56,16 +56,20 @@ typedef enum {
MASK_HANDLE_MODE_INDIVIDUAL_HANDLES = 2,
} eMaskhandleMode;
-struct MaskSplinePoint *BKE_mask_spline_point_array(struct MaskSpline *spline);
-struct MaskSplinePoint *BKE_mask_spline_point_array_from_point(
- struct MaskSpline *spline, const struct MaskSplinePoint *point_ref);
+/* -------------------------------------------------------------------- */
+/** \name Mask Layers
+ * \{ */
-/* mask layers */
struct MaskLayer *BKE_mask_layer_new(struct Mask *mask, const char *name);
+/**
+ * \note The returned mask-layer may be hidden, caller needs to check.
+ */
struct MaskLayer *BKE_mask_layer_active(struct Mask *mask);
void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay);
void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay);
+/** \brief Free all animation keys for a mask layer.
+ */
void BKE_mask_layer_free_shapes(struct MaskLayer *masklay);
void BKE_mask_layer_free(struct MaskLayer *masklay);
void BKE_mask_layer_free_list(struct ListBase *masklayers);
@@ -83,7 +87,16 @@ void BKE_mask_layer_rename(struct Mask *mask,
struct MaskLayer *BKE_mask_layer_copy(const struct MaskLayer *masklay);
void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, const struct ListBase *masklayers);
-/* splines */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Splines
+ * \{ */
+
+struct MaskSplinePoint *BKE_mask_spline_point_array(struct MaskSpline *spline);
+struct MaskSplinePoint *BKE_mask_spline_point_array_from_point(
+ struct MaskSpline *spline, const struct MaskSplinePoint *point_ref);
+
struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay);
bool BKE_mask_spline_remove(struct MaskLayer *mask_layer, struct MaskSpline *spline);
void BKE_mask_point_direction_switch(struct MaskSplinePoint *point);
@@ -104,7 +117,12 @@ float BKE_mask_spline_project_co(struct MaskSpline *spline,
const float co[2],
const eMaskSign sign);
-/* point */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Point
+ * \{ */
+
eMaskhandleMode BKE_mask_point_handles_mode_get(const struct MaskSplinePoint *point);
void BKE_mask_point_handle(const struct MaskSplinePoint *point,
eMaskWhichHandle which_handle,
@@ -139,7 +157,12 @@ void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point,
const eMaskWhichHandle which_handle,
const bool do_select);
-/* general */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General
+ * \{ */
+
struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]);
@@ -151,6 +174,9 @@ void BKE_mask_coord_from_image(struct Image *image,
struct ImageUser *iuser,
float r_co[2],
const float co[2]);
+/**
+ * Inverse of #BKE_mask_coord_from_image.
+ */
void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame_size[2]);
void BKE_mask_coord_to_movieclip(struct MovieClip *clip,
struct MovieClipUser *user,
@@ -161,7 +187,11 @@ void BKE_mask_coord_to_image(struct Image *image,
float r_co[2],
const float co[2]);
-/* parenting */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Parenting
+ * \{ */
void BKE_mask_evaluate(struct Mask *mask, const float ctime, const bool do_newframe);
void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const bool do_newframe);
@@ -169,10 +199,19 @@ void BKE_mask_parent_init(struct MaskParent *parent);
void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline,
struct MaskSplinePoint *point,
const float u);
+/**
+ * Calculates the tangent of a point by its previous and next
+ * (ignoring handles - as if its a poly line).
+ */
void BKE_mask_calc_tangent_polyline(struct MaskSpline *spline,
struct MaskSplinePoint *point,
float t[2]);
void BKE_mask_calc_handle_point(struct MaskSpline *spline, struct MaskSplinePoint *point);
+/**
+ * \brief Resets auto handles even for non-auto bezier points
+ *
+ * Useful for giving sane defaults.
+ */
void BKE_mask_calc_handle_point_auto(struct MaskSpline *spline,
struct MaskSplinePoint *point,
const bool do_recalc_length);
@@ -186,20 +225,40 @@ void BKE_mask_point_parent_matrix_get(struct MaskSplinePoint *point,
float ctime,
float parent_matrix[3][3]);
-/* animation */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Animation
+ * \{ */
+
int BKE_mask_layer_shape_totvert(struct MaskLayer *masklay);
+/**
+ * Inverse of #BKE_mask_layer_shape_to_mask
+ */
void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay,
struct MaskLayerShape *masklay_shape);
+/**
+ * Inverse of #BKE_mask_layer_shape_from_mask
+ */
void BKE_mask_layer_shape_to_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape);
+/**
+ * \note Linear interpolation only.
+ */
void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay,
struct MaskLayerShape *masklay_shape_a,
struct MaskLayerShape *masklay_shape_b,
const float fac);
struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, const int frame);
+/**
+ * When returning 2 - the frame isn't found but before/after frames are.
+ */
int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay,
const float frame,
struct MaskLayerShape **r_masklay_shape_a,
struct MaskLayerShape **r_masklay_shape_b);
+/**
+ * \note Does *not* add to the list.
+ */
struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame);
void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape);
struct MaskLayerShape *BKE_mask_layer_shape_verify_frame(struct MaskLayer *masklay,
@@ -214,19 +273,42 @@ bool BKE_mask_layer_shape_spline_from_index(struct MaskLayer *masklay,
int *r_index);
int BKE_mask_layer_shape_spline_to_index(struct MaskLayer *masklay, struct MaskSpline *spline);
+/**
+ * When a new points added, resizing all shape-key arrays.
+ */
void BKE_mask_layer_shape_changed_add(struct MaskLayer *masklay,
int index,
bool do_init,
bool do_init_interpolate);
+/**
+ * Move array elements to account for removed point.
+ */
void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, int count);
int BKE_mask_get_duration(struct Mask *mask);
-/* clipboard */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clipboard
+ * \{ */
+
+/**
+ * Free the clipboard.
+ */
void BKE_mask_clipboard_free(void);
+/**
+ * Copy selected visible splines from the given layer to clipboard.
+ */
void BKE_mask_clipboard_copy_from_layer(struct MaskLayer *mask_layer);
+/**
+ * Check clipboard is empty.
+ */
bool BKE_mask_clipboard_is_empty(void);
+/**
+ * Paste the contents of clipboard to given mask layer.
+ */
void BKE_mask_clipboard_paste_to_layer(struct Main *bmain, struct MaskLayer *mask_layer);
#define MASKPOINT_ISSEL_ANY(p) ((((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f3) & SELECT) != 0)
@@ -260,9 +342,16 @@ void BKE_mask_clipboard_paste_to_layer(struct Main *bmain, struct MaskLayer *mas
} \
(void)0
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Evaluation
+ * \{ */
+
#define MASK_RESOL_MAX 128
/* mask_evaluate.c */
+
unsigned int BKE_mask_spline_resolution(struct MaskSpline *spline, int width, int height);
unsigned int BKE_mask_spline_feather_resolution(struct MaskSpline *spline, int width, int height);
int BKE_mask_spline_differentiate_calc_total(const struct MaskSpline *spline,
@@ -276,6 +365,10 @@ void BKE_mask_spline_feather_collapse_inner_loops(struct MaskSpline *spline,
const unsigned int tot_feather_point);
float (*BKE_mask_spline_differentiate(
struct MaskSpline *spline, int width, int height, unsigned int *r_tot_diff_point))[2];
+/**
+ * values align with #BKE_mask_spline_differentiate_with_resolution
+ * when \a resol arguments match.
+ */
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(
struct MaskSpline *spline,
const unsigned int resol,
@@ -283,6 +376,7 @@ float (*BKE_mask_spline_feather_differentiated_points_with_resolution(
unsigned int *r_tot_feather_point))[2];
/* *** mask point functions which involve evaluation *** */
+
float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2];
float *BKE_mask_point_segment_diff(struct MaskSpline *spline,
@@ -291,6 +385,8 @@ float *BKE_mask_point_segment_diff(struct MaskSpline *spline,
int height,
unsigned int *r_tot_diff_point);
+/* *** mask point functions which involve evaluation *** */
+
float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline,
struct MaskSplinePoint *point,
int width,
@@ -303,7 +399,14 @@ void BKE_mask_layer_evaluate_deform(struct MaskLayer *masklay, const float ctime
void BKE_mask_eval_animation(struct Depsgraph *depsgraph, struct Mask *mask);
void BKE_mask_eval_update(struct Depsgraph *depsgraph, struct Mask *mask);
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Rasterization
+ * \{ */
+
/* mask_rasterize.c */
+
struct MaskRasterHandle;
typedef struct MaskRasterHandle MaskRasterHandle;
@@ -318,11 +421,16 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
const bool do_feather);
float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2]);
+/**
+ * \brief Rasterize a buffer from a single mask (threaded execution).
+ */
void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle,
const unsigned int width,
const unsigned int height,
float *buffer);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index b1eaf7207fa..5f9007c79b0 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -34,12 +34,18 @@ struct Object;
struct Scene;
struct bNode;
-/* Module */
+/* -------------------------------------------------------------------- */
+/** \name Module
+ * \{ */
void BKE_materials_init(void);
void BKE_materials_exit(void);
-/* Materials */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Materials
+ * \{ */
void BKE_object_materials_test(struct Main *bmain, struct Object *ob, struct ID *id);
void BKE_objects_materials_test_all(struct Main *bmain, struct ID *id);
@@ -48,9 +54,18 @@ void BKE_object_material_resize(struct Main *bmain,
const short totcol,
bool do_id_user);
void BKE_object_material_remap(struct Object *ob, const unsigned int *remap);
+/**
+ * Calculate a material remapping from \a ob_src to \a ob_dst.
+ *
+ * \param remap_src_to_dst: An array the size of `ob_src->totcol`
+ * where index values are filled in which map to \a ob_dst materials.
+ */
void BKE_object_material_remap_calc(struct Object *ob_dst,
struct Object *ob_src,
short *remap_src_to_dst);
+/**
+ * Copy materials from evaluated geometry to the original geometry of an object.
+ */
void BKE_object_material_from_eval_data(struct Main *bmain,
struct Object *ob_orig,
struct ID *data_eval);
@@ -61,10 +76,17 @@ void BKE_gpencil_material_attr_init(struct Material *ma);
/* UNUSED */
// void automatname(struct Material *);
-/* material slots */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Material Slots
+ * \{ */
struct Material ***BKE_object_material_array_p(struct Object *ob);
short *BKE_object_material_len_p(struct Object *ob);
+/**
+ * \note Same as #BKE_object_material_len_p but for ID's.
+ */
struct Material ***BKE_id_material_array_p(struct ID *id); /* same but for ID's */
short *BKE_id_material_len_p(struct ID *id);
@@ -81,6 +103,9 @@ struct Material *BKE_object_material_get(struct Object *ob, short act);
void BKE_id_material_assign(struct Main *bmain, struct ID *id, struct Material *ma, short act);
void BKE_object_material_assign(
struct Main *bmain, struct Object *ob, struct Material *ma, short act, int assign_type);
+/**
+ * \warning this calls many more update calls per object then are needed, could be optimized.
+ */
void BKE_object_material_array_assign(struct Main *bmain,
struct Object *ob,
struct Material ***matar,
@@ -99,7 +124,12 @@ void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
struct bNode *BKE_texpaint_slot_material_find_node(struct Material *ma, short texpaint_slot);
-/* rna api */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name RNA API
+ * \{ */
+
void BKE_id_materials_copy(struct Main *bmain, struct ID *id_src, struct ID *id_dst);
void BKE_id_material_resize(struct Main *bmain, struct ID *id, short totcol, bool do_id_user);
void BKE_id_material_append(struct Main *bmain, struct ID *id, struct Material *ma);
@@ -109,23 +139,57 @@ struct Material *BKE_id_material_pop(struct Main *bmain,
int index);
void BKE_id_material_clear(struct Main *bmain, struct ID *id);
-/* eval api */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Evaluation API
+ * \{ */
+
+/**
+ * On evaluated objects the number of materials on an object and its data might go out of sync.
+ * This is because during evaluation materials can be added/removed on the object data.
+ *
+ * For rendering or exporting we generally use the materials on the object data. However, some
+ * material indices might be overwritten by the object.
+ */
struct Material *BKE_object_material_get_eval(struct Object *ob, short act);
int BKE_object_material_count_eval(struct Object *ob);
void BKE_id_material_eval_assign(struct ID *id, int slot, struct Material *material);
+/**
+ * Add an empty material slot if the id has no material slots. This material slot allows the
+ * material to be overwritten by object-linked materials.
+ */
void BKE_id_material_eval_ensure_default_slot(struct ID *id);
-/* rendering */
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Rendering
+ * \{ */
+
+/**
+ * \param r_col: current value.
+ * \param col: new value.
+ * \param fac: Zero for is no change.
+ */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
-/* copy/paste */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy/Paste
+ * \{ */
+
void BKE_material_copybuf_clear(void);
void BKE_material_copybuf_free(void);
void BKE_material_copybuf_copy(struct Main *bmain, struct Material *ma);
void BKE_material_copybuf_paste(struct Main *bmain, struct Material *ma);
-/* Default Materials */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Default Materials
+ * \{ */
struct Material *BKE_material_default_empty(void);
struct Material *BKE_material_default_holdout(void);
@@ -135,12 +199,18 @@ struct Material *BKE_material_default_gpencil(void);
void BKE_material_defaults_free_gpu(void);
-/* Dependency graph evaluation. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dependency graph evaluation
+ * \{ */
struct Depsgraph;
void BKE_material_eval(struct Depsgraph *depsgraph, struct Material *material);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index db4dca14535..895fe5a28f9 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -41,13 +41,45 @@ bool BKE_mball_is_any_selected(const struct MetaBall *mb);
bool BKE_mball_is_any_selected_multi(struct Base **bases, int bases_len);
bool BKE_mball_is_any_unselected(const struct MetaBall *mb);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
+/**
+ * Test, if \a ob is a basis meta-ball.
+ *
+ * It test last character of Object ID name.
+ * If last character is digit it return 0, else it return 1.
+ */
bool BKE_mball_is_basis(struct Object *ob);
+/**
+ * This function finds the basis meta-ball.
+ *
+ * Basis meta-ball doesn't include any number at the end of
+ * its name. All meta-balls with same base of name can be
+ * blended. meta-balls with different basic name can't be blended.
+ *
+ * \warning #BKE_mball_is_basis() can fail on returned object, see function docs for details.
+ */
struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob);
+/**
+ * Compute bounding box of all meta-elements / meta-ball.
+ *
+ * Bounding box is computed from polygonized surface. \a ob is
+ * basic meta-balls (with name `Meta` for example). All other meta-ball objects
+ * (with names `Meta.001`, `Meta.002`, etc) are included in this bounding-box.
+ */
void BKE_mball_texspace_calc(struct Object *ob);
+/**
+ * Return or compute bounding-box for given meta-ball object.
+ */
struct BoundBox *BKE_mball_boundbox_get(struct Object *ob);
float *BKE_mball_make_orco(struct Object *ob, struct ListBase *dispbase);
+/**
+ * Copy some properties from object to other meta-ball object with same base name.
+ *
+ * When some properties (wire-size, threshold, update flags) of meta-ball are changed, then this
+ * properties are copied to all meta-balls in same "group" (meta-balls with same base name:
+ * `MBall`, `MBall.001`, `MBall.002`, etc). The most important is to copy properties to the base
+ * meta-ball, because this meta-ball influence polygonization of meta-balls. */
void BKE_mball_properties_copy(struct Scene *scene, struct Object *active_object);
bool BKE_mball_minmax_ex(const struct MetaBall *mb,
@@ -55,14 +87,24 @@ bool BKE_mball_minmax_ex(const struct MetaBall *mb,
float max[3],
const float obmat[4][4],
const short flag);
+
+/* Basic vertex data functions. */
+
bool BKE_mball_minmax(const struct MetaBall *mb, float min[3], float max[3]);
bool BKE_mball_center_median(const struct MetaBall *mb, float r_cent[3]);
bool BKE_mball_center_bounds(const struct MetaBall *mb, float r_cent[3]);
void BKE_mball_transform(struct MetaBall *mb, const float mat[4][4], const bool do_props);
void BKE_mball_translate(struct MetaBall *mb, const float offset[3]);
+/**
+ * Most simple meta-element adding function.
+ *
+ * \note don't do context manipulation here (rna uses).
+ */
struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type);
+/* *** select funcs *** */
+
int BKE_mball_select_count(const struct MetaBall *mb);
int BKE_mball_select_count_multi(struct Base **bases, int bases_len);
bool BKE_mball_select_all(struct MetaBall *mb);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index be9b84ccd62..c39583d234a 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -84,21 +84,51 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
const struct CustomData_MeshMasks *cd_mask_extra,
const struct Mesh *me_settings);
+/**
+ * Find the index of the loop in 'poly' which references vertex,
+ * returns -1 if not found
+ */
int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert);
+/**
+ * Fill \a r_adj with the loop indices in \a poly adjacent to the
+ * vertex. Returns the index of the loop matching vertex, or -1 if the
+ * vertex is not in \a poly
+ */
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const struct MLoop *mloop,
unsigned int vert,
unsigned int r_adj[2]);
+/**
+ * Return the index of the edge vert that is not equal to \a v. If
+ * neither edge vertex is equal to \a v, returns -1.
+ */
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
+/**
+ * Sets each output array element to the edge index if it is a real edge, or -1.
+ */
void BKE_mesh_looptri_get_real_edges(const struct Mesh *mesh,
const struct MLoopTri *looptri,
int r_edges[3]);
+/**
+ * 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(nullptr, me)` should be used.
+ */
void BKE_mesh_free_data_for_undo(struct Mesh *me);
void BKE_mesh_clear_geometry(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
+/**
+ * A version of #BKE_mesh_copy_parameters that is intended for evaluated output
+ * (the modifier stack for example).
+ *
+ * \warning User counts are not handled for ID's.
+ */
void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *me_src);
+/**
+ * Copy user editable settings that we want to preserve
+ * when a new mesh is based on an existing mesh.
+ */
void BKE_mesh_copy_parameters(struct Mesh *me_dst, const struct Mesh *me_src);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
@@ -121,12 +151,16 @@ struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
void BKE_mesh_eval_delete(struct Mesh *mesh_eval);
-/* Performs copy for use during evaluation,
- * optional referencing original arrays to reduce memory. */
+/**
+ * Performs copy for use during evaluation,
+ * optional referencing original arrays to reduce memory.
+ */
struct Mesh *BKE_mesh_copy_for_eval(const struct Mesh *source, bool reference);
-/* These functions construct a new Mesh,
- * contrary to BKE_mesh_to_curve_nurblist which modifies ob itself. */
+/**
+ * These functions construct a new Mesh,
+ * contrary to #BKE_mesh_to_curve_nurblist which modifies ob itself.
+ */
struct Mesh *BKE_mesh_new_nomain_from_curve(const struct Object *ob);
struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
const struct ListBase *dispbase);
@@ -136,6 +170,16 @@ bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);
+
+/**
+ * Add a #CD_ORCO layer to the Mesh if there is none already.
+ */
+void BKE_mesh_orco_ensure(struct Object *ob, struct Mesh *mesh);
+
+/**
+ * Rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0.
+ * this is necessary to make the if #MFace.v4 check for quads work.
+ */
int BKE_mesh_mface_index_validate(struct MFace *mface,
struct CustomData *mfdata,
int mfindex,
@@ -166,9 +210,17 @@ void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
void BKE_mesh_smooth_flag_set(struct Mesh *me, const bool use_smooth);
-/* Needed after converting a mesh with subsurf optimal display to mesh. */
+/**
+ * Needed after converting a mesh with subsurf optimal display to mesh.
+ */
void BKE_mesh_edges_set_draw_render(struct Mesh *me);
+/**
+ * Used for unit testing; compares two meshes, checking only
+ * differences we care about. should be usable with leaf's
+ * testing framework I get RNA work done, will use hackish
+ * testing code for now.
+ */
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob);
@@ -177,34 +229,49 @@ void BKE_mesh_texspace_calc(struct Mesh *me);
void BKE_mesh_texspace_ensure(struct Mesh *me);
void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_get_reference(struct Mesh *me,
- short **r_texflag,
+ char **r_texflag,
float **r_loc,
float **r_size);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
+/**
+ * Split faces based on the edge angle and loop normals.
+ * Matches behavior of face splitting in render engines.
+ *
+ * \note Will leave #CD_NORMAL loop data layer which is used by render engines to set shading up.
+ */
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
-/* Create new mesh from the given object at its current state.
+/**
+ * Create new mesh from the given object at its current state.
* The owner of this mesh is unknown, it is up to the caller to decide.
*
* If preserve_all_data_layers is truth then the modifier stack is re-evaluated to ensure it
* preserves all possible custom data layers.
*
- * NOTE: Dependency graph argument is required when preserve_all_data_layers is truth, and is
- * ignored otherwise. */
+ * \note Dependency graph argument is required when preserve_all_data_layers is truth, and is
+ * ignored otherwise.
+ */
struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph,
struct Object *object,
const bool preserve_all_data_layers,
const bool preserve_origindex);
-/* This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database.
+/**
+ * This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database.
* However, that function enforces object type to be a geometry one, and ensures a mesh is always
- * generated, be it empty. */
+ * generated, be it empty.
+ */
struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Object *object,
bool preserve_all_data_layers);
+/**
+ * \param use_virtual_modifiers: When enabled calculate virtual-modifiers before applying `md_eval`
+ * support this since virtual-modifiers are not modifiers from a user perspective,
+ * allowing shape keys to be included with the modifier being applied, see: T91923.
+ */
struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_eval,
@@ -212,7 +279,9 @@ struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
const bool use_virtual_modifiers,
const bool build_shapekey_layers);
-/* Copies a nomain-Mesh into an existing Mesh. */
+/**
+ * Copies a nomain-Mesh into an existing Mesh.
+ */
void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src,
struct Mesh *mesh_dst,
struct Object *ob,
@@ -222,6 +291,7 @@ void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, st
/* vertex level transformations & checks (no derived mesh) */
+/* basic vertex data functions */
bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3]);
void BKE_mesh_transform(struct Mesh *me, const float mat[4][4], bool do_keys);
void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
@@ -233,7 +303,13 @@ void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
void BKE_mesh_mselect_clear(struct Mesh *me);
void BKE_mesh_mselect_validate(struct Mesh *me);
+/**
+ * \return the index within `me->mselect`, or -1
+ */
int BKE_mesh_mselect_find(struct Mesh *me, int index, int type);
+/**
+ * \return The index of the active element.
+ */
int BKE_mesh_mselect_active_get(struct Mesh *me, int type);
void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
@@ -250,6 +326,17 @@ void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vert_normals)[
/* *** mesh_tessellate.c *** */
+/**
+ * Recreate #MFace Tessellation.
+ *
+ * \param do_face_nor_copy: Controls whether the normals from the poly
+ * are copied to the tessellated faces.
+ *
+ * \return number of tessellation faces.
+ *
+ * \note This doesn't use multi-threading like #BKE_mesh_recalc_looptri since
+ * it's not used in many places and #MFace should be phased out.
+ */
int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
struct CustomData *ldata,
struct CustomData *pdata,
@@ -260,12 +347,23 @@ int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
const bool do_face_nor_copy);
void BKE_mesh_tessface_calc(struct Mesh *mesh);
+/**
+ * Calculate tessellation into #MLoopTri which exist only for this purpose.
+ */
void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
int totloop,
int totpoly,
struct MLoopTri *mlooptri);
+/**
+ * A version of #BKE_mesh_recalc_looptri which takes pre-calculated polygon normals
+ * (used to avoid having to calculate the face normal for NGON tessellation).
+ *
+ * \note Only use this function if normals have already been calculated, there is no need
+ * to calculate normals just to use this function as it will cause the normals for triangles
+ * to be calculated which aren't needed for tessellation.
+ */
void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
@@ -292,8 +390,15 @@ void BKE_mesh_calc_normals_poly_and_vertex(struct MVert *mvert,
int mpoly_len,
float (*r_poly_normals)[3],
float (*r_vert_normals)[3]);
+/**
+ * \note this does not update the #CD_NORMAL layer,
+ * but does update the normals in the #CD_MVERT layer.
+ */
void BKE_mesh_calc_normals(struct Mesh *me);
void BKE_mesh_ensure_normals(struct Mesh *me);
+/**
+ * Called after calculating all modifiers.
+ */
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
void BKE_mesh_calc_normals_looptri(struct MVert *mverts,
int numVerts,
@@ -311,6 +416,12 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const struct MLoop *mloops,
int *r_mlfan_vert_index,
int *r_mpfan_curr_index);
+/**
+ * Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
+ *
+ * Used when defining an empty custom loop normals data layer,
+ * to keep same shading as with auto-smooth!
+ */
void BKE_edges_sharp_from_angle_set(const struct MVert *mverts,
const int numVerts,
struct MEdge *medges,
@@ -379,17 +490,42 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr);
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr);
+/**
+ * Utility for multi-threaded calculation that ensures
+ * `lnors_spacearr_tls` doesn't share memory with `lnors_spacearr`
+ * that would cause it not to be thread safe.
+ *
+ * \note This works as long as threads never operate on the same loops at once.
+ */
void BKE_lnor_spacearr_tls_init(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpaceArray *lnors_spacearr_tls);
+/**
+ * Utility for multi-threaded calculation
+ * that merges `lnors_spacearr_tls` into `lnors_spacearr`.
+ */
void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpaceArray *lnors_spacearr_tls);
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr);
+/**
+ * Should only be called once.
+ * Beware, this modifies ref_vec and other_vec in place!
+ * In case no valid space can be generated, ref_alpha and ref_beta are set to zero
+ * (which means 'use auto lnors').
+ */
void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
const float lnor[3],
float vec_ref[3],
float vec_other[3],
struct BLI_Stack *edge_vectors);
+/**
+ * Add a new given loop to given lnor_space.
+ * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct
+ * (in case of BMLOOP_PTR), or nullptr (in case of LOOP_INDEX), loop index is then stored in
+ * pointer. If \a is_single is set, the BMLoop or loop index is directly stored in \a
+ * lnor_space->loops pointer (since there is only one loop in this fan), else it is added to the
+ * linked list of loops in the fan.
+ */
void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpace *lnor_space,
const int ml_index,
@@ -403,6 +539,12 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space,
short r_clnor_data[2]);
/* Medium-level custom normals functions. */
+
+/**
+ * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
+ * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
+ * (splitting edges).
+ */
void BKE_mesh_normals_loop_split(const struct MVert *mverts,
const int numVerts,
struct MEdge *medges,
@@ -442,20 +584,49 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(const struct MVert *mverts,
const int numPolys,
short (*r_clnors_data)[2]);
+/**
+ * Computes average per-vertex normals from given custom loop normals.
+ *
+ * \param clnors: The computed custom loop normals.
+ * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals.
+ */
void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const struct MLoop *mloops,
const int numLoops,
const float (*clnors)[3],
float (*r_vert_clnors)[3]);
-/* High-level custom normals functions. */
+/**
+ * High-level custom normals functions.
+ */
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
void BKE_mesh_calc_normals_split(struct Mesh *mesh);
+/**
+ * Compute 'split' (aka loop, or per face corner's) normals.
+ *
+ * \param r_lnors_spacearr: Allows to get computed loop normal space array.
+ * That data, among other things, contains 'smooth fan' info, useful e.g.
+ * to split geometry along sharp edges.
+ */
void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
struct MLoopNorSpaceArray *r_lnors_spacearr);
+/**
+ * Higher level functions hiding most of the code needed around call to
+ * #BKE_mesh_normals_loop_custom_set().
+ *
+ * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there
+ * with automatically computed vectors.
+ */
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loopnors)[3]);
+/**
+ * Higher level functions hiding most of the code needed around call to
+ * #BKE_mesh_normals_loop_custom_from_vertices_set().
+ *
+ * \param r_custom_vertnors: is not const, since code will replace zero_v3 normals there
+ * with automatically computed vectors.
+ */
void BKE_mesh_set_custom_normals_from_vertices(struct Mesh *mesh, float (*r_custom_vertnors)[3]);
/* *** mesh_evaluate.cc *** */
@@ -472,6 +643,7 @@ void BKE_mesh_calc_poly_center(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray,
float r_cent[3]);
+/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */
float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray);
@@ -490,11 +662,25 @@ void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap,
const struct MLoop *mloop);
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
+/**
+ * Calculate the center from polygons,
+ * use when we want to ignore vertex locations that don't have connected faces.
+ */
bool BKE_mesh_center_median_from_polys(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]);
+/**
+ * \note Mesh must be manifold with consistent face-winding,
+ * see #mesh_calc_poly_volume_centroid for details.
+ */
bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]);
+/**
+ * Calculate the volume and center.
+ *
+ * \param r_volume: Volume (unsigned).
+ * \param r_center: Center of mass.
+ */
void BKE_mesh_calc_volume(const struct MVert *mverts,
const int mverts_num,
const struct MLoopTri *mlooptri,
@@ -505,6 +691,19 @@ void BKE_mesh_calc_volume(const struct MVert *mverts,
/* tessface */
void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
+/**
+ * The same as #BKE_mesh_convert_mfaces_to_mpolys
+ * but oriented to be used in #do_versions from `readfile.c`
+ * the difference is how active/render/clone/stencil indices are handled here.
+ *
+ * normally they're being set from `pdata` which totally makes sense for meshes which are already
+ * converted to #BMesh structures, but when loading older files indices shall be updated in other
+ * way around, so newly added `pdata` and `ldata` would have this indices set
+ * based on `fdata` layer.
+ *
+ * this is normally only needed when reading older files,
+ * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used.
+ */
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id,
struct CustomData *fdata,
@@ -521,8 +720,20 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id,
struct MLoop **r_mloop,
struct MPoly **r_mpoly);
+/**
+ * Flip a single MLoop's #MDisps structure,
+ * low level function to be called from face-flipping code which re-arranged the mdisps themselves.
+ */
void BKE_mesh_mdisp_flip(struct MDisps *md, const bool use_loop_mdisp_flip);
+/**
+ * Flip (invert winding of) the given \a mpoly, i.e. reverse order of its loops
+ * (keeping the same vertex as 'start point').
+ *
+ * \param mpoly: the polygon to flip.
+ * \param mloop: the full loops array.
+ * \param ldata: the loops custom data.
+ */
void BKE_mesh_polygon_flip_ex(struct MPoly *mpoly,
struct MLoop *mloop,
struct CustomData *ldata,
@@ -530,6 +741,11 @@ void BKE_mesh_polygon_flip_ex(struct MPoly *mpoly,
struct MDisps *mdisp,
const bool use_loop_mdisp_flip);
void BKE_mesh_polygon_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata);
+/**
+ * Flip (invert winding of) all polygons (used to inverse their normals).
+ *
+ * \note Invalidates tessellation, caller must handle that.
+ */
void BKE_mesh_polygons_flip(struct MPoly *mpoly,
struct MLoop *mloop,
struct CustomData *ldata,
@@ -542,12 +758,48 @@ enum {
MESH_MERGE_VERTS_DUMP_IF_MAPPED,
MESH_MERGE_VERTS_DUMP_IF_EQUAL,
};
+/**
+ * Merge Verts
+ *
+ * This frees the given mesh and returns a new mesh.
+ *
+ * \param vtargetmap: The table that maps vertices to target vertices. a value of -1
+ * indicates a vertex is a target, and is to be kept.
+ * This array is aligned with 'mesh->totvert'
+ * \warning \a vtargetmap must **not** contain any chained mapping (v1 -> v2 -> v3 etc.),
+ * this is not supported and will likely generate corrupted geometry.
+ *
+ * \param tot_vtargetmap: The number of non '-1' values in vtargetmap. (not the size)
+ *
+ * \param merge_mode: enum with two modes.
+ * - #MESH_MERGE_VERTS_DUMP_IF_MAPPED
+ * When called by the Mirror Modifier,
+ * In this mode it skips any faces that have all vertices merged (to avoid creating pairs
+ * of faces sharing the same set of vertices)
+ * - #MESH_MERGE_VERTS_DUMP_IF_EQUAL
+ * When called by the Array Modifier,
+ * In this mode, faces where all vertices are merged are double-checked,
+ * to see whether all target vertices actually make up a poly already.
+ * Indeed it could be that all of a poly's vertices are merged,
+ * but merged to vertices that do not make up a single poly,
+ * in which case the original poly should not be dumped.
+ * Actually this later behavior could apply to the Mirror Modifier as well,
+ * but the additional checks are costly and not necessary in the case of mirror,
+ * because each vertex is only merged to its own mirror.
+ *
+ * \note #BKE_mesh_tessface_calc_ex has to run on the returned DM
+ * if you want to access tess-faces.
+ */
struct Mesh *BKE_mesh_merge_verts(struct Mesh *mesh,
const int *vtargetmap,
const int tot_vtargetmap,
const int merge_mode);
-/* flush flags */
+/* Flush flags. */
+
+/**
+ * Update the hide flag for edges and faces from the corresponding flag in verts.
+ */
void BKE_mesh_flush_hidden_from_verts_ex(const struct MVert *mvert,
const struct MLoop *mloop,
struct MEdge *medge,
@@ -562,6 +814,9 @@ void BKE_mesh_flush_hidden_from_polys_ex(struct MVert *mvert,
const struct MPoly *mpoly,
const int totpoly);
void BKE_mesh_flush_hidden_from_polys(struct Mesh *me);
+/**
+ * simple poly -> vert/edge selection.
+ */
void BKE_mesh_flush_select_from_polys_ex(struct MVert *mvert,
const int totvert,
const struct MLoop *mloop,
@@ -580,6 +835,17 @@ void BKE_mesh_flush_select_from_verts_ex(const struct MVert *mvert,
void BKE_mesh_flush_select_from_verts(struct Mesh *me);
/* spatial evaluation */
+/**
+ * This function takes the difference between 2 vertex-coord-arrays
+ * (\a vert_cos_src, \a vert_cos_dst),
+ * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
+ *
+ * \param vert_cos_src: reference deform source.
+ * \param vert_cos_dst: reference deform destination.
+ *
+ * \param vert_cos_org: reference for the output location.
+ * \param vert_cos_new: resulting coords.
+ */
void BKE_mesh_calc_relative_deform(const struct MPoly *mpoly,
const int totpoly,
const struct MLoop *mloop,
@@ -593,10 +859,41 @@ void BKE_mesh_calc_relative_deform(const struct MPoly *mpoly,
/* *** mesh_validate.c *** */
+/**
+ * Validates and corrects a Mesh.
+ *
+ * \returns true if a change is made.
+ */
bool BKE_mesh_validate(struct Mesh *me, const bool do_verbose, const bool cddata_check_mask);
+/**
+ * Checks if a Mesh is valid without any modification. This is always verbose.
+ *
+ * \see #DM_is_valid to call on derived meshes
+ *
+ * \returns is_valid.
+ */
bool BKE_mesh_is_valid(struct Mesh *me);
+/**
+ * Check all material indices of polygons are valid, invalid ones are set to 0.
+ * \returns is_valid.
+ */
bool BKE_mesh_validate_material_indices(struct Mesh *me);
+/**
+ * Validate the mesh, \a do_fixes requires \a mesh to be non-null.
+ *
+ * \return false if no changes needed to be made.
+ *
+ * Vertex Normals
+ * ==============
+ *
+ * While zeroed normals are checked, these checks aren't comprehensive.
+ * Technically, to detect errors here a normal recalculation and comparison is necessary.
+ * However this function is mainly to prevent severe errors in geometry
+ * (invalid data that will crash Blender, or cause some features to behave incorrectly),
+ * not to detect subtle differences in the resulting normals which could be caused
+ * by importers that load normals (for example).
+ */
bool BKE_mesh_validate_arrays(struct Mesh *me,
struct MVert *mverts,
unsigned int totvert,
@@ -613,6 +910,9 @@ bool BKE_mesh_validate_arrays(struct Mesh *me,
const bool do_fixes,
bool *r_change);
+/**
+ * \returns is_valid.
+ */
bool BKE_mesh_validate_all_customdata(struct CustomData *vdata,
const uint totvert,
struct CustomData *edata,
@@ -627,12 +927,31 @@ bool BKE_mesh_validate_all_customdata(struct CustomData *vdata,
bool *r_change);
void BKE_mesh_strip_loose_faces(struct Mesh *me);
+/**
+ * Works on both loops and polys!
+ *
+ * \note It won't try to guess which loops of an invalid poly to remove!
+ * this is the work of the caller, to mark those loops.
+ * See e.g. #BKE_mesh_validate_arrays().
+ */
void BKE_mesh_strip_loose_polysloops(struct Mesh *me);
void BKE_mesh_strip_loose_edges(struct Mesh *me);
+/**
+ * If the mesh is from a very old blender version,
+ * convert mface->edcode to edge drawflags
+ */
void BKE_mesh_calc_edges_legacy(struct Mesh *me, const bool use_old);
void BKE_mesh_calc_edges_loose(struct Mesh *mesh);
+/**
+ * Calculate edges from polygons.
+ */
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, const bool select_new_edges);
+/**
+ * Calculate/create edges from tessface data
+ *
+ * \param mesh: The mesh to add edges into
+ */
void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
/* In DerivedMesh.cc */
diff --git a/source/blender/blenkernel/BKE_mesh_boolean_convert.hh b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh
index 59f6e75183e..a7a7529f217 100644
--- a/source/blender/blenkernel/BKE_mesh_boolean_convert.hh
+++ b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh
@@ -32,6 +32,16 @@ struct Mesh;
namespace blender::meshintersect {
+/**
+ * Do a mesh boolean operation directly on meshes (without going back and forth to BMesh).
+ * \param meshes: An array of Mesh pointers.
+ * \param obmats: An array of pointers to the obmat matrices that transform local
+ * coordinates to global ones. It is allowed for the pointers to be null, meaning the
+ * transformation is the identity.
+ * \param material_remaps: An array of pointers to arrays of maps from material slot numbers in the
+ * corresponding mesh to the material slot in the first mesh. It is OK for material_remaps or any
+ * of its constituent arrays to be empty.
+ */
Mesh *direct_mesh_boolean(blender::Span<const Mesh *> meshes,
blender::Span<const float4x4 *> obmats,
const float4x4 &target_transform,
diff --git a/source/blender/blenkernel/BKE_mesh_iterators.h b/source/blender/blenkernel/BKE_mesh_iterators.h
index a65f25ee182..83f0228dc76 100644
--- a/source/blender/blenkernel/BKE_mesh_iterators.h
+++ b/source/blender/blenkernel/BKE_mesh_iterators.h
@@ -39,6 +39,11 @@ void BKE_mesh_foreach_mapped_vert(struct Mesh *mesh,
const short no_s[3]),
void *userData,
MeshForeachFlag flag);
+/**
+ * Copied from #cdDM_foreachMappedEdge.
+ * \param tot_edges: Number of original edges. Used to avoid calling the callback with invalid
+ * edge indices.
+ */
void BKE_mesh_foreach_mapped_edge(
struct Mesh *mesh,
int tot_edges,
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index 0518f303744..acc1628de1d 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -105,6 +105,11 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly,
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
+/**
+ * Generates a map where the key is the vertex and the value
+ * is a list of polys that use that vertex as a corner.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *mpoly,
@@ -112,6 +117,11 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int totvert,
int totpoly,
int totloop);
+/**
+ * Generates a map where the key is the vertex and the value
+ * is a list of loops that use that vertex as a corner.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *mpoly,
@@ -119,6 +129,11 @@ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int totvert,
int totpoly,
int totloop);
+/**
+ * Generates a map where the key is the edge and the value
+ * is a list of looptris that use that edge.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MVert *mvert,
@@ -127,10 +142,24 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
const int totlooptri,
const struct MLoop *mloop,
const int totloop);
+/**
+ * Generates a map where the key is the vertex and the value
+ * is a list of edges that use that vertex as an endpoint.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_vert_edge_map_create(
MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge);
+/**
+ * A version of #BKE_mesh_vert_edge_map_create that references connected vertices directly
+ * (not their edges).
+ */
void BKE_mesh_vert_edge_vert_map_create(
MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge);
+/**
+ * Generates a map where the key is the edge and the value is a list of loops that use that edge.
+ * Loops indices of a same poly are contiguous and in winding order.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MEdge *medge,
@@ -139,6 +168,11 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
const int totpoly,
const struct MLoop *mloop,
const int totloop);
+/**
+ * Generates a map where the key is the edge and the value
+ * is a list of polygons that use that edge.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MEdge *medge,
@@ -147,11 +181,29 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
const int totpoly,
const struct MLoop *mloop,
const int totloop);
+/**
+ * This function creates a map so the source-data (vert/edge/loop/poly)
+ * can loop over the destination data (using the destination arrays origindex).
+ *
+ * This has the advantage that it can operate on any data-types.
+ *
+ * \param totsource: The total number of elements that \a final_origindex points to.
+ * \param totfinal: The size of \a final_origindex
+ * \param final_origindex: The size of the final array.
+ *
+ * \note `totsource` could be `totpoly`,
+ * `totfinal` could be `tottessface` and `final_origindex` its ORIGINDEX custom-data.
+ * This would allow an MPoly to loop over its tessfaces.
+ */
void BKE_mesh_origindex_map_create(MeshElemMap **r_map,
int **r_mem,
const int totsource,
const int *final_origindex,
const int totfinal);
+/**
+ * A version of #BKE_mesh_origindex_map_create that takes a looptri array.
+ * Making a poly -> looptri map.
+ */
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *mpoly,
@@ -212,7 +264,11 @@ typedef bool (*MeshRemapIslandsCalc)(struct MVert *verts,
struct MeshIslandStore *r_island_store);
/* Above vert/UV mapping stuff does not do what we need here, but does things we do not need here.
- * So better keep them separated for now, I think.
+ * So better keep them separated for now, I think. */
+
+/**
+ * Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams),
+ * not some UV layers coordinates.
*/
bool BKE_mesh_calc_islands_loop_poly_edgeseam(struct MVert *verts,
const int totvert,
@@ -224,6 +280,19 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(struct MVert *verts,
const int totloop,
MeshIslandStore *r_island_store);
+/**
+ * Calculate UV islands.
+ *
+ * \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries.
+ * This has the advantages of simplicity, and being valid/common to all UV maps.
+ * However, it means actual UV islands without matching UV seams will not be handled correctly.
+ * If a valid UV layer is passed as \a luvs parameter,
+ * UV coordinates are also used to detect islands boundaries.
+ *
+ * \note All this could be optimized.
+ * Not sure it would be worth the more complex code, though,
+ * those loops are supposed to be really quick to do.
+ */
bool BKE_mesh_calc_islands_loop_poly_uvmap(struct MVert *verts,
const int totvert,
struct MEdge *edges,
@@ -235,6 +304,14 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(struct MVert *verts,
const struct MLoopUV *luvs,
MeshIslandStore *r_island_store);
+/**
+ * Calculate smooth groups from sharp edges.
+ *
+ * \param r_totgroup: The total number of groups, 1 or more.
+ * \return Polygon aligned array of group index values (bitflags if use_bitflags is true),
+ * starting at 1 (0 being used as 'invalid' flag).
+ * Note it's callers's responsibility to MEM_freeN returned array.
+ */
int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge,
const int totedge,
const struct MPoly *mpoly,
diff --git a/source/blender/blenkernel/BKE_mesh_mirror.h b/source/blender/blenkernel/BKE_mesh_mirror.h
index 7b230b04410..abb8e4d3e44 100644
--- a/source/blender/blenkernel/BKE_mesh_mirror.h
+++ b/source/blender/blenkernel/BKE_mesh_mirror.h
@@ -43,10 +43,16 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
const int axis,
const float dist);
-struct Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(struct MirrorModifierData *mmd,
- struct Object *ob,
- const struct Mesh *mesh,
- const int axis);
+/**
+ * \warning This should _not_ be used to modify original meshes since
+ * it doesn't handle shape-keys, use #BKE_mesh_mirror_apply_mirror_on_axis instead.
+ */
+struct Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(
+ struct MirrorModifierData *mmd,
+ struct Object *ob,
+ const struct Mesh *mesh,
+ const int axis,
+ const bool use_correct_order_on_merge);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h
index 7f8f028c26b..c33b3800aa4 100644
--- a/source/blender/blenkernel/BKE_mesh_remap.h
+++ b/source/blender/blenkernel/BKE_mesh_remap.h
@@ -161,11 +161,24 @@ void BKE_mesh_remap_calc_source_cddata_masks_from_map_modes(
const int poly_mode,
struct CustomData_MeshMasks *cddata_mask);
+/**
+ * Compute a value of the difference between both given meshes.
+ * The smaller the result, the better the match.
+ *
+ * We return the inverse of the average of the inversed
+ * shortest distance from each dst vertex to src ones.
+ * In other words, beyond a certain (relatively small) distance, all differences have more or less
+ * the same weight in final result, which allows to reduce influence of a few high differences,
+ * in favor of a global good matching.
+ */
float BKE_mesh_remap_calc_difference_from_mesh(const struct SpaceTransform *space_transform,
const struct MVert *verts_dst,
const int numverts_dst,
struct Mesh *me_src);
+/**
+ * Set r_space_transform so that best bbox of dst matches best bbox of src.
+ */
void BKE_mesh_remap_find_best_match_from_mesh(const struct MVert *verts_dst,
const int numverts_dst,
struct Mesh *me_src,
diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h
index df111360bcd..764241e7f92 100644
--- a/source/blender/blenkernel/BKE_mesh_runtime.h
+++ b/source/blender/blenkernel/BKE_mesh_runtime.h
@@ -41,18 +41,42 @@ struct Mesh;
struct Object;
struct Scene;
+/**
+ * \brief Initialize the runtime of the given mesh.
+ *
+ * Function expects that the runtime is already cleared.
+ */
void BKE_mesh_runtime_init_data(struct Mesh *mesh);
+/**
+ * \brief Free all data (and mutexes) inside the runtime of the given mesh.
+ */
void BKE_mesh_runtime_free_data(struct Mesh *mesh);
+/**
+ * Clear all pointers which we don't want to be shared on copying the datablock.
+ * However, keep all the flags which defines what the mesh is (for example, that
+ * it's deformed only, or that its custom data layers are out of date.)
+ */
void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag);
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh);
+/**
+ * \note This function only fills a cache, and therefore the mesh argument can
+ * be considered logically const. Concurrent access is protected by a mutex.
+ * \note This is a ported copy of dm_getLoopTriArray(dm).
+ */
const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh);
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh);
bool BKE_mesh_runtime_clear_edit_data(struct Mesh *mesh);
bool BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);
void BKE_mesh_runtime_clear_geometry(struct Mesh *mesh);
+/**
+ * \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(struct Mesh *mesh);
+/* This is a copy of DM_verttri_from_looptri(). */
void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri,
const struct MLoop *mloop,
const struct MLoopTri *looptri,
@@ -62,6 +86,7 @@ void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri,
* to a more suitable location when that file is removed.
* They should also be renamed to use conventions from BKE, not old DerivedMesh.cc.
* For now keep the names similar to avoid confusion. */
+
struct Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
@@ -99,6 +124,7 @@ void BKE_mesh_runtime_eval_to_meshkey(struct Mesh *me_deformed,
#ifndef NDEBUG
char *BKE_mesh_runtime_debug_info(struct Mesh *me_eval);
void BKE_mesh_runtime_debug_print(struct Mesh *me_eval);
+/* XXX Should go in customdata file? */
void BKE_mesh_runtime_debug_print_cdlayers(struct CustomData *data);
bool BKE_mesh_runtime_is_valid(struct Mesh *me_eval);
#endif /* NDEBUG */
diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h
index 96eaa23ce71..39d4072085c 100644
--- a/source/blender/blenkernel/BKE_mesh_tangent.h
+++ b/source/blender/blenkernel/BKE_mesh_tangent.h
@@ -25,6 +25,12 @@ extern "C" {
struct ReportList;
+/**
+ * Compute simplified tangent space normals, i.e.
+ * tangent vector + sign of bi-tangent one, which combined with
+ * split normals can be used to recreate the full tangent space.
+ * NOTE: * The mesh should be made of only tris and quads!
+ */
void BKE_mesh_calc_loop_tangent_single_ex(const struct MVert *mverts,
const int numVerts,
const struct MLoop *mloops,
@@ -35,11 +41,20 @@ void BKE_mesh_calc_loop_tangent_single_ex(const struct MVert *mverts,
const struct MPoly *mpolys,
const int numPolys,
struct ReportList *reports);
+/**
+ * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boiling code.
+ * \note
+ * - There must be a valid loop's CD_NORMALS available.
+ * - The mesh should be made of only tris and quads!
+ */
void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh,
const char *uvmap,
float (*r_looptangents)[4],
struct ReportList *reports);
+/**
+ * See: #BKE_editmesh_loop_tangent_calc (matching logic).
+ */
void BKE_mesh_calc_loop_tangent_ex(const struct MVert *mvert,
const struct MPoly *mpoly,
const uint mpoly_len,
@@ -71,6 +86,12 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(struct CustomData *uv_data,
const char *layer_name);
#define DM_TANGENT_MASK_ORCO (1 << 9)
+/**
+ * Here we get some useful information such as active uv layer name and
+ * search if it is already in tangent_names.
+ * Also, we calculate tangent_mask that works as a descriptor of tangents state.
+ * If tangent_mask has changed, then recalculate tangents.
+ */
void BKE_mesh_calc_loop_tangent_step_0(const struct CustomData *loopData,
bool calc_active_tangent,
const char (*tangent_names)[64],
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 8be563e4c96..278189633a6 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -98,7 +98,7 @@ typedef enum {
eModifierTypeFlag_RequiresOriginalData = (1 << 5),
/**
- * For modifiers that support pointcache,
+ * For modifiers that support point-cache,
* so we can check to see if it has files we need to deal with.
*/
eModifierTypeFlag_UsesPointCache = (1 << 6),
@@ -403,6 +403,10 @@ void BKE_modifier_init(void);
const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type);
/* For modifier UI panels. */
+
+/**
+ * Get the idname of the modifier type's panel, which was defined in the #panelRegister callback.
+ */
void BKE_modifier_type_panel_id(ModifierType type, char *r_idname);
void BKE_modifier_panel_expand(struct ModifierData *md);
@@ -413,6 +417,9 @@ struct ModifierData *BKE_modifier_new(int type);
void BKE_modifier_free_ex(struct ModifierData *md, const int flag);
void BKE_modifier_free(struct ModifierData *md);
+/**
+ * Use instead of `BLI_remlink` when the object's active modifier should change.
+ */
void BKE_modifier_remove_from_list(struct Object *ob, struct ModifierData *md);
/* Generate new UUID for the given modifier. */
@@ -420,6 +427,9 @@ void BKE_modifier_session_uuid_generate(struct ModifierData *md);
bool BKE_modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md);
+/**
+ * Callback's can use this to avoid copying every member.
+ */
void BKE_modifier_copydata_generic(const struct ModifierData *md,
struct ModifierData *md_dst,
const int flag);
@@ -434,9 +444,21 @@ bool BKE_modifier_couldbe_cage(struct Scene *scene, struct ModifierData *md);
bool BKE_modifier_is_correctable_deformed(struct ModifierData *md);
bool BKE_modifier_is_same_topology(ModifierData *md);
bool BKE_modifier_is_non_geometrical(ModifierData *md);
+/**
+ * Check whether is enabled.
+ *
+ * \param scene: Current scene, may be NULL,
+ * in which case `isDisabled` callback of the modifier is never called.
+ */
bool BKE_modifier_is_enabled(const struct Scene *scene,
struct ModifierData *md,
int required_mode);
+/**
+ * Check whether given modifier is not local (i.e. from linked data) when the object is a library
+ * override.
+ *
+ * \param md: May be NULL, in which case we consider it as a non-local modifier case.
+ */
bool BKE_modifier_is_nonlocal_in_liboverride(const struct Object *ob,
const struct ModifierData *md);
void BKE_modifier_set_error(const struct Object *ob,
@@ -451,6 +473,12 @@ void BKE_modifiers_foreach_tex_link(struct Object *ob, TexWalkFunc walk, void *u
struct ModifierData *BKE_modifiers_findby_type(const struct Object *ob, ModifierType type);
struct ModifierData *BKE_modifiers_findby_name(const struct Object *ob, const char *name);
void BKE_modifiers_clear_errors(struct Object *ob);
+/**
+ * used for buttons, to find out if the 'draw deformed in edit-mode option is there.
+ *
+ * Also used in transform_conversion.c, to detect crazy-space (2nd arg then is NULL).
+ * Also used for some mesh tools to give warnings.
+ */
int BKE_modifiers_get_cage_index(const struct Scene *scene,
struct Object *ob,
int *r_lastPossibleCageIndex,
@@ -461,9 +489,21 @@ bool BKE_modifiers_is_softbody_enabled(struct Object *ob);
bool BKE_modifiers_is_cloth_enabled(struct Object *ob);
bool BKE_modifiers_is_particle_enabled(struct Object *ob);
+/**
+ * Takes an object and returns its first selected armature, else just its armature.
+ * This should work for multiple armatures per object.
+ */
struct Object *BKE_modifiers_is_deformed_by_armature(struct Object *ob);
struct Object *BKE_modifiers_is_deformed_by_meshdeform(struct Object *ob);
+/**
+ * Takes an object and returns its first selected lattice, else just its lattice.
+ * This should work for multiple lattices per object.
+ */
struct Object *BKE_modifiers_is_deformed_by_lattice(struct Object *ob);
+/**
+ * Takes an object and returns its first selected curve, else just its curve.
+ * This should work for multiple curves per object.
+ */
struct Object *BKE_modifiers_is_deformed_by_curve(struct Object *ob);
bool BKE_modifiers_uses_multires(struct Object *ob);
bool BKE_modifiers_uses_armature(struct Object *ob, struct bArmature *arm);
@@ -500,23 +540,36 @@ typedef struct VirtualModifierData {
ShapeKeyModifierData smd;
} VirtualModifierData;
+/**
+ * This is to include things that are not modifiers in the evaluation of the modifier stack,
+ * for example parenting to an armature.
+ */
struct ModifierData *BKE_modifiers_get_virtual_modifierlist(const struct Object *ob,
struct VirtualModifierData *data);
-/** Ensure modifier correctness when changing ob->data. */
+/**
+ * Ensure modifier correctness when changing `ob->data`.
+ */
void BKE_modifiers_test_object(struct Object *ob);
-/* here for do_versions */
+/**
+ * Here for #do_versions.
+ */
void BKE_modifier_mdef_compact_influences(struct ModifierData *md);
+/**
+ * Initializes `path` with either the blend file or temporary directory.
+ */
void BKE_modifier_path_init(char *path, int path_maxlen, const char *name);
const char *BKE_modifier_path_relbase(struct Main *bmain, struct Object *ob);
const char *BKE_modifier_path_relbase_from_global(struct Object *ob);
/* Accessors of original/evaluated modifiers. */
-/* For a given modifier data, get corresponding original one.
- * If the modifier data is already original, return it as-is. */
+/**
+ * For a given modifier data, get corresponding original one.
+ * If the modifier data is already original, return it as-is.
+ */
struct ModifierData *BKE_modifier_get_original(struct ModifierData *md);
struct ModifierData *BKE_modifier_get_evaluated(struct Depsgraph *depsgraph,
struct Object *object,
@@ -541,6 +594,15 @@ void BKE_modifier_deform_vertsEM(ModifierData *md,
float (*vertexCos)[3],
int numVerts);
+/**
+ * Get evaluated mesh for other evaluated object, which is used as an operand for the modifier,
+ * e.g. second operand for boolean modifier.
+ * Note that modifiers in stack always get fully evaluated COW ID pointers,
+ * never original ones. Makes things simpler.
+ *
+ * \param get_cage_mesh: Return evaluated mesh with only deforming modifiers applied
+ * (i.e. mesh topology remains the same as original one, a.k.a. 'cage' mesh).
+ */
struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval,
const bool get_cage_mesh);
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 73c7494b8fa..9148d5b760f 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -35,6 +35,10 @@ struct MovieClipScopes;
struct MovieClipUser;
struct MovieDistortion;
+/**
+ * Checks if image was already loaded, then returns same image otherwise creates new.
+ * does not load ibuf itself pass on optional frame for #name images.
+ */
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
struct MovieClip *BKE_movieclip_file_add_exists_ex(struct Main *bmain,
const char *filepath,
@@ -44,6 +48,11 @@ void BKE_movieclip_reload(struct Main *bmain, struct MovieClip *clip);
void BKE_movieclip_clear_cache(struct MovieClip *clip);
void BKE_movieclip_clear_proxy_cache(struct MovieClip *clip);
+/**
+ * Will try to make image buffer usable when originating from the multi-layer source.
+ * Internally finds a first combined pass and uses that as a buffer.
+ * Not ideal, but is better than a complete empty buffer.
+ */
void BKE_movieclip_convert_multilayer_ibuf(struct ImBuf *ibuf);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
@@ -75,11 +84,18 @@ void BKE_movieclip_update_scopes(struct MovieClip *clip,
struct MovieClipUser *user,
struct MovieClipScopes *scopes);
+/**
+ * Get segments of cached frames. useful for debugging cache policies.
+ */
void BKE_movieclip_get_cache_segments(struct MovieClip *clip,
struct MovieClipUser *user,
int *r_totseg,
int **r_points);
+/**
+ * \note currently used by proxy job for movies, threading happens within single frame
+ * (meaning scaling shall be threaded).
+ */
void BKE_movieclip_build_proxy_frame(struct MovieClip *clip,
int clip_flag,
struct MovieDistortion *distortion,
@@ -88,6 +104,10 @@ void BKE_movieclip_build_proxy_frame(struct MovieClip *clip,
int build_count,
bool undistorted);
+/**
+ * \note currently used by proxy job for sequences, threading happens within sequence
+ * (different threads handles different frames, no threading within frame is needed)
+ */
void BKE_movieclip_build_proxy_frame_for_ibuf(struct MovieClip *clip,
struct ImBuf *ibuf,
struct MovieDistortion *distortion,
@@ -104,8 +124,10 @@ void BKE_movieclip_filename_for_frame(struct MovieClip *clip,
struct MovieClipUser *user,
char *name);
-/* Read image buffer from the given movie clip without acquiring the `LOCK_MOVIECLIP` lock.
- * Used by a prefetch job which takes care of creating a local copy of the clip. */
+/**
+ * Read image buffer from the given movie clip without acquiring the #LOCK_MOVIECLIP lock.
+ * Used by a prefetch job which takes care of creating a local copy of the clip.
+ */
struct ImBuf *BKE_movieclip_anim_ibuf_for_frame_no_lock(struct MovieClip *clip,
struct MovieClipUser *user);
@@ -126,10 +148,10 @@ void BKE_movieclip_eval_update(struct Depsgraph *depsgraph,
struct MovieClip *clip);
void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, struct MovieClip *clip);
-/* caching flags */
+/** Caching flags. */
#define MOVIECLIP_CACHE_SKIP (1 << 0)
-/* postprocessing flags */
+/** Post-processing flags. */
#define MOVIECLIP_DISABLE_RED (1 << 0)
#define MOVIECLIP_DISABLE_GREEN (1 << 1)
#define MOVIECLIP_DISABLE_BLUE (1 << 2)
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 11bfc4b2b3a..c83022c4658 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -45,7 +45,9 @@ struct MLoopTri;
struct MPoly;
struct MVert;
-/* Delete mesh mdisps and grid paint masks */
+/**
+ * Delete mesh mdisps and grid paint masks.
+ */
void multires_customdata_delete(struct Mesh *me);
void multires_set_tot_level(struct Object *ob, struct MultiresModifierData *mmd, int lvl);
@@ -62,6 +64,9 @@ void multires_force_external_reload(struct Object *object);
void multires_modifier_update_mdisps(struct DerivedMesh *dm, struct Scene *scene);
void multires_modifier_update_hidden(struct DerivedMesh *dm);
+/**
+ * Reset the multi-res levels to match the number of mdisps.
+ */
void multiresModifier_set_levels_from_disps(struct MultiresModifierData *mmd, struct Object *ob);
typedef enum {
@@ -79,6 +84,10 @@ struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm,
struct MultiresModifierData *find_multires_modifier_before(struct Scene *scene,
struct ModifierData *lastmd);
+/**
+ * used for applying scale on mdisps layer and syncing subdivide levels when joining objects.
+ * \param use_first: return first multi-res modifier if all multi-res'es are disabled.
+ */
struct MultiresModifierData *get_multires_modifier(struct Scene *scene,
struct Object *ob,
bool use_first);
@@ -88,18 +97,25 @@ int multires_get_level(const struct Scene *scene,
bool render,
bool ignore_simplify);
-/* Creates mesh with multires modifier applied on current object's deform mesh. */
+/**
+ * Creates mesh with multi-res modifier applied on current object's deform mesh.
+ */
struct Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph,
struct Object *object,
struct MultiresModifierData *mmd);
-/* Get coordinates of a deformed base mesh which is an input to the given multires modifier.
- * NOTE: The modifiers will be re-evaluated. */
+/**
+ * Get coordinates of a deformed base mesh which is an input to the given multi-res modifier.
+ * \note The modifiers will be re-evaluated.
+ */
float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *depsgraph,
struct Object *object,
struct MultiresModifierData *mmd,
int *r_num_deformed_verts))[3];
+/**
+ * \param direction: 1 for delete higher, 0 for lower (not implemented yet).
+ */
void multiresModifier_del_levels(struct MultiresModifierData *mmd,
struct Scene *scene,
struct Object *object,
@@ -112,6 +128,10 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph,
struct MultiresModifierData *mmd,
int rebuild_limit,
bool switch_view_to_lower_level);
+/**
+ * If `ob_src` and `ob_dst` both have multi-res modifiers,
+ * synchronize them such that `ob_dst` has the same total number of levels as `ob_src`.
+ */
void multiresModifier_sync_levels_ex(struct Object *ob_dst,
struct MultiresModifierData *mmd_src,
struct MultiresModifierData *mmd_dst);
@@ -128,15 +148,29 @@ void multiresModifier_prepare_join(struct Depsgraph *depsgraph,
int multires_mdisp_corners(struct MDisps *s);
-/* update multires data after topology changing */
+/**
+ * Update multi-res data after topology changing.
+ */
void multires_topology_changed(struct Mesh *me);
+/**
+ * Makes sure data from an external file is fully read.
+ *
+ * Since the multi-res data files only contain displacement vectors without knowledge about
+ * subdivision level some extra work is needed. Namely make is to all displacement grids have
+ * proper level and number of displacement vectors set.
+ */
void multires_ensure_external_read(struct Mesh *mesh, int top_level);
void multiresModifier_ensure_external_read(struct Mesh *mesh,
const struct MultiresModifierData *mmd);
/**** interpolation stuff ****/
+/* Adapted from `sculptmode.c` */
+
void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v);
+/**
+ * Find per-corner coordinate with given per-face UV coord.
+ */
int mdisp_rot_face_to_crn(struct MVert *mvert,
struct MPoly *mpoly,
struct MLoop *mloop,
@@ -154,6 +188,12 @@ bool multiresModifier_reshapeFromVertcos(struct Depsgraph *depsgraph,
struct MultiresModifierData *mmd,
const float (*vert_coords)[3],
const int num_vert_coords);
+/**
+ * Returns truth on success, false otherwise.
+ *
+ * This function might fail in cases like source and destination not having
+ * matched amount of vertices.
+ */
bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph,
struct MultiresModifierData *mmd,
struct Object *dst,
@@ -166,7 +206,7 @@ bool multiresModifier_reshapeFromCCG(const int tot_level,
struct Mesh *coarse_mesh,
struct SubdivCCG *subdiv_ccg);
-/* Subdivide multires displacement once. */
+/* Subdivide multi-res displacement once. */
typedef enum eMultiresSubdivideModeType {
MULTIRES_SUBDIVIDE_CATMULL_CLARK,
@@ -180,8 +220,10 @@ void multiresModifier_subdivide(struct Object *object,
void multires_subdivide_create_tangent_displacement_linear_grids(struct Object *object,
struct MultiresModifierData *mmd);
-/* Subdivide displacement to the given level.
- * If level is lower than the current top level nothing happens. */
+/**
+ * Subdivide displacement to the given level.
+ * If level is lower than the current top level nothing happens.
+ */
void multiresModifier_subdivide_to_level(struct Object *object,
struct MultiresModifierData *mmd,
const int top_level,
@@ -206,12 +248,12 @@ void BKE_multires_subdiv_mesh_settings_init(struct SubdivToMeshSettings *mesh_se
/* General helpers. */
-/* For a given partial derivatives of a ptex face get tangent matrix for
- * displacement.
+/**
+ * For a given partial derivatives of a PTEX face get tangent matrix for displacement.
*
* Corner needs to be known to properly "rotate" partial derivatives when the
- * matrix is being constructed for quad. For non-quad the corner is to be set
- * to 0. */
+ * matrix is being constructed for quad. For non-quad the corner is to be set to 0.
+ */
BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3],
const float dPdu[3],
const float dPdv[3],
@@ -219,8 +261,10 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3]
/* Versioning. */
-/* Convert displacement which is stored for simply-subdivided mesh to a Catmull-Clark
- * subdivided mesh. */
+/**
+ * Convert displacement which is stored for simply-subdivided mesh to a Catmull-Clark
+ * subdivided mesh.
+ */
void multires_do_versions_simple_to_catmull_clark(struct Object *object,
struct MultiresModifierData *mmd);
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index cf8848fe607..b297851ad90 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -46,106 +46,291 @@ struct PropertyRNA;
/* ----------------------------- */
/* Data Management */
+/**
+ * Remove the given NLA strip from the NLA track it occupies, free the strip's data,
+ * and the strip itself.
+ */
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user);
+/**
+ * Remove the given NLA track from the set of NLA tracks, free the track's data,
+ * and the track itself.
+ */
void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user);
+/**
+ * Free the elements of type NLA Tracks provided in the given list, but do not free
+ * the list itself since that is not free-standing
+ */
void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user);
+/**
+ * Copy NLA strip
+ *
+ * \param use_same_action: When true, the existing action is used (instead of being duplicated)
+ * \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
+ * flags in BKE_lib_id.h
+ */
struct NlaStrip *BKE_nlastrip_copy(struct Main *bmain,
struct NlaStrip *strip,
const bool use_same_action,
const int flag);
+/**
+ * Copy a single NLA Track.
+ * \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
+ * flags in BKE_lib_id.h
+ */
struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain,
struct NlaTrack *nlt,
const bool use_same_actions,
const int flag);
+/**
+ * Copy all NLA data.
+ * \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
+ * flags in BKE_lib_id.h
+ */
void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, const ListBase *src, const int flag);
-/* Copy NLA tracks from #adt_source to #adt_dest, and update the active track/strip pointers to
- * point at those copies. */
+/**
+ * Copy NLA tracks from #adt_source to #adt_dest, and update the active track/strip pointers to
+ * point at those copies.
+ */
void BKE_nla_tracks_copy_from_adt(struct Main *bmain,
struct AnimData *adt_dest,
const struct AnimData *adt_source,
int flag);
+/**
+ * Add a NLA Track to the given AnimData.
+ * \param prev: NLA-Track to add the new one after.
+ */
struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt,
struct NlaTrack *prev,
bool is_liboverride);
+/**
+ * Create a NLA Strip referencing the given Action.
+ */
struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
+/**
+ * Add new NLA-strip to the top of the NLA stack - i.e.
+ * into the last track if space, or a new one otherwise.
+ */
struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt,
struct bAction *act,
const bool is_liboverride);
+/**
+ * Add a NLA Strip referencing the given speaker's sound.
+ */
struct NlaStrip *BKE_nla_add_soundstrip(struct Main *bmain,
struct Scene *scene,
struct Speaker *speaker);
+/**
+ * Callback used by lib_query to walk over all ID usages
+ * (mimics `foreach_id` callback of #IDTypeInfo structure).
+ */
void BKE_nla_strip_foreach_id(struct NlaStrip *strip, struct LibraryForeachIDData *data);
/* ----------------------------- */
/* API */
+/**
+ * Check if there is any space in the given list to add the given strip.
+ */
bool BKE_nlastrips_has_space(ListBase *strips, float start, float end);
+/**
+ * Rearrange the strips in the track so that they are always in order
+ * (usually only needed after a strip has been moved)
+ */
void BKE_nlastrips_sort_strips(ListBase *strips);
+/**
+ * Add the given NLA-Strip to the given list of strips, assuming that it
+ * isn't currently a member of another list
+ */
bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
+/**
+ * Convert 'islands' (i.e. continuous string of) selected strips to be
+ * contained within 'Meta-Strips' which act as strips which contain strips.
+ *
+ * \param is_temp: are the meta-strips to be created 'temporary' ones used for transforms?
+ */
void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp);
+/**
+ * Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips.
+ *
+ * \param only_sel: only consider selected meta-strips, otherwise all meta-strips are removed
+ * \param only_temp: only remove the 'temporary' meta-strips used for transforms
+ */
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp);
+/**
+ * Split a meta-strip into a set of normal strips.
+ */
void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip);
+/**
+ * Add the given NLA-Strip to the given Meta-Strip, assuming that the
+ * strip isn't attached to any list of strips
+ */
bool BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip);
+/**
+ * Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively),
+ * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
+ */
void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip);
/* ............ */
+/**
+ * Find the active NLA-track for the given stack.
+ */
struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
+/**
+ * Make the given NLA-track the active one for the given stack. If no track is provided,
+ * this function can be used to simply deactivate all the NLA tracks in the given stack too.
+ */
void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
+/**
+ * Get the NLA Track that the active action/action strip comes from,
+ * since this info is not stored in AnimData. It also isn't as simple
+ * as just using the active track, since multiple tracks may have been
+ * entered at the same time.
+ */
struct NlaTrack *BKE_nlatrack_find_tweaked(struct AnimData *adt);
+/**
+ * Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
+ * that has this status in its AnimData block.
+ */
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt);
+/**
+ * Check if there is any space in the given track to add a strip of the given length.
+ */
bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
+/**
+ * Rearrange the strips in the track so that they are always in order
+ * (usually only needed after a strip has been moved).
+ */
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
+/**
+ * Add the given NLA-Strip to the given NLA-Track, assuming that it
+ * isn't currently attached to another one.
+ */
bool BKE_nlatrack_add_strip(struct NlaTrack *nlt,
struct NlaStrip *strip,
const bool is_liboverride);
+/**
+ * Get the extents of the given NLA-Track including gaps between strips,
+ * returning whether this succeeded or not
+ */
bool BKE_nlatrack_get_bounds(struct NlaTrack *nlt, float bounds[2]);
-
+/**
+ * Check whether given NLA track is not local (i.e. from linked data) when the object is a library
+ * override.
+ *
+ * \param nlt: May be NULL, in which case we consider it as a non-local track case.
+ */
bool BKE_nlatrack_is_nonlocal_in_liboverride(const struct ID *id, const struct NlaTrack *nlt);
/* ............ */
+/**
+ * Find the active NLA-strip within the given track.
+ */
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
+/**
+ * Make the given NLA-Strip the active one within the given block.
+ */
void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip);
+/**
+ * Does the given NLA-strip fall within the given bounds (times)?.
+ */
bool BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
+/**
+ * Recalculate the start and end frames for the current strip, after changing
+ * the extents of the action or the mapping (repeats or scale factor) info.
+ */
void BKE_nlastrip_recalculate_bounds(struct NlaStrip *strip);
+/**
+ * Recalculate the start and end frames for the strip to match the bounds of its action such that
+ * the overall NLA animation result is unchanged.
+ */
void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip);
+/**
+ * Find (and set) a unique name for a strip from the whole AnimData block
+ * Uses a similar method to the BLI method, but is implemented differently
+ * as we need to ensure that the name is unique over several lists of tracks,
+ * not just a single track.
+ */
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip);
/* ............ */
+/**
+ * Check if the given NLA-Track has any strips with own F-Curves.
+ */
bool BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt);
+/**
+ * Check if given NLA-Tracks have any strips with own F-Curves.
+ */
bool BKE_nlatracks_have_animated_strips(ListBase *tracks);
+/**
+ * Validate the NLA-Strips 'control' F-Curves based on the flags set.
+ */
void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip);
+/**
+ * Check if the given RNA pointer + property combo should be handled by
+ * NLA strip curves or not.
+ */
bool BKE_nlastrip_has_curves_for_property(const struct PointerRNA *ptr,
const struct PropertyRNA *prop);
+/**
+ * Ensure that auto-blending and other settings are set correctly.
+ */
void BKE_nla_validate_state(struct AnimData *adt);
/* ............ */
+/**
+ * Check if an action is "stashed" in the NLA already
+ *
+ * The criteria for this are:
+ * 1) The action in question lives in a "stash" track.
+ * 2) We only check first-level strips. That is, we will not check inside meta strips.
+ */
bool BKE_nla_action_is_stashed(struct AnimData *adt, struct bAction *act);
+/**
+ * "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing)
+ * to retain it in the file for future uses.
+ */
bool BKE_nla_action_stash(struct AnimData *adt, const bool is_liboverride);
/* ............ */
+/**
+ * For the given AnimData block, add the active action to the NLA
+ * stack (i.e. 'push-down' action). The UI should only allow this
+ * for normal editing only (i.e. not in edit-mode for some strip's action),
+ * so no checks for this are performed.
+ *
+ * TODO: maybe we should have checks for this too.
+ */
void BKE_nla_action_pushdown(struct AnimData *adt, const bool is_liboverride);
+/**
+ * Find the active strip + track combination, and set them up as the tweaking track,
+ * and return if successful or not.
+ */
bool BKE_nla_tweakmode_enter(struct AnimData *adt);
+/**
+ * Exit tweak-mode for this AnimData block.
+ */
void BKE_nla_tweakmode_exit(struct AnimData *adt);
/* ----------------------------- */
@@ -163,6 +348,13 @@ enum eNlaTime_ConvertModes {
NLATIME_CONVERT_MAP,
};
+/**
+ * Non clipped mapping for strip-time <-> global time:
+ * `mode = eNlaTime_ConvertModes -> NLATIME_CONVERT_*`
+ *
+ * Public API method - perform this mapping using the given AnimData block
+ * and perform any necessary sanity checks on the value
+ */
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode);
/* ----------------------------- */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index bbeb01de0ff..a2959556810 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -34,6 +34,10 @@
#include "RNA_types.h"
#ifdef __cplusplus
+# include "BLI_string_ref.hh"
+#endif
+
+#ifdef __cplusplus
extern "C" {
#endif
@@ -114,6 +118,7 @@ namespace nodes {
class NodeMultiFunctionBuilder;
class GeoNodeExecParams;
class NodeDeclarationBuilder;
+class GatherLinkSearchOpParams;
} // namespace nodes
namespace fn {
class CPPType;
@@ -121,23 +126,28 @@ class MFDataType;
} // namespace fn
} // namespace blender
+using CPPTypeHandle = blender::fn::CPPType;
using NodeMultiFunctionBuildFunction = void (*)(blender::nodes::NodeMultiFunctionBuilder &builder);
using NodeGeometryExecFunction = void (*)(blender::nodes::GeoNodeExecParams params);
using NodeDeclareFunction = void (*)(blender::nodes::NodeDeclarationBuilder &builder);
-using SocketGetCPPTypeFunction = const blender::fn::CPPType *(*)();
using SocketGetCPPValueFunction = void (*)(const struct bNodeSocket &socket, void *r_value);
-using SocketGetGeometryNodesCPPTypeFunction = const blender::fn::CPPType *(*)();
using SocketGetGeometryNodesCPPValueFunction = void (*)(const struct bNodeSocket &socket,
void *r_value);
+/* Adds socket link operations that are specific to this node type. */
+using NodeGatherSocketLinkOperationsFunction =
+ void (*)(blender::nodes::GatherLinkSearchOpParams &params);
+
#else
typedef void *NodeMultiFunctionBuildFunction;
typedef void *NodeGeometryExecFunction;
typedef void *NodeDeclareFunction;
+typedef void *NodeGatherSocketLinkOperationsFunction;
typedef void *SocketGetCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPValueFunction;
typedef void *SocketGetCPPValueFunction;
+typedef struct CPPTypeHandle CPPTypeHandle;
#endif
/**
@@ -164,20 +174,20 @@ typedef struct bNodeSocketType {
void (*interface_draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr);
void (*interface_draw_color)(struct bContext *C, struct PointerRNA *ptr, float *r_color);
void (*interface_register_properties)(struct bNodeTree *ntree,
- struct bNodeSocket *stemp,
+ struct bNodeSocket *interface_socket,
struct StructRNA *data_srna);
void (*interface_init_socket)(struct bNodeTree *ntree,
- struct bNodeSocket *stemp,
+ const struct bNodeSocket *interface_socket,
struct bNode *node,
struct bNodeSocket *sock,
const char *data_path);
void (*interface_verify_socket)(struct bNodeTree *ntree,
- struct bNodeSocket *stemp,
+ const struct bNodeSocket *interface_socket,
struct bNode *node,
struct bNodeSocket *sock,
const char *data_path);
void (*interface_from_socket)(struct bNodeTree *ntree,
- struct bNodeSocket *stemp,
+ struct bNodeSocket *interface_socket,
struct bNode *node,
struct bNodeSocket *sock);
@@ -197,11 +207,11 @@ typedef struct bNodeSocketType {
void (*free_self)(struct bNodeSocketType *stype);
/* Return the CPPType of this socket. */
- SocketGetCPPTypeFunction get_base_cpp_type;
+ const CPPTypeHandle *base_cpp_type;
/* Get the value of this socket in a generic way. */
SocketGetCPPValueFunction get_base_cpp_value;
/* Get geometry nodes cpp type. */
- SocketGetGeometryNodesCPPTypeFunction get_geometry_nodes_cpp_type;
+ const CPPTypeHandle *geometry_nodes_cpp_type;
/* Get geometry nodes cpp value. */
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value;
} bNodeSocketType;
@@ -229,8 +239,6 @@ typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat,
* implementing the node behavior.
*/
typedef struct bNodeType {
- void *next, *prev;
-
char idname[64]; /* identifier name */
int type;
@@ -247,18 +255,6 @@ typedef struct bNodeType {
char storagename[64]; /* struct name for DNA */
- /* Main draw function for the node */
- void (*draw_nodetype)(const struct bContext *C,
- struct ARegion *region,
- struct SpaceNode *snode,
- struct bNodeTree *ntree,
- struct bNode *node,
- bNodeInstanceKey key);
- /* Updates the node geometry attributes according to internal state before actual drawing */
- void (*draw_nodetype_prepare)(const struct bContext *C,
- struct bNodeTree *ntree,
- struct bNode *node);
-
/* Draw the option buttons on the node */
void (*draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
/* Additional parameters in the side panel */
@@ -272,13 +268,10 @@ typedef struct bNodeType {
* Optional custom label function for the node header.
* \note Used as a fallback when #bNode.label isn't set.
*/
- void (*labelfunc)(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
- /** Optional custom resize handle polling. */
- int (*resize_area_func)(struct bNode *node, int x, int y);
- /** Optional selection area polling. */
- int (*select_area_func)(struct bNode *node, int x, int y);
- /** Optional tweak area polling (for grabbing). */
- int (*tweak_area_func)(struct bNode *node, int x, int y);
+ void (*labelfunc)(const struct bNodeTree *ntree,
+ const struct bNode *node,
+ char *label,
+ int maxlen);
/** Called when the node is updated in the editor. */
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node);
@@ -301,7 +294,7 @@ typedef struct bNodeType {
/**
* Can this node type be added to a node tree?
- * \param r_disabled_hint: Optional hint to display in the UI when the poll fails.
+ * \param r_disabled_hint: Hint to display in the UI when the poll fails.
* The callback can set this to a static string without having to
* null-check it (or without setting it to null if it's not used).
* The caller must pass a valid `const char **` and null-initialize it
@@ -342,6 +335,13 @@ typedef struct bNodeType {
/* Declaration to be used when it is not dynamic. */
NodeDeclarationHandle *fixed_declaration;
+ /**
+ * Add to the list of search names and operations gathered by node link drag searching.
+ * Usually it isn't necessary to override the default behavior here, but a node type can have
+ * custom behavior here like adding custom search items.
+ */
+ NodeGatherSocketLinkOperationsFunction gather_link_search_ops;
+
/** True when the node cannot be muted. */
bool no_muting;
@@ -379,12 +379,6 @@ typedef struct bNodeType {
#define NODE_CLASS_ATTRIBUTE 42
#define NODE_CLASS_LAYOUT 100
-/* node resize directions */
-#define NODE_RESIZE_TOP 1
-#define NODE_RESIZE_BOTTOM 2
-#define NODE_RESIZE_RIGHT 4
-#define NODE_RESIZE_LEFT 8
-
typedef enum eNodeSizePreset {
NODE_SIZE_DEFAULT,
NODE_SIZE_SMALL,
@@ -425,7 +419,7 @@ typedef struct bNodeTreeType {
/* Tree update. Overrides `nodetype->updatetreefunc` ! */
void (*update)(struct bNodeTree *ntree);
- bool (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
+ bool (*validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to);
void (*node_add_init)(struct bNodeTree *ntree, struct bNode *bnode);
@@ -462,20 +456,44 @@ struct GHashIterator *ntreeTypeGetIterator(void);
} \
(void)0
+/**
+ * Try to initialize all type-info in a node tree.
+ *
+ * \note In general undefined type-info is a perfectly valid case,
+ * the type may just be registered later.
+ * In that case the update_typeinfo function will set type-info on registration
+ * and do necessary updates.
+ */
void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
+
+/**
+ * Free (or release) any data used by this node-tree.
+ * Does not free the node-tree itself and does no ID user counting.
+ */
void ntreeFreeTree(struct bNodeTree *ntree);
-/* Free tree which is embedded into another datablock. */
+/**
+ * Free tree which is embedded into another data-block.
+ */
void ntreeFreeEmbeddedTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree,
struct Main *bmain,
const bool do_id_user);
struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree);
+/**
+ * Get address of potential node-tree pointer of given ID.
+ *
+ * \warning Using this function directly is potentially dangerous, if you don't know or are not
+ * sure, please use `ntreeFromID()` instead.
+ */
struct bNodeTree **BKE_ntree_ptr_from_id(struct ID *id);
+/**
+ * Returns the private NodeTree object of the data-block, if it has one.
+ */
struct bNodeTree *ntreeFromID(struct ID *id);
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node);
@@ -485,13 +503,17 @@ bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree);
void ntreeUpdateAllNew(struct Main *main);
+/**
+ * \param tree_update_flag: #eNodeTreeUpdate enum.
+ */
void ntreeUpdateAllUsers(struct Main *main, struct ID *id, int tree_update_flag);
void ntreeGetDependencyList(struct bNodeTree *ntree,
struct bNode ***r_deplist,
int *r_deplist_len);
-/* XXX old trees handle output flags automatically based on special output
+/**
+ * XXX: old trees handle output flags automatically based on special output
* node types and last active selection.
* New tree types have a per-output socket flag to indicate the final output to use explicitly.
*/
@@ -502,11 +524,31 @@ void ntreeFreeCache(struct bNodeTree *ntree);
bool ntreeNodeExists(const struct bNodeTree *ntree, const struct bNode *testnode);
bool ntreeOutputExists(const struct bNode *node, const struct bNodeSocket *testsock);
void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable);
+/**
+ * Returns localized tree for execution in threads.
+ */
struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
+/**
+ * Sync local composite with real tree.
+ * The local tree is supposed to be running, be careful moving previews!
+ *
+ * Is called by jobs manager, outside threads, so it doesn't happen during draw.
+ */
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
+/**
+ * Merge local tree results back, and free local tree.
+ *
+ * We have to assume the editor already changed completely.
+ */
void ntreeLocalMerge(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree);
+/**
+ * This is only direct data, tree itself should have been written.
+ */
void ntreeBlendWrite(struct BlendWriter *writer, struct bNodeTree *ntree);
+/**
+ * \note `ntree` itself has been read!
+ */
void ntreeBlendReadData(struct BlendDataReader *reader, struct bNodeTree *ntree);
void ntreeBlendReadLib(struct BlendLibReader *reader, struct bNodeTree *ntree);
void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntree);
@@ -516,6 +558,7 @@ void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntre
/* -------------------------------------------------------------------- */
/** \name Node Tree Interface
* \{ */
+
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree,
eNodeSocketInOut in_out,
const char *identifier);
@@ -550,7 +593,7 @@ void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
struct bNodeType *nodeTypeFind(const char *idname);
void nodeRegisterType(struct bNodeType *ntype);
void nodeUnregisterType(struct bNodeType *ntype);
-bool nodeTypeUndefined(struct bNode *node);
+bool nodeTypeUndefined(const struct bNode *node);
struct GHashIterator *nodeTypeGetIterator(void);
/* Helper macros for iterating over node types. */
@@ -640,27 +683,42 @@ void nodeModifySocketTypeStatic(
struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
+/**
+ * \note Goes over entire tree.
+ */
void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
+/**
+ * Find the first available, non-duplicate name for a given node.
+ */
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
-/* Delete node, associated animation data and ID user count. */
+/**
+ * Delete node, associated animation data and ID user count.
+ */
void nodeRemoveNode(struct Main *bmain,
struct bNodeTree *ntree,
struct bNode *node,
bool do_id_user);
+/**
+ * \param ntree: is the target tree.
+ *
+ * \note keep socket list order identical, for copying links.
+ * \note `unique_name` needs to be true. It's only disabled for speed when doing GPUnodetrees.
+ */
struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree,
const struct bNode *node_src,
const int flag,
const bool unique_name);
-/* Same as BKE_node_copy_ex() but stores pointers to a new node and its sockets in the source
- * node.
+/**
+ * Same as #BKE_node_copy_ex but stores pointers to a new node and its sockets in the source node.
*
* NOTE: DANGER ZONE!
*
* TODO(sergey): Maybe it's better to make BKE_node_copy_ex() return a mapping from old node and
- * sockets to new one. */
+ * sockets to new one.
+ */
struct bNode *BKE_node_copy_store_new_pointers(struct bNodeTree *ntree,
struct bNode *node_src,
const int flag);
@@ -668,6 +726,9 @@ struct bNodeTree *ntreeCopyTree_ex_new_pointers(const struct bNodeTree *ntree,
struct Main *bmain,
const bool do_id_user);
+/**
+ * Also used via RNA API, so we check for proper input output direction.
+ */
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree,
struct bNode *fromnode,
struct bNodeSocket *fromsock,
@@ -691,25 +752,62 @@ void nodePositionRelative(struct bNode *from_node,
struct bNodeSocket *to_sock);
void nodePositionPropagate(struct bNode *node);
+/**
+ * Finds a node based on its name.
+ */
struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
+/**
+ * Finds a node based on given socket and returns true on success.
+ */
bool nodeFindNode(struct bNodeTree *ntree,
struct bNodeSocket *sock,
struct bNode **r_node,
int *r_sockindex);
+/**
+ * \note Recursive.
+ */
struct bNode *nodeFindRootParent(bNode *node);
+/**
+ * \returns true if \a child has \a parent as a parent/grandparent/... etc.
+ * \note Recursive
+ */
bool nodeIsChildOf(const bNode *parent, const bNode *child);
+/**
+ * Iterate over a chain of nodes, starting with \a node_start, executing
+ * \a callback for each node (which can return false to end iterator).
+ *
+ * \param reversed: for backwards iteration
+ * \note Recursive
+ */
void nodeChainIter(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *, const bool),
void *userdata,
const bool reversed);
+/**
+ * Iterate over a chain of nodes, starting with \a node_start, executing
+ * \a callback for each node (which can return false to end iterator).
+ *
+ * Faster than nodeChainIter. Iter only once per node.
+ * Can be called recursively (using another nodeChainIterBackwards) by
+ * setting the recursion_lvl accordingly.
+ *
+ * \note Needs updated socket links (ntreeUpdateTree).
+ * \note Recursive
+ */
void nodeChainIterBackwards(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
void *userdata,
int recursion_lvl);
+/**
+ * Iterate over all parents of \a node, executing \a callback for each parent
+ * (which can return false to end iterator)
+ *
+ * \note Recursive
+ */
void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree,
@@ -718,11 +816,20 @@ struct bNodeLink *nodeFindLink(struct bNodeTree *ntree,
int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock);
void nodeSetSelected(struct bNode *node, bool select);
+/**
+ * Two active flags, ID nodes have special flag for buttons display.
+ */
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeGetActive(struct bNodeTree *ntree);
+/**
+ * Two active flags, ID nodes have special flag for buttons display.
+ */
struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
bool nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id);
void nodeClearActive(struct bNodeTree *ntree);
+/**
+ * Two active flags, ID nodes have special flag for buttons display.
+ */
void nodeClearActiveID(struct bNodeTree *ntree, short idtype);
struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
@@ -738,14 +845,31 @@ void nodeSetSocketAvailability(struct bNodeTree *ntree,
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
+/**
+ * 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(struct bNodeTree *ntree, struct bNode *node);
+/**
+ * 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(struct bNodeTree *ntree, struct bNode *node);
+/**
+ * Update `socket->declaration` for all sockets in the node. This assumes that the node declaration
+ * and sockets are up to date already.
+ */
void nodeSocketDeclarationsUpdate(struct bNode *node);
-/* Node Clipboard */
+/**
+ * Node Clipboard.
+ */
void BKE_node_clipboard_init(const struct bNodeTree *ntree);
void BKE_node_clipboard_clear(void);
void BKE_node_clipboard_free(void);
+/**
+ * Return false when one or more ID's are lost.
+ */
bool BKE_node_clipboard_validate(void);
void BKE_node_clipboard_add_node(struct bNode *node);
void BKE_node_clipboard_add_link(struct bNodeLink *link);
@@ -753,7 +877,9 @@ const struct ListBase *BKE_node_clipboard_get_nodes(void);
const struct ListBase *BKE_node_clipboard_get_links(void);
int BKE_node_clipboard_get_type(void);
-/* Node Instance Hash */
+/**
+ * Node Instance Hash.
+ */
typedef struct bNodeInstanceHash {
/** XXX should be made a direct member, #GHash allocation needs to support it */
GHash *ghash;
@@ -761,6 +887,9 @@ typedef struct bNodeInstanceHash {
typedef void (*bNodeInstanceValueFP)(void *value);
+/**
+ * Magic number for initial hash key.
+ */
extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE;
extern const bNodeInstanceKey NODE_INSTANCE_KEY_NONE;
@@ -845,6 +974,11 @@ void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree,
struct bNodeTree *from_ntree,
bool remove_old);
+/**
+ * Hack warning! this function is only used for shader previews,
+ * and since it gets called multiple times per pixel for Z-transparency we only add the color once.
+ * Preview gets cleared before it starts render though.
+ */
void BKE_node_preview_set_pixel(
struct bNodePreview *preview, const float col[4], int x, int y, bool do_manage);
@@ -854,14 +988,19 @@ void BKE_node_preview_set_pixel(
/** \name Node Type Access
* \{ */
-void nodeLabel(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
+void nodeLabel(const struct bNodeTree *ntree, const struct bNode *node, char *label, int maxlen);
+/**
+ * Get node socket label if it is set.
+ */
const char *nodeSocketLabel(const struct bNodeSocket *sock);
bool nodeGroupPoll(struct bNodeTree *nodetree,
struct bNodeTree *grouptree,
const char **r_disabled_hint);
-/* Init a new node type struct with default values and callbacks */
+/**
+ * Initialize a new node type struct with default values and callbacks.
+ */
void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
void node_type_base_custom(
struct bNodeType *ntype, const char *idname, const char *name, short nclass, short flag);
@@ -872,15 +1011,16 @@ void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwid
void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size);
void node_type_init(struct bNodeType *ntype,
void (*initfunc)(struct bNodeTree *ntree, struct bNode *node));
+/**
+ * \warning Nodes defining a storage type _must_ allocate this for new nodes.
+ * Otherwise nodes will reload as undefined (T46619).
+ */
void node_type_storage(struct bNodeType *ntype,
const char *storagename,
void (*freefunc)(struct bNode *node),
void (*copyfunc)(struct bNodeTree *dest_ntree,
struct bNode *dest_node,
const struct bNode *src_node));
-void node_type_label(
- struct bNodeType *ntype,
- void (*labelfunc)(struct bNodeTree *ntree, struct bNode *, char *label, int maxlen));
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node));
void node_type_group_update(struct bNodeType *ntype,
@@ -986,6 +1126,7 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
} \
} \
((void)0)
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1121,8 +1262,21 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
+/**
+ Find an output node of the shader tree.
+ *
+ * \note it will only return output which is NOT in the group, which isn't how
+ * render engines works but it's how the GPU shader compilation works. This we
+ * can change in the future and make it a generic function, but for now it stays
+ * private here.
+ */
struct bNode *ntreeShaderOutputNode(struct bNodeTree *ntree, int target);
-
+/**
+ * This one needs to work on a local tree.
+ *
+ * TODO: This is *not* part of `blenkernel`, it's defined under "source/blender/nodes/".
+ * This declaration should be moved out of BKE.
+ */
void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
struct GPUMaterial *mat,
bool *has_surface_output,
@@ -1314,7 +1468,25 @@ void ntreeCompositExecTree(struct Scene *scene,
const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
const char *view_name);
+
+/**
+ * Called from render pipeline, to tag render input and output.
+ * need to do all scenes, to prevent errors when you re-render 1 scene.
+ */
void ntreeCompositTagRender(struct Scene *scene);
+/**
+ * Update the outputs of the render layer nodes.
+ * Since the outputs depend on the render engine, this part is a bit complex:
+ * - #ntreeCompositUpdateRLayers is called and loops over all render layer nodes.
+ * - Each render layer node calls the update function of the
+ * render engine that's used for its scene.
+ * - The render engine calls RE_engine_register_pass for each pass.
+ * - #RE_engine_register_pass calls #ntreeCompositRegisterPass,
+ * which calls #node_cmp_rlayers_register_pass for every render layer node.
+ *
+ * TODO: This is *not* part of `blenkernel`, it's defined under "source/blender/nodes/".
+ * This declaration should be moved out of BKE.
+ */
void ntreeCompositUpdateRLayers(struct bNodeTree *ntree);
void ntreeCompositRegisterPass(struct bNodeTree *ntree,
struct Scene *scene,
@@ -1355,8 +1527,10 @@ void ntreeCompositCryptomatteLayerPrefix(const Scene *scene,
const bNode *node,
char *r_prefix,
size_t prefix_len);
-/* Update the runtime layer names with the crypto-matte layer names of the references
- * render layer or image. */
+/**
+ * Update the runtime layer names with the crypto-matte layer names of the references render layer
+ * or image.
+ */
void ntreeCompositCryptomatteUpdateLayerNames(const Scene *scene, bNode *node);
struct CryptomatteSession *ntreeCompositCryptomatteSession(const Scene *scene, bNode *node);
@@ -1413,6 +1587,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
int cfra,
int preview,
struct MTex *mtex);
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1507,7 +1682,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_SAMPLE_CURVE 1085
#define GEO_NODE_INPUT_TANGENT 1086
#define GEO_NODE_STRING_JOIN 1087
-#define GEO_NODE_CURVE_PARAMETER 1088
+#define GEO_NODE_CURVE_SPLINE_PARAMETER 1088
#define GEO_NODE_FILLET_CURVE 1089
#define GEO_NODE_DISTRIBUTE_POINTS_ON_FACES 1090
#define GEO_NODE_STRING_TO_CURVES 1091
@@ -1554,6 +1729,16 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_VOLUME_TO_MESH 1133
#define GEO_NODE_INPUT_ID 1134
#define GEO_NODE_SET_ID 1135
+#define GEO_NODE_ATTRIBUTE_DOMAIN_SIZE 1136
+#define GEO_NODE_DUAL_MESH 1137
+#define GEO_NODE_INPUT_MESH_EDGE_VERTICES 1138
+#define GEO_NODE_INPUT_MESH_FACE_AREA 1139
+#define GEO_NODE_INPUT_MESH_FACE_NEIGHBORS 1140
+#define GEO_NODE_INPUT_MESH_VERTEX_NEIGHBORS 1141
+#define GEO_NODE_GEOMETRY_TO_INSTANCE 1142
+#define GEO_NODE_INPUT_MESH_EDGE_NEIGHBORS 1143
+#define GEO_NODE_INPUT_MESH_ISLAND 1144
+#define GEO_NODE_INPUT_SCENE_TIME 1145
/** \} */
@@ -1562,7 +1747,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
* \{ */
#define FN_NODE_BOOLEAN_MATH 1200
-#define FN_NODE_COMPARE_FLOATS 1202
+#define FN_NODE_COMPARE 1202
#define FN_NODE_LEGACY_RANDOM_FLOAT 1206
#define FN_NODE_INPUT_VECTOR 1207
#define FN_NODE_INPUT_STRING 1208
@@ -1599,3 +1784,25 @@ extern struct bNodeSocketType NodeSocketTypeUndefined;
#ifdef __cplusplus
}
#endif
+
+#ifdef __cplusplus
+
+namespace blender::bke {
+
+bNodeSocket *node_find_enabled_socket(bNode &node, eNodeSocketInOut in_out, StringRef name);
+bNodeSocket *node_find_enabled_input_socket(bNode &node, StringRef name);
+bNodeSocket *node_find_enabled_output_socket(bNode &node, StringRef name);
+
+} // namespace blender::bke
+
+#endif
+
+#define NODE_STORAGE_FUNCS(StorageT) \
+ [[maybe_unused]] static StorageT &node_storage(bNode &node) \
+ { \
+ return *static_cast<StorageT *>(node.storage); \
+ } \
+ [[maybe_unused]] static const StorageT &node_storage(const bNode &node) \
+ { \
+ return *static_cast<const StorageT *>(node.storage); \
+ }
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 4e53af5562f..03565bd3bda 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -52,6 +52,14 @@ struct View3D;
struct ViewLayer;
void BKE_object_workob_clear(struct Object *workob);
+/**
+ * For calculation of the inverse parent transform, only used for editor.
+ *
+ * It assumes the object parent is already in the depsgraph.
+ * Otherwise, after changing ob->parent you need to call:
+ * - #DEG_relations_tag_update(bmain);
+ * - #BKE_scene_graph_update_tagged(depsgraph, bmain);
+ */
void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
@@ -67,6 +75,9 @@ void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_curve_cache(struct Object *ob);
+/**
+ * Free data derived from mesh, called when mesh changes or is freed.
+ */
void BKE_object_free_derived_caches(struct Object *ob);
void BKE_object_free_caches(struct Object *object);
@@ -77,19 +88,55 @@ bool BKE_object_modifier_gpencil_use_time(struct Object *ob, struct GpencilModif
bool BKE_object_shaderfx_use_time(struct Object *ob, struct ShaderFxData *fx);
+/**
+ * \return True if the object's type supports regular modifiers (not grease pencil modifiers).
+ */
bool BKE_object_supports_modifiers(const struct Object *ob);
bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifier_type);
/* Active modifier. */
+
+/**
+ * Set the object's active modifier.
+ *
+ * \param md: If nullptr, only clear the active modifier, otherwise
+ * it must be in the #Object.modifiers list.
+ */
void BKE_object_modifier_set_active(struct Object *ob, struct ModifierData *md);
struct ModifierData *BKE_object_active_modifier(const struct Object *ob);
+/**
+ * Copy a single modifier.
+ *
+ * \note *Do not* use this function to copy a whole modifier stack (see note below too). Use
+ * `BKE_object_modifier_stack_copy` instead.
+ *
+ * \note Complex modifiers relaying on other data (like e.g. dynamic paint or fluid using particle
+ * systems) are not always 100% 'correctly' copied here, since we have to use heuristics to decide
+ * which particle system to use or add in `ob_dst`, and it's placement in the stack, etc. If used
+ * more than once, this function should preferably be called in stack order.
+ */
bool BKE_object_copy_modifier(struct Main *bmain,
struct Scene *scene,
struct Object *ob_dst,
const struct Object *ob_src,
struct ModifierData *md);
+/**
+ * Copy a single GPencil modifier.
+ *
+ * \note *Do not* use this function to copy a whole modifier stack. Use
+ * `BKE_object_modifier_stack_copy` instead.
+ */
bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, struct GpencilModifierData *gmd_src);
+/**
+ * Copy the whole stack of modifiers from one object into another.
+ *
+ * \warning *Does not* clear modifier stack and related data (particle systems, soft-body,
+ * etc.) in `ob_dst`, if needed calling code must do it.
+ *
+ * \param do_copy_all: If true, even modifiers that should not support copying (like Hook one)
+ * will be duplicated.
+ */
bool BKE_object_modifier_stack_copy(struct Object *ob_dst,
const struct Object *ob_src,
const bool do_copy_all,
@@ -98,6 +145,12 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
void BKE_object_free_modifiers(struct Object *ob, const int flag);
void BKE_object_free_shaderfx(struct Object *ob, const int flag);
+/**
+ * Proxy rule:
+ * - `lib_object->proxy_from` == the one we borrow from, set temporally while object_update.
+ * - `local_object->proxy` == pointer to library object, saved in files and read.
+ * - `local_object->proxy_group` == pointer to collection dupli-object, saved in files and read.
+ */
void BKE_object_make_proxy(struct Main *bmain,
struct Object *ob,
struct Object *target,
@@ -105,6 +158,9 @@ void BKE_object_make_proxy(struct Main *bmain,
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
+/**
+ * Actual check for internal data, not context or flags.
+ */
bool BKE_object_is_in_editmode(const struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(const struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob);
@@ -115,6 +171,9 @@ bool BKE_object_data_is_in_editmode(const struct ID *id);
char *BKE_object_data_editmode_flush_ptr_get(struct ID *id);
+/**
+ * Updates select_id of all objects in the given \a bmain.
+ */
void BKE_object_update_select_id(struct Main *bmain);
typedef enum eObjectVisibilityResult {
@@ -124,14 +183,33 @@ typedef enum eObjectVisibilityResult {
OB_VISIBLE_ALL = (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES | OB_VISIBLE_INSTANCES),
} eObjectVisibilityResult;
+/**
+ * Return which parts of the object are visible, as evaluated by depsgraph.
+ */
int BKE_object_visibility(const struct Object *ob, const int dag_eval_mode);
+/**
+ * More general add: creates minimum required data, but without vertices etc.
+ */
struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name)
ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
+/**
+ * General add: to scene, with layer from area and default name.
+ *
+ * Object is added to the active #Collection.
+ * If there is no linked collection to the active #ViewLayer we create a new one.
+ *
+ * \note Creates minimum required data, but without vertices etc.
+ */
struct Object *BKE_object_add(struct Main *bmain,
struct ViewLayer *view_layer,
int type,
const char *name) ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+/**
+ * Add a new object, using another one as a reference
+ *
+ * \param ob_src: object to use to determine the collections of the new object.
+ */
struct Object *BKE_object_add_from(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
@@ -139,6 +217,15 @@ struct Object *BKE_object_add_from(struct Main *bmain,
const char *name,
struct Object *ob_src)
ATTR_NONNULL(1, 2, 3, 6) ATTR_RETURNS_NONNULL;
+/**
+ * Add a new object, but assign the given data-block as the `ob->data`
+ * for the newly created 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.
+ */
struct Object *BKE_object_add_for_data(struct Main *bmain,
struct ViewLayer *view_layer,
int type,
@@ -147,16 +234,39 @@ struct Object *BKE_object_add_for_data(struct Main *bmain,
bool do_id_user) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(struct Main *bmain, int type, const char *name)
ATTR_NONNULL(1);
+/**
+ * Return -1 on failure.
+ */
int BKE_object_obdata_to_type(const struct ID *id) ATTR_NONNULL(1);
+/**
+ * Returns true if the Object is from an external blend file (libdata).
+ */
bool BKE_object_is_libdata(const struct Object *ob);
+/**
+ * Returns true if the Object data is from an external blend file (libdata).
+ */
bool BKE_object_obdata_is_libdata(const struct Object *ob);
+/**
+ * Perform deep-copy of object and its 'children' data-blocks (obdata, materials, actions, etc.).
+ *
+ * \param dupflag: Controls which sub-data are also duplicated
+ * (see #eDupli_ID_Flags in DNA_userdef_types.h).
+ *
+ * \note This function does not do any remapping to new IDs, caller must do it
+ * (\a #BKE_libblock_relink_to_newid()).
+ * \note Caller MUST free \a newid pointers itself (#BKE_main_id_newptr_and_tag_clear()) and call
+ * updates of DEG too (#DAG_relations_tag_update()).
+ */
struct Object *BKE_object_duplicate(struct Main *bmain,
struct Object *ob,
uint dupflag,
uint duplicate_options);
+/**
+ * Use with newly created objects to set their size (used to apply scene-scale).
+ */
void BKE_object_obdata_size_init(struct Object *ob, const float size);
void BKE_object_scale_to_mat3(struct Object *ob, float r_mat[3][3]);
@@ -164,15 +274,26 @@ void BKE_object_rot_to_mat3(const struct Object *ob, float r_mat[3][3], bool use
void BKE_object_mat3_to_rot(struct Object *ob, float r_mat[3][3], bool use_compat);
void BKE_object_to_mat3(struct Object *ob, float r_mat[3][3]);
void BKE_object_to_mat4(struct Object *ob, float r_mat[4][4]);
-void BKE_object_apply_mat4(struct Object *ob,
- const float mat[4][4],
- const bool use_compat,
- const bool use_parent);
+/**
+ * Applies the global transformation \a mat to the \a ob using a relative parent space if
+ * supplied.
+ *
+ * \param mat: the global transformation mat that the object should be set object to.
+ * \param parent: the parent space in which this object will be set relative to
+ * (should probably always be parent_eval).
+ * \param use_compat: true to ensure that rotations are set using the
+ * min difference between the old and new orientation.
+ */
void BKE_object_apply_mat4_ex(struct Object *ob,
const float mat[4][4],
struct Object *parent,
const float parentinv[4][4],
const bool use_compat);
+/** See #BKE_object_apply_mat4_ex */
+void BKE_object_apply_mat4(struct Object *ob,
+ const float mat[4][4],
+ const bool use_compat,
+ const bool use_parent);
void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4]);
bool BKE_object_pose_context_check(const struct Object *ob);
@@ -181,6 +302,9 @@ struct Object *BKE_object_pose_armature_get_visible(struct Object *ob,
struct ViewLayer *view_layer,
struct View3D *v3d);
+/**
+ * Access pose array with special check to get pose object when in weight paint mode.
+ */
struct Object **BKE_object_pose_array_get_ex(struct ViewLayer *view_layer,
struct View3D *v3d,
unsigned int *r_objects_len,
@@ -205,7 +329,9 @@ struct Base **BKE_object_pose_base_array_get(struct ViewLayer *view_layer,
void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4]);
-/* Compute object world transform and store it in ob->obmat. */
+/**
+ * Compute object world transform and store it in `ob->obmat`.
+ */
void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_object_where_is_calc_ex(struct Depsgraph *depsgraph,
struct Scene *scene,
@@ -216,9 +342,16 @@ void BKE_object_where_is_calc_time(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
float ctime);
+/**
+ * Calculate object transformation matrix without recalculating dependencies and
+ * constraints -- assume dependencies are already solved by depsgraph.
+ * No changes to object and its parent would be done.
+ * Used for bundles orientation in 3d space relative to parented blender camera.
+ */
void BKE_object_where_is_calc_mat4(struct Object *ob, float r_obmat[4][4]);
/* Possibly belong in own module? */
+
struct BoundBox *BKE_boundbox_alloc_unit(void);
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3]);
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
@@ -230,6 +363,14 @@ void BKE_boundbox_minmax(const struct BoundBox *bb,
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float r_vec[3]);
+/**
+ * The original scale and object matrix can be passed in so any difference
+ * of the objects matrix and the final matrix can be accounted for,
+ * typically this caused by parenting, constraints or delta-scale.
+ *
+ * Re-using these values from the object causes a feedback loop
+ * when multiple values are modified at once in some situations. see: T69536.
+ */
void BKE_object_dimensions_set_ex(struct Object *ob,
const float value[3],
int axis_mask,
@@ -238,8 +379,12 @@ void BKE_object_dimensions_set_ex(struct Object *ob,
void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis_mask);
void BKE_object_empty_draw_type_set(struct Object *ob, const int value);
+/**
+ * Use this to temporally disable/enable bound-box.
+ */
void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set);
void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval);
+bool BKE_object_boundbox_calc_from_evaluated_geometry(struct Object *ob);
void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph,
struct Scene *scene,
@@ -248,7 +393,9 @@ bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph,
float r_max[3],
const bool use_hidden);
-/* sometimes min-max isn't enough, we need to loop over each point */
+/**
+ * Sometimes min-max isn't enough, we need to loop over each point.
+ */
void BKE_object_foreach_display_point(struct Object *ob,
const float obmat[4][4],
void (*func_cb)(const float[3], void *),
@@ -279,9 +426,18 @@ void BKE_object_tfm_protected_restore(struct Object *ob,
void BKE_object_tfm_copy(struct Object *object_dst, const struct Object *object_src);
+/**
+ * Restore the object->data to a non-modifier evaluated state.
+ *
+ * Some changes done directly in evaluated object require them to be reset
+ * before being re-evaluated.
+ * For example, we need to call this before #BKE_mesh_new_from_object(),
+ * in case we removed/added modifiers in the evaluated object.
+ */
void BKE_object_eval_reset(struct Object *ob_eval);
/* Dependency graph evaluation callbacks. */
+
void BKE_object_eval_local_transform(struct Depsgraph *depsgraph, struct Object *ob);
void BKE_object_eval_parent(struct Depsgraph *depsgraph, struct Object *ob);
void BKE_object_eval_constraints(struct Depsgraph *depsgraph,
@@ -294,6 +450,9 @@ void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *
void BKE_object_eval_uber_data(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
+/**
+ * Assign #Object.data after modifier stack evaluation.
+ */
void BKE_object_eval_assign_data(struct Object *object, struct ID *data, bool is_owned);
void BKE_object_sync_to_original(struct Depsgraph *depsgraph, struct Object *object);
@@ -319,7 +478,27 @@ void BKE_object_eval_eval_base_flags(struct Depsgraph *depsgraph,
void BKE_object_handle_data_update(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
+/**
+ * \warning "scene" here may not be the scene object actually resides in.
+ * When dealing with background-sets, "scene" is actually the active scene.
+ * e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
+ * rigid bodies depend on their world so use #BKE_object_handle_update_ex()
+ * to also pass along the current rigid body world.
+ */
void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
+/**
+ * Proxy rule:
+ * - lib_object->proxy_from == the one we borrow from, only set temporal and cleared here.
+ * - local_object->proxy == pointer to library object, saved in files and read.
+ *
+ * Function below is polluted with proxy exceptions, cleanup will follow!
+ *
+ * The main object update call, for object matrix, constraints, keys and displist (modifiers)
+ * requires flags to be set!
+ *
+ * Ideally we shouldn't have to pass the rigid body world,
+ * but need bigger restructuring to avoid id.
+ */
void BKE_object_handle_update_ex(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
@@ -329,17 +508,32 @@ void BKE_object_handle_update_ex(struct Depsgraph *depsgraph,
void BKE_object_sculpt_data_create(struct Object *ob);
bool BKE_object_obdata_texspace_get(struct Object *ob,
- short **r_texflag,
+ char **r_texflag,
float **r_loc,
float **r_size);
+/** Get evaluated mesh for given object. */
struct Mesh *BKE_object_get_evaluated_mesh(const struct Object *object);
+/**
+ * Get mesh which is not affected by modifiers:
+ * - For original objects it will be same as `object->data`, and it is a mesh
+ * which is in the corresponding #Main.
+ * - For copied-on-write objects it will give pointer to a copied-on-write
+ * mesh which corresponds to original object's mesh.
+ */
struct Mesh *BKE_object_get_pre_modified_mesh(const struct Object *object);
+/**
+ * Get a mesh which corresponds to the very original mesh from #Main.
+ * - For original objects it will be object->data.
+ * - For evaluated objects it will be same mesh as corresponding original
+ * object uses as data.
+ */
struct Mesh *BKE_object_get_original_mesh(const struct Object *object);
/* Lattice accessors.
* These functions return either the regular lattice, or the edit-mode lattice,
* whichever is currently in use. */
+
struct Lattice *BKE_object_get_lattice(const struct Object *object);
struct Lattice *BKE_object_get_evaluated_lattice(const struct Object *object);
@@ -356,12 +550,38 @@ bool BKE_object_flag_test_recursive(const struct Object *ob, short flag);
bool BKE_object_is_child_recursive(const struct Object *ob_parent, const struct Object *ob_child);
-/* return ModifierMode flag */
+/**
+ * Most important if this is modified it should _always_ return true, in certain
+ * cases false positives are hard to avoid (shape keys for example).
+ *
+ * \return #ModifierMode flag.
+ */
int BKE_object_is_modified(struct Scene *scene, struct Object *ob);
+/**
+ * Test if object is affected by deforming modifiers (for motion blur). again
+ * most important is to avoid false positives, this is to skip computations
+ * and we can still if there was actual deformation afterwards.
+ */
int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob);
+/**
+ * Check of objects moves in time.
+ *
+ * \note This function is currently optimized for usage in combination
+ * with modifier deformation checks (#eModifierTypeType_OnlyDeform),
+ * so modifiers can quickly check if their target objects moves
+ * (causing deformation motion blur) or not.
+ *
+ * This makes it possible to give some degree of false-positives here,
+ * but it's currently an acceptable tradeoff between complexity and check
+ * speed. In combination with checks of modifier stack and real life usage
+ * percentage of false-positives shouldn't be that high.
+ *
+ * \note This function does not consider physics systems.
+ */
bool BKE_object_moves_in_time(const struct Object *object, bool recurse_parent);
+/** Return the number of scenes using (instantiating) that object in their collections. */
int BKE_object_scenes_users_get(struct Main *bmain, struct Object *ob);
struct MovieClip *BKE_object_movieclip_get(struct Scene *scene,
@@ -369,7 +589,16 @@ struct MovieClip *BKE_object_movieclip_get(struct Scene *scene,
bool use_default);
void BKE_object_runtime_reset(struct Object *object);
+/**
+ * Reset all pointers which we don't want to be shared when copying the object.
+ */
void BKE_object_runtime_reset_on_copy(struct Object *object, const int flag);
+/**
+ * The function frees memory used by the runtime data, but not the runtime field itself.
+ *
+ * All runtime data is cleared to ensure it's not used again,
+ * in keeping with other `_free_data(..)` functions.
+ */
void BKE_object_runtime_free_data(struct Object *object);
void BKE_object_batch_cache_dirty_tag(struct Object *ob);
@@ -393,12 +622,31 @@ typedef enum eObjectSet {
OB_SET_ALL, /* All Objects. */
} eObjectSet;
+/**
+ * Iterates over all objects of the given scene layer.
+ * Depending on the #eObjectSet flag:
+ * collect either #OB_SET_ALL, #OB_SET_VISIBLE or #OB_SET_SELECTED objects.
+ * If #OB_SET_VISIBLE or#OB_SET_SELECTED are collected,
+ * then also add related objects according to the given \a includeFilter.
+ */
struct LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer,
eObjectSet objectSet,
eObRelationTypes includeFilter);
+/**
+ * \return All groups this object is a part of, caller must free.
+ */
struct LinkNode *BKE_object_groups(struct Main *bmain, struct Scene *scene, struct Object *ob);
void BKE_object_groups_clear(struct Main *bmain, struct Scene *scene, struct Object *object);
+/**
+ * Return a KDTree_3d from the deformed object (in world-space).
+ *
+ * \note Only mesh objects currently support deforming, others are TODO.
+ *
+ * \param ob:
+ * \param r_tot:
+ * \return The KD-tree or nullptr if it can't be created.
+ */
struct KDTree_3d *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
bool BKE_object_modifier_use_time(struct Scene *scene,
@@ -406,6 +654,10 @@ bool BKE_object_modifier_use_time(struct Scene *scene,
struct ModifierData *md,
int dag_eval_mode);
+/**
+ * \note this function should eventually be replaced by depsgraph functionality.
+ * Avoid calling this in new code unless there is a very good reason for it!
+ */
bool BKE_object_modifier_update_subframe(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
@@ -419,7 +671,8 @@ bool BKE_object_empty_image_frame_is_visible_in_view3d(const struct Object *ob,
bool BKE_object_empty_image_data_is_visible_in_view3d(const struct Object *ob,
const struct RegionView3D *rv3d);
-/* This is an utility function for Python's object.to_mesh() (the naming is not very clear though).
+/**
+ * This is an utility function for Python's object.to_mesh() (the naming is not very clear though).
* The result is owned by the object.
*
* The mesh will be freed when object is re-evaluated or is destroyed. It is possible to force to
@@ -436,11 +689,12 @@ struct Mesh *BKE_object_to_mesh(struct Depsgraph *depsgraph,
void BKE_object_to_mesh_clear(struct Object *object);
-/* This is an utility function for Python's object.to_curve().
+/**
+ * This is an utility function for Python's `object.to_curve()`.
* The result is owned by the object.
*
* The curve will be freed when object is re-evaluated or is destroyed. It is possible to force
- * clear memory used by this curve by calling BKE_object_to_curve_clear().
+ * clear memory used by this curve by calling #BKE_object_to_curve_clear().
*
* If apply_modifiers is true and the object is a curve one, then spline deform modifiers are
* applied on the curve control points.
diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h
index a10158254c2..ddbf5178ab0 100644
--- a/source/blender/blenkernel/BKE_object_deform.h
+++ b/source/blender/blenkernel/BKE_object_deform.h
@@ -31,24 +31,73 @@ struct MDeformVert;
struct Object;
struct bDeformGroup;
-/* General vgroup operations */
+/* General vgroup operations. */
+
+/**
+ * Update users of vgroups from this object, according to given map.
+ *
+ * Use it when you remove or reorder vgroups in the object.
+ *
+ * \param map: an array mapping old indices to new indices.
+ */
void BKE_object_defgroup_remap_update_users(struct Object *ob, const int *map);
+/**
+ * Get #MDeformVert vgroup data from given object. Should only be used in Object mode.
+ *
+ * \return True if the id type supports weights.
+ */
bool BKE_object_defgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
+/**
+ * Add a vgroup of default name to object. *Does not* handle #MDeformVert data at all!
+ */
struct bDeformGroup *BKE_object_defgroup_add(struct Object *ob);
+/**
+ * Add a vgroup of given name to object. *Does not* handle #MDeformVert data at all!
+ */
struct bDeformGroup *BKE_object_defgroup_add_name(struct Object *ob, const char *name);
+/**
+ * Create #MDeformVert data for given ID. Work in Object mode only.
+ */
struct MDeformVert *BKE_object_defgroup_data_create(struct ID *id);
+/**
+ * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes.
+ *
+ * \param use_selection: Only operate on selection.
+ * \return True if any vertex was removed, false otherwise.
+ */
bool BKE_object_defgroup_clear(struct Object *ob,
struct bDeformGroup *dg,
const bool use_selection);
+/**
+ * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes.
+ *
+ * \param use_selection: Only operate on selection.
+ * \return True if any vertex was removed, false otherwise.
+ */
bool BKE_object_defgroup_clear_all(struct Object *ob, const bool use_selection);
+/**
+ * Remove given vgroup from object. Work in Object and Edit modes.
+ */
void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
+/**
+ * Remove all vgroups from object. Work in Object and Edit modes.
+ * When only_unlocked=true, locked vertex groups are not removed.
+ */
void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked);
+/**
+ * Remove all vgroups from object. Work in Object and Edit modes.
+ */
void BKE_object_defgroup_remove_all(struct Object *ob);
+/**
+ * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
+ * Returns null if no remapping is required.
+ * The returned array has to be freed.
+ */
int *BKE_object_defgroup_index_map_create(struct Object *ob_src,
struct Object *ob_dst,
int *r_map_len);
@@ -57,34 +106,69 @@ void BKE_object_defgroup_index_map_apply(struct MDeformVert *dvert,
const int *map,
int map_len);
-/* Select helpers */
+/* Select helpers. */
+
enum eVGroupSelect;
+/**
+ * Return the subset type of the Vertex Group Selection.
+ */
bool *BKE_object_defgroup_subset_from_select_type(struct Object *ob,
enum eVGroupSelect subset_type,
int *r_defgroup_tot,
int *r_subset_count);
+/**
+ * Store indices from the defgroup_validmap (faster lookups in some cases).
+ */
void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap,
const int defgroup_tot,
int *r_defgroup_subset_map);
/* ********** */
+/**
+ * Gets the status of "flag" for each #bDeformGroup
+ * in the object data's vertex group list and returns an array containing them
+ */
bool *BKE_object_defgroup_lock_flags_get(struct Object *ob, const int defbase_tot);
bool *BKE_object_defgroup_validmap_get(struct Object *ob, const int defbase_tot);
+/**
+ * Returns total selected vgroups,
+ * `wpi.defbase_sel` is assumed malloc'd, all values are set.
+ */
bool *BKE_object_defgroup_selected_get(struct Object *ob,
int defbase_tot,
int *r_dg_flags_sel_tot);
+/**
+ * Checks if the lock relative mode is applicable.
+ *
+ * \return true if an unlocked deform group is active.
+ */
bool BKE_object_defgroup_check_lock_relative(const bool *lock_flags,
const bool *validmap,
int index);
+/**
+ * Additional check for whether the lock relative mode is applicable in multi-paint mode.
+ *
+ * \return true if none of the selected groups are locked.
+ */
bool BKE_object_defgroup_check_lock_relative_multi(int defbase_tot,
const bool *lock_flags,
const bool *selected,
int sel_tot);
+/**
+ * Takes a pair of boolean masks of all locked and all deform groups, and computes
+ * a pair of masks for locked deform and unlocked deform groups. Output buffers may
+ * reuse the input ones.
+ */
void BKE_object_defgroup_split_locked_validmap(
int defbase_tot, const bool *locked, const bool *deform, bool *r_locked, bool *r_unlocked);
+/**
+ * Marks mirror vgroups in output and counts them.
+ * Output and counter assumed to be already initialized.
+ * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
+ */
void BKE_object_defgroup_mirror_selection(struct Object *ob,
int defbase_tot,
const bool *selection,
diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h
index 186e0ec174b..4388190221d 100644
--- a/source/blender/blenkernel/BKE_ocean.h
+++ b/source/blender/blenkernel/BKE_ocean.h
@@ -74,12 +74,21 @@ struct Ocean *BKE_ocean_add(void);
void BKE_ocean_free_data(struct Ocean *oc);
void BKE_ocean_free(struct Ocean *oc);
bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution);
+/**
+ * Return true if the ocean data is valid and can be used.
+ */
bool BKE_ocean_init_from_modifier(struct Ocean *ocean,
struct OceanModifierData const *omd,
const int resolution);
+/**
+ * Return true if the ocean is valid and can be used.
+ */
bool BKE_ocean_is_valid(const struct Ocean *o);
+/**
+ * Return true if the ocean data is valid and can be used.
+ */
bool BKE_ocean_init(struct Ocean *o,
int M,
int N,
@@ -104,15 +113,26 @@ bool BKE_ocean_init(struct Ocean *o,
int seed);
void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount);
-/* sampling the ocean surface */
float BKE_ocean_jminus_to_foam(float jminus, float coverage);
+/**
+ * Sampling the ocean surface.
+ */
void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v);
+/**
+ * Use catmullrom interpolation rather than linear.
+ */
void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v);
void BKE_ocean_eval_xz(struct Ocean *oc, struct OceanResult *ocr, float x, float z);
void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x, float z);
+/**
+ * Note that this doesn't wrap properly for i, j < 0, but its not really meant for that being
+ * just a way to get the raw data out to save in some image format.
+ */
void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j);
-/* ocean cache handling */
+/**
+ * Ocean cache handling.
+ */
struct OceanCache *BKE_ocean_init_cache(const char *bakepath,
const char *relbase,
int start,
@@ -136,8 +156,26 @@ void BKE_ocean_free_cache(struct OceanCache *och);
void BKE_ocean_free_modifier_cache(struct OceanModifierData *omd);
/* ocean_spectrum.c */
+
+/**
+ * Pierson-Moskowitz model, 1964, assumes waves reach equilibrium with wind.
+ * Model is intended for large area 'fully developed' sea, where winds have been steadily blowing
+ * for days over an area that includes hundreds of wavelengths on a side.
+ */
float BLI_ocean_spectrum_piersonmoskowitz(const struct Ocean *oc, const float kx, const float kz);
+/**
+ * TMA extends the JONSWAP spectrum.
+ * This spectral model is best suited to shallow water.
+ */
float BLI_ocean_spectrum_texelmarsenarsloe(const struct Ocean *oc, const float kx, const float kz);
+/**
+ * Hasselmann et al, 1973. This model extends the Pierson-Moskowitz model with a peak sharpening
+ * function This enhancement is an artificial construct to address the problem that the wave
+ * spectrum is never fully developed.
+ *
+ * The fetch parameter represents the distance from a lee shore,
+ * called the fetch, or the distance over which the wind blows with constant velocity.
+ */
float BLI_ocean_spectrum_jonswap(const struct Ocean *oc, const float kx, const float kz);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 8ddf77e3d49..e3deff9d8fa 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -57,17 +57,32 @@ enum ePF_FileStatus {
PF_ASK = 10,
};
-/* pack */
+/* Pack. */
+
struct PackedFile *BKE_packedfile_duplicate(const struct PackedFile *pf_src);
struct PackedFile *BKE_packedfile_new(struct ReportList *reports,
const char *filename,
const char *basepath);
struct PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen);
+/**
+ * No libraries for now.
+ */
void BKE_packedfile_pack_all(struct Main *bmain, struct ReportList *reports, bool verbose);
void BKE_packedfile_pack_all_libraries(struct Main *bmain, struct ReportList *reports);
-/* unpack */
+/* Unpack. */
+
+/**
+ * #BKE_packedfile_unpack_to_file() looks at the existing files (abs_name, local_name)
+ * and a packed file.
+ *
+ * It returns a char *to the existing file name / new file name or NULL when
+ * there was an error or when the user decides to cancel the operation.
+ *
+ * \warning 'abs_name' may be relative still! (use a "//" prefix)
+ * be sure to run #BLI_path_abs on it first.
+ */
char *BKE_packedfile_unpack_to_file(struct ReportList *reports,
const char *ref_file_name,
const char *abs_name,
@@ -107,23 +122,38 @@ int BKE_packedfile_write_to_file(struct ReportList *reports,
struct PackedFile *pf,
const bool guimode);
-/* free */
+/* Free. */
+
void BKE_packedfile_free(struct PackedFile *pf);
-/* info */
+/* Info. */
+
int BKE_packedfile_count_all(struct Main *bmain);
+/**
+ * This function compares a packed file to a 'real' file.
+ * It returns an integer indicating if:
+ *
+ * - #PF_EQUAL: the packed file and original file are identical.
+ * - #PF_DIFFERENT: the packed file and original file differ.
+ * - #PF_NOFILE: the original file doesn't exist.
+ */
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
const char *filename,
struct PackedFile *pf);
-/* read */
+/* Read. */
+
int BKE_packedfile_seek(struct PackedFile *pf, int offset, int whence);
void BKE_packedfile_rewind(struct PackedFile *pf);
int BKE_packedfile_read(struct PackedFile *pf, void *data, int size);
-/* ID should be not NULL, return true if there's a packed file */
+/**
+ * ID should be not NULL, return true if there's a packed file.
+ */
bool BKE_packedfile_id_check(const struct ID *id);
-/* ID should be not NULL, throws error when ID is Library */
+/**
+ * ID should be not NULL, throws error when ID is Library.
+ */
void BKE_packedfile_id_unpack(struct Main *bmain,
struct ID *id,
struct ReportList *reports,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 6fc5ef4d870..40e3ab74fac 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -111,10 +111,11 @@ typedef enum ePaintOverlayControlFlags {
(PAINT_OVERLAY_OVERRIDE_SECONDARY | PAINT_OVERLAY_OVERRIDE_PRIMARY | \
PAINT_OVERLAY_OVERRIDE_CURSOR)
-/* Defines 8 areas resulting of splitting the object space by the XYZ axis planes. This is used to
+/**
+ * Defines 8 areas resulting of splitting the object space by the XYZ axis planes. This is used to
* flip or mirror transform values depending on where the vertex is and where the transform
- * operation started to support XYZ symmetry on those operations in a predictable way. */
-
+ * operation started to support XYZ symmetry on those operations in a predictable way.
+ */
#define PAINT_SYMM_AREA_DEFAULT 0
typedef enum ePaintSymmetryAreas {
@@ -136,10 +137,14 @@ ePaintOverlayControlFlags BKE_paint_get_overlay_flags(void);
void BKE_paint_reset_overlay_invalid(ePaintOverlayControlFlags flag);
void BKE_paint_set_overlay_override(enum eOverlayFlags flag);
-/* palettes */
+/* Palettes. */
+
struct Palette *BKE_palette_add(struct Main *bmain, const char *name);
struct PaletteColor *BKE_palette_color_add(struct Palette *palette);
bool BKE_palette_is_empty(const struct Palette *palette);
+/**
+ * Remove color from palette. Must be certain color is inside the palette!
+ */
void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color);
void BKE_palette_clear(struct Palette *palette);
@@ -152,12 +157,21 @@ bool BKE_palette_from_hash(struct Main *bmain,
const char *name,
const bool linear);
-/* paint curves */
+/* Paint curves. */
+
struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
+/**
+ * Call when entering each respective paint mode.
+ */
bool BKE_paint_ensure(struct ToolSettings *ts, struct Paint **r_paint);
void BKE_paint_init(struct Main *bmain, struct Scene *sce, ePaintMode mode, const char col[3]);
void BKE_paint_free(struct Paint *p);
+/**
+ * Called when copying scene settings, so even if 'src' and 'tar' are the same still do a
+ * #id_us_plus(), rather than if we were copying between 2 existing scenes where a matching
+ * value should decrease the existing user count as with #paint_brush_set()
+ */
void BKE_paint_copy(struct Paint *src, struct Paint *tar, const int flag);
void BKE_paint_runtime_init(const struct ToolSettings *ts, struct Paint *paint);
@@ -181,26 +195,46 @@ void BKE_paint_palette_set(struct Paint *p, struct Palette *palette);
void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc);
void BKE_paint_curve_clamp_endpoint_add_index(struct PaintCurve *pc, const int add_index);
-/* testing face select mode
- * Texture paint could be removed since selected faces are not used
- * however hiding faces is useful */
+/**
+ * Return true when in vertex/weight/texture paint + face-select mode?
+ */
bool BKE_paint_select_face_test(struct Object *ob);
+/**
+ * Return true when in vertex/weight paint + vertex-select mode?
+ */
bool BKE_paint_select_vert_test(struct Object *ob);
+/**
+ * used to check if selection is possible
+ * (when we don't care if its face or vert)
+ */
bool BKE_paint_select_elem_test(struct Object *ob);
-/* partial visibility */
+/* Partial visibility. */
+
+/**
+ * Returns non-zero if any of the face's vertices are hidden, zero otherwise.
+ */
bool paint_is_face_hidden(const struct MLoopTri *lt,
const struct MVert *mvert,
const struct MLoop *mloop);
+/**
+ * Returns non-zero if any of the corners of the grid
+ * face whose inner corner is at (x, y) are hidden, zero otherwise.
+ */
bool paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, int x, int y);
+/**
+ * Return true if all vertices in the face are visible, false otherwise.
+ */
bool paint_is_bmesh_face_hidden(struct BMFace *f);
-/* paint masks */
+/* Paint masks. */
+
float paint_grid_paint_mask(const struct GridPaintMask *gpm, uint level, uint x, uint y);
void BKE_paint_face_set_overlay_color_get(const int face_set, const int seed, uchar r_color[4]);
-/* stroke related */
+/* Stroke related. */
+
bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups,
struct Brush *brush,
const float mouse_pos[2]);
@@ -211,14 +245,20 @@ void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups,
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
/* Tool slot API. */
+
void BKE_paint_toolslots_init_from_main(struct Main *bmain);
void BKE_paint_toolslots_len_ensure(struct Paint *paint, int len);
void BKE_paint_toolslots_brush_update_ex(struct Paint *paint, struct Brush *brush);
void BKE_paint_toolslots_brush_update(struct Paint *paint);
+/**
+ * Run this to ensure brush types are set for each slot on entering modes
+ * (for new scenes for example).
+ */
void BKE_paint_toolslots_brush_validate(struct Main *bmain, struct Paint *paint);
struct Brush *BKE_paint_toolslots_brush_get(struct Paint *paint, int slot_index);
/* .blend I/O */
+
void BKE_paint_blend_write(struct BlendWriter *writer, struct Paint *paint);
void BKE_paint_blend_read_data(struct BlendDataReader *reader,
const struct Scene *scene,
@@ -229,7 +269,7 @@ void BKE_paint_blend_read_lib(struct BlendLibReader *reader,
#define SCULPT_FACE_SET_NONE 0
-/* Used for both vertex color and weight paint */
+/** Used for both vertex color and weight paint. */
struct SculptVertexPaintGeomMap {
int *vert_map_mem;
struct MeshElemMap *vert_to_loop;
@@ -237,7 +277,7 @@ struct SculptVertexPaintGeomMap {
struct MeshElemMap *vert_to_poly;
};
-/* Pose Brush IK Chain */
+/** Pose Brush IK Chain. */
typedef struct SculptPoseIKChainSegment {
float orig[3];
float head[3];
@@ -620,10 +660,15 @@ void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
-/* Create new color layer on object if it doesn't have one and if experimental feature set has
- * sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */
+/**
+ * Create new color layer on object if it doesn't have one and if experimental feature set has
+ * sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise.
+ */
void BKE_sculpt_color_layer_create_if_needed(struct Object *object);
+/**
+ * \warning Expects a fully evaluated depsgraph.
+ */
void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph,
struct Object *ob_orig,
bool need_pmap,
@@ -632,6 +677,10 @@ void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph,
void BKE_sculpt_update_object_before_eval(struct Object *ob_eval);
void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Object *ob_eval);
+/**
+ * Sculpt mode handles multi-res differently from regular meshes, but only if
+ * it's the last modifier on the stack and it is not on the first level.
+ */
struct MultiresModifierData *BKE_sculpt_multires_active(struct Scene *scene, struct Object *ob);
int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd);
void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene);
@@ -640,19 +689,37 @@ struct PBVH *BKE_sculpt_object_pbvh_ensure(struct Depsgraph *depsgraph, struct O
void BKE_sculpt_bvh_update_from_ccg(struct PBVH *pbvh, struct SubdivCCG *subdiv_ccg);
-/* This ensure that all elements in the mesh (both vertices and grids) have their visibility
- * updated according to the face sets. */
+/**
+ * This ensure that all elements in the mesh (both vertices and grids) have their visibility
+ * updated according to the face sets.
+ */
void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg);
-/* Individual function to sync the Face Set visibility to mesh and grids. */
+/**
+ * Individual function to sync the Face Set visibility to mesh and grids.
+ */
void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(struct Mesh *mesh);
void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh,
struct SubdivCCG *subdiv_ccg);
+/**
+ * Ensures that a Face Set data-layers exists. If it does not, it creates one respecting the
+ * visibility stored in the vertices of the mesh. If it does, it copies the visibility from the
+ * mesh to the Face Sets. */
void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh);
+/**
+ * Ensures we do have expected mesh data in original mesh for the sculpt mode.
+ *
+ * \note IDs are expected to be original ones here, and calling code should ensure it updates its
+ * depsgraph properly after calling this function if it needs up-to-date evaluated data.
+ */
void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object);
+/**
+ * Test if PBVH can be used directly for drawing, which is faster than
+ * drawing the mesh and all updates that come with it.
+ */
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
enum {
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 78a6e47ec48..972cba2d132 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -286,6 +286,9 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve
/* ----------- functions needed outside particlesystem ---------------- */
/* particle.c */
+
+/* Few helpers for count-all etc. */
+
int count_particles(struct ParticleSystem *psys);
int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);
@@ -296,8 +299,13 @@ int psys_get_tot_child(struct Scene *scene,
struct ParticleSystem *psys,
const bool use_render_params);
+/**
+ * Get object's active particle system safely.
+ */
struct ParticleSystem *psys_get_current(struct Object *ob);
-/* for rna */
+
+/* For RNA API. */
+
short psys_get_current_num(struct Object *ob);
void psys_set_current_num(struct Object *ob, int index);
/* UNUSED */
@@ -305,14 +313,17 @@ void psys_set_current_num(struct Object *ob, int index);
struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
-/* For a given evaluated particle system get its original.
+/**
+ * For a given evaluated particle system get its original.
*
- * If this input is an original particle system already, the return value is the
- * same as the input. */
+ * If this input is an original particle system already, the return value is the same as the input.
+ */
struct ParticleSystem *psys_orig_get(struct ParticleSystem *psys);
-/* For a given original object and its particle system, get evaluated particle
- * system within a given dependency graph. */
+/**
+ * For a given original object and its particle system,
+ * get evaluated particle system within a given dependency graph.
+ */
struct ParticleSystem *psys_eval_get(struct Depsgraph *depsgraph,
struct Object *object,
struct ParticleSystem *psys);
@@ -328,11 +339,17 @@ void psys_check_group_weights(struct ParticleSettings *part);
int psys_uses_gravity(struct ParticleSimulationData *sim);
void BKE_particlesettings_fluid_default_settings(struct ParticleSettings *part);
-/* free */
+/**
+ * Free cache path.
+ */
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
+/**
+ * Free everything.
+ */
void psys_free(struct Object *ob, struct ParticleSystem *psys);
-
-/* Copy. */
+/**
+ * Copy.
+ */
void psys_copy_particles(struct ParticleSystem *psys_dst, struct ParticleSystem *psys_src);
bool psys_render_simplify_params(struct ParticleSystem *psys,
@@ -379,6 +396,12 @@ void psys_find_parents(struct ParticleSimulationData *sim, const bool use_render
void psys_unique_name(struct Object *object, struct ParticleSystem *psys, const char *defname);
+/**
+ * Calculates paths ready for drawing/rendering
+ * - Useful for making use of opengl vertex arrays for super fast strand drawing.
+ * - Makes child strands possible and creates them too into the cache.
+ * - Cached path data is also used to determine cut position for the edit-mode tool.
+ */
void psys_cache_paths(struct ParticleSimulationData *sim,
float cfra,
const bool use_render_params);
@@ -409,16 +432,24 @@ float psys_get_child_size(struct ParticleSystem *psys,
struct ChildParticle *cpa,
float cfra,
float *pa_time);
+/**
+ * Gets hair (or keyed) particles state at the "path time" specified in `state->time`.
+ */
void psys_get_particle_on_path(struct ParticleSimulationData *sim,
int pa_num,
struct ParticleKey *state,
const bool vel);
-int psys_get_particle_state(struct ParticleSimulationData *sim,
- int p,
- struct ParticleKey *state,
- int always);
+/**
+ * Gets particle's state at a time.
+ * \return true if particle exists and can be seen and false if not.
+ */
+bool psys_get_particle_state(struct ParticleSimulationData *sim,
+ int p,
+ struct ParticleKey *state,
+ const bool always);
+
+/* Child paths. */
-/* child paths */
void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
void BKE_particlesettings_twist_curve_init(struct ParticleSettings *part);
@@ -434,9 +465,13 @@ void psys_apply_child_modifiers(struct ParticleThreadContext *ctx,
void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
void psys_sph_finalize(struct SPHData *sphdata);
+/**
+ * Sample the density field at a point in space.
+ */
void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]);
-/* for anim.c */
+/* For anim.c */
+
void psys_get_dupli_texture(struct ParticleSystem *psys,
struct ParticleSettings *part,
struct ParticleSystemModifierData *psmd,
@@ -451,6 +486,9 @@ void psys_get_dupli_path_transform(struct ParticleSimulationData *sim,
float mat[4][4],
float *scale);
+/**
+ * Threaded child particle distribution and path caching.
+ */
void psys_thread_context_init(struct ParticleThreadContext *ctx,
struct ParticleSimulationData *sim);
void psys_thread_context_free(struct ParticleThreadContext *ctx);
@@ -467,9 +505,16 @@ void psys_apply_hair_lattice(struct Depsgraph *depsgraph,
struct ParticleSystem *psys);
/* particle_system.c */
+
struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
+/**
+ * Counts valid keyed targets.
+ */
void psys_count_keyed_targets(struct ParticleSimulationData *sim);
void psys_update_particle_tree(struct ParticleSystem *psys, float cfra);
+/**
+ * System type has changed so set sensible defaults and clear non applicable flags.
+ */
void psys_changed_type(struct Object *ob, struct ParticleSystem *psys);
void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
@@ -486,13 +531,19 @@ void psys_get_birth_coords(struct ParticleSimulationData *sim,
float dtime,
float cfra);
+/**
+ * Main particle update call, checks that things are ok on the large scale and
+ * then advances in to actual particle calculations depending on particle type.
+ */
void particle_system_update(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct ParticleSystem *psys,
const bool use_render_params);
-/* Callback format for performing operations on ID-pointers for particle systems */
+/**
+ * Callback format for performing operations on ID-pointers for particle systems.
+ */
typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys,
struct ID **idpoin,
void *userdata,
@@ -502,11 +553,15 @@ void BKE_particlesystem_id_loop(struct ParticleSystem *psys,
ParticleSystemIDFunc func,
void *userdata);
-/* Reset all particle systems in the given object. */
+/**
+ * Reset all particle systems in the given object.
+ */
void BKE_particlesystem_reset_all(struct Object *object);
/* ----------- functions needed only inside particlesystem ------------ */
+
/* particle.c */
+
void psys_disable_all(struct Object *ob);
void psys_enable_all(struct Object *ob);
@@ -544,6 +599,9 @@ void psys_get_texture(struct ParticleSimulationData *sim,
struct ParticleTexture *ptex,
int event,
float cfra);
+/**
+ * Interpolate a location on a face based on face coordinates.
+ */
void psys_interpolate_face(struct MVert *mvert,
struct MFace *mface,
struct MTFace *tface,
@@ -561,11 +619,16 @@ float psys_particle_value_from_verts(struct Mesh *mesh,
void psys_get_from_key(
struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time);
-/* BLI_bvhtree_ray_cast callback */
+/**
+ * Callback for #BVHTree near test.
+ */
void BKE_psys_collision_neartest_cb(void *userdata,
int index,
const struct BVHTreeRay *ray,
struct BVHTreeRayHit *hit);
+/**
+ * Interprets particle data to get a point on a mesh in object space.
+ */
void psys_particle_on_dm(struct Mesh *mesh_final,
int from,
int index,
@@ -579,18 +642,37 @@ void psys_particle_on_dm(struct Mesh *mesh_final,
float orco[3]);
/* particle_system.c */
+
void distribute_particles(struct ParticleSimulationData *sim, int from);
+/**
+ * Set particle parameters that don't change during particle's life.
+ */
void init_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
void psys_calc_dmcache(struct Object *ob,
struct Mesh *mesh_final,
struct Mesh *mesh_original,
struct ParticleSystem *psys);
+/**
+ * Find the final derived mesh tessface for a particle, from its original tessface index.
+ * This is slow and can be optimized but only for many lookups.
+ *
+ * \param mesh_final: Final mesh, it may not have the same topology as original mesh.
+ * \param mesh_original: Original mesh, use for accessing #MPoly to #MFace mapping.
+ * \param findex_orig: The input tessface index.
+ * \param fw: Face weights (position of the particle inside the \a findex_orig tessface).
+ * \param poly_nodes: May be NULL, otherwise an array of linked list,
+ * one for each final \a mesh_final polygon, containing all its tessfaces indices.
+ * \return The \a mesh_final tessface index.
+ */
int psys_particle_dm_face_lookup(struct Mesh *mesh_final,
struct Mesh *mesh_original,
- int findex,
+ int findex_orig,
const float fw[4],
struct LinkNode **poly_nodes);
+/**
+ * Sets particle to the emitter surface with initial velocity & rotation.
+ */
void reset_particle(struct ParticleSimulationData *sim,
struct ParticleData *pa,
float dtime,
@@ -629,6 +711,7 @@ extern void (*BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys
extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys);
/* .blend file I/O */
+
void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader,
struct PartDeflect *pd);
void BKE_particle_partdeflect_blend_read_lib(struct BlendLibReader *reader,
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 3a0e9d48af7..5e7a9883de6 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -90,7 +90,9 @@ void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
/* Callbacks */
-/* returns 1 if the search should continue from this node, 0 otherwise */
+/**
+ * Returns true if the search should continue from this node, false otherwise.
+ */
typedef bool (*BKE_pbvh_SearchCallback)(PBVHNode *node, void *data);
typedef void (*BKE_pbvh_HitCallback)(PBVHNode *node, void *data);
@@ -101,6 +103,12 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float
/* Building */
PBVH *BKE_pbvh_new(void);
+/**
+ * Do a full rebuild with on Mesh data structure.
+ *
+ * \note Unlike mpoly/mloop/verts, looptri is *totally owned* by PBVH
+ * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
+ */
void BKE_pbvh_build_mesh(PBVH *pbvh,
const struct Mesh *mesh,
const struct MPoly *mpoly,
@@ -112,6 +120,9 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
struct CustomData *pdata,
const struct MLoopTri *looptri,
int looptri_num);
+/**
+ * Do a full rebuild with on Grids data structure.
+ */
void BKE_pbvh_build_grids(PBVH *pbvh,
struct CCGElem **grids,
int totgrid,
@@ -119,6 +130,9 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
void **gridfaces,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
+/**
+ * Build a PBVH from a BMesh.
+ */
void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMesh *bm,
bool smooth_shading,
@@ -170,8 +184,10 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
float *depth,
float *r_edge_length);
-/* for orthographic cameras, project the far away ray segment points to the root node so
- * we can have better precision. */
+/**
+ * For orthographic cameras, project the far away ray segment points to the root node so
+ * we can have better precision.
+ */
void BKE_pbvh_raycast_project_ray_root(
PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
@@ -215,12 +231,19 @@ typedef enum {
PBVHType BKE_pbvh_type(const PBVH *pbvh);
bool BKE_pbvh_has_faces(const PBVH *pbvh);
-/* Get the PBVH root's bounding box */
+/**
+ * Get the PBVH root's bounding box.
+ */
void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]);
-/* multires hidden data, only valid for type == PBVH_GRIDS */
+/**
+ * Multi-res hidden data, only valid for type == PBVH_GRIDS.
+ */
unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh);
+/**
+ * Returns the number of visible quads in the nodes' grids.
+ */
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
const int *grid_indices,
int totgrid,
@@ -228,7 +251,9 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh);
-/* multires level, only valid for type == PBVH_GRIDS */
+/**
+ * Multi-res level, only valid for type == #PBVH_GRIDS.
+ */
const struct CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh);
struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh);
@@ -236,7 +261,9 @@ BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh);
-/* Only valid for type == PBVH_BMESH */
+/**
+ * Only valid for type == #PBVH_BMESH.
+ */
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
@@ -244,6 +271,9 @@ typedef enum {
PBVH_Subdivide = 1,
PBVH_Collapse = 2,
} PBVHTopologyUpdateMode;
+/**
+ * Collapse short edges, subdivide long edges.
+ */
bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
@@ -287,18 +317,28 @@ void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max
float BKE_pbvh_node_get_tmin(PBVHNode *node);
-/* test if AABB is at least partially inside the PBVHFrustumPlanes volume */
+/**
+ * Test if AABB is at least partially inside the #PBVHFrustumPlanes volume.
+ */
bool BKE_pbvh_node_frustum_contain_AABB(PBVHNode *node, void *frustum);
-/* test if AABB is at least partially outside the PBVHFrustumPlanes volume */
+/**
+ * Test if AABB is at least partially outside the #PBVHFrustumPlanes volume.
+ */
bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *frustum);
struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
+/**
+ * In order to perform operations on the original node coordinates
+ * (currently just ray-cast), store the node's triangles and vertices.
+ *
+ * Skips triangles that are hidden.
+ */
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
-/* Update Bounding Box/Redraw and clear flags */
+/* Update Bounding Box/Redraw and clear flags. */
void BKE_pbvh_update_bounds(PBVH *pbvh, int flags);
void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags);
@@ -318,14 +358,15 @@ void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default);
void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide);
-/* vertex deformer */
+/* Vertex Deformer. */
+
float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3];
void BKE_pbvh_vert_coords_apply(struct PBVH *pbvh, const float (*vertCos)[3], const int totvert);
bool BKE_pbvh_is_deformed(struct PBVH *pbvh);
-/* Vertex Iterator */
+/* Vertex Iterator. */
-/* this iterator has quite a lot of code, but it's designed to:
+/* This iterator has quite a lot of code, but it's designed to:
* - allow the compiler to eliminate dead code and variables
* - spend most of the time in the relatively simple inner loop */
@@ -469,6 +510,11 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int *r_orco_tris_num,
float (**r_orco_coords)[3]);
+/**
+ * \note doing a full search on all vertices here seems expensive,
+ * however this is important to avoid having to recalculate bound-box & sync the buffers to the
+ * GPU (which is far more expensive!) See: T47232.
+ */
bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
@@ -480,7 +526,8 @@ void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
bool pbvh_has_face_sets(PBVH *pbvh);
void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
-/* Parallelization */
+/* Parallelization. */
+
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
bool use_threading,
int totnode);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index c83fca767a1..47d3d83f8bb 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -273,19 +273,28 @@ typedef struct PTCacheEdit {
int totpoint, totframes, totcached, edited;
} PTCacheEdit;
-/* Particle functions */
void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **data, float time);
/**************** Creating ID's ****************************/
+
void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd);
+/**
+ * The fluid modifier does not actually use this anymore, but some parts of Blender expect that it
+ * still has a point cache currently. For example, the fluid modifier uses
+ * #DEG_add_collision_relations, which internally creates relations with the point cache.
+ */
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *fmd);
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid,
struct Object *ob,
struct DynamicPaintSurface *surface);
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw);
+/**
+ * \param ob: Optional, may be NULL.
+ * \param scene: Optional may be NULL.
+ */
PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache);
void BKE_ptcache_ids_from_object(struct ListBase *lb,
struct Object *ob,
@@ -294,12 +303,11 @@ void BKE_ptcache_ids_from_object(struct ListBase *lb,
/****************** Query funcs ****************************/
-/* Check whether object has a point cache. */
+/**
+ * Check whether object has a point cache.
+ */
bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis);
-/***************** Global funcs ****************************/
-void BKE_ptcache_remove(void);
-
/************ ID specific functions ************************/
void BKE_ptcache_id_clear(PTCacheID *id, int mode, unsigned int cfra);
bool BKE_ptcache_id_exist(PTCacheID *id, int cfra);
@@ -316,23 +324,35 @@ void BKE_ptcache_update_info(PTCacheID *pid);
/*********** General cache reading/writing ******************/
-/* Size of cache data type. */
+/**
+ * Size of cache data type.
+ */
int BKE_ptcache_data_size(int data_type);
-/* Is point with index in memory cache */
+/**
+ * Is point with index in memory cache?
+ * Check to see if point number "index" is in `pm` (uses binary search for index data).
+ */
int BKE_ptcache_mem_index_find(struct PTCacheMem *pm, unsigned int index);
/* Memory cache read/write helpers. */
+
void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm, void *cur[BPHYS_TOT_DATA]);
void BKE_ptcache_mem_pointers_incr(void *cur[BPHYS_TOT_DATA]);
int BKE_ptcache_mem_pointers_seek(int point_index,
struct PTCacheMem *pm,
void *cur[BPHYS_TOT_DATA]);
-/* Main cache reading call. */
+/**
+ * Main cache reading call.
+ * Possible to get old or interpolated result.
+ */
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old);
-/* Main cache writing call. */
+/**
+ * Main cache writing call.
+ * Writes cache to disk or memory.
+ */
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra);
/******************* Allocate & free ***************/
@@ -340,41 +360,56 @@ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
void BKE_ptcache_free_mem(struct ListBase *mem_cache);
void BKE_ptcache_free(struct PointCache *cache);
void BKE_ptcache_free_list(struct ListBase *ptcaches);
+/* returns first point cache */
struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new,
const struct ListBase *ptcaches_old,
const int flag);
/********************** Baking *********************/
-/* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */
+/**
+ * Bakes cache with cache_step sized jumps in time, not accurate but very fast.
+ */
void BKE_ptcache_quick_cache_all(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
-/* Bake cache or simulate to current frame with settings defined in the baker. */
+/**
+ * Bake cache or simulate to current frame with settings defined in the baker.
+ * if bake is not given run simulations to current frame.
+ */
void BKE_ptcache_bake(struct PTCacheBaker *baker);
-/* Convert disk cache to memory cache. */
+/**
+ * Convert disk cache to memory cache.
+ */
void BKE_ptcache_disk_to_mem(struct PTCacheID *pid);
-
-/* Convert memory cache to disk cache. */
+/**
+ * Convert memory cache to disk cache.
+ */
void BKE_ptcache_mem_to_disk(struct PTCacheID *pid);
-
-/* Convert disk cache to memory cache and vice versa. Clears the cache that was converted. */
+/**
+ * Convert disk cache to memory cache and vice versa. Clears the cache that was converted.
+ */
void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
-
-/* Rename all disk cache files with a new name. Doesn't touch the actual content of the files. */
+/**
+ * Rename all disk cache files with a new name. Doesn't touch the actual content of the files.
+ */
void BKE_ptcache_disk_cache_rename(struct PTCacheID *pid,
const char *name_src,
const char *name_dst);
-/* Loads simulation from external (disk) cache files. */
+/**
+ * Loads simulation from external (disk) cache files.
+ */
void BKE_ptcache_load_external(struct PTCacheID *pid);
-
-/* Set correct flags after successful simulation step */
+/**
+ * Set correct flags after successful simulation step.
+ */
void BKE_ptcache_validate(struct PointCache *cache, int framenr);
-
-/* Set correct flags after unsuccessful simulation step */
+/**
+ * Set correct flags after unsuccessful simulation step.
+ */
void BKE_ptcache_invalidate(struct PointCache *cache);
/********************** .blend File I/O *********************/
diff --git a/source/blender/blenkernel/BKE_pointcloud.h b/source/blender/blenkernel/BKE_pointcloud.h
index d2d390dc786..af8a6ed293d 100644
--- a/source/blender/blenkernel/BKE_pointcloud.h
+++ b/source/blender/blenkernel/BKE_pointcloud.h
@@ -18,7 +18,7 @@
/** \file
* \ingroup bke
- * \brief General operations for point-clouds.
+ * \brief General operations for point clouds.
*/
#ifdef __cplusplus
extern "C" {
diff --git a/source/blender/blenkernel/BKE_preferences.h b/source/blender/blenkernel/BKE_preferences.h
index e9cb024f117..6d6c58e5c1e 100644
--- a/source/blender/blenkernel/BKE_preferences.h
+++ b/source/blender/blenkernel/BKE_preferences.h
@@ -35,6 +35,10 @@ struct bUserAssetLibrary;
struct bUserAssetLibrary *BKE_preferences_asset_library_add(struct UserDef *userdef,
const char *name,
const char *path) ATTR_NONNULL(1);
+/**
+ * Unlink and free a library preference member.
+ * \note Free's \a library itself.
+ */
void BKE_preferences_asset_library_remove(struct UserDef *userdef,
struct bUserAssetLibrary *library) ATTR_NONNULL();
@@ -42,6 +46,12 @@ void BKE_preferences_asset_library_name_set(struct UserDef *userdef,
struct bUserAssetLibrary *library,
const char *name) ATTR_NONNULL();
+/**
+ * Set the library path, ensuring it is pointing to a directory.
+ * Single blend files can only act as "Current File" library; libraries on disk
+ * should always be directories. If the path does not exist, that's fine; it can
+ * created as directory if necessary later.
+ */
void BKE_preferences_asset_library_path_set(struct bUserAssetLibrary *library, const char *path)
ATTR_NONNULL();
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index ec2e8d0f875..8b585fd0167 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -35,9 +35,14 @@ extern "C" {
* These functions also accept NULL in case no error reporting
* is needed. */
-/* report structures are stored in DNA */
+/* Report structures are stored in DNA. */
void BKE_reports_init(ReportList *reports, int flag);
+/**
+ * Only frees the list \a reports.
+ * To make displayed reports disappear, either remove window-manager reports
+ * (#wmWindowManager.reports, or #CTX_wm_reports()), or use #WM_report_banners_cancel().
+ */
void BKE_reports_clear(ReportList *reports);
void BKE_report(ReportList *reports, eReportType type, const char *message);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index e28f668d189..1c9bad7fbe8 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -38,11 +38,21 @@ struct Object;
struct ReportList;
struct Scene;
-/* -------------- */
-/* Memory Management */
+/* -------------------------------------------------------------------- */
+/** \name Memory Management
+ * \{ */
+/**
+ * Free rigid-body world.
+ */
void BKE_rigidbody_free_world(struct Scene *scene);
+/**
+ * Free rigid-body settings and simulation instances.
+ */
void BKE_rigidbody_free_object(struct Object *ob, struct RigidBodyWorld *rbw);
+/**
+ * Free rigid-body constraint and simulation instance.
+ */
void BKE_rigidbody_free_constraint(struct Object *ob);
/* ...... */
@@ -52,7 +62,15 @@ void BKE_rigidbody_object_copy(struct Main *bmain,
const struct Object *ob_src,
const int flag);
-/* Callback format for performing operations on ID-pointers for rigidbody world. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Iterator
+ * \{ */
+
+/**
+ * Callback format for performing operations on ID-pointers for rigid-body world.
+ */
typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw,
struct ID **idpoin,
void *userdata,
@@ -62,43 +80,83 @@ void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw,
RigidbodyWorldIDFunc func,
void *userdata);
-/* -------------- */
-/* Setup */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Setup
+ * \{ */
-/* create Blender-side settings data - physics objects not initialized yet */
+/**
+ * Set up RigidBody world.
+ *
+ * Create Blender-side settings data - physics objects not initialized yet.
+ */
struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene);
+/**
+ * Add rigid body settings to the specified object.
+ */
struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene,
struct Object *ob,
short type);
+/**
+ * Add rigid body constraint to the specified object.
+ */
struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene,
struct Object *ob,
short type);
-/* Ensure newly set collections' objects all have required data. */
+/**
+ * Ensure newly set collections' objects all have required data.
+ */
void BKE_rigidbody_objects_collection_validate(struct Scene *scene, struct RigidBodyWorld *rbw);
void BKE_rigidbody_constraints_collection_validate(struct Scene *scene,
struct RigidBodyWorld *rbw);
-/* Ensure object added to collection gets RB data if that collection is a RB one. */
+/**
+ * Ensure object added to collection gets RB data if that collection is a RB one.
+ */
void BKE_rigidbody_main_collection_object_add(struct Main *bmain,
struct Collection *collection,
struct Object *object);
-/* copy */
+/**
+ * Copy.
+ */
struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw, const int flag);
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
-/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
+/**
+ * 'validate' (i.e. make new or replace old) Physics-Engine objects.
+ */
+/**
+ * Create physics sim world given RigidBody world settings
+ *
+ * \note this does NOT update object references that the scene uses,
+ * in case those aren't ready yet!
+ */
void BKE_rigidbody_validate_sim_world(struct Scene *scene,
struct RigidBodyWorld *rbw,
bool rebuild);
+/**
+ * Helper function to calculate volume of rigid-body object.
+
+ * TODO: allow a parameter to specify method used to calculate this?
+ */
void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol);
void BKE_rigidbody_calc_center_of_mass(struct Object *ob, float r_center[3]);
-/* -------------- */
-/* Utilities */
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+/**
+ * Get RigidBody world for the given scene, creating one if needed
+ *
+ * \param scene: Scene to find active Rigid Body world for.
+ */
struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene);
bool BKE_rigidbody_add_object(struct Main *bmain,
struct Scene *scene,
@@ -115,41 +173,68 @@ void BKE_rigidbody_remove_constraint(struct Main *bmain,
struct Object *ob,
const bool free_us);
-/* -------------- */
-/* Utility Macros */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utility Macros
+ * \{ */
-/* get mass of Rigid Body Object to supply to RigidBody simulators */
+/**
+ * Get mass of Rigid Body Object to supply to RigidBody simulators.
+ */
#define RBO_GET_MASS(rbo) \
(((rbo) && (((rbo)->type == RBO_TYPE_PASSIVE) || ((rbo)->flag & RBO_FLAG_KINEMATIC) || \
((rbo)->flag & RBO_FLAG_DISABLED))) ? \
(0.0f) : \
((rbo)->mass))
-/* Get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin,
- * convex hull always uses custom margin. */
+/**
+ * Get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin,
+ * convex hull always uses custom margin.
+ */
#define RBO_GET_MARGIN(rbo) \
(((rbo)->flag & RBO_FLAG_USE_MARGIN || (rbo)->shape == RB_SHAPE_CONVEXH || \
(rbo)->shape == RB_SHAPE_TRIMESH || (rbo)->shape == RB_SHAPE_CONE) ? \
((rbo)->margin) : \
(0.04f))
-/* -------------- */
-/* Simulation */
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Simulation
+ * \{ */
+
+/**
+ * Used when canceling transforms - return rigidbody and object to initial states.
+ */
void BKE_rigidbody_aftertrans_update(struct Object *ob,
float loc[3],
float rot[3],
float quat[4],
float rotAxis[3],
float rotAngle);
+/**
+ * Sync rigid body and object transformations.
+ */
void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime);
bool BKE_rigidbody_is_affected_by_simulation(struct Object *ob);
void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
+/**
+ * Rebuild rigid body world.
+ *
+ * NOTE: this needs to be called before frame update to work correctly.
+ */
void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, struct Scene *scene, float ctime);
+/**
+ * Run RigidBody simulation for the specified physics world.
+ */
void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, struct Scene *scene, float ctime);
-/* -------------------- */
-/* Depsgraph evaluation */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Depsgraph evaluation
+ * \{ */
void BKE_rigidbody_rebuild_sim(struct Depsgraph *depsgraph, struct Scene *scene);
@@ -159,6 +244,8 @@ void BKE_rigidbody_object_sync_transforms(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index f3edf8e9f64..77cf250471f 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -46,7 +46,7 @@ typedef enum eSceneCopyMethod {
SCE_COPY_FULL = 3,
} eSceneCopyMethod;
-/* Use as the contents of a 'for' loop: for (SETLOOPER(...)) { ... */
+/** Use as the contents of a 'for' loop: `for (SETLOOPER(...)) { ... }`. */
#define SETLOOPER(_sce_basis, _sce_iter, _base) \
_sce_iter = _sce_basis, \
_base = _setlooper_base_step( \
@@ -64,6 +64,12 @@ typedef enum eSceneCopyMethod {
_base; \
_base = _setlooper_base_step(&_sce_iter, NULL, _base)
+/**
+ * Helper function for the #SETLOOPER and #SETLOOPER_VIEW_LAYER macros
+ *
+ * It iterates over the bases of the active layer and then the bases
+ * of the active layer of the background (set) scenes recursively.
+ */
struct Base *_setlooper_base_step(struct Scene **sce_iter,
struct ViewLayer *view_layer,
struct Base *base);
@@ -77,6 +83,9 @@ void BKE_scene_remove_rigidbody_object(struct Main *bmain,
struct Object *ob,
const bool free_us);
+/**
+ * Check if there is any instance of the object in the scene.
+ */
bool BKE_scene_object_find(struct Scene *scene, struct Object *ob);
struct Object *BKE_scene_object_find_by_name(const struct Scene *scene, const char *name);
@@ -91,6 +100,10 @@ typedef struct SceneBaseIter {
int phase;
} SceneBaseIter;
+/**
+ * Used by meta-balls, return *all* objects (including duplis)
+ * existing in the scene (including scene's sets).
+ */
int BKE_scene_base_iter_next(struct Depsgraph *depsgraph,
struct SceneBaseIter *iter,
struct Scene **scene,
@@ -99,11 +112,33 @@ int BKE_scene_base_iter_next(struct Depsgraph *depsgraph,
struct Object **ob);
void BKE_scene_base_flag_to_objects(struct ViewLayer *view_layer);
+/**
+ * Synchronize object base flags
+ *
+ * This is usually handled by the depsgraph.
+ * However, in rare occasions we need to use the latest object flags
+ * before depsgraph is fully updated.
+ *
+ * It should (ideally) only run for copy-on-written objects since this is
+ * runtime data generated per-view-layer.
+ */
void BKE_scene_object_base_flag_sync_from_base(struct Base *base);
+/**
+ * Sets the active scene, mainly used when running in background mode
+ * (`--scene` command line argument).
+ * This is also called to set the scene directly, bypassing windowing code.
+ * Otherwise #WM_window_set_active_scene is used when changing scenes by the user.
+ */
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
+/**
+ * Called from `creator_args.c`.
+ */
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
+/**
+ * \param flag: copying options (see BKE_lib_id.h's `LIB_ID_COPY_...` flags for more).
+ */
struct ToolSettings *BKE_toolsettings_copy(struct ToolSettings *toolsettings, const int flag);
void BKE_toolsettings_free(struct ToolSettings *toolsettings);
@@ -122,23 +157,49 @@ struct Object *BKE_scene_camera_switch_find(struct Scene *scene); /* DURIAN_CAME
bool BKE_scene_camera_switch_update(struct Scene *scene);
const char *BKE_scene_find_marker_name(const struct Scene *scene, int frame);
+/**
+ * Return the current marker for this frame,
+ * we can have more than 1 marker per frame, this just returns the first (unfortunately).
+ */
const char *BKE_scene_find_last_marker_name(const struct Scene *scene, int frame);
int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int frame);
-/* checks for cycle, returns 1 if it's all OK */
+/**
+ * Checks for cycle, returns true if it's all OK.
+ */
bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce);
+/**
+ * Return fractional frame number taking into account sub-frames and time
+ * remapping. This the time value used by animation, modifiers and physics
+ * evaluation. */
float BKE_scene_ctime_get(const struct Scene *scene);
+/**
+ * Convert integer frame number to fractional frame number taking into account
+ * sub-frames and time remapping.
+ */
float BKE_scene_frame_to_ctime(const struct Scene *scene, const int frame);
+/**
+ * Get current fractional frame based on frame and sub-frame.
+ */
float BKE_scene_frame_get(const struct Scene *scene);
+/**
+ * Set current frame and sub-frame based on a fractional frame.
+ */
void BKE_scene_frame_set(struct Scene *scene, float frame);
struct TransformOrientationSlot *BKE_scene_orientation_slot_get_from_flag(struct Scene *scene,
int flag);
struct TransformOrientationSlot *BKE_scene_orientation_slot_get(struct Scene *scene,
int slot_index);
+/**
+ * Activate a transform orientation in a 3D view based on an enum value.
+ *
+ * \param orientation: If this is #V3D_ORIENT_CUSTOM or greater, the custom transform orientation
+ * with index \a orientation - #V3D_ORIENT_CUSTOM gets activated.
+ */
void BKE_scene_orientation_slot_set_index(struct TransformOrientationSlot *orient_slot,
int orientation);
int BKE_scene_orientation_slot_get_index(const struct TransformOrientationSlot *orient_slot);
@@ -154,16 +215,29 @@ void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph, struct Main *bma
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain);
void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph);
+/**
+ * Applies changes right away, does all sets too.
+ */
void BKE_scene_graph_update_for_newframe_ex(struct Depsgraph *depsgraph, const bool clear_recalc);
+/**
+ * Ensures given scene/view_layer pair has a valid, up-to-date depsgraph.
+ *
+ * \warning Sets matching depsgraph as active,
+ * so should only be called from the active editing context (usually, from operators).
+ */
void BKE_scene_view_layer_graph_evaluated_ensure(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
+/**
+ * Return default view.
+ */
struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
-/* render profile */
+/* Render profile. */
+
int get_render_subsurf_level(const struct RenderData *r, int lvl, bool for_render);
int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render);
@@ -174,8 +248,12 @@ bool BKE_scene_uses_blender_eevee(const struct Scene *scene);
bool BKE_scene_uses_blender_workbench(const struct Scene *scene);
bool BKE_scene_uses_cycles(const struct Scene *scene);
-/* Return whether the Cycles experimental feature is enabled. It is invalid to call without first
- * ensuring that Cycles is the active render engine (e.g. with BKE_scene_uses_cycles). */
+/**
+ * Return whether the Cycles experimental feature is enabled. It is invalid to call without first
+ * ensuring that Cycles is the active render engine (e.g. with #BKE_scene_uses_cycles).
+ *
+ * \note We cannot use `const` as RNA_id_pointer_create is not using a const ID.
+ */
bool BKE_scene_uses_cycles_experimental_features(struct Scene *scene);
void BKE_scene_copy_data_eevee(struct Scene *sce_dst, const struct Scene *sce_src);
@@ -191,13 +269,27 @@ int BKE_render_preview_pixel_size(const struct RenderData *r);
/**********************************/
+/**
+ * Apply the needed correction factor to value, based on unit_type
+ * (only length-related are affected currently) and `unit->scale_length`.
+ */
double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
-/* multiview */
+/* Multi-view. */
+
bool BKE_scene_multiview_is_stereo3d(const struct RenderData *rd);
+/**
+ * Return whether to render this #SceneRenderView.
+ */
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd,
const struct SceneRenderView *srv);
+/**
+ * \return true if `viewname` is the first or if the name is NULL or not found.
+ */
bool BKE_scene_multiview_is_render_view_first(const struct RenderData *rd, const char *viewname);
+/**
+ * \return true if `viewname` is the last or if the name is NULL or not found.
+ */
bool BKE_scene_multiview_is_render_view_last(const struct RenderData *rd, const char *viewname);
int BKE_scene_multiview_num_views_get(const struct RenderData *rd);
struct SceneRenderView *BKE_scene_multiview_render_view_findindex(const struct RenderData *rd,
@@ -208,6 +300,12 @@ int BKE_scene_multiview_view_id_get(const struct RenderData *rd, const char *vie
void BKE_scene_multiview_filepath_get(struct SceneRenderView *srv,
const char *filepath,
char *r_filepath);
+/**
+ * When multi-view is not used the `filepath` is as usual (e.g., `Image.jpg`).
+ * When multi-view is on, even if only one view is enabled the view is incorporated
+ * into the file name (e.g., `Image_L.jpg`). That allows for the user to re-render
+ * individual views.
+ */
void BKE_scene_multiview_view_filepath_get(const struct RenderData *rd,
const char *filepath,
const char *view,
@@ -231,10 +329,14 @@ void BKE_scene_ensure_depsgraph_hash(struct Scene *scene);
void BKE_scene_free_depsgraph_hash(struct Scene *scene);
void BKE_scene_free_view_layer_depsgraph(struct Scene *scene, struct ViewLayer *view_layer);
-/* Do not allocate new depsgraph. */
+/**
+ * \note Do not allocate new depsgraph.
+ */
struct Depsgraph *BKE_scene_get_depsgraph(const struct Scene *scene,
const struct ViewLayer *view_layer);
-/* Allocate new depsgraph if necessary. */
+/**
+ * \note Allocate new depsgraph if necessary.
+ */
struct Depsgraph *BKE_scene_ensure_depsgraph(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
@@ -246,6 +348,10 @@ void BKE_scene_transform_orientation_remove(struct Scene *scene,
struct TransformOrientation *orientation);
struct TransformOrientation *BKE_scene_transform_orientation_find(const struct Scene *scene,
const int index);
+/**
+ * \return the index that \a orientation has within \a scene's transform-orientation list
+ * or -1 if not found.
+ */
int BKE_scene_transform_orientation_get_index(const struct Scene *scene,
const struct TransformOrientation *orientation);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 5c913ed851f..fd0682ee8f0 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -396,7 +396,8 @@ typedef struct Menu {
struct uiLayout *layout; /* runtime for drawing */
} Menu;
-/* spacetypes */
+/* Space-types. */
+
struct SpaceType *BKE_spacetype_from_id(int spaceid);
struct ARegionType *BKE_regiontype_from_id_or_first(const struct SpaceType *st, int regionid);
struct ARegionType *BKE_regiontype_from_id(const struct SpaceType *st, int regionid);
@@ -405,11 +406,26 @@ void BKE_spacetype_register(struct SpaceType *st);
bool BKE_spacetype_exists(int spaceid);
void BKE_spacetypes_free(void); /* only for quitting blender */
-/* spacedata */
+/* Space-data. */
+
void BKE_spacedata_freelist(ListBase *lb);
-void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
+/**
+ * \param lb_dst: should be empty (will be cleared).
+ */
+void BKE_spacedata_copylist(ListBase *lb_dst, ListBase *lb_src);
+
+/**
+ * Facility to set locks for drawing to survive (render) threads accessing drawing data.
+ *
+ * \note Lock can become bit-flag too.
+ * \note Should be replaced in future by better local data handling for threads.
+ */
void BKE_spacedata_draw_locks(bool set);
+/**
+ * Version of #BKE_area_find_region_type that also works if \a slink
+ * is not the active space of \a area.
+ */
struct ARegion *BKE_spacedata_find_region_type(const struct SpaceLink *slink,
const struct ScrArea *area,
int region_type) ATTR_WARN_UNUSED_RESULT
@@ -417,21 +433,42 @@ struct ARegion *BKE_spacedata_find_region_type(const struct SpaceLink *slink,
void BKE_spacedata_callback_id_remap_set(void (*func)(
struct ScrArea *area, struct SpaceLink *sl, struct ID *old_id, struct ID *new_id));
+/**
+ * Currently unused!
+ */
void BKE_spacedata_id_unref(struct ScrArea *area, struct SpaceLink *sl, struct ID *id);
-/* area/regions */
+/* Area/regions. */
+
struct ARegion *BKE_area_region_copy(const struct SpaceType *st, const struct ARegion *region);
+/**
+ * Doesn't free the region itself.
+ */
void BKE_area_region_free(struct SpaceType *st, struct ARegion *region);
void BKE_area_region_panels_free(struct ListBase *panels);
+/**
+ * Doesn't free the area itself.
+ */
void BKE_screen_area_free(struct ScrArea *area);
-/* Gizmo-maps of a region need to be freed with the region.
- * Uses callback to avoid low-level call. */
+/**
+ * Gizmo-maps of a region need to be freed with the region.
+ * Uses callback to avoid low-level call.
+ */
void BKE_region_callback_free_gizmomap_set(void (*callback)(struct wmGizmoMap *));
void BKE_region_callback_refresh_tag_gizmomap_set(void (*callback)(struct wmGizmoMap *));
+/**
+ * Find a region of type \a region_type in the currently active space of \a area.
+ *
+ * \note This does _not_ work if the region to look up is not in the active space.
+ * Use #BKE_spacedata_find_region_type if that may be the case.
+ */
struct ARegion *BKE_area_find_region_type(const struct ScrArea *area, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *area);
struct ARegion *BKE_area_find_region_xy(struct ScrArea *area, const int regiontype, int x, int y);
+/**
+ * \note This is only for screen level regions (typically menus/popups).
+ */
struct ARegion *BKE_screen_find_region_xy(struct bScreen *screen,
const int regiontype,
int x,
@@ -442,9 +479,17 @@ struct ARegion *BKE_screen_find_main_region_at_xy(struct bScreen *screen,
const int x,
const int y);
+/**
+ * \note Ideally we can get the area from the context,
+ * there are a few places however where this isn't practical.
+ */
struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *screen,
struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2);
+/**
+ * \note Using this function is generally a last resort, you really want to be
+ * using the context when you can - campbell
+ */
struct ScrArea *BKE_screen_find_big_area(struct bScreen *screen,
const int spacetype,
const short min);
@@ -462,15 +507,24 @@ bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSE
ATTR_NONNULL();
bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-/* zoom factor conversion */
+/* Zoom factor conversion. */
+
float BKE_screen_view3d_zoom_to_fac(float camzoom);
float BKE_screen_view3d_zoom_from_fac(float zoomfac);
void BKE_screen_view3d_shading_init(struct View3DShading *shading);
-/* screen */
+/* Screen. */
+
+/**
+ * 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(struct LibraryForeachIDData *data, struct ScrArea *area);
+/**
+ * Free (or release) any data used by this screen (does not free the screen itself).
+ */
void BKE_screen_free_data(struct bScreen *screen);
void BKE_screen_area_map_free(struct ScrAreaMap *area_map) ATTR_NONNULL();
@@ -486,18 +540,28 @@ void BKE_screen_remove_unused_scrverts(struct bScreen *screen);
void BKE_screen_header_alignment_reset(struct bScreen *screen);
/* .blend file I/O */
+
void BKE_screen_view3d_shading_blend_write(struct BlendWriter *writer,
struct View3DShading *shading);
void BKE_screen_view3d_shading_blend_read_data(struct BlendDataReader *reader,
struct View3DShading *shading);
void BKE_screen_area_map_blend_write(struct BlendWriter *writer, struct ScrAreaMap *area_map);
+/**
+ * \return false on error.
+ */
bool BKE_screen_area_map_blend_read_data(struct BlendDataReader *reader,
struct ScrAreaMap *area_map);
+/**
+ * And as patch for 2.48 and older.
+ */
void BKE_screen_view3d_do_versions_250(struct View3D *v3d, ListBase *regions);
void BKE_screen_area_blend_read_lib(struct BlendLibReader *reader,
struct ID *parent_id,
struct ScrArea *area);
+/**
+ * Cannot use #IDTypeInfo callback yet, because of the return value.
+ */
bool BKE_screen_blend_read_data(struct BlendDataReader *reader, struct bScreen *screen);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h
index 8d1fe709355..a82112ff967 100644
--- a/source/blender/blenkernel/BKE_shader_fx.h
+++ b/source/blender/blenkernel/BKE_shader_fx.h
@@ -149,17 +149,34 @@ typedef struct ShaderFxTypeInfo {
#define SHADERFX_TYPE_PANEL_PREFIX "FX_PT_"
-/* Initialize global data (type info and some common global storage). */
+/**
+ * Initialize global data (type info and some common global storage).
+ */
void BKE_shaderfx_init(void);
+/**
+ * Get an effect's panel type, which was defined in the #panelRegister callback.
+ *
+ * \note ShaderFx panel types are assumed to be named with the struct name field concatenated to
+ * the defined prefix.
+ */
void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname);
void BKE_shaderfx_panel_expand(struct ShaderFxData *fx);
const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type);
struct ShaderFxData *BKE_shaderfx_new(int type);
void BKE_shaderfx_free_ex(struct ShaderFxData *fx, const int flag);
void BKE_shaderfx_free(struct ShaderFxData *fx);
+/**
+ * Check unique name.
+ */
bool BKE_shaderfx_unique_name(struct ListBase *shaderfx, struct ShaderFxData *fx);
bool BKE_shaderfx_depends_ontime(struct ShaderFxData *fx);
+/**
+ * Check whether given shaderfx is not local (i.e. from linked data) when the object is a library
+ * override.
+ *
+ * \param shaderfx: May be NULL, in which case we consider it as a non-local shaderfx case.
+ */
bool BKE_shaderfx_is_nonlocal_in_liboverride(const struct Object *ob,
const struct ShaderFxData *shaderfx);
struct ShaderFxData *BKE_shaderfx_findby_type(struct Object *ob, ShaderFxType type);
@@ -172,6 +189,9 @@ void BKE_shaderfx_copydata_ex(struct ShaderFxData *fx,
void BKE_shaderfx_copy(struct ListBase *dst, const struct ListBase *src);
void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData);
+/**
+ * Check if exist grease pencil effects.
+ */
bool BKE_shaderfx_has_gpencil(const struct Object *ob);
void BKE_shaderfx_blend_write(struct BlendWriter *writer, struct ListBase *fxbase);
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 70aeb37d995..088b270bfed 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -34,11 +34,11 @@ extern "C" {
* Shrinkwrap is composed by a set of functions and options that define the type of shrink.
*
* 3 modes are available:
- * - Nearest vertex
- * - Nearest surface
- * - Normal projection
+ * - Nearest vertex.
+ * - Nearest surface.
+ * - Normal projection.
*
- * ShrinkwrapCalcData encapsulates all needed data for shrinkwrap functions.
+ * #ShrinkwrapCalcData encapsulates all needed data for shrink-wrap functions.
* (So that you don't have to pass an enormous amount of arguments to functions)
*/
@@ -48,6 +48,7 @@ struct Mesh;
struct ModifierEvalContext;
struct Object;
struct ShrinkwrapModifierData;
+struct ShrinkwrapGpencilModifierData;
struct SpaceTransform;
/* Information about boundary edges in the mesh. */
@@ -74,6 +75,9 @@ typedef struct ShrinkwrapBoundaryData {
const ShrinkwrapBoundaryVertData *boundary_verts;
} ShrinkwrapBoundaryData;
+/**
+ * Free boundary data for target project.
+ */
void BKE_shrinkwrap_discard_boundary_data(struct Mesh *mesh);
void BKE_shrinkwrap_compute_boundary_data(struct Mesh *mesh);
@@ -89,20 +93,28 @@ typedef struct ShrinkwrapTreeData {
ShrinkwrapBoundaryData *boundary;
} ShrinkwrapTreeData;
-/* Checks if the modifier needs target normals with these settings. */
+/**
+ * Checks if the modifier needs target normals with these settings.
+ */
bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode);
-/* Initializes the mesh data structure from the given mesh and settings. */
+/**
+ * Initializes the mesh data structure from the given mesh and settings.
+ */
bool BKE_shrinkwrap_init_tree(struct ShrinkwrapTreeData *data,
Mesh *mesh,
int shrinkType,
int shrinkMode,
bool force_normals);
-/* Frees the tree data if necessary. */
+/**
+ * Frees the tree data if necessary.
+ */
void BKE_shrinkwrap_free_tree(struct ShrinkwrapTreeData *data);
-/* Implementation of the Shrinkwrap modifier */
+/**
+ * Main shrink-wrap function (implementation of the shrink-wrap modifier).
+ */
void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd,
const struct ModifierEvalContext *ctx,
struct Scene *scene,
@@ -112,27 +124,44 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd,
const int defgrp_index,
float (*vertexCos)[3],
int numVerts);
-
-/* Used in editmesh_mask_extract.c to shrinkwrap the extracted mesh to the sculpt */
+/* Implementation of the Shrinkwrap Grease Pencil modifier. */
+void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd,
+ struct Object *ob,
+ struct MDeformVert *dvert,
+ const int defgrp_index,
+ float (*vertexCos)[3],
+ int numVerts);
+
+/**
+ * Used in `editmesh_mask_extract.c` to shrink-wrap the extracted mesh to the sculpt.
+ */
void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
struct Object *ob_source,
struct Object *ob_target);
-/* Used in object_remesh.cc to preserve the details and volume in the voxel remesher */
+/**
+ * Used in `object_remesh.cc` to preserve the details and volume in the voxel remesher.
+ */
void BKE_shrinkwrap_remesh_target_project(struct Mesh *src_me,
struct Mesh *target_me,
struct Object *ob_target);
-/*
- * This function casts a ray in the given BVHTree.
- * but it takes into consideration the space_transform, that is:
+/**
+ * This function ray-cast a single vertex and updates the hit if the "hit" is considered valid.
*
- * if transf was configured with "SPACE_TRANSFORM_SETUP( &transf, ob1, ob2 )"
- * then the input (vert, dir, BVHTreeRayHit) must be defined in ob1 coordinates space
- * and the BVHTree must be built in ob2 coordinate space.
+ * \param options: Opts control whether an hit is valid or not.
+ * Supported options are:
+ * - #MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored)
+ * - #MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored)
*
+ * \param transf: Take into consideration the space_transform, that is:
+ * if `transf` was configured with `SPACE_TRANSFORM_SETUP( &transf, ob1, ob2)`
+ * then the input (vert, dir, #BVHTreeRayHit) must be defined in ob1 coordinates space
+ * and the #BVHTree must be built in ob2 coordinate space.
* Thus it provides an easy way to cast the same ray across several trees
- * (where each tree was built on its own coords space)
+ * (where each tree was built on its own coords space).
+ *
+ * \return true if "hit" was updated.
*/
bool BKE_shrinkwrap_project_normal(char options,
const float vert[3],
@@ -142,14 +171,21 @@ bool BKE_shrinkwrap_project_normal(char options,
struct ShrinkwrapTreeData *tree,
BVHTreeRayHit *hit);
-/* Maps the point to the nearest surface, either by simple nearest,
- * or by target normal projection. */
+/**
+ * Maps the point to the nearest surface, either by simple nearest, or by target normal projection.
+ */
void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree,
struct BVHTreeNearest *nearest,
float co[3],
int type);
-/* Computes a smooth normal of the target (if applicable) at the hit location. */
+/**
+ * Compute a smooth normal of the target (if applicable) at the hit location.
+ *
+ * \param tree: information about the mesh.
+ * \param transform: transform from the hit coordinate space to the object space; may be null.
+ * \param r_no: output in hit coordinate space; may be shared with inputs.
+ */
void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
const struct SpaceTransform *transform,
int looptri_idx,
@@ -157,7 +193,13 @@ void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
const float hit_no[3],
float r_no[3]);
-/* Apply the shrink to surface modes to the given original coordinates and nearest point. */
+/**
+ * Apply the shrink to surface modes to the given original coordinates and nearest point.
+ *
+ * \param tree: mesh data for smooth normals.
+ * \param transform: transform from the hit coordinate space to the object space; may be null.
+ * \param r_point_co: may be the same memory location as `point_co`, `hit_co`, or `hit_no`.
+ */
void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree,
const struct SpaceTransform *transform,
int mode,
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h
index 58dc90f62dc..5d010fa2155 100644
--- a/source/blender/blenkernel/BKE_softbody.h
+++ b/source/blender/blenkernel/BKE_softbody.h
@@ -46,16 +46,24 @@ typedef struct BodyPoint {
float springweight;
} BodyPoint;
-/* allocates and initializes general main data */
+/**
+ * Allocates and initializes general main data.
+ */
extern struct SoftBody *sbNew(void);
-/* frees internal data and soft-body itself */
+/**
+ * Frees internal data and soft-body itself.
+ */
extern void sbFree(struct Object *ob);
-/* frees simulation data to reset simulation */
+/**
+ * Frees simulation data to reset simulation.
+ */
extern void sbFreeSimulation(struct SoftBody *sb);
-/* do one simul step, reading and writing vertex locs from given array */
+/**
+ * Do one simulation step, reading and writing vertex locs from given array.
+ * */
extern void sbObjectStep(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
@@ -63,13 +71,30 @@ extern void sbObjectStep(struct Depsgraph *depsgraph,
float (*vertexCos)[3],
int numVerts);
-/* makes totally fresh start situation, resets time */
+/**
+ * Makes totally fresh start situation, resets time.
+ */
extern void sbObjectToSoftbody(struct Object *ob);
-/* links the soft-body module to a 'test for Interrupt' function */
-/* pass NULL to unlink again */
+/**
+ * Soft-body global visible functions.
+ * Links the soft-body module to a 'test for Interrupt' function, pass NULL to clear the callback.
+ */
extern void sbSetInterruptCallBack(int (*f)(void));
+/**
+ * A precise position vector denoting the motion of the center of mass give a rotation/scale matrix
+ * using averaging method, that's why estimate and not calculate see: this is kind of reverse
+ * engineering: having to states of a point cloud and recover what happened our advantage here we
+ * know the identity of the vertex there are others methods giving other results.
+ *
+ * \param ob: Any object that can do soft-body e.g. mesh, lattice, curve.
+ * \param lloc: Output of the calculated location (or NULL).
+ * \param lrot: Output of the calculated rotation (or NULL).
+ * \param lscale: Output for the calculated scale (or NULL).
+ *
+ * For velocity & 2nd order stuff see: #vcloud_estimate_transform_v3.
+ */
extern void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3]);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index c332e9a8dac..ebdc4a0ca0b 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -40,7 +40,8 @@ using SplinePtr = std::unique_ptr<Spline>;
/**
* A spline is an abstraction of a single branch-less curve section, its evaluation methods,
* and data. The spline data itself is just control points and a set of attributes by the set
- * of "evaluated" data is often used instead.
+ * of "evaluated" data is often used instead. Conceptually, the derived vs. original data is
+ * an essential distinction. Derived data is usually calculated lazily and cached on the spline.
*
* Any derived class of Spline has to manage two things:
* 1. Interpolating arbitrary attribute data from the control points to evaluated points.
@@ -106,8 +107,17 @@ class Spline {
copy_base_settings(other, *this);
}
+ /**
+ * Return a new spline with the same data, settings, and attributes.
+ */
SplinePtr copy() const;
+ /**
+ * Return a new spline with the same type and settings like "cyclic", but without any data.
+ */
SplinePtr copy_only_settings() const;
+ /**
+ * The same as #copy, but skips copying dynamic attributes to the new spline.
+ */
SplinePtr copy_without_attributes() const;
static void copy_base_settings(const Spline &src, Spline &dst);
@@ -147,8 +157,22 @@ class Spline {
virtual blender::Span<blender::float3> evaluated_positions() const = 0;
+ /**
+ * Return non-owning access to the cache of accumulated lengths along the spline. Each item is
+ * the length of the subsequent segment, i.e. the first value is the length of the first segment
+ * rather than 0. This calculation is rather trivial, and only depends on the evaluated
+ * positions. However, the results are used often, and it is necessarily single threaded, so it
+ * is cached.
+ */
blender::Span<float> evaluated_lengths() const;
+ /**
+ * Return non-owning access to the direction of the curve at each evaluated point.
+ */
blender::Span<blender::float3> evaluated_tangents() const;
+ /**
+ * Return non-owning access to the direction vectors perpendicular to the tangents at every
+ * evaluated point. The method used to generate the normal vectors depends on Spline.normal_mode.
+ */
blender::Span<blender::float3> evaluated_normals() const;
void bounds_min_max(blender::float3 &min, blender::float3 &max, const bool use_evaluated) const;
@@ -172,12 +196,32 @@ class Spline {
*/
float factor;
};
+ /**
+ * Find the position on the evaluated spline at the given portion of the total length.
+ * The return value is the indices of the two neighboring points at that location and the
+ * factor between them, which can be used to look up any attribute on the evaluated points.
+ * \note This does not support extrapolation.
+ */
LookupResult lookup_evaluated_factor(const float factor) const;
+ /**
+ * The same as #lookup_evaluated_factor, but looks up a length directly instead of
+ * a portion of the total.
+ */
LookupResult lookup_evaluated_length(const float length) const;
+ /**
+ * Return an array of evenly spaced samples along the length of the spline. The samples are
+ * indices and factors to the next index encoded in floats. The logic for converting from the
+ * float values to interpolation data is in #lookup_data_from_index_factor.
+ */
blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
LookupResult lookup_data_from_index_factor(const float index_factor) const;
+ /**
+ * Sample any input data with a value for each evaluated point (already interpolated to evaluated
+ * points) to arbitrary parameters in between the evaluated points. The interpolation is quite
+ * simple, but this handles the cyclic and end point special cases.
+ */
void sample_with_index_factors(const blender::fn::GVArray &src,
blender::Span<float> index_factors,
blender::fn::GMutableSpan dst) const;
@@ -286,6 +330,9 @@ class BezierSpline final : public Spline {
int resolution() const;
void set_resolution(const int value);
+ /**
+ * \warning Call #reallocate on the spline's attributes after adding all points.
+ */
void add_point(const blender::float3 position,
const HandleType handle_type_left,
const blender::float3 handle_position_left,
@@ -321,12 +368,24 @@ class BezierSpline final : public Spline {
* uninitialized memory while auto-generating handles.
*/
blender::MutableSpan<blender::float3> handle_positions_right(bool write_only = false);
+ /**
+ * Recalculate all #Auto and #Vector handles with positions automatically
+ * derived from the neighboring control points.
+ */
void ensure_auto_handles() const;
void translate(const blender::float3 &translation) override;
void transform(const blender::float4x4 &matrix) override;
+ /**
+ * Set positions for the right handle of the control point, ensuring that
+ * aligned handles stay aligned. Has no effect for auto and vector type handles.
+ */
void set_handle_position_right(const int index, const blender::float3 &value);
+ /**
+ * Set positions for the left handle of the control point, ensuring that
+ * aligned handles stay aligned. Has no effect for auto and vector type handles.
+ */
void set_handle_position_left(const int index, const blender::float3 &value);
bool point_is_sharp(const int index) const;
@@ -334,7 +393,22 @@ class BezierSpline final : public Spline {
void mark_cache_invalid() final;
int evaluated_points_size() const final;
+ /**
+ * Returns access to a cache of offsets into the evaluated point array for each control point.
+ * While most control point edges generate the number of edges specified by the resolution,
+ * vector segments only generate one edge.
+ *
+ * \note The length of the result is one greater than the number of points, so that the last item
+ * is the total number of evaluated points. This is useful to avoid recalculating the size of the
+ * last segment everywhere.
+ */
blender::Span<int> control_point_offsets() const;
+ /**
+ * Returns non-owning access to an array of values containing the information necessary to
+ * interpolate values from the original control points to evaluated points. The control point
+ * index is the integer part of each value, and the factor used for interpolating to the next
+ * control point is the remaining factional part.
+ */
blender::Span<float> evaluated_mappings() const;
blender::Span<blender::float3> evaluated_positions() const final;
struct InterpolationData {
@@ -346,6 +420,11 @@ class BezierSpline final : public Spline {
*/
float factor;
};
+ /**
+ * Convert the data encoded in #evaulated_mappings into its parts-- the information necessary
+ * to interpolate data from control points to evaluated points between them. The next control
+ * point index result will not overflow the size of the control point vectors.
+ */
InterpolationData interpolation_data_from_index_factor(const float index_factor) const;
virtual blender::fn::GVArray interpolate_to_evaluated(
@@ -354,6 +433,9 @@ class BezierSpline final : public Spline {
void evaluate_segment(const int index,
const int next_index,
blender::MutableSpan<blender::float3> positions) const;
+ /**
+ * \warning This functional assumes that the spline has more than one point.
+ */
bool segment_is_vector(const int start_index) const;
/** See comment and diagram for #calculate_segment_insertion. */
@@ -364,11 +446,36 @@ class BezierSpline final : public Spline {
blender::float3 right_handle;
blender::float3 handle_next;
};
+ /**
+ * De Casteljau Bezier subdivision.
+ * \param index: The index of the segment's start control point.
+ * \param next_index: The index of the control point at the end of the segment. Could be 0,
+ * if the spline is cyclic.
+ * \param parameter: The factor along the segment, between 0 and 1. Note that this is used
+ * directly by the calculation, it doesn't correspond to a portion of the evaluated length.
+ *
+ * <pre>
+ * handle_prev handle_next
+ * x----------------x
+ * / \
+ * / x---O---x \
+ * / result \
+ * / \
+ * O O
+ * point_prev point_next
+ * </pre>
+ */
InsertResult calculate_segment_insertion(const int index,
const int next_index,
const float parameter);
private:
+ /**
+ * If the spline is not cyclic, the direction for the first and last points is just the
+ * direction formed by the corresponding handles and control points. In the unlikely situation
+ * that the handles define a zero direction, fallback to using the direction defined by the
+ * first and last evaluated segments already calculated in #Spline::evaluated_tangents().
+ */
void correct_end_tangents() const final;
void copy_settings(Spline &dst) const final;
void copy_data(Spline &dst) const final;
@@ -460,6 +567,9 @@ class NURBSpline final : public Spline {
uint8_t order() const;
void set_order(const uint8_t value);
+ /**
+ * \warning Call #reallocate on the spline's attributes after adding all points.
+ */
void add_point(const blender::float3 position,
const float radius,
const float tilt,
@@ -498,9 +608,12 @@ class NURBSpline final : public Spline {
};
/**
- * A Poly spline is like a bezier spline with a resolution of one. The main reason to distinguish
+ * A Poly spline is like a Bézier spline with a resolution of one. The main reason to distinguish
* the two is for reduced complexity and increased performance, since interpolating data to control
* points does not change it.
+ *
+ * Poly spline code is very simple, since it doesn't do anything that the base #Spline doesn't
+ * handle. Mostly it just worries about storing the data used by the base class.
*/
class PolySpline final : public Spline {
blender::Vector<blender::float3> positions_;
@@ -521,6 +634,9 @@ class PolySpline final : public Spline {
int size() const final;
+ /**
+ * \warning Call #reallocate on the spline's attributes after adding all points.
+ */
void add_point(const blender::float3 position, const float radius, const float tilt);
void resize(const int size) final;
@@ -536,6 +652,12 @@ class PolySpline final : public Spline {
blender::Span<blender::float3> evaluated_positions() const final;
+ /**
+ * Poly spline interpolation from control points to evaluated points is a special case, since
+ * the result data is the same as the input data. This function returns a #GVArray that points to
+ * the original data. Therefore the lifetime of the returned virtual array must not be longer
+ * than the source data.
+ */
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
protected:
@@ -546,8 +668,12 @@ class PolySpline final : public Spline {
};
/**
- * A #CurveEval corresponds to the #Curve object data. The name is different for clarity, since
- * more of the data is stored in the splines, but also just to be different than the name in DNA.
+ * A collection of #Spline objects with the same attribute types and names. Most data and
+ * functionality is in splines, but this contains some helpers for working with them as a group.
+ *
+ * \note A #CurveEval corresponds to the #Curve object data. The name is different for clarity,
+ * since more of the data is stored in the splines, but also just to be different than the name in
+ * DNA.
*/
struct CurveEval {
private:
@@ -566,22 +692,56 @@ struct CurveEval {
blender::Span<SplinePtr> splines() const;
blender::MutableSpan<SplinePtr> splines();
+ /**
+ * \return True if the curve contains a spline with the given type.
+ *
+ * \note If you are looping over all of the splines in the same scope anyway,
+ * it's better to avoid calling this function, in case there are many splines.
+ */
bool has_spline_with_type(const Spline::Type type) const;
void resize(const int size);
+ /**
+ * \warning Call #reallocate on the spline's attributes after adding all splines.
+ */
void add_spline(SplinePtr spline);
+ void add_splines(blender::MutableSpan<SplinePtr> splines);
void remove_splines(blender::IndexMask mask);
void translate(const blender::float3 &translation);
void transform(const blender::float4x4 &matrix);
void bounds_min_max(blender::float3 &min, blender::float3 &max, const bool use_evaluated) const;
+ /**
+ * Return the start indices for each of the curve spline's control points, if they were part
+ * of a flattened array. This can be used to facilitate parallelism by avoiding the need to
+ * accumulate an offset while doing more complex calculations.
+ *
+ * \note The result is one longer than the spline count; the last element is the total size.
+ */
blender::Array<int> control_point_offsets() const;
+ /**
+ * Exactly like #control_point_offsets, but uses the number of evaluated points instead.
+ */
blender::Array<int> evaluated_point_offsets() const;
+ /**
+ * Return the accumulated length at the start of every spline in the curve.
+ * \note The result is one longer than the spline count; the last element is the total length.
+ */
blender::Array<float> accumulated_spline_lengths() const;
+ float total_length() const;
+ int total_control_point_size() const;
+
void mark_cache_invalid();
+ /**
+ * Check the invariants that curve control point attributes should always uphold, necessary
+ * because attributes are stored on splines rather than in a flat array on the curve:
+ * - The same set of attributes exists on every spline.
+ * - Attributes with the same name have the same type on every spline.
+ * - Attributes are in the same order on every spline.
+ */
void assert_valid_point_attributes() const;
};
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index 59b1c2b28d9..792186dd260 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -143,6 +143,8 @@ typedef struct StudioLight {
void *free_function_data;
} StudioLight;
+/* API */
+
void BKE_studiolight_init(void);
void BKE_studiolight_free(void);
void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3]);
@@ -151,12 +153,18 @@ struct StudioLight *BKE_studiolight_findindex(int index, int flag);
struct StudioLight *BKE_studiolight_find_default(int flag);
void BKE_studiolight_preview(uint *icon_buffer, StudioLight *sl, int icon_id_type);
struct ListBase *BKE_studiolight_listbase(void);
+/**
+ * Ensure state of studio-lights.
+ */
void BKE_studiolight_ensure_flag(StudioLight *sl, int flag);
void BKE_studiolight_refresh(void);
StudioLight *BKE_studiolight_load(const char *path, int type);
StudioLight *BKE_studiolight_create(const char *path,
const SolidLight light[4],
const float light_ambient[3]);
+/**
+ * Only useful for workbench while editing the user-preferences.
+ */
StudioLight *BKE_studiolight_studio_edit_get(void);
void BKE_studiolight_remove(StudioLight *sl);
void BKE_studiolight_set_free_function(StudioLight *sl,
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index 3816a822279..db57076082c 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -66,18 +66,30 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm,
void subsurf_calculate_limit_positions(struct Mesh *me, float (*r_positions)[3]);
-/* get gridsize from 'level', level must be greater than zero */
+/**
+ * Get grid-size from 'level', level must be greater than zero.
+ */
int BKE_ccg_gridsize(int level);
-/* x/y grid coordinates at 'low_level' can be multiplied by the result
- * of this function to convert to grid coordinates at 'high_level' */
+/**
+ * X/Y grid coordinates at 'low_level' can be multiplied by the result
+ * of this function to convert to grid coordinates at 'high_level'.
+ */
int BKE_ccg_factor(int low_level, int high_level);
+/**
+ * Translate #GridHidden into the #ME_HIDE flag for MVerts. Assumes
+ * vertices are in the order output by #ccgDM_copyFinalVertArray.
+ */
void subsurf_copy_grid_hidden(struct DerivedMesh *dm,
const struct MPoly *mpoly,
struct MVert *mvert,
const struct MDisps *mdisps);
+/**
+ * Translate #GridPaintMask into vertex paint masks. Assumes vertices
+ * are in the order output by #ccgDM_copyFinalVertArray.
+ */
void subsurf_copy_grid_paint_mask(struct DerivedMesh *dm,
const struct MPoly *mpoly,
float *paint_mask,
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index c7120c60020..a979ba6d2cc 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -30,17 +30,44 @@ struct Main;
struct Text;
struct TextLine;
+/**
+ * \note caller must handle `compiled` member.
+ */
void BKE_text_free_lines(struct Text *text);
struct Text *BKE_text_add(struct Main *bmain, const char *name);
+/**
+ * Use to a valid UTF-8 sequences.
+ * this function replaces extended ascii characters.
+ */
int txt_extended_ascii_as_utf8(char **str);
bool BKE_text_reload(struct Text *text);
+/**
+ * Load a text file.
+ *
+ * \param is_internal: If \a true, this text data-block only exists in memory,
+ * not as a file on disk.
+ *
+ * \note text data-blocks have no real user but have 'fake user' enabled by default
+ */
struct Text *BKE_text_load_ex(struct Main *bmain,
const char *file,
const char *relpath,
const bool is_internal);
+/**
+ * Load a text file.
+ *
+ * \note Text data-blocks have no user by default, only the 'real user' flag.
+ */
struct Text *BKE_text_load(struct Main *bmain, const char *file, const char *relpath);
void BKE_text_clear(struct Text *text);
void BKE_text_write(struct Text *text, const char *str);
+/**
+ * \return codes:
+ * - 0 if file on disk is the same or Text is in memory only.
+ * - 1 if file has been modified on disk since last local edit.
+ * - 2 if file on disk has been deleted.
+ * - -1 is returned if an error occurs.
+ */
int BKE_text_file_modified_check(struct Text *text);
void BKE_text_file_modified_ignore(struct Text *text);
@@ -61,12 +88,20 @@ void txt_move_eof(struct Text *text, const bool sel);
void txt_move_bol(struct Text *text, const bool sel);
void txt_move_eol(struct Text *text, const bool sel);
void txt_move_toline(struct Text *text, unsigned int line, const bool sel);
+/**
+ * Moves to a certain byte in a line, not a certain utf8-character.
+ */
void txt_move_to(struct Text *text, unsigned int line, unsigned int ch, const bool sel);
void txt_pop_sel(struct Text *text);
void txt_delete_char(struct Text *text);
void txt_delete_word(struct Text *text);
void txt_delete_selected(struct Text *text);
void txt_sel_all(struct Text *text);
+/**
+ * Reverse of #txt_pop_sel
+ * Clears the selection and ensures the cursor is located
+ * at the selection (where the cursor is visually while editing).
+ */
void txt_sel_clear(struct Text *text);
void txt_sel_line(struct Text *text);
void txt_sel_set(struct Text *text, int startl, int startc, int endl, int endc);
@@ -91,7 +126,9 @@ bool txt_cursor_is_line_end(const struct Text *text);
int txt_calc_tab_left(struct TextLine *tl, int ch);
int txt_calc_tab_right(struct TextLine *tl, int ch);
-/* Utility functions, could be moved somewhere more generic but are python/text related. */
+/**
+ * Utility functions, could be moved somewhere more generic but are python/text related.
+ */
int text_check_bracket(const char ch);
bool text_check_delim(const char ch);
bool text_check_digit(const char ch);
@@ -100,7 +137,7 @@ bool text_check_identifier_nodigit(const char ch);
bool text_check_whitespace(const char ch);
int text_find_identifier_start(const char *str, int i);
-/* defined in bpy_interface.c */
+/* EVIL: defined in `bpy_interface.c`. */
extern int text_check_identifier_unicode(const unsigned int ch);
extern int text_check_identifier_nodigit_unicode(const unsigned int ch);
@@ -110,7 +147,14 @@ enum {
};
/* Fast non-validating buffer conversion for undo. */
+
+/**
+ * Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it.
+ */
char *txt_to_buf_for_undo(struct Text *text, int *r_buf_len);
+/**
+ * Decode a buffer from #txt_to_buf_for_undo.
+ */
void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index ef322d0cd31..380b5cf035c 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -42,6 +42,9 @@ struct TexResult;
/** #ColorBand.data length. */
#define MAXCOLORBAND 32
+/**
+ * Utility for all IDs using those texture slots.
+ */
void BKE_texture_mtex_foreach_id(struct LibraryForeachIDData *data, struct MTex *mtex);
void BKE_texture_default(struct Tex *tex);
@@ -50,6 +53,9 @@ void BKE_texture_type_set(struct Tex *tex, int type);
void BKE_texture_mtex_default(struct MTex *mtex);
struct MTex *BKE_texture_mtex_add(void);
+/**
+ * Slot -1 for first free ID.
+ */
struct MTex *BKE_texture_mtex_add_id(struct ID *id, int slot);
/* UNUSED */
// void autotexname(struct Tex *tex);
@@ -79,6 +85,9 @@ struct PointDensity *BKE_texture_pointdensity_add(void);
struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd, const int flag);
bool BKE_texture_dependsOnTime(const struct Tex *texture);
+/**
+ * \returns true if this texture can use its #Texture.ima (even if its NULL).
+ */
bool BKE_texture_is_image_user(const struct Tex *tex);
void BKE_texture_get_value_ex(const struct Scene *scene,
@@ -94,6 +103,9 @@ void BKE_texture_get_value(const struct Scene *scene,
struct TexResult *texres,
bool use_color_management);
+/**
+ * Make sure all images used by texture are loaded into pool.
+ */
void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 47145a7d6bd..9caf5d31765 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -46,20 +46,53 @@ struct rcti;
/* **** Common functions **** */
+/**
+ * Free tracking structure, only frees structure contents
+ * (if structure is allocated in heap, it shall be handled outside).
+ *
+ * All the pointers inside structure becomes invalid after this call.
+ */
void BKE_tracking_free(struct MovieTracking *tracking);
+/**
+ * Copy tracking structure content.
+ */
void BKE_tracking_copy(struct MovieTracking *tracking_dst,
const struct MovieTracking *tracking_src,
const int flag);
+/**
+ * Initialize motion tracking settings to default values,
+ * used when new movie clip data-block is created.
+ */
void BKE_tracking_settings_init(struct MovieTracking *tracking);
+/**
+ * Get list base of active object's tracks.
+ */
struct ListBase *BKE_tracking_get_active_tracks(struct MovieTracking *tracking);
+/**
+ * Get list base of active object's plane tracks.
+ */
struct ListBase *BKE_tracking_get_active_plane_tracks(struct MovieTracking *tracking);
+/**
+ * Get reconstruction data of active object.
+ */
struct MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(
struct MovieTracking *tracking);
-/* matrices for constraints and drawing */
+/* Matrices for constraints and drawing. */
+
+/**
+ * Get transformation matrix for a given object which is used
+ * for parenting motion tracker reconstruction to 3D world.
+ */
void BKE_tracking_get_camera_object_matrix(struct Object *camera_object, float mat[4][4]);
+/**
+ * Get projection matrix for camera specified by given tracking object
+ * and frame number.
+ *
+ * \note frame number should be in clip space, not scene space.
+ */
void BKE_tracking_get_projection_matrix(struct MovieTracking *tracking,
struct MovieTrackingObject *object,
int framenr,
@@ -68,16 +101,45 @@ void BKE_tracking_get_projection_matrix(struct MovieTracking *tracking,
float mat[4][4]);
/* **** Clipboard **** */
+/**
+ * Free clipboard by freeing memory used by all tracks in it.
+ */
void BKE_tracking_clipboard_free(void);
+/**
+ * Copy selected tracks from specified object to the clipboard.
+ */
void BKE_tracking_clipboard_copy_tracks(struct MovieTracking *tracking,
struct MovieTrackingObject *object);
+/**
+ * Check whether there are any tracks in the clipboard.
+ */
bool BKE_tracking_clipboard_has_tracks(void);
+/**
+ * Paste tracks from clipboard to specified object.
+ *
+ * Names of new tracks in object are guaranteed to be unique here.
+ */
void BKE_tracking_clipboard_paste_tracks(struct MovieTracking *tracking,
struct MovieTrackingObject *object);
/* **** Track **** */
+
+/**
+ * Add new empty track to the given list of tracks.
+ *
+ * It is required that caller will append at least one marker to avoid degenerate tracks.
+ */
struct MovieTrackingTrack *BKE_tracking_track_add_empty(struct MovieTracking *tracking,
struct ListBase *tracks_list);
+/**
+ * Add new track to a specified tracks base.
+ *
+ * Coordinates are expected to be in normalized 0..1 space,
+ * frame number is expected to be in clip space.
+ *
+ * Width and height are clip's dimension used to scale track's
+ * pattern and search regions.
+ */
struct MovieTrackingTrack *BKE_tracking_track_add(struct MovieTracking *tracking,
struct ListBase *tracksbase,
float x,
@@ -85,14 +147,35 @@ struct MovieTrackingTrack *BKE_tracking_track_add(struct MovieTracking *tracking
int framenr,
int width,
int height);
+/**
+ * Duplicate the specified track, result will no belong to any list.
+ */
struct MovieTrackingTrack *BKE_tracking_track_duplicate(struct MovieTrackingTrack *track);
+/**
+ * Ensure specified track has got unique name,
+ * if it's not name of specified track will be changed
+ * keeping names of all other tracks unchanged.
+ */
void BKE_tracking_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track);
+/**
+ * Free specified track, only frees contents of a structure
+ * (if track is allocated in heap, it shall be handled outside).
+ *
+ * All the pointers inside track becomes invalid after this call.
+ */
void BKE_tracking_track_free(struct MovieTrackingTrack *track);
+/**
+ * Get frame numbers of the very first and last markers.
+ * There is no check on whether the marker is enabled or not.
+ */
void BKE_tracking_track_first_last_frame_get(const struct MovieTrackingTrack *track,
int *r_first_frame,
int *r_last_frame);
+/**
+ * Find the minimum starting frame and maximum ending frame within given set of tracks.
+ */
void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ struct MovieTrackingTrack **tracks,
const int num_tracks,
int *r_first_frame,
@@ -101,17 +184,50 @@ void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ struct MovieTrackingT
int BKE_tracking_count_selected_tracks_in_list(const struct ListBase *tracks_list);
int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ struct MovieTracking *tracking);
-/* Get array of selected tracks from the current active object in the tracking structure.
- * If nothing is selected then the result is nullptr and `r_num_tracks` is set to 0. */
+/**
+ * Get array of selected tracks from the current active object in the tracking structure.
+ * If nothing is selected then the result is nullptr and `r_num_tracks` is set to 0.
+ */
struct MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(
struct MovieTracking *tracking, int *r_num_tracks);
+/**
+ * Set flag for all specified track's areas.
+ *
+ * \param area: which part of marker should be selected. see TRACK_AREA_* constants.
+ * \param flag: flag to be set for areas.
+ */
void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag);
+/**
+ * Clear flag from all specified track's areas.
+ *
+ * \param area: which part of marker should be selected. see TRACK_AREA_* constants.
+ * \param flag: flag to be cleared for areas.
+ */
void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag);
+/**
+ * Check whether track has got marker at specified frame.
+ *
+ * \note frame number should be in clip space, not scene space.
+ */
bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
+/**
+ * Check whether track has got enabled marker at specified frame.
+ *
+ * \note frame number should be in clip space, not scene space.
+ */
bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
+/**
+ * Clear track's path:
+ *
+ * - If action is #TRACK_CLEAR_REMAINED path from `ref_frame+1` up to end will be clear.
+ * - If action is #TRACK_CLEAR_UPTO path from the beginning up to `ref_frame-1` will be clear.
+ * - If action is #TRACK_CLEAR_ALL only marker at frame ref_frame will remain.
+ *
+ * \note frame number should be in clip space, not scene space.
+ */
void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action);
void BKE_tracking_tracks_join(struct MovieTracking *tracking,
@@ -140,7 +256,11 @@ float BKE_tracking_track_get_weight_for_marker(struct MovieClip *clip,
struct MovieTrackingTrack *track,
struct MovieTrackingMarker *marker);
-/* selection */
+/* Selection */
+
+/**
+ * \param area: which part of marker should be selected. see TRACK_AREA_* constants.
+ */
void BKE_tracking_track_select(struct ListBase *tracksbase,
struct MovieTrackingTrack *track,
int area,
@@ -155,19 +275,31 @@ void BKE_tracking_marker_delete(struct MovieTrackingTrack *track, int framenr);
void BKE_tracking_marker_clamp(struct MovieTrackingMarker *marker, int event);
+/**
+ * Get marker closest to the given frame number.
+ *
+ * If there is maker with exact frame number it returned.
+ * Otherwise, marker with highest frame number but lower than the requested
+ * frame is returned if such marker exists. Otherwise, the marker with lowest
+ * frame number greater than the requested frame number is returned.
+ *
+ * This function has complexity of `O(log number_of_markers)`.
+ */
struct MovieTrackingMarker *BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr);
struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track,
int framenr);
struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track,
int framenr);
-/* Get marker position, possibly interpolating gap between key-framed/tracked markers.
+/**
+ * Get marker position, possibly interpolating gap between key-framed/tracked markers.
*
* The result marker frame number is set to the requested frame number. Its flags are 0 if the
* marker is interpolated, and is set to original marker flag if there were no interpolation
* involved.
*
- * Returns truth if the result is usable. */
+ * \returns truth if the result is usable.
+ */
bool BKE_tracking_marker_get_interpolated(struct MovieTrackingTrack *track,
const int framenr,
struct MovieTrackingMarker *r_marker);
@@ -181,12 +313,21 @@ void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track,
float pos[2]);
/* **** Plane Track **** */
+/**
+ * Creates new plane track out of selected point tracks.
+ */
struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(struct MovieTracking *tracking,
struct ListBase *plane_tracks_base,
struct ListBase *tracks,
int framenr);
void BKE_tracking_plane_track_unique_name(struct ListBase *plane_tracks_base,
struct MovieTrackingPlaneTrack *plane_track);
+/**
+ * Free specified plane track, only frees contents of a structure
+ * (if track is allocated in heap, it shall be handled outside).
+ *
+ * All the pointers inside track becomes invalid after this call.
+ */
void BKE_tracking_plane_track_free(struct MovieTrackingPlaneTrack *plane_track);
bool BKE_tracking_plane_track_has_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track,
@@ -222,10 +363,21 @@ struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(
struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingPlaneMarker *plane_marker);
void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+/**
+ * Get a plane marker at given frame,
+ * If there's no such marker, closest one from the left side will be returned.
+ */
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(
struct MovieTrackingPlaneTrack *plane_track, int framenr);
+/**
+ * Get a plane marker at exact given frame, if there's no marker at the frame,
+ * NULL will be returned.
+ */
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(
struct MovieTrackingPlaneTrack *plane_track, int framenr);
+/**
+ * Ensure there's a marker for the given frame.
+ */
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(
struct MovieTrackingPlaneTrack *plane_track, int framenr);
void BKE_tracking_plane_marker_get_subframe_corners(struct MovieTrackingPlaneTrack *plane_track,
@@ -255,6 +407,9 @@ struct MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(
struct MovieTracking *tracking, struct MovieTrackingObject *object);
/* **** Camera **** */
+/**
+ * Converts principal offset from center to offset of blender's camera.
+ */
void BKE_tracking_camera_shift_get(
struct MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty);
void BKE_tracking_camera_to_blender(struct MovieTracking *tracking,
@@ -346,10 +501,21 @@ struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf,
bool anchored,
bool disable_channels);
+/**
+ * Zap channels from the imbuf that are disabled by the user. this can lead to
+ * better tracks sometimes. however, instead of simply zeroing the channels
+ * out, do a partial gray-scale conversion so the display is better.
+ */
void BKE_tracking_disable_channels(
struct ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale);
/* **** 2D tracking **** */
+
+/**
+ * Refine marker's position using previously known keyframe.
+ * Direction of searching for a keyframe depends on backwards flag,
+ * which means if backwards is false, previous keyframe will be as reference.
+ */
void BKE_tracking_refine_marker(struct MovieClip *clip,
struct MovieTrackingTrack *track,
struct MovieTrackingMarker *marker,
@@ -368,6 +534,9 @@ void BKE_autotrack_context_free(struct AutoTrackContext *context);
/* **** Plane tracking **** */
+/**
+ * \note frame number should be in clip space, not scene space.
+ */
void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track,
int start_frame);
void BKE_tracking_retrack_plane_from_existing_motion_at_segment(
@@ -377,11 +546,20 @@ void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners
float H[3][3]);
/* **** Camera solving **** */
+
+/**
+ * Perform early check on whether everything is fine to start reconstruction.
+ */
bool BKE_tracking_reconstruction_check(struct MovieTracking *tracking,
struct MovieTrackingObject *object,
char *error_msg,
int error_size);
+/**
+ * Create context for camera/object motion reconstruction.
+ * Copies all data needed for reconstruction from movie clip datablock,
+ * so editing this clip is safe during reconstruction job is in progress.
+ */
struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(
struct MovieClip *clip,
struct MovieTrackingObject *object,
@@ -389,13 +567,29 @@ struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(
int keyframe2,
int width,
int height);
+/**
+ * Free memory used by a reconstruction process.
+ */
void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context);
+/**
+ * Solve camera/object motion and reconstruct 3D markers position
+ * from a prepared reconstruction context.
+ *
+ * stop is not actually used at this moment, so reconstruction
+ * job could not be stopped.
+ *
+ * do_update, progress and stat_message are set by reconstruction
+ * callback in libmv side and passing to an interface.
+ */
void BKE_tracking_reconstruction_solve(struct MovieReconstructContext *context,
short *stop,
short *do_update,
float *progress,
char *stats_message,
int message_size);
+/**
+ * Finish reconstruction process by copying reconstructed data to an actual movie clip data-block.
+ */
bool BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context,
struct MovieTracking *tracking);
@@ -405,9 +599,16 @@ void BKE_tracking_reconstruction_report_error_message(struct MovieReconstructCon
const char *BKE_tracking_reconstruction_error_message_get(
const struct MovieReconstructContext *context);
+/**
+ * Apply scale on all reconstructed cameras and bundles, used by camera scale apply operator.
+ */
void BKE_tracking_reconstruction_scale(struct MovieTracking *tracking, float scale[3]);
/* **** Feature detection **** */
+
+/**
+ * Detect features using FAST detector.
+ */
void BKE_tracking_detect_fast(struct MovieTracking *tracking,
struct ListBase *tracksbase,
struct ImBuf *ibuf,
@@ -418,6 +619,9 @@ void BKE_tracking_detect_fast(struct MovieTracking *tracking,
struct bGPDlayer *layer,
bool place_outside_layer);
+/**
+ * Detect features using Harris detector.
+ */
void BKE_tracking_detect_harris(struct MovieTracking *tracking,
struct ListBase *tracksbase,
struct ImBuf *ibuf,
@@ -429,6 +633,24 @@ void BKE_tracking_detect_harris(struct MovieTracking *tracking,
bool place_outside_layer);
/* **** 2D stabilization **** */
+
+/**
+ * Get stabilization data (translation, scaling and angle) for a given frame.
+ * Returned data describes how to compensate the detected movement, but with any
+ * chosen scale factor already applied and any target frame position already compensated.
+ * In case stabilization fails or is disabled, neutral values are returned.
+ *
+ * \param framenr: is a frame number, relative to the clip (not relative to the scene timeline).
+ * \param width: is an effective width of the canvas (square pixels), used to scale the
+ * determined translation.
+ *
+ * Outputs:
+ * \param translation: of the lateral shift, absolute canvas coordinates (square pixels).
+ * \param scale: of the scaling to apply.
+ * \param angle: of the rotation angle, relative to the frame center.
+ *
+ * TODO(sergey): Use `r_` prefix for output parameters here.
+ */
void BKE_tracking_stabilization_data_get(struct MovieClip *clip,
int framenr,
int width,
@@ -436,12 +658,30 @@ void BKE_tracking_stabilization_data_get(struct MovieClip *clip,
float translation[2],
float *scale,
float *angle);
+/**
+ * Stabilize given image buffer using stabilization data for a specified frame number.
+ *
+ * \note frame number should be in clip space, not scene space.
+ *
+ * TODO(sergey): Use `r_` prefix for output parameters here.
+ */
struct ImBuf *BKE_tracking_stabilize_frame(struct MovieClip *clip,
int framenr,
struct ImBuf *ibuf,
float translation[2],
float *scale,
float *angle);
+/**
+ * Build a 4x4 transformation matrix based on the given 2D stabilization data.
+ * mat is a 4x4 matrix in homogeneous coordinates, adapted to the
+ * final image buffer size and compensated for pixel aspect ratio,
+ * ready for direct OpenGL drawing.
+ *
+ * TODO(sergey): The signature of this function should be changed. we actually
+ * don't need the dimensions of the image buffer. Instead we
+ * should consider to provide the pivot point of the rotation as a
+ * further stabilization data parameter.
+ */
void BKE_tracking_stabilization_data_to_mat4(int width,
int height,
float aspect,
@@ -450,17 +690,30 @@ void BKE_tracking_stabilization_data_to_mat4(int width,
float angle,
float mat[4][4]);
-/* Dopesheet */
+/* Dope-sheet */
+
+/**
+ * Tag dope-sheet for update, actual update will happen later when it'll be actually needed.
+ */
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking);
+/**
+ * Do dope-sheet update, if update is not needed nothing will happen.
+ */
void BKE_tracking_dopesheet_update(struct MovieTracking *tracking);
/* **** Query/search **** */
+/**
+ * \note Returns NULL if the track comes from camera object,.
+ */
struct MovieTrackingObject *BKE_tracking_find_object_for_track(
const struct MovieTracking *tracking, const struct MovieTrackingTrack *track);
struct ListBase *BKE_tracking_find_tracks_list_for_track(struct MovieTracking *tracking,
const struct MovieTrackingTrack *track);
+/**
+ * \note Returns NULL if the track comes from camera object,.
+ */
struct MovieTrackingObject *BKE_tracking_find_object_for_plane_track(
const struct MovieTracking *tracking, const struct MovieTrackingPlaneTrack *plane_track);
struct ListBase *BKE_tracking_find_tracks_list_for_plane_track(
diff --git a/source/blender/blenkernel/BKE_type_conversions.hh b/source/blender/blenkernel/BKE_type_conversions.hh
new file mode 100644
index 00000000000..ebfb13cd08f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_type_conversions.hh
@@ -0,0 +1,84 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include "FN_multi_function.hh"
+
+namespace blender::bke {
+
+using fn::CPPType;
+
+struct ConversionFunctions {
+ const fn::MultiFunction *multi_function;
+ void (*convert_single_to_initialized)(const void *src, void *dst);
+ void (*convert_single_to_uninitialized)(const void *src, void *dst);
+};
+
+class DataTypeConversions {
+ private:
+ Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_;
+
+ public:
+ void add(fn::MFDataType from_type,
+ fn::MFDataType to_type,
+ const fn::MultiFunction &fn,
+ void (*convert_single_to_initialized)(const void *src, void *dst),
+ void (*convert_single_to_uninitialized)(const void *src, void *dst))
+ {
+ conversions_.add_new({from_type, to_type},
+ {&fn, convert_single_to_initialized, convert_single_to_uninitialized});
+ }
+
+ const ConversionFunctions *get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const
+ {
+ return conversions_.lookup_ptr({from, to});
+ }
+
+ const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
+ {
+ return this->get_conversion_functions(fn::MFDataType::ForSingle(from),
+ fn::MFDataType::ForSingle(to));
+ }
+
+ const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from,
+ fn::MFDataType to) const
+ {
+ const ConversionFunctions *functions = this->get_conversion_functions(from, to);
+ return functions ? functions->multi_function : nullptr;
+ }
+
+ bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
+ {
+ return conversions_.contains(
+ {fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)});
+ }
+
+ void convert_to_uninitialized(const CPPType &from_type,
+ const CPPType &to_type,
+ const void *from_value,
+ void *to_value) const;
+
+ void convert_to_initialized_n(fn::GSpan from_span, fn::GMutableSpan to_span) const;
+
+ fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const;
+
+ fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const;
+};
+
+const DataTypeConversions &get_implicit_type_conversions();
+
+} // namespace blender::bke
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index 2a90211f8e0..6e1f9468ce4 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -171,7 +171,12 @@ typedef enum eUndoTypeFlags {
UNDOTYPE_FLAG_DECODE_ACTIVE_STEP = 1 << 1,
} eUndoTypeFlags;
-/* Expose since we need to perform operations on specific undo types (rarely). */
+/* -------------------------------------------------------------------- */
+/** \name Public Undo Types
+ *
+ * Expose since we need to perform operations on specific undo types (rarely).
+ * \{ */
+
extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
@@ -179,17 +184,25 @@ extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
extern const UndoType *BKE_UNDOSYS_TYPE_TEXT;
+/** \} */
+
#define BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(ty) ELEM(ty, BKE_UNDOSYS_TYPE_IMAGE)
UndoStack *BKE_undosys_stack_create(void);
void BKE_undosys_stack_destroy(UndoStack *ustack);
void BKE_undosys_stack_clear(UndoStack *ustack);
void BKE_undosys_stack_clear_active(UndoStack *ustack);
+/* name optional */
bool BKE_undosys_stack_has_undo(const UndoStack *ustack, const char *name);
void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain);
+/* called after 'BKE_undosys_stack_init_from_main' */
void BKE_undosys_stack_init_from_context(UndoStack *ustack, struct bContext *C);
UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut);
UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut);
+/**
+ * \param steps: Limit the number of undo steps.
+ * \param memory_limit: Limit the amount of memory used by the undo stack.
+ */
void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit);
#define BKE_undosys_stack_limit_steps_and_memory_defaults(ustack) \
BKE_undosys_stack_limit_steps_and_memory(ustack, U.undosteps, (size_t)U.undomemory * 1024 * 1024)
@@ -197,13 +210,18 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size
void BKE_undosys_stack_group_begin(UndoStack *ustack);
void BKE_undosys_stack_group_end(UndoStack *ustack);
-/* Only some UndoType's require init. */
+/**
+ * Only some UndoType's require init.
+ */
UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
struct bContext *C,
const char *name,
const UndoType *ut);
UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, struct bContext *C, const char *name);
+/**
+ * \param C: Can be NULL from some callers if their encoding function doesn't need it
+ */
eUndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack,
struct bContext *C,
const char *name,
@@ -216,40 +234,117 @@ UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack,
UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut);
UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name);
+/**
+ * Return direction of the undo/redo from `us_reference` (or `ustack->step_active` if NULL), and
+ * `us_target`.
+ *
+ * \note If `us_reference` and `us_target` are the same, we consider this is an undo.
+ *
+ * \return -1 for undo, 1 for redo, 0 in case of error.
+ */
eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack,
const UndoStep *us_target,
const UndoStep *us_reference);
+/**
+ * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
+ *
+ * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target`
+ * will become the active step.
+ *
+ * \note In case `use_skip` is true, the final target will always be **beyond** the given one
+ * (if the given one has to be skipped).
+ *
+ * \param us_reference: If NULL, will be set to current active step in the undo stack. Otherwise,
+ * it is assumed to match the current state, and will be used as basis for the undo/redo process
+ * (i.e. all steps in-between `us_reference` and `us_target` will be processed).
+ */
bool BKE_undosys_step_load_data_ex(UndoStack *ustack,
struct bContext *C,
UndoStep *us_target,
UndoStep *us_reference,
const bool use_skip);
+/**
+ * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
+ */
bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us_target);
+/**
+ * Undo/Redo until the step matching given `index` in the undo stack becomes the active
+ * (currently loaded) one.
+ */
void BKE_undosys_step_load_from_index(UndoStack *ustack, struct bContext *C, const int index);
+/**
+ * Undo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \warning This function assumes that the given target step is _before_ current active one.
+ *
+ * \note Unless `us_target` is a 'skipped' one and `use_skip` is true,
+ * `us_target` will become the active step.
+ *
+ * \note In case `use_skip` is true, the final target will always be **before** the given one
+ * (if the given one has to be skipped).
+ */
bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
struct bContext *C,
UndoStep *us,
bool use_skip);
+/**
+ * Undo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \note See #BKE_undosys_step_undo_with_data_ex for details.
+ */
bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us_target);
+/**
+ * Undo one step from current active (currently loaded) one.
+ */
bool BKE_undosys_step_undo(UndoStack *ustack, struct bContext *C);
+/**
+ * Redo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \warning This function assumes that the given target step is _after_ current active one.
+ *
+ * \note Unless `us_target` is a 'skipped' one and `use_skip` is true,
+ * `us_target` will become the active step.
+ *
+ * \note In case `use_skip` is true, the final target will always be **after** the given one
+ * (if the given one has to be skipped).
+ */
bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
struct bContext *C,
UndoStep *us,
bool use_skip);
+/**
+ * Redo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \note See #BKE_undosys_step_redo_with_data_ex for details.
+ */
bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us_target);
+/**
+ * Redo one step from current active one.
+ */
bool BKE_undosys_step_redo(UndoStack *ustack, struct bContext *C);
+/**
+ * Useful when we want to diff against previous undo data but can't be sure the types match.
+ */
UndoStep *BKE_undosys_step_same_type_next(UndoStep *us);
+/**
+ * Useful when we want to diff against previous undo data but can't be sure the types match.
+ */
UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us);
-/* Type System */
+/* Type System. */
+
+/**
+ * Similar to #WM_operatortype_append
+ */
UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *));
void BKE_undosys_type_free_all(void);
-/* ID Accessor */
+/* ID Accessor. */
+
#if 0 /* functionality is only used internally for now. */
void BKE_undosys_foreach_ID_ref(UndoStack *ustack,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h
index b28215a72d1..505cfee3adf 100644
--- a/source/blender/blenkernel/BKE_unit.h
+++ b/source/blender/blenkernel/BKE_unit.h
@@ -26,9 +26,11 @@ extern "C" {
struct UnitSettings;
-/* in all cases the value is assumed to be scaled by the user preference */
+/* In all cases the value is assumed to be scaled by the user-preference. */
-/* humanly readable representation of a value in units (used for button drawing) */
+/**
+ * Humanly readable representation of a value in units (used for button drawing).
+ */
size_t BKE_unit_value_as_string_adaptive(
char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad);
size_t BKE_unit_value_as_string(char *str,
@@ -39,29 +41,59 @@ size_t BKE_unit_value_as_string(char *str,
const struct UnitSettings *settings,
bool pad);
-/* replace units with values, used before python button evaluation */
+/**
+ * Replace units with values, used before python button evaluation.
+ *
+ * Make a copy of the string that replaces the units with numbers.
+ * This is only used when evaluating user input and can afford to be a bit slower
+ *
+ * This is to be used before python evaluation so:
+ * `10.1km -> 10.1*1000.0`
+ * ...will be resolved by Python.
+ *
+ * Values will be split by an add sign:
+ * `5'2" -> 5*0.3048 + 2*0.0254`
+ *
+ * \param str_prev: is optional, when valid it is used to get a base unit when none is set.
+ *
+ * \return True of a change was made.
+ */
bool BKE_unit_replace_string(
char *str, int len_max, const char *str_prev, double scale_pref, int system, int type);
-/* return true if the string contains any valid unit for the given type */
+/**
+ * \return true if the string contains any valid unit for the given type.
+ */
bool BKE_unit_string_contains_unit(const char *str, int type);
-/* If user does not specify a unit, this converts it to the unit from the settings. */
+/**
+ * If user does not specify a unit, this converts it to the unit from the settings.
+ */
double BKE_unit_apply_preferred_unit(const struct UnitSettings *settings, int type, double value);
-/* make string keyboard-friendly: 10µm --> 10um */
+/**
+ * Make string keyboard-friendly, e.g: `10µm -> 10um`.
+ */
void BKE_unit_name_to_alt(char *str, int len_max, const char *orig_str, int system, int type);
-/* the size of the unit used for this value (used for calculating the ckickstep) */
+/**
+ * The size of the unit used for this value (used for calculating the click-step).
+ */
double BKE_unit_closest_scalar(double value, int system, int type);
-/* base scale for these units */
+/**
+ * Base scale for these units.
+ */
double BKE_unit_base_scalar(int system, int type);
-/* return true is the unit system exists */
+/**
+ * \return true is the unit system exists.
+ */
bool BKE_unit_is_valid(int system, int type);
-/* loop over scales, could add names later */
+/**
+ * Loop over scales, could add names later.
+ */
// double bUnit_Iter(void **unit, char **name, int system, int type);
void BKE_unit_system_get(int system, int type, const void **r_usys_pt, int *r_len);
@@ -73,7 +105,7 @@ const char *BKE_unit_identifier_get(const void *usys_pt, int index);
double BKE_unit_scalar_get(const void *usys_pt, int index);
bool BKE_unit_is_suppressed(const void *usys_pt, int index);
-/* aligned with PropertyUnit */
+/** Aligned with #PropertyUnit. */
enum {
B_UNIT_NONE = 0,
B_UNIT_LENGTH = 1,
diff --git a/source/blender/blenkernel/BKE_vfont.h b/source/blender/blenkernel/BKE_vfont.h
index 827ae1b6a0f..cd1b30b9358 100644
--- a/source/blender/blenkernel/BKE_vfont.h
+++ b/source/blender/blenkernel/BKE_vfont.h
@@ -84,6 +84,9 @@ bool BKE_vfont_to_curve_ex(struct Object *ob,
bool *r_text_free,
struct CharTrans **r_chartransdata);
bool BKE_vfont_to_curve_nubase(struct Object *ob, int mode, struct ListBase *r_nubase);
+/**
+ * \warning Expects to have access to evaluated data (i.e. passed object should be evaluated one).
+ */
bool BKE_vfont_to_curve(struct Object *ob, int mode);
void BKE_vfont_build_char(struct Curve *cu,
struct ListBase *nubase,
diff --git a/source/blender/blenkernel/BKE_vfontdata.h b/source/blender/blenkernel/BKE_vfontdata.h
index b6e57dad934..692857b0458 100644
--- a/source/blender/blenkernel/BKE_vfontdata.h
+++ b/source/blender/blenkernel/BKE_vfontdata.h
@@ -49,6 +49,12 @@ typedef struct VChar {
float width;
} VChar;
+/**
+ * Construct a new #VFontData structure from free-type font data in `pf`.
+ *
+ * \param pf: The font data.
+ * \retval A new #VFontData structure, or NULL if unable to load.
+ */
VFontData *BKE_vfontdata_from_freetypefont(struct PackedFile *pf);
VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, const int flag);
diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h
index 601e0cf26a9..f4f00844b8d 100644
--- a/source/blender/blenkernel/BKE_volume.h
+++ b/source/blender/blenkernel/BKE_volume.h
@@ -88,6 +88,7 @@ const char *BKE_volume_grids_frame_filepath(const struct Volume *volume);
const VolumeGrid *BKE_volume_grid_get_for_read(const struct Volume *volume, int grid_index);
VolumeGrid *BKE_volume_grid_get_for_write(struct Volume *volume, int grid_index);
const VolumeGrid *BKE_volume_grid_active_get_for_read(const struct Volume *volume);
+/* Tries to find a grid with the given name. Make sure that the volume has been loaded. */
const VolumeGrid *BKE_volume_grid_find_for_read(const struct Volume *volume, const char *name);
/* Grid
@@ -115,9 +116,13 @@ void BKE_volume_grid_unload(const struct Volume *volume, const struct VolumeGrid
bool BKE_volume_grid_is_loaded(const struct VolumeGrid *grid);
/* Metadata */
+
const char *BKE_volume_grid_name(const struct VolumeGrid *grid);
VolumeGridType BKE_volume_grid_type(const struct VolumeGrid *grid);
int BKE_volume_grid_channels(const struct VolumeGrid *grid);
+/**
+ * Transformation from index space to object space.
+ */
void BKE_volume_grid_transform_matrix(const struct VolumeGrid *grid, float mat[4][4]);
/* Volume Editing
diff --git a/source/blender/blenkernel/BKE_volume_to_mesh.hh b/source/blender/blenkernel/BKE_volume_to_mesh.hh
index 9532da8c23c..dd8ae7ea554 100644
--- a/source/blender/blenkernel/BKE_volume_to_mesh.hh
+++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh
@@ -14,6 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
+
#include "BLI_span.hh"
#include "DNA_modifier_types.h"
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index 82a4e5fe08e..ff4e21732c4 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -31,9 +31,17 @@ struct bScreen;
struct bToolRef;
/* -------------------------------------------------------------------- */
-/* Create, delete, init */
+/** \name Create, Delete, Initialize
+ * \{ */
struct WorkSpace *BKE_workspace_add(struct Main *bmain, const char *name);
+/**
+ * Remove \a workspace by freeing itself and its data. This is a higher-level wrapper that
+ * calls #workspace_free_data (through #BKE_id_free) to free the workspace data, and frees
+ * other data-blocks owned by \a workspace and its layouts (currently that is screens only).
+ *
+ * Always use this to remove (and free) workspaces. Don't free non-ID workspace members here.
+ */
void BKE_workspace_remove(struct Main *bmain, struct WorkSpace *workspace);
struct WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Main *bmain,
@@ -41,6 +49,9 @@ struct WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Ma
void BKE_workspace_instance_hook_free(const struct Main *bmain,
struct WorkSpaceInstanceHook *hook);
+/**
+ * Add a new layout to \a workspace for \a screen.
+ */
struct WorkSpaceLayout *BKE_workspace_layout_add(struct Main *bmain,
struct WorkSpace *workspace,
struct bScreen *screen,
@@ -51,17 +62,36 @@ void BKE_workspace_layout_remove(struct Main *bmain,
void BKE_workspace_relations_free(ListBase *relation_list);
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* General Utils */
+/** \name General Utilities
+ * \{ */
struct WorkSpaceLayout *BKE_workspace_layout_find(const struct WorkSpace *workspace,
const struct bScreen *screen)
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+/**
+ * Find the layout for \a screen without knowing which workspace to look in.
+ * Can also be used to find the workspace that contains \a screen.
+ *
+ * \param r_workspace: Optionally return the workspace that contains the
+ * looked up layout (if found).
+ */
struct WorkSpaceLayout *BKE_workspace_layout_find_global(const struct Main *bmain,
const struct bScreen *screen,
struct WorkSpace **r_workspace)
ATTR_NONNULL(1, 2);
+/**
+ * Circular workspace layout iterator.
+ *
+ * \param callback: Custom function which gets executed for each layout.
+ * Can return false to stop iterating.
+ * \param arg: Custom data passed to each \a callback call.
+ *
+ * \return the layout at which \a callback returned false.
+ */
struct WorkSpaceLayout *BKE_workspace_layout_iter_circular(
const struct WorkSpace *workspace,
struct WorkSpaceLayout *start,
@@ -72,8 +102,11 @@ struct WorkSpaceLayout *BKE_workspace_layout_iter_circular(
void BKE_workspace_tool_remove(struct WorkSpace *workspace, struct bToolRef *tref)
ATTR_NONNULL(1, 2);
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Getters/Setters */
+/** \name Getters/Setters
+ * \{ */
#define GETTER_ATTRS ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
#define SETTER_ATTRS ATTR_NONNULL(1)
@@ -81,8 +114,23 @@ void BKE_workspace_tool_remove(struct WorkSpace *workspace, struct bToolRef *tre
struct WorkSpace *BKE_workspace_active_get(struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
void BKE_workspace_active_set(struct WorkSpaceInstanceHook *hook,
struct WorkSpace *workspace) SETTER_ATTRS;
+/**
+ * Get the layout that is active for \a hook (which is the visible layout for the active workspace
+ * in \a hook).
+ */
struct WorkSpaceLayout *BKE_workspace_active_layout_get(const struct WorkSpaceInstanceHook *hook)
GETTER_ATTRS;
+/**
+ * \brief Activate a layout
+ *
+ * Sets \a layout as active for \a workspace when activated through or already active in \a hook.
+ * So when the active workspace of \a hook is \a workspace, \a layout becomes the active layout of
+ * \a hook too. See #BKE_workspace_active_set().
+ *
+ * \a workspace does not need to be active for this.
+ *
+ * #WorkSpaceInstanceHook.act_layout should only be modified directly to update the layout pointer.
+ */
void BKE_workspace_active_layout_set(struct WorkSpaceInstanceHook *hook,
const int winid,
struct WorkSpace *workspace,
@@ -100,6 +148,9 @@ void BKE_workspace_layout_name_set(struct WorkSpace *workspace,
const char *new_name) ATTR_NONNULL();
struct bScreen *BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
+/**
+ * Get the layout to be activated should \a workspace become or be the active workspace in \a hook.
+ */
struct WorkSpaceLayout *BKE_workspace_active_layout_for_workspace_get(
const struct WorkSpaceInstanceHook *hook, const struct WorkSpace *workspace) GETTER_ATTRS;
@@ -111,6 +162,8 @@ void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL(
#undef GETTER_ATTRS
#undef SETTER_ATTRS
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h
index 97f998cc1c1..d2a5100ffad 100644
--- a/source/blender/blenkernel/BKE_writeavi.h
+++ b/source/blender/blenkernel/BKE_writeavi.h
@@ -64,6 +64,10 @@ typedef struct bMovieHandle {
} bMovieHandle;
bMovieHandle *BKE_movie_handle_get(const char imtype);
+
+/**
+ * \note Similar to #BKE_image_path_from_imformat()
+ */
void BKE_movie_filepath_get(char *string,
const struct RenderData *rd,
bool preview,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index b2418d0539c..f6e7f1c2473 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -100,6 +100,7 @@ set(SRC
intern/blender_undo.c
intern/blender_user_menu.c
intern/blendfile.c
+ intern/blendfile_link_append.c
intern/boids.c
intern/bpath.c
intern/brush.c
@@ -117,7 +118,7 @@ set(SRC
intern/context.c
intern/crazyspace.c
intern/cryptomatte.cc
- intern/curve.c
+ intern/curve.cc
intern/curve_bevel.c
intern/curve_convert.c
intern/curve_decimate.c
@@ -138,7 +139,6 @@ set(SRC
intern/editmesh_cache.c
intern/editmesh_tangent.c
intern/effect.c
- intern/extern_implementations.cc
intern/fcurve.c
intern/fcurve_cache.c
intern/fcurve_driver.c
@@ -164,7 +164,7 @@ set(SRC
intern/idtype.c
intern/image.c
intern/image_gen.c
- intern/image_gpu.c
+ intern/image_gpu.cc
intern/image_save.c
intern/ipo.c
intern/kelvinlet.c
@@ -226,6 +226,7 @@ set(SRC
intern/multires_versioning.c
intern/nla.c
intern/node.cc
+ intern/type_conversions.cc
intern/object.cc
intern/object_deform.c
intern/object_dupli.cc
@@ -326,6 +327,7 @@ set(SRC
BKE_blender_user_menu.h
BKE_blender_version.h
BKE_blendfile.h
+ BKE_blendfile_link_append.h
BKE_boids.h
BKE_bpath.h
BKE_brush.h
@@ -455,6 +457,7 @@ set(SRC
BKE_text_suggestions.h
BKE_texture.h
BKE_tracking.h
+ BKE_type_conversions.hh
BKE_undo_system.h
BKE_unit.h
BKE_vfont.h
@@ -806,6 +809,7 @@ if(WITH_GTESTS)
intern/asset_library_service_test.cc
intern/asset_library_test.cc
intern/asset_test.cc
+ intern/bpath_test.cc
intern/cryptomatte_test.cc
intern/fcurve_test.cc
intern/lattice_deform_test.cc
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 67e7b890548..74f848ac580 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -939,7 +939,6 @@ void ccgSubSurf__effectedFaceNeighbors(CCGSubSurf *ss,
*numEdges = numE;
}
-/* copy face grid coordinates to other places */
CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
{
int i, S, x, gridSize, cornerIdx, subdivLevels;
@@ -986,7 +985,6 @@ CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF
return eCCGError_None;
}
-/* copy other places to face grid coordinates */
CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
{
int i, S, x, gridSize, cornerIdx, subdivLevels;
@@ -1035,8 +1033,6 @@ CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF,
return eCCGError_None;
}
-/* stitch together face grids, averaging coordinates at edges
- * and vertices, for multires displacements */
CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
{
CCGVert **effectedV;
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index a9e0d6882c1..9349c33d72a 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -100,13 +100,30 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL);
CCGError ccgSubSurf_processSync(CCGSubSurf *ss);
+/**
+ * Copy face grid coordinates to other places.
+ */
CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss,
int lvl,
CCGFace **effectedF,
int numEffectedF);
+/**
+ * Copy other places to face grid coordinates.
+ */
CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF);
+/**
+ * Update normals for specified faces.
+ */
CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF);
+/**
+ * Compute subdivision levels from a given starting point, used by multi-res subdivide/propagate,
+ * by filling in coordinates at a certain level, and then subdividing that up to the highest level.
+ */
CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF);
+/**
+ * Stitch together face grids, averaging coordinates at edges and vertices, for multi-res
+ * displacements.
+ */
CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF);
CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels);
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c
index 99ea1fb9607..e19e01ec034 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c
@@ -1309,7 +1309,6 @@ void ccgSubSurf__sync_legacy(CCGSubSurf *ss)
/* ** Public API exposed to other areas which depends on old CCG code. ** */
-/* Update normals for specified faces. */
CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF)
{
CCGVert **effectedV;
@@ -1344,9 +1343,6 @@ CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEf
return eCCGError_None;
}
-/* compute subdivision levels from a given starting point, used by
- * multires subdivide/propagate, by filling in coordinates at a
- * certain level, and then subdividing that up to the highest level */
CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
{
CCGVert **effectedV;
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index ced9076bbfd..6c9c5490ca0 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -295,10 +295,6 @@ static CustomData *dm_getPolyCData(DerivedMesh *dm)
return &dm->polyData;
}
-/**
- * Utility function to initialize a DerivedMesh's function pointers to
- * the default implementation (for those functions which have a default)
- */
void DM_init_funcs(DerivedMesh *dm)
{
/* default function implementations */
@@ -335,11 +331,6 @@ void DM_init_funcs(DerivedMesh *dm)
dm->getLoopDataArray = DM_get_loop_data_layer;
}
-/**
- * Utility function to initialize a DerivedMesh for the desired number
- * of vertices, edges and faces (doesn't allocate memory for them, just
- * sets up the custom data layers)
- */
void DM_init(DerivedMesh *dm,
DerivedMeshType type,
int numVerts,
@@ -368,10 +359,6 @@ void DM_init(DerivedMesh *dm,
copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
}
-/**
- * Utility function to initialize a DerivedMesh for the desired number
- * of vertices, edges and faces, with a layer setup copied from source
- */
void DM_from_template_ex(DerivedMesh *dm,
DerivedMesh *source,
DerivedMeshType type,
@@ -485,12 +472,6 @@ void DM_ensure_normals(DerivedMesh *dm)
BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
}
-/**
- * Ensure the array is large enough
- *
- * \note This function must always be thread-protected by caller.
- * It should only be used by internal code.
- */
void DM_ensure_looptri_data(DerivedMesh *dm)
{
const unsigned int totpoly = dm->numPolyData;
@@ -519,11 +500,11 @@ void DM_ensure_looptri_data(DerivedMesh *dm)
}
}
-/** Utility function to convert an (evaluated) Mesh to a shape key block. */
-/* Just a shallow wrapper around BKE_keyblock_convert_from_mesh,
- * that ensures both evaluated mesh and original one has same number of vertices. */
void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb)
{
+ /* Just a shallow wrapper around #BKE_keyblock_convert_from_mesh,
+ * that ensures both evaluated mesh and original one has same number of vertices. */
+
const int totvert = me_deformed->totvert;
if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) {
@@ -533,11 +514,6 @@ void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb)
BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb);
}
-/**
- * set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
- * zero for the layer type, so only layer types specified by the mask
- * will be copied
- */
void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
{
CustomData_set_only_copy(&dm->vertData, mask->vmask);
@@ -658,11 +634,6 @@ void DM_copy_vert_data(
CustomData_copy_data(&source->vertData, &dest->vertData, source_index, dest_index, count);
}
-/**
- * interpolates vertex data from the vertices indexed by src_indices in the
- * source mesh using the given weights and stores the result in the vertex
- * indexed by dest_index in the dest mesh
- */
void DM_interp_vert_data(DerivedMesh *source,
DerivedMesh *dest,
int *src_indices,
@@ -2097,12 +2068,10 @@ Mesh *mesh_create_eval_final(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
-
+ Mesh *result;
mesh_calc_modifiers(
- depsgraph, scene, ob, true, false, dataMask, -1, false, false, nullptr, &final, nullptr);
-
- return final;
+ depsgraph, scene, ob, true, false, dataMask, -1, false, false, nullptr, &result, nullptr);
+ return result;
}
Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph,
@@ -2111,12 +2080,10 @@ Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph,
const CustomData_MeshMasks *dataMask,
int index)
{
- Mesh *final;
-
+ Mesh *result;
mesh_calc_modifiers(
- depsgraph, scene, ob, true, false, dataMask, index, false, false, nullptr, &final, nullptr);
-
- return final;
+ depsgraph, scene, ob, true, false, dataMask, index, false, false, nullptr, &result, nullptr);
+ return result;
}
Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
@@ -2124,12 +2091,10 @@ Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
-
+ Mesh *result;
mesh_calc_modifiers(
- depsgraph, scene, ob, false, false, dataMask, -1, false, false, nullptr, &final, nullptr);
-
- return final;
+ depsgraph, scene, ob, false, false, dataMask, -1, false, false, nullptr, &result, nullptr);
+ return result;
}
Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
@@ -2137,12 +2102,10 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
Object *ob,
const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
-
+ Mesh *result;
mesh_calc_modifiers(
- depsgraph, scene, ob, false, false, dataMask, -1, false, false, nullptr, &final, nullptr);
-
- return final;
+ depsgraph, scene, ob, false, false, dataMask, -1, false, false, nullptr, &result, nullptr);
+ return result;
}
/***/
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 2cc1cba99cd..ddba726ba83 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -289,7 +289,7 @@ static void action_blend_read_expand(BlendExpander *expander, ID *id)
static IDProperty *action_asset_type_property(const bAction *action)
{
- const bool is_single_frame = !BKE_action_has_single_frame(action);
+ const bool is_single_frame = BKE_action_has_single_frame(action);
IDPropertyTemplate idprop = {0};
idprop.i = is_single_frame;
@@ -320,6 +320,7 @@ IDTypeInfo IDType_ID_AC = {
.name_plural = "actions",
.translation_context = BLT_I18NCONTEXT_ID_ACTION,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = &AssetType_AC,
.init_data = NULL,
.copy_data = action_copy_data,
@@ -327,6 +328,7 @@ IDTypeInfo IDType_ID_AC = {
.make_local = NULL,
.foreach_id = action_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = action_blend_write,
@@ -337,8 +339,6 @@ IDTypeInfo IDType_ID_AC = {
.blend_read_undo_preserve = NULL,
.lib_override_apply_post = NULL,
-
- .asset_type_info = &AssetType_AC,
};
/* ***************** Library data level operations on action ************** */
@@ -356,7 +356,6 @@ bAction *BKE_action_add(Main *bmain, const char name[])
/* *************** Action Groups *************** */
-/* Get the active action-group for an Action */
bActionGroup *get_active_actiongroup(bAction *act)
{
bActionGroup *agrp = NULL;
@@ -372,7 +371,6 @@ bActionGroup *get_active_actiongroup(bAction *act)
return agrp;
}
-/* Make the given Action-Group the active one */
void set_active_action_group(bAction *act, bActionGroup *agrp, short select)
{
bActionGroup *grp;
@@ -393,7 +391,6 @@ void set_active_action_group(bAction *act, bActionGroup *agrp, short select)
}
}
-/* Sync colors used for action/bone group with theme settings */
void action_group_colors_sync(bActionGroup *grp, const bActionGroup *ref_grp)
{
/* Only do color copying if using a custom color (i.e. not default color). */
@@ -424,7 +421,6 @@ void action_group_colors_sync(bActionGroup *grp, const bActionGroup *ref_grp)
}
}
-/* Add a new action group with the given name to the action */
bActionGroup *action_groups_add_new(bAction *act, const char name[])
{
bActionGroup *agrp;
@@ -450,10 +446,6 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[])
return agrp;
}
-/* Add given channel into (active) group
- * - assumes that channel is not linked to anything anymore
- * - always adds at the end of the group
- */
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
{
/* sanity checks */
@@ -522,10 +514,6 @@ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
fcurve->grp = agrp;
}
-/* Reconstruct group channel pointers.
- * Assumes that the groups referred to by the FCurves are already in act->groups.
- * Reorders the main channel list to match group order.
- */
void BKE_action_groups_reconstruct(bAction *act)
{
/* Sanity check. */
@@ -565,7 +553,6 @@ void BKE_action_groups_reconstruct(bAction *act)
BLI_movelisttolist(&act->curves, &ungrouped);
}
-/* Remove the given channel from all groups */
void action_groups_remove_channel(bAction *act, FCurve *fcu)
{
/* sanity checks */
@@ -606,7 +593,6 @@ void action_groups_remove_channel(bAction *act, FCurve *fcu)
BLI_remlink(&act->curves, fcu);
}
-/* Find a group with the given name */
bActionGroup *BKE_action_group_find_name(bAction *act, const char name[])
{
/* sanity checks */
@@ -618,7 +604,6 @@ bActionGroup *BKE_action_group_find_name(bAction *act, const char name[])
return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name));
}
-/* Clear all 'temp' flags on all groups */
void action_groups_clear_tempflags(bAction *act)
{
bActionGroup *agrp;
@@ -641,10 +626,6 @@ void BKE_pose_channel_session_uuid_generate(bPoseChannel *pchan)
pchan->runtime.session_uuid = BLI_session_uuid_generate();
}
-/**
- * Return a pointer to the pose channel of the given name
- * from this pose.
- */
bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
{
if (ELEM(NULL, pose, name) || (name[0] == '\0')) {
@@ -658,14 +639,6 @@ bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
return BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name));
}
-/**
- * Looks to see if the channel with the given name
- * already exists in this pose - if not a new one is
- * allocated and initialized.
- *
- * \note Use with care, not on Armature poses but for temporal ones.
- * \note (currently used for action constraints and in rebuild_pose).
- */
bPoseChannel *BKE_pose_channel_ensure(bPose *pose, const char *name)
{
bPoseChannel *chan;
@@ -732,12 +705,6 @@ bool BKE_pose_channels_is_valid(const bPose *pose)
#endif
-/**
- * Find the active pose-channel for an object
- * (we can't just use pose, as layer info is in armature)
- *
- * \note #Object, not #bPose is used here, as we need layer info from Armature.
- */
bPoseChannel *BKE_pose_channel_active(Object *ob)
{
bArmature *arm = (ob) ? ob->data : NULL;
@@ -757,15 +724,6 @@ bPoseChannel *BKE_pose_channel_active(Object *ob)
return NULL;
}
-/**
- * Use this when detecting the "other selected bone",
- * when we have multiple armatures in pose mode.
- *
- * In this case the active-selected is an obvious choice when finding the target for a
- * constraint for eg. however from the users perspective the active pose bone of the
- * active object is the _real_ active bone, so any other non-active selected bone
- * is a candidate for being the other selected bone, see: T58447.
- */
bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob)
{
bArmature *arm = (ob) ? ob->data : NULL;
@@ -789,9 +747,6 @@ bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob)
return NULL;
}
-/**
- * \see #ED_armature_ebone_get_mirrored (edit-mode, matching function)
- */
bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
{
char name_flip[MAXBONENAME];
@@ -818,12 +773,6 @@ const char *BKE_pose_ikparam_get_name(bPose *pose)
return NULL;
}
-/**
- * Allocate a new pose on the heap, and copy the src pose and its channels
- * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
- *
- * \param dst: Should be freed already, makes entire duplicate.
- */
void BKE_pose_copy_data_ex(bPose **dst,
const bPose *src,
const int flag,
@@ -975,10 +924,6 @@ bool BKE_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
return pose_channel_in_IK_chain(ob, pchan, 0);
}
-/**
- * Removes the hash for quick lookup of channels, must
- * be done when adding/removing channels.
- */
void BKE_pose_channels_hash_ensure(bPose *pose)
{
if (!pose->chanhash) {
@@ -1014,9 +959,6 @@ static void pose_channels_remove_internal_links(Object *ob, bPoseChannel *unlink
}
}
-/**
- * Selectively remove pose channels.
- */
void BKE_pose_channels_remove(Object *ob,
bool (*filter_fn)(const char *bone_name, void *user_data),
void *user_data)
@@ -1086,10 +1028,6 @@ void BKE_pose_channels_remove(Object *ob,
}
}
-/**
- * Deallocates a pose channel.
- * Does not free the pose channel itself.
- */
void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
{
if (pchan->custom) {
@@ -1118,13 +1056,11 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
BKE_pose_channel_runtime_free(&pchan->runtime);
}
-/** Clears the runtime cache of a pose channel without free. */
void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime)
{
memset(runtime, 0, sizeof(*runtime));
}
-/* Reset all non-persistent fields. */
void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime)
{
const SessionUUID uuid = runtime->session_uuid;
@@ -1132,13 +1068,11 @@ void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime)
runtime->session_uuid = uuid;
}
-/** Deallocates runtime cache of a pose channel */
void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime)
{
BKE_pose_channel_free_bbone_cache(runtime);
}
-/** Deallocates runtime cache of a pose channel's B-Bone shape. */
void BKE_pose_channel_free_bbone_cache(bPoseChannel_Runtime *runtime)
{
runtime->bbone_segments = 0;
@@ -1153,10 +1087,6 @@ void BKE_pose_channel_free(bPoseChannel *pchan)
BKE_pose_channel_free_ex(pchan, true);
}
-/**
- * Removes and deallocates all channels from a pose.
- * Does not free the pose itself.
- */
void BKE_pose_channels_free_ex(bPose *pose, bool do_id_user)
{
bPoseChannel *pchan;
@@ -1203,9 +1133,6 @@ void BKE_pose_free_data(bPose *pose)
BKE_pose_free_data_ex(pose, true);
}
-/**
- * Removes and deallocates all data from a pose, and also frees the pose.
- */
void BKE_pose_free_ex(bPose *pose, bool do_id_user)
{
if (pose) {
@@ -1220,13 +1147,6 @@ void BKE_pose_free(bPose *pose)
BKE_pose_free_ex(pose, true);
}
-/**
- * Copy the internal members of each pose channel including constraints
- * and ID-Props, used when duplicating bones in editmode.
- * (unlike copy_pose_channel_data which only does posing-related stuff).
- *
- * \note use when copying bones in editmode (on returned value from #BKE_pose_channel_ensure)
- */
void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_from)
{
/* copy transform locks */
@@ -1276,10 +1196,6 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
pchan->drawflag = pchan_from->drawflag;
}
-/* checks for IK constraint, Spline IK, and also for Follow-Path constraint.
- * can do more constraints flags later
- */
-/* pose should be entirely OK */
void BKE_pose_update_constraint_flags(bPose *pose)
{
bPoseChannel *pchan, *parchan;
@@ -1354,7 +1270,6 @@ void BKE_pose_tag_update_constraint_flags(bPose *pose)
/* ************************** Bone Groups ************************** */
-/* Adds a new bone-group (name may be NULL) */
bActionGroup *BKE_pose_add_group(bPose *pose, const char *name)
{
bActionGroup *grp;
@@ -1373,8 +1288,6 @@ bActionGroup *BKE_pose_add_group(bPose *pose, const char *name)
return grp;
}
-/* Remove the given bone-group (expects 'virtual' index (+1 one, used by active_group etc.))
- * index might be invalid ( < 1), in which case it will be find from grp. */
void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index)
{
bPoseChannel *pchan;
@@ -1413,7 +1326,6 @@ void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index)
}
}
-/* Remove the indexed bone-group (expects 'virtual' index (+1 one, used by active_group etc.)) */
void BKE_pose_remove_group_index(bPose *pose, const int index)
{
bActionGroup *grp = NULL;
@@ -1427,7 +1339,6 @@ void BKE_pose_remove_group_index(bPose *pose, const int index)
/* ************** F-Curve Utilities for Actions ****************** */
-/* Check if the given action has any keyframes */
bool action_has_motion(const bAction *act)
{
FCurve *fcu;
@@ -1486,7 +1397,6 @@ bool BKE_action_has_single_frame(const struct bAction *act)
return found_key;
}
-/* Calculate the extents of given action */
void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers)
{
FCurve *fcu;
@@ -1574,9 +1484,27 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
}
}
-/* Return flags indicating which transforms the given object/posechannel has
- * - if 'curves' is provided, a list of links to these curves are also returned
- */
+void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end)
+{
+ if (act && (act->flag & ACT_FRAME_RANGE)) {
+ *r_start = act->frame_start;
+ *r_end = act->frame_end;
+ }
+ else {
+ calc_action_range(act, r_start, r_end, false);
+ }
+
+ /* Ensure that action is at least 1 frame long (for NLA strips to have a valid length). */
+ if (*r_start >= *r_end) {
+ *r_end = *r_start + 1.0f;
+ }
+}
+
+bool BKE_action_is_cyclic(const struct bAction *act)
+{
+ return act && (act->flag & ACT_FRAME_RANGE) && (act->flag & ACT_CYCLIC);
+}
+
short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan, ListBase *curves)
{
PointerRNA ptr;
@@ -1707,9 +1635,6 @@ short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan,
/* ************** Pose Management Tools ****************** */
-/**
- * Zero the pose transforms for the entire pose or only for selected bones.
- */
void BKE_pose_rest(bPose *pose, bool selected_bones_only)
{
bPoseChannel *pchan;
@@ -1774,7 +1699,6 @@ void BKE_pose_copy_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchan
pchanto->protectflag = pchanfrom->protectflag;
}
-/* both poses should be in sync */
bool BKE_pose_copy_result(bPose *to, bPose *from)
{
bPoseChannel *pchanto, *pchanfrom;
@@ -1799,7 +1723,6 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
return true;
}
-/* Tag pose for recalc. Also tag all related data to be recalc. */
void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
{
pose->flag |= POSE_RECALC;
@@ -1809,9 +1732,6 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
DEG_relations_tag_update(bmain);
}
-/* For the calculation of the effects of an Action at the given frame on an object
- * This is currently only used for the Action Constraint
- */
void what_does_obaction(Object *ob,
Object *workob,
bPose *pose,
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 21887d514d9..d93d5c456d8 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -69,7 +69,6 @@ static CLG_LogRef LOG = {"bke.anim_sys"};
/* Getter/Setter -------------------------------------------- */
-/* Check if ID can have AnimData */
bool id_type_can_have_animdata(const short id_type)
{
const IDTypeInfo *typeinfo = BKE_idtype_get_info_from_idcode(id_type);
@@ -89,9 +88,6 @@ bool id_can_have_animdata(const ID *id)
return id_type_can_have_animdata(GS(id->name));
}
-/**
- * Get #AnimData from the given ID-block.
- */
AnimData *BKE_animdata_from_id(ID *id)
{
/* In order for this to work, we assume that the #AnimData pointer is stored
@@ -106,9 +102,6 @@ AnimData *BKE_animdata_from_id(ID *id)
return NULL;
}
-/**
- * Ensure #AnimData exists in the given ID-block (when supported).
- */
AnimData *BKE_animdata_ensure_id(ID *id)
{
/* In order for this to work, we assume that the #AnimData pointer is stored
@@ -137,16 +130,6 @@ AnimData *BKE_animdata_ensure_id(ID *id)
/* Action Setter --------------------------------------- */
-/**
- * Called when user tries to change the active action of an #AnimData block
- * (via RNA, Outliner, etc.)
- *
- * \param reports: Can be NULL.
- * \param id: The owner of the animation data
- * \param act: The Action to set, or NULL to clear.
- *
- * \return true when the action was successfully updated, false otherwise.
- */
bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
{
AnimData *adt = BKE_animdata_from_id(id);
@@ -226,7 +209,6 @@ bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
/* Freeing -------------------------------------------- */
-/* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */
void BKE_animdata_free(ID *id, const bool do_id_user)
{
/* Only some ID-blocks have this info for now, so we cast the
@@ -287,10 +269,6 @@ bool BKE_animdata_id_is_animated(const struct ID *id)
!BLI_listbase_is_empty(&adt->overrides);
}
-/**
- * Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
- * `IDTypeInfo` structure).
- */
void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
{
LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
@@ -309,12 +287,6 @@ void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
/* Copying -------------------------------------------- */
-/**
- * Make a copy of the given AnimData - to be used when copying data-blocks.
- * \param flag: Control ID pointers management,
- * see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_lib_id.h
- * \return The copied animdata.
- */
AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
{
AnimData *dadt;
@@ -367,11 +339,6 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
return dadt;
}
-/**
- * \param flag: Control ID pointers management,
- * see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_lib_id.h
- * \return true is successfully copied.
- */
bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag)
{
AnimData *adt;
@@ -432,7 +399,6 @@ void BKE_animdata_duplicate_id_action(struct Main *bmain,
}
}
-/* Merge copies of the data from the src AnimData into the destination AnimData */
void BKE_animdata_merge_copy(
Main *bmain, ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers)
{
@@ -647,12 +613,6 @@ static void animdata_move_drivers_by_basepath(AnimData *srcAdt,
}
}
-/* Transfer the animation data from srcID to dstID where the srcID
- * animation data is based off "basepath", creating new AnimData and
- * associated data as necessary.
- *
- * basepaths is a list of AnimationBasePathChange.
- */
void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBase *basepaths)
{
AnimData *srcAdt = NULL, *dstAdt = NULL;
@@ -716,17 +676,6 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
}
}
-/**
- * Temporary wrapper for driver operators for buttons to make it easier to create
- * such drivers by rerouting all paths through the active object instead so that
- * they will get picked up by the dependency system.
- *
- * \param C: Context pointer - for getting active data
- * \param[in,out] ptr: RNA pointer for property's data-block.
- * May be modified as result of path remapping.
- * \param prop: RNA definition of property to add for
- * \return MEM_alloc'd string representing the path to the property from the given #PointerRNA
- */
char *BKE_animdata_driver_path_hack(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
@@ -956,14 +905,6 @@ static bool nlastrips_path_rename_fix(ID *owner_id,
/* Rename Sub-ID Entities in RNA Paths ----------------------- */
-/* Fix up the given RNA-Path
- *
- * This is just an external wrapper for the RNA-Path fixing function,
- * with input validity checks on top of the basic method.
- *
- * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
- * i.e. pose.bones["Bone"]
- */
char *BKE_animsys_fix_rna_path_rename(ID *owner_id,
char *old_path,
const char *prefix,
@@ -1019,14 +960,6 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id,
return result;
}
-/* Fix all RNA_Paths in the given Action, relative to the given ID block
- *
- * This is just an external wrapper for the F-Curve fixing function,
- * with input validity checks on top of the basic method.
- *
- * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
- * i.e. pose.bones["Bone"]
- */
void BKE_action_fix_paths_rename(ID *owner_id,
bAction *act,
const char *prefix,
@@ -1070,10 +1003,6 @@ void BKE_action_fix_paths_rename(ID *owner_id,
MEM_freeN(newN);
}
-/* Fix all RNA-Paths in the AnimData block used by the given ID block
- * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
- * i.e. pose.bones["Bone"]
- */
void BKE_animdata_fix_paths_rename(ID *owner_id,
AnimData *adt,
ID *ref_id,
@@ -1282,7 +1211,6 @@ void BKE_fcurves_id_cb(ID *id, ID_FCurve_Edit_Callback func, void *user_data)
}
}
-/* apply the given callback function on all F-Curves attached to data in main database */
void BKE_fcurves_main_cb(Main *bmain, ID_FCurve_Edit_Callback func, void *user_data)
{
/* Wrap F-Curve operation stuff to pass to the general AnimData-level func */
@@ -1294,7 +1222,6 @@ void BKE_fcurves_main_cb(Main *bmain, ID_FCurve_Edit_Callback func, void *user_d
/* Whole Database Ops -------------------------------------------- */
-/* apply the given callback function on all data in main database */
void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *user_data)
{
ID *id;
@@ -1405,10 +1332,6 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
ANIMDATA_IDS_CB(bmain->simulations.first);
}
-/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
- * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
- * i.e. pose.bones["Bone"]
- */
void BKE_animdata_fix_paths_rename_all(ID *ref_id,
const char *prefix,
const char *oldName,
@@ -1418,11 +1341,6 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id,
BKE_animdata_fix_paths_rename_all_ex(bmain, ref_id, prefix, oldName, newName, 0, 0, 1);
}
-/* Fix all RNA-Paths throughout the database
- * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
- * i.e. pose.bones["Bone"]
- */
-/* TODO: use BKE_animdata_main_cb for looping over all data. */
void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
ID *ref_id,
const char *prefix,
@@ -1432,6 +1350,7 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
const int newSubscript,
const bool verify_paths)
{
+ /* TODO: use BKE_animdata_main_cb for looping over all data. */
ID *id;
diff --git a/source/blender/blenkernel/intern/anim_path.c b/source/blender/blenkernel/intern/anim_path.c
index de470a15041..43af55e9b6b 100644
--- a/source/blender/blenkernel/intern/anim_path.c
+++ b/source/blender/blenkernel/intern/anim_path.c
@@ -230,14 +230,6 @@ static bool binary_search_anim_path(const float *accum_len_arr,
}
}
-/**
- * Calculate the deformation implied by the curve path at a given parametric position,
- * and returns whether this operation succeeded.
- *
- * \param ctime: Time is normalized range <0-1>.
- *
- * \return success.
- */
bool BKE_where_on_path(const Object *ob,
float ctime,
float r_vec[4],
@@ -254,6 +246,10 @@ bool BKE_where_on_path(const Object *ob,
CLOG_WARN(&LOG, "No curve cache!");
return false;
}
+ if (ob->runtime.curve_cache->anim_path_accum_length == NULL) {
+ CLOG_WARN(&LOG, "No anim path!");
+ return false;
+ }
/* We only use the first curve. */
BevList *bl = ob->runtime.curve_cache->bev.first;
if (bl == NULL || !bl->nr) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index cbdcf43c039..b5ea68aaadc 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -84,8 +84,6 @@ static CLG_LogRef LOG = {"bke.anim_sys"};
/* Finding Tools --------------------------- */
-/* Find the first path that matches the given criteria */
-/* TODO: do we want some method to perform partial matches too? */
KS_Path *BKE_keyingset_find_path(KeyingSet *ks,
ID *id,
const char group_name[],
@@ -138,8 +136,6 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks,
/* Defining Tools --------------------------- */
-/* Used to create a new 'custom' KeyingSet for the user,
- * that will be automatically added to the stack */
KeyingSet *BKE_keyingset_add(
ListBase *list, const char idname[], const char name[], short flag, short keyingflag)
{
@@ -174,9 +170,6 @@ KeyingSet *BKE_keyingset_add(
return ks;
}
-/* Add a path to a KeyingSet. Nothing is returned for now...
- * Checks are performed to ensure that destination is appropriate for the KeyingSet in question
- */
KS_Path *BKE_keyingset_add_path(KeyingSet *ks,
ID *id,
const char group_name[],
@@ -240,7 +233,6 @@ KS_Path *BKE_keyingset_add_path(KeyingSet *ks,
return ksp;
}
-/* Free the given Keying Set path */
void BKE_keyingset_free_path(KeyingSet *ks, KS_Path *ksp)
{
/* sanity check */
@@ -257,7 +249,6 @@ void BKE_keyingset_free_path(KeyingSet *ks, KS_Path *ksp)
BLI_freelinkN(&ks->paths, ksp);
}
-/* Copy all KeyingSets in the given list */
void BKE_keyingsets_copy(ListBase *newlist, const ListBase *list)
{
KeyingSet *ksn;
@@ -276,7 +267,6 @@ void BKE_keyingsets_copy(ListBase *newlist, const ListBase *list)
/* Freeing Tools --------------------------- */
-/* Free data for KeyingSet but not set itself */
void BKE_keyingset_free(KeyingSet *ks)
{
KS_Path *ksp, *kspn;
@@ -293,7 +283,6 @@ void BKE_keyingset_free(KeyingSet *ks)
}
}
-/* Free all the KeyingSets in the given list */
void BKE_keyingsets_free(ListBase *list)
{
KeyingSet *ks, *ksn;
@@ -490,7 +479,6 @@ bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value)
return true;
}
-/* Write the given value to a setting using RNA, and return success */
bool BKE_animsys_write_to_rna_path(PathResolvedRNA *anim_rna, const float value)
{
PropertyRNA *prop = anim_rna->prop;
@@ -831,7 +819,6 @@ static void action_idcode_patch_check(ID *id, bAction *act)
/* ----------------------------------------- */
-/* Evaluate Action Group */
void animsys_evaluate_action_group(PointerRNA *ptr,
bAction *act,
bActionGroup *agrp,
@@ -864,7 +851,6 @@ void animsys_evaluate_action_group(PointerRNA *ptr,
}
}
-/* Evaluate Action (F-Curve Bag) */
void animsys_evaluate_action(PointerRNA *ptr,
bAction *act,
const AnimationEvalContext *anim_eval_context,
@@ -881,7 +867,6 @@ void animsys_evaluate_action(PointerRNA *ptr,
animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original);
}
-/* Evaluate Action and blend it into the current values of the animated properties. */
void animsys_blend_in_action(PointerRNA *ptr,
bAction *act,
const AnimationEvalContext *anim_eval_context,
@@ -960,7 +945,6 @@ static void nlastrip_evaluate_controls(NlaStrip *strip,
}
}
-/* gets the strip active at the current time for a list of strips for evaluation purposes */
NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
ListBase *strips,
short index,
@@ -2402,7 +2386,6 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr,
nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
}
-/* evaluates the given evaluation strip */
void nlastrip_evaluate(PointerRNA *ptr,
NlaEvalData *channels,
ListBase *modifiers,
@@ -2447,7 +2430,6 @@ void nlastrip_evaluate(PointerRNA *ptr,
strip->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED;
}
-/* write the accumulated settings to */
void nladata_flush_channels(PointerRNA *ptr,
NlaEvalData *channels,
NlaEvalSnapshot *snapshot,
@@ -2977,14 +2959,6 @@ void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapsh
}
}
-/**
- * Blends the \a lower_snapshot with the \a upper_snapshot into \a r_blended_snapshot according
- * to the given \a upper_blendmode and \a upper_influence.
- *
- * For \a upper_snapshot, blending limited to values in the \a blend_domain.
- * For Replace blend-mode, this allows the upper snapshot to have a location XYZ channel
- * where only a subset of values are blended.
- */
void nlasnapshot_blend(NlaEvalData *eval_data,
NlaEvalSnapshot *lower_snapshot,
NlaEvalSnapshot *upper_snapshot,
@@ -3012,14 +2986,6 @@ void nlasnapshot_blend(NlaEvalData *eval_data,
}
}
-/**
- * Using \a blended_snapshot and \a lower_snapshot, we can solve for the \a r_upper_snapshot.
- *
- * Only channels that exist within \a blended_snapshot are inverted.
- *
- * For \a r_upper_snapshot, disables \a NlaEvalChannelSnapshot->remap_domain for failed inversions.
- * Only values within the \a remap_domain are processed.
- */
void nlasnapshot_blend_get_inverted_upper_snapshot(NlaEvalData *eval_data,
NlaEvalSnapshot *lower_snapshot,
NlaEvalSnapshot *blended_snapshot,
@@ -3050,15 +3016,6 @@ void nlasnapshot_blend_get_inverted_upper_snapshot(NlaEvalData *eval_data,
/* ---------------------- */
-/**
- * Prepare data necessary to compute correct keyframe values for NLA strips
- * with non-Replace mode or influence different from 1.
- *
- * \param cache: List used to cache contexts for reuse when keying
- * multiple channels in one operation.
- * \param ptr: RNA pointer to the Object with the animation.
- * \return Keyframing context, or NULL if not necessary.
- */
NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
struct ListBase *cache,
struct PointerRNA *ptr,
@@ -3095,18 +3052,6 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
return ctx;
}
-/**
- * Apply correction from the NLA context to the values about to be keyframed.
- *
- * \param context: Context to use (may be NULL).
- * \param prop_ptr: Property about to be keyframed.
- * \param[in,out] values: Array of property values to adjust.
- * \param count: Number of values in the array.
- * \param index: Index of the element about to be updated, or -1.
- * \param[out] r_force_all: Set to true if all channels must be inserted. May be NULL.
- * \return False if correction fails due to a division by zero,
- * or null r_force_all when all channels are required.
- */
bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
struct PointerRNA *prop_ptr,
struct PropertyRNA *prop,
@@ -3202,9 +3147,6 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
return successful_remap;
}
-/**
- * Free all cached contexts from the list.
- */
void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache)
{
LISTBASE_FOREACH (NlaKeyframingContext *, ctx, cache) {
@@ -3270,12 +3212,6 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
* However, the code for this is relatively harmless, so is left in the code for now.
*/
-/* Evaluation loop for evaluation animation data
- *
- * This assumes that the animation-data provided belongs to the ID block in question,
- * and that the flags for which parts of the anim-data settings need to be recalculated
- * have been set already by the depsgraph. Now, we use the recalc
- */
void BKE_animsys_evaluate_animdata(ID *id,
AnimData *adt,
const AnimationEvalContext *anim_eval_context,
@@ -3329,13 +3265,6 @@ void BKE_animsys_evaluate_animdata(ID *id,
animsys_evaluate_overrides(&id_ptr, adt);
}
-/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only
- *
- * This will evaluate only the animation info available in the animation data-blocks
- * encountered. In order to enforce the system by which some settings controlled by a
- * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a
- * standard 'root') block are overridden by a larger 'user'
- */
void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float ctime)
{
ID *id;
diff --git a/source/blender/blenkernel/intern/anim_visualization.c b/source/blender/blenkernel/intern/anim_visualization.c
index 56bd8e769bc..fdea52bcd64 100644
--- a/source/blender/blenkernel/intern/anim_visualization.c
+++ b/source/blender/blenkernel/intern/anim_visualization.c
@@ -39,7 +39,6 @@
/* ******************************************************************** */
/* Animation Visualization */
-/* Initialize the default settings for animation visualization */
void animviz_settings_init(bAnimVizSettings *avs)
{
/* sanity check */
@@ -62,7 +61,6 @@ void animviz_settings_init(bAnimVizSettings *avs)
/* ------------------- */
-/* Free the given motion path's cache */
void animviz_free_motionpath_cache(bMotionPath *mpath)
{
/* sanity check */
@@ -84,9 +82,6 @@ void animviz_free_motionpath_cache(bMotionPath *mpath)
mpath->length = 0;
}
-/* Free the given motion path instance and its data
- * NOTE: this frees the motion path given!
- */
void animviz_free_motionpath(bMotionPath *mpath)
{
/* sanity check */
@@ -103,7 +98,6 @@ void animviz_free_motionpath(bMotionPath *mpath)
/* ------------------- */
-/* Make a copy of motionpath data, so that viewing with copy on write works */
bMotionPath *animviz_copy_motionpath(const bMotionPath *mpath_src)
{
bMotionPath *mpath_dst;
@@ -125,14 +119,6 @@ bMotionPath *animviz_copy_motionpath(const bMotionPath *mpath_src)
/* ------------------- */
-/**
- * Setup motion paths for the given data.
- * \note Only used when explicitly calculating paths on bones which may/may not be consider already
- *
- * \param scene: Current scene (for frame ranges, etc.)
- * \param ob: Object to add paths for (must be provided)
- * \param pchan: Posechannel to add paths for (optional; if not provided, object-paths are assumed)
- */
bMotionPath *animviz_verify_motionpaths(ReportList *reports,
Scene *scene,
Object *ob,
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index d872dc67dcb..9dd4c7e503a 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -99,15 +99,6 @@ static bool is_appdir_init = false;
# define ASSERT_IS_INIT() ((void)0)
#endif
-/**
- * Sanity check to ensure correct API use in debug mode.
- *
- * Run this once the first level of arguments has been passed so we can be sure
- * `--env-system-datafiles`, and other `--env-*` arguments has been passed.
- *
- * Without this any callers to this module that run early on,
- * will miss out on changes from parsing arguments.
- */
void BKE_appdir_init(void)
{
#ifndef NDEBUG
@@ -147,14 +138,6 @@ static char *blender_version_decimal(const int version)
/** \name Default Directories
* \{ */
-/**
- * Get the folder that's the "natural" starting point for browsing files on an OS.
- * - Unix: `$HOME`
- * - Windows: `%userprofile%/Documents`
- *
- * \note On Windows `Users/{MyUserName}/Documents` is used as it's the default location to save
- * documents.
- */
const char *BKE_appdir_folder_default(void)
{
#ifndef WIN32
@@ -190,29 +173,17 @@ const char *BKE_appdir_folder_default_or_root(void)
return path;
}
-/**
- * Get the user's home directory, i.e.
- * - Unix: `$HOME`
- * - Windows: `%userprofile%`
- */
const char *BKE_appdir_folder_home(void)
{
-#ifndef WIN32
- return BLI_getenv("HOME");
-#else /* Windows */
+#ifdef WIN32
return BLI_getenv("userprofile");
+#elif defined(__APPLE__)
+ return BLI_expand_tilde("~/");
+#else
+ return BLI_getenv("HOME");
#endif
}
-/**
- * Get the user's document directory, i.e.
- * - Linux: `$HOME/Documents`
- * - Windows: `%userprofile%/Documents`
- *
- * If this can't be found using OS queries (via Ghost), try manually finding it.
- *
- * \returns True if the path is valid and points to an existing directory.
- */
bool BKE_appdir_folder_documents(char *dir)
{
dir[0] = '\0';
@@ -243,15 +214,6 @@ bool BKE_appdir_folder_documents(char *dir)
return true;
}
-/**
- * Get the user's cache directory, i.e.
- * - Linux: `$HOME/.cache/blender/`
- * - Windows: `%USERPROFILE%\AppData\Local\Blender Foundation\Blender\`
- * - MacOS: `/Library/Caches/Blender`
- *
- * \returns True if the path is valid. It doesn't create or checks format
- * if the `blender` folder exists. It does check if the parent of the path exists.
- */
bool BKE_appdir_folder_caches(char *r_path, const size_t path_len)
{
r_path[0] = '\0';
@@ -276,9 +238,6 @@ bool BKE_appdir_folder_caches(char *r_path, const size_t path_len)
return true;
}
-/**
- * Gets a good default directory for fonts.
- */
bool BKE_appdir_font_folder_default(char *dir)
{
char test_dir[FILE_MAXDIR];
@@ -291,10 +250,8 @@ bool BKE_appdir_font_folder_default(char *dir)
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);
- }
+ STRNCPY(test_dir, BLI_expand_tilde("~/Library/Fonts/"));
+ BLI_path_slash_ensure(test_dir);
#else
STRNCPY(test_dir, "/usr/share/fonts");
#endif
@@ -458,10 +415,6 @@ static bool get_path_local(char *targetpath,
targetpath, targetpath_len, folder_name, subfolder_name, version, check_is_dir);
}
-/**
- * Check if this is an install with user files kept together
- * with the Blender executable and its installation files.
- */
bool BKE_appdir_app_is_portable_install(void)
{
/* Detect portable install by the existence of `config` folder. */
@@ -626,13 +579,6 @@ static bool get_path_system(char *targetpath,
/** \name Path Presets API
* \{ */
-/**
- * Get a folder out of the \a folder_id presets for paths.
- *
- * \param subfolder: The name of a directory to check for,
- * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir.
- * \return The path if found, NULL string if not.
- */
bool BKE_appdir_folder_id_ex(const int folder_id,
const char *subfolder,
char *path,
@@ -746,9 +692,6 @@ const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
return NULL;
}
-/**
- * Returns the path to a folder in the user area without checking that it actually exists first.
- */
const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder)
{
const int version = BLENDER_VERSION;
@@ -795,9 +738,6 @@ const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *su
return path;
}
-/**
- * Returns the path to a folder in the user area, creating it if it doesn't exist.
- */
const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder)
{
const char *path;
@@ -823,10 +763,6 @@ const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfold
return path;
}
-/**
- * Returns the path of the top-level version-specific local, user or system directory.
- * If check_is_dir, then the result will be NULL if the directory doesn't exist.
- */
const char *BKE_appdir_folder_id_version(const int folder_id,
const int version,
const bool check_is_dir)
@@ -942,18 +878,12 @@ void BKE_appdir_program_path_init(const char *argv0)
BLI_split_dir_part(g_app.program_filename, g_app.program_dirname, sizeof(g_app.program_dirname));
}
-/**
- * Path to executable
- */
const char *BKE_appdir_program_path(void)
{
BLI_assert(g_app.program_filename[0]);
return g_app.program_filename;
}
-/**
- * Path to directory of executable
- */
const char *BKE_appdir_program_dir(void)
{
BLI_assert(g_app.program_dirname[0]);
@@ -1047,9 +977,6 @@ static const int app_template_directory_id[2] = {
BLENDER_SYSTEM_SCRIPTS,
};
-/**
- * Return true if templates exist
- */
bool BKE_appdir_app_template_any(void)
{
char temp_dir[FILE_MAX];
@@ -1217,14 +1144,13 @@ static void tempdir_session_create(char *tempdir_session,
BLI_strncpy(tempdir_session, tempdir, tempdir_session_len);
}
-/**
- * Sets #g_app.temp_dirname_base to \a userdir if specified and is a valid directory,
- * otherwise chooses a suitable OS-specific temporary directory.
- * Sets #g_app.temp_dirname_session to a #mkdtemp
- * generated sub-dir of #g_app.temp_dirname_base.
- */
void BKE_tempdir_init(const char *userdir)
{
+ /* Sets #g_app.temp_dirname_base to \a userdir if specified and is a valid directory,
+ * otherwise chooses a suitable OS-specific temporary directory.
+ * Sets #g_app.temp_dirname_session to a #mkdtemp
+ * generated sub-dir of #g_app.temp_dirname_base. */
+
where_is_temp(g_app.temp_dirname_base, sizeof(g_app.temp_dirname_base), userdir);
/* Clear existing temp dir, if needed. */
@@ -1234,25 +1160,16 @@ void BKE_tempdir_init(const char *userdir)
g_app.temp_dirname_session, sizeof(g_app.temp_dirname_session), g_app.temp_dirname_base);
}
-/**
- * Path to temporary directory (with trailing slash)
- */
const char *BKE_tempdir_session(void)
{
return g_app.temp_dirname_session[0] ? g_app.temp_dirname_session : BKE_tempdir_base();
}
-/**
- * Path to persistent temporary directory (with trailing slash)
- */
const char *BKE_tempdir_base(void)
{
return g_app.temp_dirname_base;
}
-/**
- * Delete content of this instance's temp dir.
- */
void BKE_tempdir_session_purge(void)
{
if (g_app.temp_dirname_session[0] && BLI_is_dir(g_app.temp_dirname_session)) {
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b830c9de5f5..0a91d662c1b 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -322,6 +322,7 @@ IDTypeInfo IDType_ID_AR = {
.name_plural = "armatures",
.translation_context = BLT_I18NCONTEXT_ID_ARMATURE,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = armature_init_data,
.copy_data = armature_copy_data,
@@ -329,6 +330,7 @@ IDTypeInfo IDType_ID_AR = {
.make_local = NULL,
.foreach_id = armature_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = armature_blend_write,
@@ -607,10 +609,6 @@ static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name)
return NULL;
}
-/**
- * Walk the list until the bone is found (slow!),
- * use #BKE_armature_bone_from_name_map for multiple lookups.
- */
Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name)
{
if (!arm) {
@@ -715,10 +713,6 @@ void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmatu
/** \name Armature Layer Refresh Used
* \{ */
-/* Finds the best possible extension to the name on a particular axis. (For renaming, check for
- * unique names afterwards) strip_number: removes number extensions (TODO: not used)
- * axis: the axis to name on
- * head/tail: the head/tail co-ordinate of the bone on the specified axis */
bool bone_autoside_name(
char name[MAXBONENAME], int UNUSED(strip_number), short axis, float head, float tail)
{
@@ -930,7 +924,6 @@ static void evaluate_cubic_bezier(const float control[4][3],
madd_v3_v3v3fl(r_pos, layer2[0], r_tangent, t);
}
-/* Get "next" and "prev" bones - these are used for handle calculations. */
void BKE_pchan_bbone_handles_get(bPoseChannel *pchan, bPoseChannel **r_prev, bPoseChannel **r_next)
{
if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO) {
@@ -957,7 +950,6 @@ void BKE_pchan_bbone_handles_get(bPoseChannel *pchan, bPoseChannel **r_prev, bPo
}
}
-/* Compute B-Bone spline parameters for the given channel. */
void BKE_pchan_bbone_spline_params_get(struct bPoseChannel *pchan,
const bool rest,
struct BBoneSplineParameters *param)
@@ -1203,8 +1195,6 @@ void BKE_pchan_bbone_spline_params_get(struct bPoseChannel *pchan,
}
}
-/* Fills the array with the desired amount of bone->segments elements.
- * This calculation is done within unit bone space. */
void BKE_pchan_bbone_spline_setup(bPoseChannel *pchan,
const bool rest,
const bool for_deform,
@@ -1217,7 +1207,6 @@ void BKE_pchan_bbone_spline_setup(bPoseChannel *pchan,
pchan->bone->segments = BKE_pchan_bbone_spline_compute(&param, for_deform, result_array);
}
-/* Computes the bezier handle vectors and rolls coming from custom handles. */
void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param,
float h1[3],
float *r_roll1,
@@ -1375,8 +1364,6 @@ static void ease_handle_axis(const float deriv1[3], const float deriv2[3], float
}
}
-/* Fills the array with the desired amount of bone->segments elements.
- * This calculation is done within unit bone space. */
int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
const bool for_deform,
Mat4 *result_array)
@@ -1511,7 +1498,6 @@ static void allocate_bbone_cache(bPoseChannel *pchan, int segments)
}
}
-/** Compute and cache the B-Bone shape in the channel runtime struct. */
void BKE_pchan_bbone_segments_cache_compute(bPoseChannel *pchan)
{
bPoseChannel_Runtime *runtime = &pchan->runtime;
@@ -1563,7 +1549,6 @@ void BKE_pchan_bbone_segments_cache_compute(bPoseChannel *pchan)
}
}
-/** Copy cached B-Bone segments from one channel to another */
void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pchan_from)
{
bPoseChannel_Runtime *runtime = &pchan->runtime;
@@ -1587,10 +1572,6 @@ void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pcha
}
}
-/**
- * Calculate index and blend factor for the two B-Bone segment nodes
- * affecting the point at 0 <= pos <= 1.
- */
void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan,
float pos,
int *r_index,
@@ -1622,7 +1603,6 @@ void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan,
/** \name Bone Space to Space Conversion API
* \{ */
-/* Convert World-Space Matrix to Pose-Space Matrix */
void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float outmat[4][4])
{
float obmat[4][4];
@@ -1639,9 +1619,6 @@ void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float o
mul_m4_m4m4(outmat, inmat, obmat);
}
-/* Convert World-Space Location to Pose-Space Location
- * NOTE: this cannot be used to convert to pose-space location of the supplied
- * pose-channel into its local space (i.e. 'visual'-keyframing) */
void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outloc[3])
{
float xLocMat[4][4];
@@ -1662,8 +1639,6 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl
/** \name Bone Matrix Calculation API
* \{ */
-/* Simple helper, computes the offset bone matrix.
- * offs_bone = yoffs(b-1) + root(b) + bonemat(b). */
void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4])
{
BLI_assert(bone->parent != NULL);
@@ -1678,24 +1653,6 @@ void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4])
offs_bone[3][1] += bone->parent->length;
}
-/* Construct the matrices (rot/scale and loc)
- * to apply the PoseChannels into the armature (object) space.
- * I.e. (roughly) the "pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b)" in the
- * pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b)
- * ...function.
- *
- * This allows to get the transformations of a bone in its object space,
- * *before* constraints (and IK) get applied (used by pose evaluation code).
- * And reverse: to find pchan transformations needed to place a bone at a given loc/rot/scale
- * in object space (used by interactive transform, and snapping code).
- *
- * Note that, with the HINGE/NO_SCALE/NO_LOCAL_LOCATION options, the location matrix
- * will differ from the rotation/scale matrix...
- *
- * NOTE: This cannot be used to convert to pose-space transforms of the supplied
- * pose-channel into its local space (i.e. 'visual'-keyframing).
- * (note: I don't understand that, so I keep it :p --mont29).
- */
void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan,
BoneParentTransform *r_bpt)
{
@@ -1725,12 +1682,6 @@ void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan,
}
}
-/* Compute the parent transform using data decoupled from specific data structures.
- *
- * bone_flag: Bone->flag containing settings
- * offs_bone: delta from parent to current arm_mat (or just arm_mat if no parent)
- * parent_arm_mat, parent_pose_mat: arm_mat and pose_mat of parent, or NULL
- * r_bpt: OUTPUT parent transform */
void BKE_bone_parent_transform_calc_from_matrices(int bone_flag,
int inherit_scale_mode,
const float offs_bone[4][4],
@@ -1912,9 +1863,6 @@ void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt,
rescale_m4(outmat, bpt->post_scale);
}
-/* Convert Pose-Space Matrix to Bone-Space Matrix.
- * NOTE: this cannot be used to convert to pose-space transforms of the supplied
- * pose-channel into its local space (i.e. 'visual'-keyframing) */
void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4])
@@ -1926,7 +1874,6 @@ void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan,
BKE_bone_parent_transform_apply(&bpt, inmat, outmat);
}
-/* Convert Bone-Space Matrix to Pose-Space Matrix. */
void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4])
@@ -1937,9 +1884,6 @@ void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan,
BKE_bone_parent_transform_apply(&bpt, inmat, outmat);
}
-/* Convert Pose-Space Location to Bone-Space Location
- * NOTE: this cannot be used to convert to pose-space location of the supplied
- * pose-channel into its local space (i.e. 'visual'-keyframing) */
void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], float outloc[3])
{
float xLocMat[4][4];
@@ -1982,9 +1926,6 @@ void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph,
BKE_armature_mat_pose_to_bone(&work_pchan, inmat, outmat);
}
-/**
- * Same as #BKE_object_mat3_to_rot().
- */
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
{
BLI_ASSERT_UNIT_M3(mat);
@@ -2007,9 +1948,6 @@ void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_
}
}
-/**
- * Same as #BKE_object_rot_to_mat3().
- */
void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3])
{
/* rotations may either be quats, eulers (with various rotation orders), or axis-angle */
@@ -2034,10 +1972,6 @@ void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3])
}
}
-/**
- * Apply a 4x4 matrix to the pose bone,
- * similar to #BKE_object_apply_mat4().
- */
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
{
float rot[3][3];
@@ -2045,11 +1979,6 @@ void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_c
BKE_pchan_mat3_to_rot(pchan, rot, use_compat);
}
-/**
- * Remove rest-position effects from pose-transform for obtaining
- * 'visual' transformation of pose-channel.
- * (used by the Visual-Keyframing stuff).
- */
void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
float pose_mat[4][4],
float arm_mat[4][4])
@@ -2068,11 +1997,6 @@ void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
* Used for Objects and Pose Channels, since both can have multiple rotation representations.
* \{ */
-/**
- * Called from RNA when rotation mode changes
- * - the result should be that the rotations given in the provided pointers have had conversions
- * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed.
- */
void BKE_rotMode_change_values(
float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode)
{
@@ -2146,8 +2070,6 @@ void BKE_rotMode_change_values(
*
* \{ */
-/* Computes vector and roll based on a rotation.
- * "mat" must contain only a rotation, and no scaling. */
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
{
if (r_vec) {
@@ -2159,8 +2081,6 @@ void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
}
}
-/* Computes roll around the vector that best approximates the matrix.
- * If vec is the Y vector from purely rotational mat, result should be exact. */
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
{
float vecmat[3][3], vecmatinv[3][3], rollmat[3][3], q[4];
@@ -2176,79 +2096,6 @@ void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
*r_roll = quat_split_swing_and_twist(q, 1, NULL, NULL);
}
-/* Calculates the rest matrix of a bone based on its vector and a roll around that vector. */
-/**
- * Given `v = (v.x, v.y, v.z)` our (normalized) bone vector, we want the rotation matrix M
- * from the Y axis (so that `M * (0, 1, 0) = v`).
- * - The rotation axis a lays on XZ plane, and it is orthonormal to v,
- * hence to the projection of v onto XZ plane.
- * - `a = (v.z, 0, -v.x)`
- *
- * We know a is eigenvector of M (so M * a = a).
- * Finally, we have w, such that M * w = (0, 1, 0)
- * (i.e. the vector that will be aligned with Y axis once transformed).
- * We know w is symmetric to v by the Y axis.
- * - `w = (-v.x, v.y, -v.z)`
- *
- * Solving this, we get (x, y and z being the components of v):
- * <pre>
- * ┌ (x^2 * y + z^2) / (x^2 + z^2), x, x * z * (y - 1) / (x^2 + z^2) ┐
- * M = │ x * (y^2 - 1) / (x^2 + z^2), y, z * (y^2 - 1) / (x^2 + z^2) │
- * └ x * z * (y - 1) / (x^2 + z^2), z, (x^2 + z^2 * y) / (x^2 + z^2) ┘
- * </pre>
- *
- * This is stable as long as v (the bone) is not too much aligned with +/-Y
- * (i.e. x and z components are not too close to 0).
- *
- * Since v is normalized, we have `x^2 + y^2 + z^2 = 1`,
- * hence `x^2 + z^2 = 1 - y^2 = (1 - y)(1 + y)`.
- *
- * This allows to simplifies M like this:
- * <pre>
- * ┌ 1 - x^2 / (1 + y), x, -x * z / (1 + y) ┐
- * M = │ -x, y, -z │
- * └ -x * z / (1 + y), z, 1 - z^2 / (1 + y) ┘
- * </pre>
- *
- * Written this way, we see the case v = +Y is no more a singularity.
- * The only one
- * remaining is the bone being aligned with -Y.
- *
- * Let's handle
- * the asymptotic behavior when bone vector is reaching the limit of y = -1.
- * Each of the four corner elements can vary from -1 to 1,
- * depending on the axis a chosen for doing the rotation.
- * And the "rotation" here is in fact established by mirroring XZ plane by that given axis,
- * then inversing the Y-axis.
- * For sufficiently small x and z, and with y approaching -1,
- * all elements but the four corner ones of M will degenerate.
- * So let's now focus on these corner elements.
- *
- * We rewrite M so that it only contains its four corner elements,
- * and combine the `1 / (1 + y)` factor:
- * <pre>
- * ┌ 1 + y - x^2, -x * z ┐
- * M* = 1 / (1 + y) * │ │
- * └ -x * z, 1 + y - z^2 ┘
- * </pre>
- *
- * When y is close to -1, computing 1 / (1 + y) will cause severe numerical instability,
- * so we use a different approach based on x and z as inputs.
- * We know `y^2 = 1 - (x^2 + z^2)`, and `y < 0`, hence `y = -sqrt(1 - (x^2 + z^2))`.
- *
- * Since x and z are both close to 0, we apply the binomial expansion to the second order:
- * `y = -sqrt(1 - (x^2 + z^2)) = -1 + (x^2 + z^2) / 2 + (x^2 + z^2)^2 / 8`, which allows
- * eliminating the problematic `1` constant.
- *
- * A first order expansion allows simplifying to this, but second order is more precise:
- * <pre>
- * ┌ z^2 - x^2, -2 * x * z ┐
- * M* = 1 / (x^2 + z^2) * │ │
- * └ -2 * x * z, x^2 - z^2 ┘
- * </pre>
- *
- * P.S. In the end, this basically is a heavily optimized version of Damped Track +Y.
- */
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3])
{
const float SAFE_THRESHOLD = 6.1e-3f; /* Theta above this value has good enough precision. */
@@ -2319,10 +2166,6 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3])
/** \name Armature Bone Matrix Calculation (Recursive)
* \{ */
-/**
- * Recursive part, calculates rest-position of entire tree of children.
- * \note Used when exiting edit-mode too.
- */
void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool use_recursion)
{
float vec[3];
@@ -2361,8 +2204,6 @@ void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool
}
}
-/* updates vectors and matrices on rest-position level, only needed
- * after editing armature itself, now only on reading file */
void BKE_armature_where_is(bArmature *arm)
{
Bone *bone;
@@ -2579,10 +2420,6 @@ static int rebuild_pose_bone(
return counter;
}
-/**
- * Clear pointers of object's pose
- * (needed in remap case, since we cannot always wait for a complete pose rebuild).
- */
void BKE_pose_clear_pointers(bPose *pose)
{
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
@@ -2604,7 +2441,6 @@ static bPoseChannel *pose_channel_find_bone(bPose *pose, Bone *bone)
return (bone != NULL) ? BKE_pose_channel_find_name(pose, bone->name) : NULL;
}
-/** Update the links for the B-Bone handles from Bone data. */
void BKE_pchan_rebuild_bbone_handles(bPose *pose, bPoseChannel *pchan)
{
pchan->bbone_prev = pose_channel_find_bone(pose, pchan->bone->bbone_prev);
@@ -2622,13 +2458,6 @@ void BKE_pose_channels_clear_with_null_bone(bPose *pose, const bool do_id_user)
}
}
-/**
- * Only after leave editmode, duplicating, validating older files, library syncing.
- *
- * \note pose->flag is set for it.
- *
- * \param bmain: May be NULL, only used to tag depsgraph as being dirty...
- */
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
{
Bone *bone;
@@ -2696,11 +2525,6 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
}
}
-/**
- * Ensures object's pose is rebuilt if needed.
- *
- * \param bmain: May be NULL, only used to tag depsgraph as being dirty...
- */
void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
{
BLI_assert(!ELEM(NULL, arm, ob));
@@ -2716,9 +2540,6 @@ void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_u
/** \name Pose Solver
* \{ */
-/**
- * Convert the loc/rot/size to \a r_chanmat (typically #bPoseChannel.chan_mat).
- */
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
{
float smat[3][3];
@@ -2742,8 +2563,6 @@ void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
}
}
-/* loc/rot/size to mat4 */
-/* used in constraint.c too */
void BKE_pchan_calc_mat(bPoseChannel *pchan)
{
/* this is just a wrapper around the copy of this function which calculates the matrix
@@ -2752,7 +2571,6 @@ void BKE_pchan_calc_mat(bPoseChannel *pchan)
BKE_pchan_to_mat4(pchan, pchan->chan_mat);
}
-/* calculate tail of posechannel */
void BKE_pose_where_is_bone_tail(bPoseChannel *pchan)
{
float vec[3];
@@ -2762,10 +2580,6 @@ void BKE_pose_where_is_bone_tail(bPoseChannel *pchan)
add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec);
}
-/* The main armature solver, does all constraints excluding IK */
-/* pchan is validated, as having bone and parent pointer
- * 'do_extra': when zero skips loc/size/rot, constraints and strip modifiers.
- */
void BKE_pose_where_is_bone(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -2830,8 +2644,6 @@ void BKE_pose_where_is_bone(struct Depsgraph *depsgraph,
BKE_pose_where_is_bone_tail(pchan);
}
-/* This only reads anim data from channels, and writes to channels */
-/* This is the only function adding poses */
void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
{
bArmature *arm;
diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c
index 5f721b49361..a8e74f6b4c3 100644
--- a/source/blender/blenkernel/intern/armature_deform.c
+++ b/source/blender/blenkernel/intern/armature_deform.c
@@ -121,7 +121,6 @@ static void b_bone_deform(const bPoseChannel *pchan,
&quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat);
}
-/* using vec with dist to bone b1 - b2 */
float distfactor_to_bone(
const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
{
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 35ae2d2dbef..05c318663e9 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -277,46 +277,59 @@ static void apply_curve_transform(
*r_radius = (radius + *r_radius) / 2;
}
+static float dist_to_sphere_shell(const float sphere_origin[3],
+ const float sphere_radius,
+ const float point[3])
+{
+ float vec[3];
+ sub_v3_v3v3(vec, sphere_origin, point);
+ return sphere_radius - len_v3(vec);
+}
+
/* This function positions the tail of the bone so that it preserves the length of it.
* The length of the bone can be seen as a sphere radius.
*/
static int position_tail_on_spline(bSplineIKConstraint *ik_data,
const float head_pos[3],
const float sphere_radius,
- const int prev_seg_idx,
+ int prev_seg_idx,
float r_tail_pos[3],
float *r_new_curve_pos,
float *r_radius)
{
/* This is using the tessellated curve data.
* So we are working with piece-wise linear curve segments.
- * The same method is use in #BKE_where_on_path to get curve location data. */
+ * The same method is used in #BKE_where_on_path to get curve location data. */
const CurveCache *cache = ik_data->tar->runtime.curve_cache;
- const BevList *bl = cache->bev.first;
- BevPoint *bp = bl->bevpoints;
- const float spline_len = BKE_anim_path_get_length(cache);
const float *seg_accum_len = cache->anim_path_accum_length;
int max_seg_idx = BKE_anim_path_get_array_size(cache) - 1;
- /* Convert our initial intersection point guess to a point index.
- * If the curve was a straight line, then pointEnd would be the correct location.
+ /* Make an initial guess of where our intersection point will be.
+ * If the curve was a straight line, then the faction passed in r_new_curve_pos
+ * would be the correct location.
* So make it our first initial guess.
*/
+ const float spline_len = BKE_anim_path_get_length(cache);
const float guessed_len = *r_new_curve_pos * spline_len;
BLI_assert(prev_seg_idx >= 0);
-
int cur_seg_idx = prev_seg_idx;
while (cur_seg_idx < max_seg_idx && guessed_len > seg_accum_len[cur_seg_idx]) {
cur_seg_idx++;
}
+ /* Convert the segment to bev points.
+ * For example, the segment with index 0 will have bev points 0 and 1.
+ */
int bp_idx = cur_seg_idx + 1;
- bp = bp + bp_idx;
+ const BevList *bl = cache->bev.first;
bool is_cyclic = bl->poly >= 0;
- BevPoint *prev_bp = bp - 1;
+ BevPoint *bp = bl->bevpoints;
+ BevPoint *prev_bp;
+ bp = bp + bp_idx;
+ prev_bp = bp - 1;
/* Go to the next tessellated curve point until we cross to outside of the sphere. */
while (len_v3v3(head_pos, bp->vec) < sphere_radius) {
@@ -337,35 +350,53 @@ static int position_tail_on_spline(bSplineIKConstraint *ik_data,
bp_idx++;
}
- float isect_1[3], isect_2[3];
-
- /* Calculate the intersection point. */
- int ret = isect_line_sphere_v3(prev_bp->vec, bp->vec, head_pos, sphere_radius, isect_1, isect_2);
+ /* Calculate the intersection point using the secant root finding method */
+ float x0 = 0.0f, x1 = 1.0f, x2 = 0.5f;
+ float x0_point[3], x1_point[3], start_p[3];
+ float epsilon = max_fff(1.0f, len_v3(head_pos), len_v3(bp->vec)) * FLT_EPSILON;
- if (ret > 0) {
- /* Because of how `isect_line_sphere_v3` works, we know that `isect_1` contains the
- * intersection point we want. And it will always intersect as we go from inside to outside
- * of the sphere.
+ if (prev_seg_idx == bp_idx - 1) {
+ /* The intersection lies inside the same segment as the last point.
+ * Set the last point to be the start search point so we minimize the risks of going backwards
+ * on the curve.
*/
- copy_v3_v3(r_tail_pos, isect_1);
+ copy_v3_v3(start_p, head_pos);
}
else {
- /* Couldn't find an intersection point. This means that the floating point
- * values are too small and thus the intersection check fails.
- * So assume that the distance is so small that tail_pos == head_pos.
- */
- copy_v3_v3(r_tail_pos, head_pos);
+ copy_v3_v3(start_p, prev_bp->vec);
}
- cur_seg_idx = bp_idx - 2;
+ for (int i = 0; i < 10; i++) {
+ interp_v3_v3v3(x0_point, start_p, bp->vec, x0);
+ interp_v3_v3v3(x1_point, start_p, bp->vec, x1);
+
+ float f_x0 = dist_to_sphere_shell(head_pos, sphere_radius, x0_point);
+ float f_x1 = dist_to_sphere_shell(head_pos, sphere_radius, x1_point);
+
+ if (fabsf(f_x1) <= epsilon || f_x0 == f_x1) {
+ break;
+ }
+
+ x2 = x1 - f_x1 * (x1 - x0) / (f_x1 - f_x0);
+ x0 = x1;
+ x1 = x2;
+ }
+ /* Found the bone tail position! */
+ copy_v3_v3(r_tail_pos, x1_point);
+
+ /* Because our intersection point lies inside the current segment,
+ * Convert our bevpoint index back to the previous segment index (-2 instead of -1).
+ * This is because our actual location is prev_seg_len + isect_seg_len.
+ */
+ prev_seg_idx = bp_idx - 2;
float prev_seg_len = 0;
- if (cur_seg_idx < 0) {
- cur_seg_idx = 0;
+ if (prev_seg_idx < 0) {
+ prev_seg_idx = 0;
prev_seg_len = 0;
}
else {
- prev_seg_len = seg_accum_len[cur_seg_idx];
+ prev_seg_len = seg_accum_len[prev_seg_idx];
}
/* Convert the point back into the 0-1 interpolation range. */
@@ -380,7 +411,8 @@ static int position_tail_on_spline(bSplineIKConstraint *ik_data,
*r_radius = (1.0f - frac) * prev_bp->radius + frac * bp->radius;
}
- return cur_seg_idx;
+ /* Return the current segment. */
+ return bp_idx - 1;
}
/* Evaluate spline IK for a given bone. */
diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc
index 59e402b6680..e5509b09e20 100644
--- a/source/blender/blenkernel/intern/asset.cc
+++ b/source/blender/blenkernel/intern/asset.cc
@@ -39,7 +39,7 @@
using namespace blender;
-AssetMetaData *BKE_asset_metadata_create(void)
+AssetMetaData *BKE_asset_metadata_create()
{
AssetMetaData *asset_data = (AssetMetaData *)MEM_callocN(sizeof(*asset_data), __func__);
memcpy(asset_data, DNA_struct_default_get(AssetMetaData), sizeof(*asset_data));
@@ -78,9 +78,6 @@ AssetTag *BKE_asset_metadata_tag_add(AssetMetaData *asset_data, const char *name
return tag;
}
-/**
- * Make sure there is a tag with name \a name, create one if needed.
- */
struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(AssetMetaData *asset_data,
const char *name)
{
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index 03043f3b784..aec622bb71f 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -36,12 +36,7 @@ namespace blender::bke {
const CatalogFilePath AssetCatalogService::DEFAULT_CATALOG_FILENAME = "blender_assets.cats.txt";
-/* For now this is the only version of the catalog definition files that is supported.
- * Later versioning code may be added to handle older files. */
const int AssetCatalogDefinitionFile::SUPPORTED_VERSION = 1;
-/* String that's matched in the catalog definition file to know that the line is the version
- * declaration. It has to start with a space to ensure it won't match any hypothetical future field
- * that starts with "VERSION". */
const std::string AssetCatalogDefinitionFile::VERSION_MARKER = "VERSION ";
const std::string AssetCatalogDefinitionFile::HEADER =
@@ -98,6 +93,14 @@ bool AssetCatalogService::has_unsaved_changes() const
return catalog_collection_->has_unsaved_changes_;
}
+void AssetCatalogService::tag_all_catalogs_as_unsaved_changes()
+{
+ for (auto &catalog : catalog_collection_->catalogs_.values()) {
+ catalog->flags.has_unsaved_changes = true;
+ }
+ catalog_collection_->has_unsaved_changes_ = true;
+}
+
bool AssetCatalogService::is_empty() const
{
BLI_assert(catalog_collection_);
@@ -486,6 +489,24 @@ bool AssetCatalogService::write_to_disk_ex(const CatalogFilePath &blend_file_pat
return catalog_collection_->catalog_definition_file_->write_to_disk();
}
+void AssetCatalogService::prepare_to_merge_on_write()
+{
+ /* TODO(Sybren): expand to support multiple CDFs. */
+
+ if (!catalog_collection_->catalog_definition_file_) {
+ /* There is no CDF connected, so it's a no-op. */
+ return;
+ }
+
+ /* Remove any association with the CDF, so that a new location will be chosen
+ * when the blend file is saved. */
+ catalog_collection_->catalog_definition_file_.reset();
+
+ /* Mark all in-memory catalogs as "dirty", to force them to be kept around on
+ * the next "load-merge-write" cycle. */
+ tag_all_catalogs_as_unsaved_changes();
+}
+
CatalogFilePath AssetCatalogService::find_suitable_cdf_path_for_writing(
const CatalogFilePath &blend_file_path)
{
diff --git a/source/blender/blenkernel/intern/asset_catalog_path.cc b/source/blender/blenkernel/intern/asset_catalog_path.cc
index 20cac76b40b..d789150dba5 100644
--- a/source/blender/blenkernel/intern/asset_catalog_path.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_path.cc
@@ -74,8 +74,6 @@ StringRefNull AssetCatalogPath::name() const
return StringRefNull(this->path_.c_str() + last_sep_index + 1);
}
-/* In-class operators, because of the implicit `AssetCatalogPath(StringRef)` constructor.
- * Otherwise `string == string` could cast both sides to `AssetCatalogPath`. */
bool AssetCatalogPath::operator==(const AssetCatalogPath &other_path) const
{
return this->path_ == other_path.path_;
diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc
index 68e43852a21..74de9b93c25 100644
--- a/source/blender/blenkernel/intern/asset_library.cc
+++ b/source/blender/blenkernel/intern/asset_library.cc
@@ -71,7 +71,7 @@ bool BKE_asset_library_find_suitable_root_path_from_path(const char *input_path,
bool BKE_asset_library_find_suitable_root_path_from_main(const Main *bmain, char *r_library_path)
{
- return BKE_asset_library_find_suitable_root_path_from_path(bmain->name, r_library_path);
+ return BKE_asset_library_find_suitable_root_path_from_path(bmain->filepath, r_library_path);
}
blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service(
@@ -168,7 +168,7 @@ void AssetLibrary::on_blend_save_post(struct Main *main,
}
if (save_catalogs_when_file_is_saved) {
- this->catalog_service->write_to_disk(main->name);
+ this->catalog_service->write_to_disk(main->filepath);
}
}
diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc
index d202d6462cf..6b3f1fa3408 100644
--- a/source/blender/blenkernel/intern/asset_library_service.cc
+++ b/source/blender/blenkernel/intern/asset_library_service.cc
@@ -125,9 +125,6 @@ static void on_blendfile_load(struct Main * /*bMain*/,
AssetLibraryService::destroy();
}
-/**
- * Ensure the AssetLibraryService instance is destroyed before a new blend file is loaded.
- * This makes memory management simple, and ensures a fresh start for every blend file. */
void AssetLibraryService::app_handler_register()
{
/* The callback system doesn't own `on_load_callback_store_`. */
diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc
index ee910cab945..9fa6d100a53 100644
--- a/source/blender/blenkernel/intern/asset_library_service_test.cc
+++ b/source/blender/blenkernel/intern/asset_library_service_test.cc
@@ -97,7 +97,7 @@ TEST_F(AssetLibraryServiceTest, get_destroy)
AssetLibraryService::destroy();
AssetLibraryService::destroy();
- /* Note: there used to be a test for the opposite here, that after a call to
+ /* NOTE: there used to be a test for the opposite here, that after a call to
* AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
* cannot be reliably tested by just pointer comparison, though. */
}
@@ -113,7 +113,7 @@ TEST_F(AssetLibraryServiceTest, library_pointers)
EXPECT_EQ(curfile_lib, service->get_asset_library_current_file())
<< "Calling twice without destroying in between should return the same instance.";
- /* Note: there used to be a test for the opposite here, that after a call to
+ /* NOTE: there used to be a test for the opposite here, that after a call to
* AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
* cannot be reliably tested by just pointer comparison, though. */
}
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 3f2c1f13337..1a4265d936b 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -23,6 +23,7 @@
#include "BKE_geometry_set.hh"
#include "BKE_mesh.h"
#include "BKE_pointcloud.h"
+#include "BKE_type_conversions.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -36,8 +37,6 @@
#include "CLG_log.h"
-#include "NOD_type_conversions.hh"
-
#include "attribute_access_intern.hh"
static CLG_LogRef LOG = {"bke.attribute_access"};
@@ -50,7 +49,7 @@ using blender::bke::AttributeIDRef;
using blender::bke::OutputAttribute;
using blender::fn::GMutableSpan;
using blender::fn::GSpan;
-using blender::fn::GVMutableArrayImpl_For_GMutableSpan;
+using blender::fn::GVArrayImpl_For_GSpan;
namespace blender::bke {
@@ -183,10 +182,6 @@ static int attribute_domain_priority(const AttributeDomain domain)
}
}
-/**
- * Domains with a higher "information density" have a higher priority, in order
- * to choose a domain that will not lose data through domain conversion.
- */
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
{
int highest_priority = INT_MIN;
@@ -288,7 +283,7 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
char attribute_name_c[MAX_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
- &custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c);
+ &custom_data, data_type, alloctype, layer_data, domain_size, attribute_name_c);
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
@@ -400,7 +395,9 @@ WriteAttributeLookup BuiltinCustomDataLayerProvider::try_get_for_write(
}
if (data != new_data) {
- custom_data_access_.update_custom_data_pointers(component);
+ if (custom_data_access_.update_custom_data_pointers) {
+ custom_data_access_.update_custom_data_pointers(component);
+ }
data = new_data;
}
@@ -441,7 +438,9 @@ bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) co
const bool delete_success = CustomData_free_layer(
custom_data, stored_type_, domain_size, layer_index);
if (delete_success) {
- custom_data_access_.update_custom_data_pointers(component);
+ if (custom_data_access_.update_custom_data_pointers) {
+ custom_data_access_.update_custom_data_pointers(component);
+ }
}
return delete_success;
}
@@ -476,7 +475,9 @@ bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
*custom_data, stored_type_, domain_size, initializer);
}
if (success) {
- custom_data_access_.update_custom_data_pointers(component);
+ if (custom_data_access_.update_custom_data_pointers) {
+ custom_data_access_.update_custom_data_pointers(component);
+ }
}
return success;
}
@@ -644,7 +645,9 @@ WriteAttributeLookup NamedLegacyCustomDataProvider::try_get_for_write(
void *data_new = CustomData_duplicate_referenced_layer_named(
custom_data, stored_type_, layer.name, domain_size);
if (data_old != data_new) {
- custom_data_access_.update_custom_data_pointers(component);
+ if (custom_data_access_.update_custom_data_pointers) {
+ custom_data_access_.update_custom_data_pointers(component);
+ }
}
return {as_write_attribute_(layer.data, domain_size), domain_};
}
@@ -666,7 +669,9 @@ bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int domain_size = component.attribute_domain_size(domain_);
CustomData_free_layer(custom_data, stored_type_, domain_size, i);
- custom_data_access_.update_custom_data_pointers(component);
+ if (custom_data_access_.update_custom_data_pointers) {
+ custom_data_access_.update_custom_data_pointers(component);
+ }
return true;
}
}
@@ -734,7 +739,6 @@ CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes
std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id) const
{
- BLI_assert(size_ != 0);
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
@@ -745,11 +749,6 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
return {};
}
-/**
- * Return a virtual array for a stored attribute, or a single value virtual array with the default
- * value if the attribute doesn't exist. If no default value is provided, the default value for the
- * type will be used.
- */
GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
const void *default_value) const
@@ -766,15 +765,13 @@ GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
if (attribute->type() == *type) {
return GVArray::ForSpan(*attribute);
}
- const blender::nodes::DataTypeConversions &conversions =
- blender::nodes::get_implicit_type_conversions();
+ const blender::bke::DataTypeConversions &conversions =
+ blender::bke::get_implicit_type_conversions();
return conversions.try_convert(GVArray::ForSpan(*attribute), *type);
}
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id)
{
- /* If this assert hits, it most likely means that #reallocate was not called at some point. */
- BLI_assert(size_ != 0);
for (CustomDataLayer &layer : MutableSpan(data.layers, data.totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
@@ -821,6 +818,12 @@ void CustomDataAttributes::reallocate(const int size)
CustomData_realloc(&data, size);
}
+void CustomDataAttributes::clear()
+{
+ CustomData_free(&data, size_);
+ size_ = 0;
+}
+
bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback callback,
const AttributeDomain domain) const
{
@@ -1044,10 +1047,6 @@ Set<AttributeIDRef> GeometryComponent::attribute_ids() const
return attributes;
}
-/**
- * \return False if the callback explicitly returned false at any point, otherwise true,
- * meaning the callback made it all the way through.
- */
bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callback) const
{
using namespace blender::bke;
@@ -1112,8 +1111,8 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
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();
+ const blender::bke::DataTypeConversions &conversions =
+ blender::bke::get_implicit_type_conversions();
return conversions.try_convert(std::move(varray), to_type);
}
@@ -1178,8 +1177,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
if (attribute.varray.type() == *type) {
return attribute;
}
- const blender::nodes::DataTypeConversions &conversions =
- blender::nodes::get_implicit_type_conversions();
+ const blender::bke::DataTypeConversions &conversions =
+ blender::bke::get_implicit_type_conversions();
return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
}
@@ -1200,8 +1199,7 @@ blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeID
return blender::fn::GVArray::ForSingle(*type, domain_size, default_value);
}
-class GVMutableAttribute_For_OutputAttribute
- : public blender::fn::GVMutableArrayImpl_For_GMutableSpan {
+class GVMutableAttribute_For_OutputAttribute : public blender::fn::GVArrayImpl_For_GSpan {
public:
GeometryComponent *component;
std::string attribute_name;
@@ -1210,7 +1208,7 @@ class GVMutableAttribute_For_OutputAttribute
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
GeometryComponent &component,
const AttributeIDRef &attribute_id)
- : blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component)
+ : blender::fn::GVArrayImpl_For_GSpan(data), component(&component)
{
if (attribute_id.is_named()) {
this->attribute_name = attribute_id.name();
@@ -1300,7 +1298,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
const CPPType *cpp_type = custom_data_type_to_cpp_type(data_type);
BLI_assert(cpp_type != nullptr);
- const nodes::DataTypeConversions &conversions = nodes::get_implicit_type_conversions();
+ const DataTypeConversions &conversions = get_implicit_type_conversions();
if (component.attribute_is_builtin(attribute_id)) {
const StringRef attribute_name = attribute_id.name();
@@ -1409,23 +1407,27 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
namespace blender::bke {
-GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
- IndexMask UNUSED(mask),
- ResourceScope &UNUSED(scope)) const
+GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context,
+ IndexMask 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_);
- GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
- if (attribute) {
- return attribute;
- }
+ return this->get_varray_for_context(component, domain, mask);
}
return {};
}
+GVArray AttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask UNUSED(mask)) const
+{
+ const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
+ return component.attribute_try_get_for_read(name_, domain, data_type);
+}
+
std::string AttributeFieldInput::socket_inspection_name() const
{
std::stringstream ss;
@@ -1457,25 +1459,20 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
}
}
-GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const
+GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask mask) 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);
- 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 attribute;
- }
- /* Use the index as the fallback if no random ID attribute exists. */
- return fn::IndexFieldInput::get_index_varray(mask, scope);
+ const StringRef name = get_random_id_attribute_name(domain);
+ 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 attribute;
}
- return {};
+
+ /* Use the index as the fallback if no random ID attribute exists. */
+ return fn::IndexFieldInput::get_index_varray(mask);
}
std::string IDAttributeFieldInput::socket_inspection_name() const
@@ -1495,20 +1492,12 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
}
-GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
- IndexMask UNUSED(mask),
- ResourceScope &UNUSED(scope)) const
+GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask UNUSED(mask)) 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_);
- GVArray attribute = component.attribute_try_get_for_read(
- anonymous_id_.get(), domain, data_type);
- return attribute;
- }
- return {};
+ const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
+ return component.attribute_try_get_for_read(anonymous_id_.get(), domain, data_type);
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
@@ -1533,3 +1522,5 @@ bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
}
} // namespace blender::bke
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c
index 3aec646b024..ed2b4e4ab1b 100644
--- a/source/blender/blenkernel/intern/autoexec.c
+++ b/source/blender/blenkernel/intern/autoexec.c
@@ -36,10 +36,6 @@
#include "BKE_autoexec.h" /* own include */
-/**
- * \param path: The path to check against.
- * \return Success
- */
bool BKE_autoexec_match(const char *path)
{
bPathCompare *path_cmp;
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index fb65a9bec7e..b914b0cdf66 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -71,7 +71,6 @@ UserDef U;
/** \name Blender Free on Exit
* \{ */
-/* only to be called on exit blender */
void BKE_blender_free(void)
{
/* samples are in a global list..., also sets G_MAIN->sound->sample NULL */
@@ -272,10 +271,6 @@ static void userdef_free_addons(UserDef *userdef)
BLI_listbase_clear(&userdef->addons);
}
-/**
- * When loading a new userdef from file,
- * or when exiting Blender.
- */
void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
{
#define U BLI_STATIC_ASSERT(false, "Global 'U' not allowed, only use arguments passed in!")
@@ -310,10 +305,6 @@ void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
/** \name Blender Preferences (Application Templates)
* \{ */
-/**
- * Write U from userdef.
- * This function defines which settings a template will override for the user preferences.
- */
void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *userdef_b)
{
/* TODO:
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index f8b943d3479..211d7f693d4 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -38,6 +38,7 @@
#include "BKE_blender_copybuffer.h" /* own include */
#include "BKE_blendfile.h"
+#include "BKE_blendfile_link_append.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_layer.h"
@@ -57,25 +58,16 @@
/** \name Copy/Paste `.blend`, partial saves.
* \{ */
-/** Initialize a copy operation. */
void BKE_copybuffer_copy_begin(Main *bmain_src)
{
BKE_blendfile_write_partial_begin(bmain_src);
}
-/** 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);
}
-/**
- * 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_copy_end(Main *bmain_src, const char *filename, ReportList *reports)
{
const int write_flags = 0;
@@ -88,63 +80,60 @@ bool BKE_copybuffer_copy_end(Main *bmain_src, const char *filename, ReportList *
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.
- */
+/* Common helper for paste functions. */
+static void copybuffer_append(BlendfileLinkAppendContext *lapp_context,
+ Main *bmain,
+ ReportList *reports)
+{
+ /* Tag existing IDs in given `bmain_dst` as already existing. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+
+ BKE_blendfile_link(lapp_context, reports);
+
+ /* Mark all library linked objects to be updated. */
+ BKE_main_lib_objects_recalc_all(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* Append, rather than linking */
+ BKE_blendfile_append(lapp_context, reports);
+
+ /* This must be unset, otherwise these object won't link into other scenes from this blend
+ * file. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ /* Recreate dependency graph to include new objects. */
+ DEG_relations_tag_update(bmain);
+}
+
bool BKE_copybuffer_read(Main *bmain_dst,
const char *libname,
ReportList *reports,
const uint64_t id_types_mask)
{
- BlendFileReadReport bf_reports = {.reports = reports};
- BlendHandle *bh = BLO_blendhandle_from_file(libname, &bf_reports);
- if (bh == NULL) {
- /* Error reports will have been made by BLO_blendhandle_from_file(). */
- return false;
- }
- /* Here appending/linking starts. */
+ /* Note: No recursive append here (no `BLO_LIBLINK_APPEND_RECURSIVE`), external linked data
+ * should remain linked. */
const int flag = 0;
const int id_tag_extra = 0;
struct LibraryLink_Params liblink_params;
BLO_library_link_params_init(&liblink_params, bmain_dst, flag, id_tag_extra);
- Main *mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
- BLO_library_link_copypaste(mainl, bh, id_types_mask);
- BLO_library_link_end(mainl, &bh, &liblink_params);
- /* Mark all library linked objects to be updated. */
- BKE_main_lib_objects_recalc_all(bmain_dst);
- IMB_colormanagement_check_file_config(bmain_dst);
- /* Append, rather than linking. */
- Library *lib = BLI_findstring(&bmain_dst->libraries, libname, offsetof(Library, filepath_abs));
- BKE_library_make_local(bmain_dst, lib, NULL, true, false);
- /* Important we unset, otherwise these object won't
- * link into other scenes from this blend file.
- */
- BKE_main_id_tag_all(bmain_dst, LIB_TAG_PRE_EXISTING, false);
- BLO_blendhandle_close(bh);
+
+ BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(
+ &liblink_params);
+ BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL);
+
+ const int num_pasted = BKE_blendfile_link_append_context_item_idtypes_from_library_add(
+ lapp_context, reports, id_types_mask, 0);
+ if (num_pasted == BLENDFILE_LINK_APPEND_INVALID) {
+ BKE_blendfile_link_append_context_free(lapp_context);
+ return false;
+ }
+
+ copybuffer_append(lapp_context, bmain_dst, reports);
+
+ BKE_blendfile_link_append_context_free(lapp_context);
return true;
}
-/**
- * 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 int flag,
@@ -155,59 +144,31 @@ int BKE_copybuffer_paste(bContext *C,
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* may be NULL. */
- Main *mainl = NULL;
- Library *lib;
- BlendHandle *bh;
const int id_tag_extra = 0;
- BlendFileReadReport bf_reports = {.reports = reports};
- bh = BLO_blendhandle_from_file(libname, &bf_reports);
-
- if (bh == NULL) {
- /* error reports will have been made by BLO_blendhandle_from_file() */
- return 0;
- }
-
- BKE_view_layer_base_deselect_all(view_layer);
-
- /* tag everything, all untagged data can be made local
- * its also generally useful to know what is new
- *
- * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+ /* Note: No recursive append here, external linked data should remain linked. */
+ BLI_assert((flag & BLO_LIBLINK_APPEND_RECURSIVE) == 0);
- /* here appending/linking starts */
struct LibraryLink_Params liblink_params;
BLO_library_link_params_init_with_context(
&liblink_params, bmain, flag, id_tag_extra, scene, view_layer, v3d);
- mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
-
- const int num_pasted = BLO_library_link_copypaste(mainl, bh, id_types_mask);
-
- BLO_library_link_end(mainl, &bh, &liblink_params);
-
- /* mark all library linked objects to be updated */
- BKE_main_lib_objects_recalc_all(bmain);
- IMB_colormanagement_check_file_config(bmain);
- /* append, rather than linking */
- lib = BLI_findstring(&bmain->libraries, libname, offsetof(Library, filepath_abs));
- BKE_library_make_local(bmain, lib, NULL, true, false);
+ BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(
+ &liblink_params);
+ BKE_blendfile_link_append_context_library_add(lapp_context, libname, NULL);
- /* important we unset, otherwise these object won't
- * link into other scenes from this blend file */
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
-
- /* recreate dependency graph to include new objects */
- DEG_relations_tag_update(bmain);
+ const int num_pasted = BKE_blendfile_link_append_context_item_idtypes_from_library_add(
+ lapp_context, reports, id_types_mask, 0);
+ if (num_pasted == BLENDFILE_LINK_APPEND_INVALID) {
+ BKE_blendfile_link_append_context_free(lapp_context);
+ return 0;
+ }
- /* Tag update the scene to flush base collection settings, since the new object is added to a
- * new (active) collection, not its original collection, thus need recalculation. */
- DEG_id_tag_update(&scene->id, 0);
+ BKE_view_layer_base_deselect_all(view_layer);
- BLO_blendhandle_close(bh);
- /* remove library... */
+ copybuffer_append(lapp_context, bmain, reports);
+ BKE_blendfile_link_append_context_free(lapp_context);
return num_pasted;
}
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index 411ece21599..6c443a94def 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -68,7 +68,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu,
bContext *C)
{
Main *bmain = CTX_data_main(C);
- char mainstr[sizeof(bmain->name)];
+ char mainstr[sizeof(bmain->filepath)];
int success = 0, fileflags;
BLI_strncpy(mainstr, BKE_main_blendfile_path(bmain), sizeof(mainstr)); /* temporal store */
@@ -101,7 +101,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu,
/* Restore, bmain has been re-allocated. */
bmain = CTX_data_main(C);
- BLI_strncpy(bmain->name, mainstr, sizeof(bmain->name));
+ STRNCPY(bmain->filepath, mainstr);
G.fileflags = fileflags;
if (success) {
diff --git a/source/blender/blenkernel/intern/blender_user_menu.c b/source/blender/blenkernel/intern/blender_user_menu.c
index edd89357fd5..b186d376e52 100644
--- a/source/blender/blenkernel/intern/blender_user_menu.c
+++ b/source/blender/blenkernel/intern/blender_user_menu.c
@@ -110,3 +110,5 @@ void BKE_blender_user_menu_item_free_list(ListBase *lb)
}
BLI_listbase_clear(lb);
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index fc535fc2ad1..6ae19c8036f 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -78,7 +78,9 @@
/** \name High Level `.blend` file read/write.
* \{ */
-static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src)
+static bool foreach_path_clean_cb(BPathForeachPathData *UNUSED(bpath_data),
+ char *path_dst,
+ const char *path_src)
{
strcpy(path_dst, path_src);
BLI_path_slash_native(path_dst);
@@ -86,13 +88,16 @@ static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const c
}
/* make sure path names are correct for OS */
-static void clean_paths(Main *main)
+static void clean_paths(Main *bmain)
{
- Scene *scene;
-
- BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
-
- for (scene = main->scenes.first; scene; scene = scene->id.next) {
+ BKE_bpath_foreach_path_main(&(BPathForeachPathData){
+ .bmain = bmain,
+ .callback_function = foreach_path_clean_cb,
+ .flag = BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE,
+ .user_data = NULL,
+ });
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
BLI_path_slash_native(scene->r.pic);
}
}
@@ -355,12 +360,12 @@ static void setup_app_data(bContext *C,
/* startup.blend or recovered startup */
if (is_startup) {
- bmain->name[0] = '\0';
+ bmain->filepath[0] = '\0';
}
else if (recover) {
- /* In case of autosave or quit.blend, use original filename instead. */
+ /* In case of autosave or quit.blend, use original filepath instead. */
bmain->recovered = 1;
- BLI_strncpy(bmain->name, bfd->filename, FILE_MAX);
+ STRNCPY(bmain->filepath, bfd->filepath);
}
/* baseflags, groups, make depsgraph, etc */
@@ -447,14 +452,6 @@ static void handle_subversion_warning(Main *main, BlendFileReadReport *reports)
}
}
-/**
- * Shared setup function that makes the data from `bfd` into the current blend file,
- * replacing the contents of #G.main.
- * This uses the bfd #BKE_blendfile_read and similarly named functions.
- *
- * This is done in a separate step so the caller may perform actions after it is known the file
- * loaded correctly but before the file replaces the existing blend file contents.
- */
void BKE_blendfile_read_setup_ex(bContext *C,
BlendFileData *bfd,
const struct BlendFileReadParams *params,
@@ -480,9 +477,6 @@ void BKE_blendfile_read_setup(bContext *C,
BKE_blendfile_read_setup_ex(C, bfd, params, reports, false, NULL);
}
-/**
- * \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
- */
struct BlendFileData *BKE_blendfile_read(const char *filepath,
const struct BlendFileReadParams *params,
BlendFileReadReport *reports)
@@ -502,9 +496,6 @@ struct BlendFileData *BKE_blendfile_read(const char *filepath,
return bfd;
}
-/**
- * \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
- */
struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
@@ -520,10 +511,6 @@ struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf,
return bfd;
}
-/**
- * \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
- * \note `memfile` is the undo buffer.
- */
struct BlendFileData *BKE_blendfile_read_from_memfile(Main *bmain,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
@@ -546,10 +533,6 @@ struct BlendFileData *BKE_blendfile_read_from_memfile(Main *bmain,
return bfd;
}
-/**
- * Utility to make a file 'empty' used for startup to optionally give an empty file.
- * Handy for tests.
- */
void BKE_blendfile_read_make_empty(bContext *C)
{
Main *bmain = CTX_data_main(C);
@@ -568,7 +551,6 @@ void BKE_blendfile_read_make_empty(bContext *C)
FOREACH_MAIN_LISTBASE_END;
}
-/* only read the userdef from a .blend */
UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports)
{
BlendFileData *bfd;
@@ -671,10 +653,6 @@ UserDef *BKE_blendfile_userdef_from_defaults(void)
return userdef;
}
-/**
- * Only write the userdef in a .blend
- * \return success
- */
bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
{
Main *mainb = MEM_callocN(sizeof(Main), "empty main");
@@ -695,13 +673,6 @@ bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
return ok;
}
-/**
- * Only write the userdef in a .blend, merging with the existing blend file.
- * \return success
- *
- * \note In the future we should re-evaluate user preferences,
- * possibly splitting out system/hardware specific prefs.
- */
bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *reports)
{
/* if it fails, overwrite is OK. */
@@ -872,10 +843,6 @@ static void blendfile_write_partial_cb(void *UNUSED(handle), Main *UNUSED(bmain)
}
}
-/**
- * \param remap_mode: Choose the kind of path remapping or none #eBLO_WritePathRemap.
- * \return Success.
- */
bool BKE_blendfile_write_partial(Main *bmain_src,
const char *filepath,
const int write_flags,
@@ -887,11 +854,12 @@ bool BKE_blendfile_write_partial(Main *bmain_src,
int a, retval;
void *path_list_backup = NULL;
- const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
+ const eBPathForeachFlag path_list_flag = (BKE_BPATH_FOREACH_PATH_SKIP_LINKED |
+ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE);
/* This is needed to be able to load that file as a real one later
- * (otherwise main->name will not be set at read time). */
- BLI_strncpy(bmain_dst->name, bmain_src->name, sizeof(bmain_dst->name));
+ * (otherwise `main->filepath` will not be set at read time). */
+ STRNCPY(bmain_dst->filepath, bmain_src->filepath);
BLO_main_expander(blendfile_write_partial_cb);
BLO_expand_main(NULL, bmain_src);
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
new file mode 100644
index 00000000000..c265a6e2b7d
--- /dev/null
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -0,0 +1,1615 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * High level `.blend` file link/append code,
+ * including linking/appending several IDs from different libraries, handling instantiations of
+ * collections/objects/object-data in current scene.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "CLG_log.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_collection_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_idtype.h"
+#include "BKE_key.h"
+#include "BKE_layer.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "BKE_rigidbody.h"
+#include "BKE_scene.h"
+
+#include "BKE_blendfile_link_append.h"
+
+#include "BLO_readfile.h"
+#include "BLO_writefile.h"
+
+static CLG_LogRef LOG = {"bke.blendfile_link_append"};
+
+/* -------------------------------------------------------------------- */
+/** \name Link/append context implementation and public management API.
+ * \{ */
+
+typedef struct BlendfileLinkAppendContextItem {
+ /** Name of the ID (without the heading two-chars IDcode). */
+ char *name;
+ /** All libs (from BlendfileLinkAppendContext.libraries) to try to load this ID from. */
+ BLI_bitmap *libraries;
+ /** ID type. */
+ short idcode;
+
+ /** Type of action to perform on this item, and general status tag information.
+ * NOTE: Mostly used by append post-linking processing. */
+ char action;
+ char tag;
+
+ /** Newly linked ID (NULL until it has been successfully linked). */
+ ID *new_id;
+ /** Library ID from which the #new_id has been linked (NULL until it has been successfully
+ * linked). */
+ Library *source_library;
+ /** Opaque user data pointer. */
+ void *userdata;
+} BlendfileLinkAppendContextItem;
+
+/* A blendfile library entry in the `libraries` list of #BlendfileLinkAppendContext. */
+typedef struct BlendfileLinkAppendContextLibrary {
+ char *path; /* Absolute .blend file path. */
+ BlendHandle *blo_handle; /* Blend file handle, if any. */
+ bool blo_handle_is_owned; /* Whether the blend file handle is owned, or borrowed. */
+ /* The blendfile report associated with the `blo_handle`, if owned. */
+ BlendFileReadReport bf_reports;
+} BlendfileLinkAppendContextLibrary;
+
+typedef struct BlendfileLinkAppendContext {
+ /** List of library paths to search IDs in. */
+ LinkNodePair libraries;
+ /** List of all ID to try to link from #libraries. */
+ LinkNodePair items;
+ int num_libraries;
+ int num_items;
+ /** Linking/appending parameters. Including `bmain`, `scene`, `viewlayer` and `view3d`. */
+ LibraryLink_Params *params;
+
+ /** Allows to easily find an existing items from an ID pointer. */
+ GHash *new_id_to_item;
+
+ /** Runtime info used by append code to manage re-use of already appended matching IDs. */
+ GHash *library_weak_reference_mapping;
+
+ /** Embedded blendfile and its size, if needed. */
+ const void *blendfile_mem;
+ size_t blendfile_memsize;
+
+ /** Internal 'private' data */
+ MemArena *memarena;
+} BlendfileLinkAppendContext;
+
+typedef struct BlendfileLinkAppendContextCallBack {
+ BlendfileLinkAppendContext *lapp_context;
+ BlendfileLinkAppendContextItem *item;
+ ReportList *reports;
+
+} BlendfileLinkAppendContextCallBack;
+
+/* Actions to apply to an item (i.e. linked ID). */
+enum {
+ LINK_APPEND_ACT_UNSET = 0,
+ LINK_APPEND_ACT_KEEP_LINKED,
+ LINK_APPEND_ACT_REUSE_LOCAL,
+ LINK_APPEND_ACT_MAKE_LOCAL,
+ LINK_APPEND_ACT_COPY_LOCAL,
+};
+
+/* Various status info about an item (i.e. linked ID). */
+enum {
+ /* An indirectly linked ID. */
+ LINK_APPEND_TAG_INDIRECT = 1 << 0,
+};
+
+static BlendHandle *link_append_context_library_blohandle_ensure(
+ BlendfileLinkAppendContext *lapp_context,
+ BlendfileLinkAppendContextLibrary *lib_context,
+ ReportList *reports)
+{
+ if (reports != NULL) {
+ lib_context->bf_reports.reports = reports;
+ }
+
+ char *libname = lib_context->path;
+ BlendHandle *blo_handle = lib_context->blo_handle;
+ if (blo_handle == NULL) {
+ if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) {
+ blo_handle = BLO_blendhandle_from_memory(lapp_context->blendfile_mem,
+ (int)lapp_context->blendfile_memsize,
+ &lib_context->bf_reports);
+ }
+ else {
+ blo_handle = BLO_blendhandle_from_file(libname, &lib_context->bf_reports);
+ }
+ lib_context->blo_handle = blo_handle;
+ lib_context->blo_handle_is_owned = true;
+ }
+
+ return blo_handle;
+}
+
+static void link_append_context_library_blohandle_release(
+ BlendfileLinkAppendContext *UNUSED(lapp_context),
+ BlendfileLinkAppendContextLibrary *lib_context)
+{
+ if (lib_context->blo_handle_is_owned && lib_context->blo_handle != NULL) {
+ BLO_blendhandle_close(lib_context->blo_handle);
+ lib_context->blo_handle = NULL;
+ }
+}
+
+BlendfileLinkAppendContext *BKE_blendfile_link_append_context_new(LibraryLink_Params *params)
+{
+ MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ BlendfileLinkAppendContext *lapp_context = BLI_memarena_calloc(ma, sizeof(*lapp_context));
+
+ lapp_context->params = params;
+ lapp_context->memarena = ma;
+
+ return lapp_context;
+}
+
+void BKE_blendfile_link_append_context_free(BlendfileLinkAppendContext *lapp_context)
+{
+ if (lapp_context->new_id_to_item != NULL) {
+ BLI_ghash_free(lapp_context->new_id_to_item, NULL, NULL);
+ }
+
+ for (LinkNode *liblink = lapp_context->libraries.list; liblink != NULL;
+ liblink = liblink->next) {
+ BlendfileLinkAppendContextLibrary *lib_context = liblink->link;
+ link_append_context_library_blohandle_release(lapp_context, lib_context);
+ }
+
+ BLI_assert(lapp_context->library_weak_reference_mapping == NULL);
+
+ BLI_memarena_free(lapp_context->memarena);
+}
+
+void BKE_blendfile_link_append_context_flag_set(BlendfileLinkAppendContext *lapp_context,
+ const int flag,
+ const bool do_set)
+{
+ if (do_set) {
+ lapp_context->params->flag |= flag;
+ }
+ else {
+ lapp_context->params->flag &= ~flag;
+ }
+}
+
+void BKE_blendfile_link_append_context_embedded_blendfile_set(
+ BlendfileLinkAppendContext *lapp_context, const void *blendfile_mem, int blendfile_memsize)
+{
+ BLI_assert_msg(lapp_context->blendfile_mem == NULL,
+ "Please explicitly clear reference to an embedded blender memfile before "
+ "setting a new one");
+ lapp_context->blendfile_mem = blendfile_mem;
+ lapp_context->blendfile_memsize = (size_t)blendfile_memsize;
+}
+
+void BKE_blendfile_link_append_context_embedded_blendfile_clear(
+ BlendfileLinkAppendContext *lapp_context)
+{
+ lapp_context->blendfile_mem = NULL;
+ lapp_context->blendfile_memsize = 0;
+}
+
+void BKE_blendfile_link_append_context_library_add(BlendfileLinkAppendContext *lapp_context,
+ const char *libname,
+ BlendHandle *blo_handle)
+{
+ BLI_assert(lapp_context->items.list == NULL);
+
+ BlendfileLinkAppendContextLibrary *lib_context = BLI_memarena_calloc(lapp_context->memarena,
+ sizeof(*lib_context));
+
+ size_t len = strlen(libname) + 1;
+ char *libpath = BLI_memarena_alloc(lapp_context->memarena, len);
+ BLI_strncpy(libpath, libname, len);
+
+ lib_context->path = libpath;
+ lib_context->blo_handle = blo_handle;
+ lib_context->blo_handle_is_owned = (blo_handle == NULL);
+
+ BLI_linklist_append_arena(&lapp_context->libraries, lib_context, lapp_context->memarena);
+ lapp_context->num_libraries++;
+}
+
+BlendfileLinkAppendContextItem *BKE_blendfile_link_append_context_item_add(
+ BlendfileLinkAppendContext *lapp_context,
+ const char *idname,
+ const short idcode,
+ void *userdata)
+{
+ BlendfileLinkAppendContextItem *item = BLI_memarena_calloc(lapp_context->memarena,
+ sizeof(*item));
+ size_t len = strlen(idname) + 1;
+
+ item->name = BLI_memarena_alloc(lapp_context->memarena, len);
+ BLI_strncpy(item->name, idname, len);
+ item->idcode = idcode;
+ item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_context->memarena, lapp_context->num_libraries);
+
+ item->new_id = NULL;
+ item->action = LINK_APPEND_ACT_UNSET;
+ item->userdata = userdata;
+
+ BLI_linklist_append_arena(&lapp_context->items, item, lapp_context->memarena);
+ lapp_context->num_items++;
+
+ return item;
+}
+
+int BKE_blendfile_link_append_context_item_idtypes_from_library_add(
+ BlendfileLinkAppendContext *lapp_context,
+ ReportList *reports,
+ const uint64_t id_types_filter,
+ const int library_index)
+{
+ int id_num = 0;
+ int id_code_iter = 0;
+ short id_code;
+
+ LinkNode *lib_context_link = BLI_linklist_find(lapp_context->libraries.list, library_index);
+ BlendfileLinkAppendContextLibrary *lib_context = lib_context_link->link;
+ BlendHandle *blo_handle = link_append_context_library_blohandle_ensure(
+ lapp_context, lib_context, reports);
+
+ if (blo_handle == NULL) {
+ return BLENDFILE_LINK_APPEND_INVALID;
+ }
+
+ const bool use_assets_only = (lapp_context->params->flag & FILE_ASSETS_ONLY) != 0;
+
+ while ((id_code = BKE_idtype_idcode_iter_step(&id_code_iter))) {
+ if (!BKE_idtype_idcode_is_linkable(id_code) ||
+ (id_types_filter != 0 &&
+ (BKE_idtype_idcode_to_idfilter(id_code) & id_types_filter) == 0)) {
+ continue;
+ }
+
+ int id_names_num;
+ LinkNode *id_names_list = BLO_blendhandle_get_datablock_names(
+ blo_handle, id_code, use_assets_only, &id_names_num);
+
+ for (LinkNode *link_next = NULL; id_names_list != NULL; id_names_list = link_next) {
+ link_next = id_names_list->next;
+
+ char *id_name = id_names_list->link;
+ BlendfileLinkAppendContextItem *item = BKE_blendfile_link_append_context_item_add(
+ lapp_context, id_name, id_code, NULL);
+ BKE_blendfile_link_append_context_item_library_index_enable(
+ lapp_context, item, library_index);
+
+ MEM_freeN(id_name);
+ MEM_freeN(id_names_list);
+ }
+
+ id_num += id_names_num;
+ }
+
+ return id_num;
+}
+
+void BKE_blendfile_link_append_context_item_library_index_enable(
+ BlendfileLinkAppendContext *UNUSED(lapp_context),
+ BlendfileLinkAppendContextItem *item,
+ const int library_index)
+{
+ BLI_BITMAP_ENABLE(item->libraries, library_index);
+}
+
+bool BKE_blendfile_link_append_context_is_empty(struct BlendfileLinkAppendContext *lapp_context)
+{
+ return lapp_context->num_items == 0;
+}
+
+void *BKE_blendfile_link_append_context_item_userdata_get(
+ BlendfileLinkAppendContext *UNUSED(lapp_context), BlendfileLinkAppendContextItem *item)
+{
+ return item->userdata;
+}
+
+ID *BKE_blendfile_link_append_context_item_newid_get(
+ BlendfileLinkAppendContext *UNUSED(lapp_context), BlendfileLinkAppendContextItem *item)
+{
+ return item->new_id;
+}
+
+short BKE_blendfile_link_append_context_item_idcode_get(
+ struct BlendfileLinkAppendContext *UNUSED(lapp_context),
+ struct BlendfileLinkAppendContextItem *item)
+{
+ return item->idcode;
+}
+
+void BKE_blendfile_link_append_context_item_foreach(
+ struct BlendfileLinkAppendContext *lapp_context,
+ BKE_BlendfileLinkAppendContexteItemFunction callback_function,
+ const eBlendfileLinkAppendForeachItemFlag flag,
+ void *userdata)
+{
+ for (LinkNode *itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if ((flag & BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_DIRECT) == 0 &&
+ (item->tag & LINK_APPEND_TAG_INDIRECT) == 0) {
+ continue;
+ }
+ if ((flag & BKE_BLENDFILE_LINK_APPEND_FOREACH_ITEM_FLAG_DO_INDIRECT) == 0 &&
+ (item->tag & LINK_APPEND_TAG_INDIRECT) != 0) {
+ continue;
+ }
+
+ if (!callback_function(lapp_context, item, userdata)) {
+ break;
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Library link/append helper functions.
+ *
+ * \{ */
+
+/* Struct gathering all required data to handle instantiation of loose data-blocks. */
+typedef struct LooseDataInstantiateContext {
+ BlendfileLinkAppendContext *lapp_context;
+
+ /* The collection in which to add loose collections/objects. */
+ Collection *active_collection;
+} LooseDataInstantiateContext;
+
+static bool object_in_any_scene(Main *bmain, Object *ob)
+{
+ LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
+ if (BKE_scene_object_find(sce, ob)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool object_in_any_collection(Main *bmain, Object *ob)
+{
+ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+ if (BKE_collection_has_object(collection, ob)) {
+ return true;
+ }
+ }
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->master_collection != NULL &&
+ BKE_collection_has_object(scene->master_collection, ob)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static ID *loose_data_instantiate_process_check(LooseDataInstantiateContext *instantiate_context,
+ BlendfileLinkAppendContextItem *item)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ /* In linking case, we always want to handle instantiation. */
+ if (lapp_context->params->flag & FILE_LINK) {
+ return item->new_id;
+ }
+
+ /* We consider that if we either kept it linked, or re-used already local data, instantiation
+ * status of those should not be modified. */
+ if (!ELEM(item->action, LINK_APPEND_ACT_COPY_LOCAL, LINK_APPEND_ACT_MAKE_LOCAL)) {
+ return NULL;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ return NULL;
+ }
+
+ if (item->action == LINK_APPEND_ACT_COPY_LOCAL) {
+ BLI_assert(ID_IS_LINKED(id));
+ id = id->newid;
+ if (id == NULL) {
+ return NULL;
+ }
+
+ BLI_assert(!ID_IS_LINKED(id));
+ return id;
+ }
+
+ BLI_assert(!ID_IS_LINKED(id));
+ return id;
+}
+
+static void loose_data_instantiate_ensure_active_collection(
+ LooseDataInstantiateContext *instantiate_context)
+{
+
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = instantiate_context->lapp_context->params->bmain;
+ Scene *scene = instantiate_context->lapp_context->params->context.scene;
+ ViewLayer *view_layer = instantiate_context->lapp_context->params->context.view_layer;
+
+ /* Find or add collection as needed. */
+ if (instantiate_context->active_collection == NULL) {
+ if (lapp_context->params->flag & FILE_ACTIVE_COLLECTION) {
+ LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ instantiate_context->active_collection = lc->collection;
+ }
+ else {
+ if (lapp_context->params->flag & FILE_LINK) {
+ instantiate_context->active_collection = BKE_collection_add(
+ bmain, scene->master_collection, DATA_("Linked Data"));
+ }
+ else {
+ instantiate_context->active_collection = BKE_collection_add(
+ bmain, scene->master_collection, DATA_("Appended Data"));
+ }
+ }
+ }
+}
+
+static void loose_data_instantiate_object_base_instance_init(Main *bmain,
+ Collection *collection,
+ Object *ob,
+ ViewLayer *view_layer,
+ const View3D *v3d,
+ const int flag,
+ bool set_active)
+{
+ /* Auto-select and appending. */
+ if ((flag & FILE_AUTOSELECT) && ((flag & FILE_LINK) == 0)) {
+ /* While in general the object should not be manipulated,
+ * when the user requests the object to be selected, ensure it's visible and selectable. */
+ ob->visibility_flag &= ~(OB_HIDE_VIEWPORT | OB_HIDE_SELECT);
+ }
+
+ BKE_collection_object_add(bmain, collection, ob);
+
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (v3d != NULL) {
+ base->local_view_bits |= v3d->local_view_uuid;
+ }
+
+ if (flag & FILE_AUTOSELECT) {
+ /* All objects that use #FILE_AUTOSELECT must be selectable (unless linking data). */
+ BLI_assert((base->flag & BASE_SELECTABLE) || (flag & FILE_LINK));
+ if (base->flag & BASE_SELECTABLE) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+
+ if (set_active) {
+ view_layer->basact = base;
+ }
+
+ BKE_scene_object_base_flag_sync_from_base(base);
+}
+
+/* Tag obdata that actually need to be instantiated (those referenced by an object do not, since
+ * the object will be instantiated instead if needed. */
+static void loose_data_instantiate_obdata_preprocess(
+ LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ LinkNode *itemlink;
+
+ /* First pass on obdata to enable their instantiation by default, then do a second pass on
+ * objects to clear it for any obdata already in use. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL) {
+ continue;
+ }
+ const ID_Type idcode = GS(id->name);
+ if (!OB_DATA_SUPPORT_ID(idcode)) {
+ continue;
+ }
+
+ id->tag |= LIB_TAG_DOIT;
+ }
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL || GS(id->name) != ID_OB) {
+ continue;
+ }
+
+ Object *ob = (Object *)id;
+ Object *new_ob = (Object *)id->newid;
+ if (ob->data != NULL) {
+ ((ID *)(ob->data))->tag &= ~LIB_TAG_DOIT;
+ }
+ if (new_ob != NULL && new_ob->data != NULL) {
+ ((ID *)(new_ob->data))->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+}
+
+/* Test whether some ancestor collection is also tagged for instantiation (return true) or not
+ * (return false). */
+static bool loose_data_instantiate_collection_parents_check_recursive(Collection *collection)
+{
+ for (CollectionParent *parent_collection = collection->parents.first; parent_collection != NULL;
+ parent_collection = parent_collection->next) {
+ if ((parent_collection->collection->id.tag & LIB_TAG_DOIT) != 0) {
+ return true;
+ }
+ if (loose_data_instantiate_collection_parents_check_recursive(parent_collection->collection)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void loose_data_instantiate_collection_process(
+ LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+ Scene *scene = lapp_context->params->context.scene;
+ ViewLayer *view_layer = lapp_context->params->context.view_layer;
+ const View3D *v3d = lapp_context->params->context.v3d;
+
+ const bool do_append = (lapp_context->params->flag & FILE_LINK) == 0;
+ const bool do_instantiate_as_empty = (lapp_context->params->flag &
+ BLO_LIBLINK_COLLECTION_INSTANCE) != 0;
+
+ /* NOTE: For collections we only view_layer-instantiate duplicated collections that have
+ * non-instantiated objects in them.
+ * NOTE: Also avoid view-layer-instantiating of collections children of other instantiated
+ * collections. This is why we need two passes here. */
+ LinkNode *itemlink;
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_GR) {
+ continue;
+ }
+
+ /* Forced instantiation of indirectly appended collections is not wanted. Users can now
+ * easily instantiate collections (and their objects) as needed by themselves. See T67032. */
+ /* We need to check that objects in that collections are already instantiated in a scene.
+ * Otherwise, it's better to add the collection to the scene's active collection, than to
+ * instantiate its objects in active scene's collection directly. See T61141.
+ *
+ * NOTE: We only check object directly into that collection, not recursively into its
+ * children.
+ */
+ Collection *collection = (Collection *)id;
+ /* Always consider adding collections directly selected by the user. */
+ bool do_add_collection = (item->tag & LINK_APPEND_TAG_INDIRECT) == 0;
+ /* In linking case, do not enforce instantiating non-directly linked collections/objects.
+ * This avoids cluttering the ViewLayers, user can instantiate themselves specific collections
+ * or objects easily from the Outliner if needed. */
+ if (!do_add_collection && do_append) {
+ 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) {
+ collection->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+
+ /* Second loop to actually instantiate collections tagged as such in first loop, unless some of
+ * their ancestor is also instantiated in case this is not an empty-instantiation. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_GR) {
+ continue;
+ }
+
+ Collection *collection = (Collection *)id;
+ bool do_add_collection = (id->tag & LIB_TAG_DOIT) != 0;
+
+ /* When instantiated into view-layer, do not add collections if one of their parents is also
+ * instantiated. In case of empty-instantiation though, instantiation of all user-selected
+ * collections is the desired behavior. */
+ if (!do_add_collection ||
+ (!do_instantiate_as_empty &&
+ loose_data_instantiate_collection_parents_check_recursive(collection))) {
+ continue;
+ }
+
+ loose_data_instantiate_ensure_active_collection(instantiate_context);
+ Collection *active_collection = instantiate_context->active_collection;
+
+ /* In case user requested instantiation of collections as empties, do so for the one they
+ * explicitly selected (originally directly linked IDs) only. */
+ if (do_instantiate_as_empty && (item->tag & LINK_APPEND_TAG_INDIRECT) == 0) {
+ /* BKE_object_add(...) messes with the selection. */
+ Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
+ ob->type = OB_EMPTY;
+ ob->empty_drawsize = U.collection_instance_empty_size;
+
+ const bool set_selected = (lapp_context->params->flag & FILE_AUTOSELECT) != 0;
+ /* TODO: why is it OK to make this active here but not in other situations?
+ * See other callers of #object_base_instance_init */
+ const bool set_active = set_selected;
+ loose_data_instantiate_object_base_instance_init(
+ bmain, active_collection, ob, view_layer, v3d, lapp_context->params->flag, set_active);
+
+ /* Assign the collection. */
+ ob->instance_collection = collection;
+ id_us_plus(&collection->id);
+ ob->transflag |= OB_DUPLICOLLECTION;
+ copy_v3_v3(ob->loc, scene->cursor.location);
+ }
+ else {
+ /* Add collection as child of active collection. */
+ BKE_collection_child_add(bmain, active_collection, collection);
+
+ if ((lapp_context->params->flag & FILE_AUTOSELECT) != 0) {
+ LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
+ Object *ob = coll_ob->ob;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void loose_data_instantiate_object_process(LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+ ViewLayer *view_layer = lapp_context->params->context.view_layer;
+ const View3D *v3d = lapp_context->params->context.v3d;
+
+ /* Do NOT make base active here! screws up GUI stuff,
+ * if you want it do it at the editor level. */
+ const bool object_set_active = false;
+
+ /* NOTE: For objects we only view_layer-instantiate duplicated objects that are not yet used
+ * anywhere. */
+ LinkNode *itemlink;
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_OB) {
+ continue;
+ }
+
+ Object *ob = (Object *)id;
+
+ if (object_in_any_collection(bmain, ob)) {
+ continue;
+ }
+
+ loose_data_instantiate_ensure_active_collection(instantiate_context);
+ Collection *active_collection = instantiate_context->active_collection;
+
+ CLAMP_MIN(ob->id.us, 0);
+ ob->mode = OB_MODE_OBJECT;
+
+ loose_data_instantiate_object_base_instance_init(bmain,
+ active_collection,
+ ob,
+ view_layer,
+ v3d,
+ lapp_context->params->flag,
+ object_set_active);
+ }
+}
+
+static void loose_data_instantiate_obdata_process(LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+ Scene *scene = lapp_context->params->context.scene;
+ ViewLayer *view_layer = lapp_context->params->context.view_layer;
+ const View3D *v3d = lapp_context->params->context.v3d;
+
+ /* Do NOT make base active here! screws up GUI stuff,
+ * if you want it do it at the editor level. */
+ const bool object_set_active = false;
+
+ LinkNode *itemlink;
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL) {
+ continue;
+ }
+ const ID_Type idcode = GS(id->name);
+ if (!OB_DATA_SUPPORT_ID(idcode)) {
+ continue;
+ }
+ if ((id->tag & LIB_TAG_DOIT) == 0) {
+ continue;
+ }
+
+ loose_data_instantiate_ensure_active_collection(instantiate_context);
+ Collection *active_collection = instantiate_context->active_collection;
+
+ const int type = BKE_object_obdata_to_type(id);
+ BLI_assert(type != -1);
+ Object *ob = BKE_object_add_only_object(bmain, type, id->name + 2);
+ ob->data = id;
+ id_us_plus(id);
+ BKE_object_materials_test(bmain, ob, ob->data);
+
+ loose_data_instantiate_object_base_instance_init(bmain,
+ active_collection,
+ ob,
+ view_layer,
+ v3d,
+ lapp_context->params->flag,
+ object_set_active);
+
+ copy_v3_v3(ob->loc, scene->cursor.location);
+
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+}
+
+static void loose_data_instantiate_object_rigidbody_postprocess(
+ LooseDataInstantiateContext *instantiate_context)
+{
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ Main *bmain = lapp_context->params->bmain;
+
+ LinkNode *itemlink;
+ /* Add rigid body objects and constraints to current RB world(s). */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = loose_data_instantiate_process_check(instantiate_context, item);
+ if (id == NULL || GS(id->name) != ID_OB) {
+ continue;
+ }
+ BKE_rigidbody_ensure_local_object(bmain, (Object *)id);
+ }
+}
+
+static void loose_data_instantiate(LooseDataInstantiateContext *instantiate_context)
+{
+ if (instantiate_context->lapp_context->params->context.scene == NULL) {
+ /* In some cases, like the asset drag&drop e.g., the caller code manages instantiation itself.
+ */
+ return;
+ }
+
+ BlendfileLinkAppendContext *lapp_context = instantiate_context->lapp_context;
+ const bool do_obdata = (lapp_context->params->flag & BLO_LIBLINK_OBDATA_INSTANCE) != 0;
+
+ /* First pass on obdata to enable their instantiation by default, then do a second pass on
+ * objects to clear it for any obdata already in use. */
+ if (do_obdata) {
+ loose_data_instantiate_obdata_preprocess(instantiate_context);
+ }
+
+ /* First do collections, then objects, then obdata. */
+ loose_data_instantiate_collection_process(instantiate_context);
+ loose_data_instantiate_object_process(instantiate_context);
+ if (do_obdata) {
+ loose_data_instantiate_obdata_process(instantiate_context);
+ }
+
+ loose_data_instantiate_object_rigidbody_postprocess(instantiate_context);
+}
+
+static void new_id_to_item_mapping_add(BlendfileLinkAppendContext *lapp_context,
+ ID *id,
+ BlendfileLinkAppendContextItem *item)
+{
+ BLI_ghash_insert(lapp_context->new_id_to_item, id, item);
+
+ /* This ensures that if a liboverride reference is also linked/used by some other appended
+ * data, it gets a local copy instead of being made directly local, so that the liboverride
+ * references remain valid (i.e. linked data). */
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ id->override_library->reference->tag |= LIB_TAG_PRE_EXISTING;
+ }
+}
+
+/* Generate a mapping between newly linked IDs and their items, and tag linked IDs used as
+ * liboverride references as already existing. */
+static void new_id_to_item_mapping_create(BlendfileLinkAppendContext *lapp_context)
+{
+ lapp_context->new_id_to_item = BLI_ghash_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ for (LinkNode *itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+
+ new_id_to_item_mapping_add(lapp_context, id, item);
+ }
+}
+
+static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_data)
+{
+ /* NOTE: It is important to also skip liboverride references here, as those should never be made
+ * local. */
+ if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK |
+ IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
+ return IDWALK_RET_NOP;
+ }
+
+ BlendfileLinkAppendContextCallBack *data = cb_data->user_data;
+ ID *id = *cb_data->id_pointer;
+
+ if (id == NULL) {
+ return IDWALK_RET_NOP;
+ }
+
+ if (!BKE_idtype_idcode_is_linkable(GS(id->name))) {
+ /* While we do not want to add non-linkable ID (shape keys...) to the list of linked items,
+ * unfortunately they can use fully linkable valid IDs too, like actions. Those need to be
+ * processed, so we need to recursively deal with them here. */
+ /* NOTE: Since we are by-passing checks in `BKE_library_foreach_ID_link` by manually calling it
+ * recursively, we need to take care of potential recursion cases ourselves (e.g.animdata of
+ * shape-key referencing the shape-key itself). */
+ if (id != cb_data->id_self) {
+ BKE_library_foreach_ID_link(
+ cb_data->bmain, id, foreach_libblock_link_append_callback, data, IDWALK_NOP);
+ }
+ return IDWALK_RET_NOP;
+ }
+
+ /* In linking case, we always consider all linked IDs, even indirectly ones, for instantiation,
+ * so we need to add them all to the items list.
+ *
+ * In appending case, when `do_recursive` is false, we only make local IDs from same
+ * library(-ies) as the initially directly linked ones.
+ *
+ * NOTE: Since in append case, linked IDs are also fully skipped during instantiation step (see
+ * #append_loose_data_instantiate_process_check), we can avoid adding them to the items list
+ * completely. */
+ const bool do_link = (data->lapp_context->params->flag & FILE_LINK) != 0;
+ const bool do_recursive = (data->lapp_context->params->flag & BLO_LIBLINK_APPEND_RECURSIVE) !=
+ 0 ||
+ do_link;
+ if (!do_recursive && cb_data->id_owner->lib != id->lib) {
+ return IDWALK_RET_NOP;
+ }
+
+ BlendfileLinkAppendContextItem *item = BLI_ghash_lookup(data->lapp_context->new_id_to_item, id);
+ if (item == NULL) {
+ item = BKE_blendfile_link_append_context_item_add(
+ data->lapp_context, id->name, GS(id->name), NULL);
+ item->new_id = id;
+ item->source_library = id->lib;
+ /* Since we did not have an item for that ID yet, we know user did not selected it explicitly,
+ * it was rather linked indirectly. This info is important for instantiation of collections. */
+ item->tag |= LINK_APPEND_TAG_INDIRECT;
+ /* In linking case we already know what we want to do with those items. */
+ if (do_link) {
+ item->action = LINK_APPEND_ACT_KEEP_LINKED;
+ }
+ new_id_to_item_mapping_add(data->lapp_context, id, item);
+ }
+
+ /* NOTE: currently there is no need to do anything else here, but in the future this would be
+ * the place to add specific per-usage decisions on how to append an ID. */
+
+ return IDWALK_RET_NOP;
+}
+
+/** \} */
+
+/** \name Library link/append code.
+ * \{ */
+
+void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
+{
+ if (lapp_context->num_items == 0) {
+ /* Nothing to append. */
+ return;
+ }
+
+ Main *bmain = lapp_context->params->bmain;
+
+ BLI_assert((lapp_context->params->flag & FILE_LINK) == 0);
+
+ const bool set_fakeuser = (lapp_context->params->flag & BLO_LIBLINK_APPEND_SET_FAKEUSER) != 0;
+ const bool do_reuse_local_id = (lapp_context->params->flag &
+ BLO_LIBLINK_APPEND_LOCAL_ID_REUSE) != 0;
+
+ const int make_local_common_flags = LIB_ID_MAKELOCAL_FULL_LIBRARY |
+ ((lapp_context->params->flag &
+ BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR) != 0 ?
+ LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR :
+ 0);
+
+ LinkNode *itemlink;
+
+ new_id_to_item_mapping_create(lapp_context);
+ lapp_context->library_weak_reference_mapping = BKE_main_library_weak_reference_create(bmain);
+
+ /* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect
+ * dependencies), this list will grow and we will process those IDs later, leading to a flatten
+ * recursive processing of all the linked dependencies. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(item->userdata == NULL);
+
+ ID *existing_local_id = BKE_idtype_idcode_append_is_reusable(GS(id->name)) ?
+ BKE_main_library_weak_reference_search_item(
+ lapp_context->library_weak_reference_mapping,
+ id->lib->filepath,
+ id->name) :
+ NULL;
+
+ if (item->action != LINK_APPEND_ACT_UNSET) {
+ /* Already set, pass. */
+ }
+ if (GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name);
+ item->action = LINK_APPEND_ACT_KEEP_LINKED;
+ }
+ else if (do_reuse_local_id && existing_local_id != NULL) {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name);
+ item->action = LINK_APPEND_ACT_REUSE_LOCAL;
+ item->userdata = existing_local_id;
+ }
+ else if (id->tag & LIB_TAG_PRE_EXISTING) {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' was already linked, need to copy it...", id->name);
+ item->action = LINK_APPEND_ACT_COPY_LOCAL;
+ }
+ else {
+ CLOG_INFO(&LOG, 3, "Appended ID '%s' will be made local...", id->name);
+ item->action = LINK_APPEND_ACT_MAKE_LOCAL;
+ }
+
+ /* Only check dependencies if we are not keeping linked data, nor re-using existing local data.
+ */
+ if (!ELEM(item->action, LINK_APPEND_ACT_KEEP_LINKED, LINK_APPEND_ACT_REUSE_LOCAL)) {
+ BlendfileLinkAppendContextCallBack cb_data = {
+ .lapp_context = lapp_context, .item = item, .reports = reports};
+ BKE_library_foreach_ID_link(
+ bmain, id, foreach_libblock_link_append_callback, &cb_data, IDWALK_NOP);
+ }
+
+ /* If we found a matching existing local id but are not re-using it, we need to properly clear
+ * its weak reference to linked data. */
+ if (existing_local_id != NULL &&
+ !ELEM(item->action, LINK_APPEND_ACT_KEEP_LINKED, LINK_APPEND_ACT_REUSE_LOCAL)) {
+ BKE_main_library_weak_reference_remove_item(lapp_context->library_weak_reference_mapping,
+ id->lib->filepath,
+ id->name,
+ existing_local_id);
+ }
+ }
+
+ /* Effectively perform required operation on every linked ID. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+
+ ID *local_appended_new_id = NULL;
+ char lib_filepath[FILE_MAX];
+ BLI_strncpy(lib_filepath, id->lib->filepath, sizeof(lib_filepath));
+ char lib_id_name[MAX_ID_NAME];
+ BLI_strncpy(lib_id_name, id->name, sizeof(lib_id_name));
+
+ switch (item->action) {
+ case LINK_APPEND_ACT_COPY_LOCAL:
+ BKE_lib_id_make_local(bmain, id, make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_COPY);
+ local_appended_new_id = id->newid;
+ break;
+ case LINK_APPEND_ACT_MAKE_LOCAL:
+ BKE_lib_id_make_local(bmain,
+ id,
+ make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL |
+ LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ BLI_assert(id->newid == NULL);
+ local_appended_new_id = id;
+ break;
+ case LINK_APPEND_ACT_KEEP_LINKED:
+ /* Nothing to do here. */
+ break;
+ case LINK_APPEND_ACT_REUSE_LOCAL:
+ /* We only need to set `newid` to ID found in previous loop, for proper remapping. */
+ ID_NEW_SET(id, item->userdata);
+ /* This is not a 'new' local appended id, do not set `local_appended_new_id` here. */
+ break;
+ case LINK_APPEND_ACT_UNSET:
+ CLOG_ERROR(
+ &LOG, "Unexpected unset append action for '%s' ID, assuming 'keep link'", id->name);
+ break;
+ default:
+ BLI_assert(0);
+ }
+
+ if (local_appended_new_id != NULL) {
+ if (BKE_idtype_idcode_append_is_reusable(GS(local_appended_new_id->name))) {
+ BKE_main_library_weak_reference_add_item(lapp_context->library_weak_reference_mapping,
+ lib_filepath,
+ lib_id_name,
+ local_appended_new_id);
+ }
+
+ if (set_fakeuser) {
+ if (!ELEM(GS(local_appended_new_id->name), ID_OB, ID_GR)) {
+ /* Do not set fake user on objects nor collections (instancing). */
+ id_fake_user_set(local_appended_new_id);
+ }
+ }
+ }
+ }
+
+ BKE_main_library_weak_reference_destroy(lapp_context->library_weak_reference_mapping);
+ lapp_context->library_weak_reference_mapping = NULL;
+
+ /* Remap IDs as needed. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if (item->action == LINK_APPEND_ACT_KEEP_LINKED) {
+ continue;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ if (ELEM(item->action, LINK_APPEND_ACT_COPY_LOCAL, LINK_APPEND_ACT_REUSE_LOCAL)) {
+ BLI_assert(ID_IS_LINKED(id));
+ id = id->newid;
+ if (id == NULL) {
+ continue;
+ }
+ }
+
+ BLI_assert(!ID_IS_LINKED(id));
+
+ BKE_libblock_relink_to_newid(bmain, id, 0);
+ }
+
+ /* Remove linked IDs when a local existing data has been reused instead. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if (item->action != LINK_APPEND_ACT_REUSE_LOCAL) {
+ continue;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(ID_IS_LINKED(id));
+ BLI_assert(id->newid != NULL);
+
+ id->tag |= LIB_TAG_DOIT;
+ item->new_id = id->newid;
+ }
+ BKE_id_multi_tagged_delete(bmain);
+
+ /* Instantiate newly created (duplicated) IDs as needed. */
+ LooseDataInstantiateContext instantiate_context = {.lapp_context = lapp_context,
+ .active_collection = NULL};
+ loose_data_instantiate(&instantiate_context);
+
+ /* Attempt to deal with object proxies.
+ *
+ * NOTE: Copied from `BKE_library_make_local`, but this is not really working (as in, not
+ * producing any useful result in any known use case), neither here nor in
+ * `BKE_library_make_local` currently.
+ * Proxies are end of life anyway, so not worth spending time on this. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+
+ if (item->action != LINK_APPEND_ACT_COPY_LOCAL) {
+ continue;
+ }
+
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(ID_IS_LINKED(id));
+
+ /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
+ * from another blend file into this one, even when that blend file contains proxified
+ * armatures that have local references. Since the proxified object needs to be linked
+ * (not local), this will only work when the "Localize all" checkbox is disabled.
+ * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
+ if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
+ Object *ob = (Object *)id;
+ Object *ob_new = (Object *)id->newid;
+ bool is_local = false, is_lib = false;
+
+ /* Proxies only work when the proxified object is linked-in from a library. */
+ if (!ID_IS_LINKED(ob->proxy)) {
+ CLOG_WARN(&LOG,
+ "Proxy object %s will lose its link to %s, because the "
+ "proxified object is local",
+ id->newid->name,
+ ob->proxy->id.name);
+ continue;
+ }
+
+ BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
+
+ /* We can only switch the proxy'ing to a made-local proxy if it is no longer
+ * referred to from a library. Not checking for local use; if new local proxy
+ * was not used locally would be a nasty bug! */
+ if (is_local || is_lib) {
+ CLOG_WARN(&LOG,
+ "Made-local proxy object %s will lose its link to %s, "
+ "because the linked-in proxy is referenced (is_local=%i, is_lib=%i)",
+ id->newid->name,
+ ob->proxy->id.name,
+ is_local,
+ is_lib);
+ }
+ else {
+ /* we can switch the proxy'ing from the linked-in to the made-local proxy.
+ * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
+ * was already allocated by object_make_local() (which called BKE_object_copy). */
+ ob_new->proxy = ob->proxy;
+ ob_new->proxy_group = ob->proxy_group;
+ ob_new->proxy_from = ob->proxy_from;
+ ob_new->proxy->proxy_from = ob_new;
+ ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
+ }
+ }
+ }
+
+ BKE_main_id_newptr_and_tag_clear(bmain);
+}
+
+void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
+{
+ if (lapp_context->num_items == 0) {
+ /* Nothing to be linked. */
+ return;
+ }
+
+ BLI_assert(lapp_context->num_libraries != 0);
+
+ Main *mainl;
+ Library *lib;
+
+ LinkNode *liblink, *itemlink;
+ int lib_idx, item_idx;
+
+ for (lib_idx = 0, liblink = lapp_context->libraries.list; liblink;
+ lib_idx++, liblink = liblink->next) {
+ BlendfileLinkAppendContextLibrary *lib_context = liblink->link;
+ char *libname = lib_context->path;
+ BlendHandle *blo_handle = link_append_context_library_blohandle_ensure(
+ lapp_context, lib_context, reports);
+
+ if (blo_handle == NULL) {
+ /* Unlikely since we just browsed it, but possible
+ * Error reports will have been made by BLO_blendhandle_from_file() */
+ continue;
+ }
+
+ /* here appending/linking starts */
+
+ mainl = BLO_library_link_begin(&blo_handle, libname, lapp_context->params);
+ lib = mainl->curlib;
+ BLI_assert(lib);
+ UNUSED_VARS_NDEBUG(lib);
+
+ if (mainl->versionfile < 250) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Linking or appending from a very old .blend file format (%d.%d), no animation "
+ "conversion will "
+ "be done! You may want to re-save your lib file with current Blender",
+ mainl->versionfile,
+ mainl->subversionfile);
+ }
+
+ /* For each lib file, we try to link all items belonging to that lib,
+ * and tag those successful to not try to load them again with the other libs. */
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *new_id;
+
+ if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) {
+ continue;
+ }
+
+ new_id = BLO_library_link_named_part(
+ mainl, &blo_handle, item->idcode, item->name, lapp_context->params);
+
+ if (new_id) {
+ /* If the link is successful, clear item's libs 'todo' flags.
+ * This avoids trying to link same item with other libraries to come. */
+ BLI_bitmap_set_all(item->libraries, false, lapp_context->num_libraries);
+ item->new_id = new_id;
+ item->source_library = new_id->lib;
+ }
+ }
+
+ BLO_library_link_end(mainl, &blo_handle, lapp_context->params);
+ link_append_context_library_blohandle_release(lapp_context, lib_context);
+ }
+
+ /* Instantiate newly linked IDs as needed, if no append is scheduled. */
+ if ((lapp_context->params->flag & FILE_LINK) != 0 &&
+ lapp_context->params->context.scene != NULL) {
+ new_id_to_item_mapping_create(lapp_context);
+ /* NOTE: Since we append items for IDs not already listed (i.e. implicitly linked indirect
+ * dependencies), this list will grow and we will process those IDs later, leading to a flatten
+ * recursive processing of all the linked dependencies. */
+ for (itemlink = lapp_context->items.list; itemlink; itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *id = item->new_id;
+ if (id == NULL) {
+ continue;
+ }
+ BLI_assert(item->userdata == NULL);
+
+ BlendfileLinkAppendContextCallBack cb_data = {
+ .lapp_context = lapp_context, .item = item, .reports = reports};
+ BKE_library_foreach_ID_link(lapp_context->params->bmain,
+ id,
+ foreach_libblock_link_append_callback,
+ &cb_data,
+ IDWALK_NOP);
+ }
+
+ LooseDataInstantiateContext instantiate_context = {.lapp_context = lapp_context,
+ .active_collection = NULL};
+ loose_data_instantiate(&instantiate_context);
+ }
+}
+
+/** \} */
+
+/** \name Library relocating code.
+ * \{ */
+
+static void blendfile_library_relocate_remap(Main *bmain,
+ ID *old_id,
+ ID *new_id,
+ ReportList *reports,
+ const bool do_reload,
+ const short remap_flags)
+{
+ BLI_assert(old_id);
+ if (do_reload) {
+ /* Since we asked for placeholders in case of missing IDs,
+ * we expect to always get a valid one. */
+ BLI_assert(new_id);
+ }
+ if (new_id) {
+ CLOG_INFO(&LOG,
+ 4,
+ "Before remap of %s, old_id users: %d, new_id users: %d",
+ old_id->name,
+ old_id->us,
+ new_id->us);
+ BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
+
+ if (old_id->flag & LIB_FAKEUSER) {
+ id_fake_user_clear(old_id);
+ id_fake_user_set(new_id);
+ }
+
+ CLOG_INFO(&LOG,
+ 4,
+ "After remap of %s, old_id users: %d, new_id users: %d",
+ old_id->name,
+ old_id->us,
+ new_id->us);
+
+ /* In some cases, new_id might become direct link, remove parent of library in this case. */
+ if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
+ if (do_reload) {
+ BLI_assert_unreachable(); /* Should not happen in 'pure' reload case... */
+ }
+ new_id->lib->parent = NULL;
+ }
+ }
+
+ if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) {
+ /* Note that this *should* not happen - but better be safe than sorry in this area,
+ * at least until we are 100% sure this cannot ever happen.
+ * Also, we can safely assume names were unique so far,
+ * so just replacing '.' by '~' should work,
+ * but this does not totally rules out the possibility of name collision. */
+ size_t len = strlen(old_id->name);
+ size_t dot_pos;
+ bool has_num = false;
+
+ for (dot_pos = len; dot_pos--;) {
+ char c = old_id->name[dot_pos];
+ if (c == '.') {
+ break;
+ }
+ if (c < '0' || c > '9') {
+ has_num = false;
+ break;
+ }
+ has_num = true;
+ }
+
+ if (has_num) {
+ old_id->name[dot_pos] = '~';
+ }
+ else {
+ len = MIN2(len, MAX_ID_NAME - 7);
+ BLI_strncpy(&old_id->name[len], "~000", 7);
+ }
+
+ id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL);
+
+ BKE_reportf(
+ reports,
+ RPT_WARNING,
+ "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, "
+ "old one (%d remaining users) had to be kept and was renamed to '%s'",
+ new_id->name,
+ old_id->us,
+ old_id->name);
+ }
+}
+
+void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
+ ReportList *reports,
+ Library *library,
+ const bool do_reload)
+{
+ ListBase *lbarray[INDEX_ID_MAX];
+ int lba_idx;
+
+ LinkNode *itemlink;
+ int item_idx;
+
+ Main *bmain = lapp_context->params->bmain;
+
+ /* All override rules need to be up to date, since there will be no do_version here, otherwise
+ * older, now-invalid rules might be applied and likely fail, or some changes might be missing,
+ * etc. See T93353. */
+ BKE_lib_override_library_main_operations_create(bmain, true);
+
+ /* Remove all IDs to be reloaded from Main. */
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id = lbarray[lba_idx]->first;
+ const short idcode = id ? GS(id->name) : 0;
+
+ if (!id || !BKE_idtype_idcode_is_linkable(idcode)) {
+ /* No need to reload non-linkable datatypes,
+ * those will get relinked with their 'users ID'. */
+ continue;
+ }
+
+ for (; id; id = id->next) {
+ if (id->lib == library) {
+ BlendfileLinkAppendContextItem *item;
+
+ /* We remove it from current Main, and add it to items to link... */
+ /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */
+ BLI_remlink(lbarray[lba_idx], id);
+ /* Usual special code for ShapeKeys snowflakes... */
+ Key *old_key = BKE_key_from_id(id);
+ if (old_key != NULL) {
+ BLI_remlink(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
+ }
+
+ item = BKE_blendfile_link_append_context_item_add(lapp_context, id->name + 2, idcode, id);
+ BLI_bitmap_set_all(item->libraries, true, (size_t)lapp_context->num_libraries);
+
+ CLOG_INFO(&LOG, 4, "Datablock to seek for: %s", id->name);
+ }
+ }
+ }
+
+ if (lapp_context->num_items == 0) {
+ /* Early out in case there is nothing to do. */
+ return;
+ }
+
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+
+ /* We do not want any instantiation here! */
+ BKE_blendfile_link(lapp_context, reports);
+
+ BKE_main_lock(bmain);
+
+ /* We add back old id to bmain.
+ * We need to do this in a first, separated loop, otherwise some of those may not be handled by
+ * ID remapping, which means they would still reference old data to be deleted... */
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *old_id = item->userdata;
+
+ BLI_assert(old_id);
+ BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id);
+
+ /* Usual special code for ShapeKeys snowflakes... */
+ Key *old_key = BKE_key_from_id(old_id);
+ if (old_key != NULL) {
+ BLI_addtail(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
+ }
+ }
+
+ /* Since our (old) reloaded IDs were removed from main, the user count done for them in linking
+ * code is wrong, we need to redo it here after adding them back to main. */
+ BKE_main_id_refcount_recompute(bmain, false);
+
+ /* Note that in reload case, we also want to replace indirect usages. */
+ const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
+ ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
+ (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *old_id = item->userdata;
+ ID *new_id = item->new_id;
+
+ blendfile_library_relocate_remap(bmain, old_id, new_id, reports, do_reload, remap_flags);
+ if (new_id == NULL) {
+ continue;
+ }
+ /* Usual special code for ShapeKeys snowflakes... */
+ Key **old_key_p = BKE_key_from_id_p(old_id);
+ if (old_key_p == NULL) {
+ continue;
+ }
+ Key *old_key = *old_key_p;
+ Key *new_key = BKE_key_from_id(new_id);
+ if (old_key != NULL) {
+ *old_key_p = NULL;
+ id_us_min(&old_key->id);
+ blendfile_library_relocate_remap(
+ bmain, &old_key->id, &new_key->id, reports, do_reload, remap_flags);
+ *old_key_p = old_key;
+ id_us_plus_no_lib(&old_key->id);
+ }
+ }
+
+ BKE_main_unlock(bmain);
+
+ for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
+ item_idx++, itemlink = itemlink->next) {
+ BlendfileLinkAppendContextItem *item = itemlink->link;
+ ID *old_id = item->userdata;
+
+ if (old_id->us == 0) {
+ BKE_id_free(bmain, old_id);
+ }
+ }
+
+ /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable
+ * (shape keys e.g.), so we need another loop here to clear old ones if possible. */
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id, *id_next;
+ for (id = lbarray[lba_idx]->first; id; id = id_next) {
+ id_next = id->next;
+ /* XXX That check may be a bit to generic/permissive? */
+ if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) {
+ BKE_id_free(bmain, id);
+ }
+ }
+ }
+
+ /* Get rid of no more used libraries... */
+ BKE_main_id_tag_idcode(bmain, ID_LI, LIB_TAG_DOIT, true);
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id;
+ for (id = lbarray[lba_idx]->first; id; id = id->next) {
+ if (id->lib) {
+ id->lib->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ }
+ Library *lib, *lib_next;
+ for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) {
+ lib_next = lib->id.next;
+ if (lib->id.tag & LIB_TAG_DOIT) {
+ id_us_clear_real(&lib->id);
+ if (lib->id.us == 0) {
+ BKE_id_free(bmain, (ID *)lib);
+ }
+ }
+ }
+
+ /* Update overrides of reloaded linked data-blocks. */
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
+ (id->tag & LIB_TAG_PRE_EXISTING) == 0) {
+ continue;
+ }
+ if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) {
+ BKE_lib_override_library_update(bmain, id);
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ /* Resync overrides if needed. */
+ if (!USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
+ BKE_lib_override_library_main_resync(bmain,
+ lapp_context->params->context.scene,
+ lapp_context->params->context.view_layer,
+ &(struct BlendFileReadReport){
+ .reports = reports,
+ });
+ /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
+ BKE_lib_override_library_main_operations_create(bmain, true);
+ }
+
+ BKE_main_collection_sync(bmain);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index a7257133821..a9f26d00007 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -1061,7 +1061,6 @@ static int boid_condition_is_true(BoidCondition *cond)
}
#endif
-/* determines the velocity the boid wants to have */
void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
{
BoidRule *rule;
@@ -1218,7 +1217,6 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
}
}
}
-/* tries to realize the wanted velocity taking all constraints into account */
void boid_body(BoidBrainData *bbd, ParticleData *pa)
{
BoidSettings *boids = bbd->part->boids;
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 9ce58d8129b..85e49774dfd 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -66,6 +66,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_idtype.h"
#include "BKE_image.h"
#include "BKE_lib_id.h"
#include "BKE_library.h"
@@ -87,213 +88,156 @@
static CLG_LogRef LOG = {"bke.bpath"};
/* -------------------------------------------------------------------- */
-/** \name Check Missing Files
+/** \name Generic File Path Traversal API
* \{ */
-static bool checkMissingFiles_visit_cb(void *userdata,
- char *UNUSED(path_dst),
- const char *path_src)
+void BKE_bpath_foreach_path_id(BPathForeachPathData *bpath_data, ID *id)
{
- ReportList *reports = (ReportList *)userdata;
+ const eBPathForeachFlag flag = bpath_data->flag;
+ const char *absbase = (flag & BKE_BPATH_FOREACH_PATH_ABSOLUTE) ?
+ ID_BLEND_PATH(bpath_data->bmain, id) :
+ NULL;
+ bpath_data->absolute_base_path = absbase;
- if (!BLI_exists(path_src)) {
- BKE_reportf(reports, RPT_WARNING, "Path '%s' not found", path_src);
+ if ((flag & BKE_BPATH_FOREACH_PATH_SKIP_LINKED) && ID_IS_LINKED(id)) {
+ return;
}
- return false;
-}
-
-/* high level function */
-void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports)
-{
- BKE_bpath_traverse_main(bmain,
- checkMissingFiles_visit_cb,
- BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_SKIP_PACKED,
- reports);
-}
+ if (id->library_weak_reference != NULL &&
+ (flag & BKE_BPATH_TRAVERSE_SKIP_WEAK_REFERENCES) == 0) {
+ BKE_bpath_foreach_path_fixed_process(bpath_data, id->library_weak_reference->library_filepath);
+ }
-/** \} */
+ bNodeTree *embedded_node_tree = ntreeFromID(id);
+ if (embedded_node_tree != NULL) {
+ BKE_bpath_foreach_path_id(bpath_data, &embedded_node_tree->id);
+ }
-/* -------------------------------------------------------------------- */
-/** \name Rebase Relative Paths
- * \{ */
+ const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
-typedef struct BPathRebase_Data {
- const char *basedir_src;
- const char *basedir_dst;
- ReportList *reports;
+ BLI_assert(id_type != NULL);
+ if (id_type == NULL || id_type->foreach_path == NULL) {
+ return;
+ }
- int count_tot;
- int count_changed;
- int count_failed;
-} BPathRebase_Data;
+ id_type->foreach_path(id, bpath_data);
+}
-static bool bpath_relative_rebase_visit_cb(void *userdata, char *path_dst, const char *path_src)
+void BKE_bpath_foreach_path_main(BPathForeachPathData *bpath_data)
{
- BPathRebase_Data *data = (BPathRebase_Data *)userdata;
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bpath_data->bmain, id) {
+ BKE_bpath_foreach_path_id(bpath_data, id);
+ }
+ FOREACH_MAIN_ID_END;
+}
- data->count_tot++;
+bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path)
+{
+ const char *absolute_base_path = bpath_data->absolute_base_path;
- if (BLI_path_is_rel(path_src)) {
- char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
- BLI_strncpy(filepath, path_src, FILE_MAX);
- if (BLI_path_abs(filepath, data->basedir_src)) {
- BLI_path_normalize(NULL, filepath);
+ char path_src_buf[FILE_MAX];
+ const char *path_src;
+ char path_dst[FILE_MAX];
- /* This may fail, if so it's fine to leave absolute since the path is still valid. */
- BLI_path_rel(filepath, data->basedir_dst);
+ if (absolute_base_path) {
+ BLI_strncpy(path_src_buf, path, sizeof(path_src_buf));
+ BLI_path_abs(path_src_buf, absolute_base_path);
+ path_src = path_src_buf;
+ }
+ else {
+ path_src = path;
+ }
- BLI_strncpy(path_dst, filepath, FILE_MAX);
- data->count_changed++;
- return true;
- }
+ /* so functions can check old value */
+ BLI_strncpy(path_dst, path, FILE_MAX);
- /* Failed to make relative path absolute. */
- BLI_assert(0);
- BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
- data->count_failed++;
- return false;
+ if (bpath_data->callback_function(bpath_data, path_dst, path_src)) {
+ BLI_strncpy(path, path_dst, FILE_MAX);
+ return true;
}
- /* Absolute, leave this as-is. */
return false;
}
-void BKE_bpath_relative_rebase(Main *bmain,
- const char *basedir_src,
- const char *basedir_dst,
- ReportList *reports)
+bool BKE_bpath_foreach_path_dirfile_fixed_process(BPathForeachPathData *bpath_data,
+ char *path_dir,
+ char *path_file)
{
- BPathRebase_Data data = {NULL};
- const int flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
-
- BLI_assert(basedir_src[0] != '\0');
- BLI_assert(basedir_dst[0] != '\0');
+ const char *absolute_base_path = bpath_data->absolute_base_path;
- data.basedir_src = basedir_src;
- data.basedir_dst = basedir_dst;
- data.reports = reports;
-
- BKE_bpath_traverse_main(bmain, bpath_relative_rebase_visit_cb, flag, (void *)&data);
+ char path_src[FILE_MAX];
+ char path_dst[FILE_MAX];
- BKE_reportf(reports,
- data.count_failed ? RPT_WARNING : RPT_INFO,
- "Total files %d | Changed %d | Failed %d",
- data.count_tot,
- data.count_changed,
- data.count_failed);
-}
+ BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
-/** \} */
+ /* So that functions can access the old value. */
+ BLI_strncpy(path_dst, path_src, FILE_MAX);
-/* -------------------------------------------------------------------- */
-/** \name Make Paths Relative
- * \{ */
+ if (absolute_base_path) {
+ BLI_path_abs(path_src, absolute_base_path);
+ }
-typedef struct BPathRemap_Data {
- const char *basedir;
- ReportList *reports;
+ if (bpath_data->callback_function(bpath_data, path_dst, (const char *)path_src)) {
+ BLI_split_dirfile(path_dst, path_dir, path_file, FILE_MAXDIR, FILE_MAXFILE);
+ return true;
+ }
- int count_tot;
- int count_changed;
- int count_failed;
-} BPathRemap_Data;
+ return false;
+}
-static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
+bool BKE_bpath_foreach_path_allocated_process(BPathForeachPathData *bpath_data, char **path)
{
- BPathRemap_Data *data = (BPathRemap_Data *)userdata;
+ const char *absolute_base_path = bpath_data->absolute_base_path;
- data->count_tot++;
-
- if (BLI_path_is_rel(path_src)) {
- return false; /* already relative */
- }
+ char path_src_buf[FILE_MAX];
+ const char *path_src;
+ char path_dst[FILE_MAX];
- strcpy(path_dst, path_src);
- BLI_path_rel(path_dst, data->basedir);
- if (BLI_path_is_rel(path_dst)) {
- data->count_changed++;
+ if (absolute_base_path) {
+ BLI_strncpy(path_src_buf, *path, sizeof(path_src_buf));
+ BLI_path_abs(path_src_buf, absolute_base_path);
+ path_src = path_src_buf;
}
else {
- BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src);
- data->count_failed++;
+ path_src = *path;
}
- return true;
-}
-
-void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
-{
- BPathRemap_Data data = {NULL};
- const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
- if (basedir[0] == '\0') {
- CLOG_ERROR(&LOG, "basedir='', this is a bug");
- return;
+ if (bpath_data->callback_function(bpath_data, path_dst, path_src)) {
+ MEM_freeN(*path);
+ (*path) = BLI_strdup(path_dst);
+ return true;
}
- data.basedir = basedir;
- data.reports = reports;
-
- BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (void *)&data);
-
- BKE_reportf(reports,
- data.count_failed ? RPT_WARNING : RPT_INFO,
- "Total files %d | Changed %d | Failed %d",
- data.count_tot,
- data.count_changed,
- data.count_failed);
+ return false;
}
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Make Paths Absolute
+/** \name Check Missing Files
* \{ */
-static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool check_missing_files_foreach_path_cb(BPathForeachPathData *bpath_data,
+ char *UNUSED(path_dst),
+ const char *path_src)
{
- BPathRemap_Data *data = (BPathRemap_Data *)userdata;
-
- data->count_tot++;
+ ReportList *reports = (ReportList *)bpath_data->user_data;
- if (BLI_path_is_rel(path_src) == false) {
- return false; /* already absolute */
+ if (!BLI_exists(path_src)) {
+ BKE_reportf(reports, RPT_WARNING, "Path '%s' not found", path_src);
}
- strcpy(path_dst, path_src);
- BLI_path_abs(path_dst, data->basedir);
- if (BLI_path_is_rel(path_dst) == false) {
- data->count_changed++;
- }
- else {
- BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
- data->count_failed++;
- }
- return true;
+ return false;
}
-/* similar to BKE_bpath_relative_convert - keep in sync! */
-void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
+void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports)
{
- BPathRemap_Data data = {NULL};
- const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
-
- if (basedir[0] == '\0') {
- CLOG_ERROR(&LOG, "basedir='', this is a bug");
- return;
- }
-
- data.basedir = basedir;
- data.reports = reports;
-
- BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data);
-
- BKE_reportf(reports,
- data.count_failed ? RPT_WARNING : RPT_INFO,
- "Total files %d | Changed %d | Failed %d",
- data.count_tot,
- data.count_changed,
- data.count_failed);
+ BKE_bpath_foreach_path_main(&(BPathForeachPathData){
+ .bmain = bmain,
+ .callback_function = check_missing_files_foreach_path_cb,
+ .flag = BKE_BPATH_FOREACH_PATH_ABSOLUTE | BKE_BPATH_FOREACH_PATH_SKIP_PACKED,
+ .user_data = reports});
}
/** \} */
@@ -302,72 +246,79 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
/** \name Find Missing Files
* \{ */
-/**
- * find this file recursively, use the biggest file so thumbnails don't get used by mistake
- * \param filename_new: the path will be copied here, caller must initialize as empty string.
- * \param dirname: subdir to search
- * \param filename: set this filename
- * \param filesize: filesize for the file
+#define MAX_DIR_RECURSE 16
+#define FILESIZE_INVALID_DIRECTORY -1
+
+/** Find the given filename recursively in the given search directory and its sub-directories.
+ *
+ * \note Use the biggest matching file found, so that thumbnails don't get used by mistake.
+ *
+ * \param search_directory: Directory to search in.
+ * \param filename_src: Search for this filename.
+ * \param r_filename_new: The path of the new found file will be copied here, caller must
+ * initialize as empty string.
+ * \param r_filesize: Size of the file, `FILESIZE_INVALID_DIRECTORY` if search directory could not
+ * be opened.
+ * \param r_recurse_depth: Current recursion depth.
*
- * \returns found: 1/0.
+ * \return true if found, false otherwise.
*/
-#define MAX_RECUR 16
-static bool missing_files_find__recursive(char *filename_new,
- const char *dirname,
- const char *filename,
+static bool missing_files_find__recursive(const char *search_directory,
+ const char *filename_src,
+ char r_filename_new[FILE_MAX],
int64_t *r_filesize,
- int *r_recur_depth)
+ int *r_recurse_depth)
{
- /* file searching stuff */
+ /* TODO: Move this function to BLI_path_utils? The 'biggest size' behavior is quite specific
+ * though... */
DIR *dir;
- struct dirent *de;
BLI_stat_t status;
char path[FILE_MAX];
int64_t size;
bool found = false;
- dir = opendir(dirname);
+ dir = opendir(search_directory);
if (dir == NULL) {
return found;
}
- if (*r_filesize == -1) {
- *r_filesize = 0; /* dir opened fine */
+ if (*r_filesize == FILESIZE_INVALID_DIRECTORY) {
+ *r_filesize = 0; /* The directory opened fine. */
}
- while ((de = readdir(dir)) != NULL) {
-
+ for (struct dirent *de = readdir(dir); de != NULL; de = readdir(dir)) {
if (FILENAME_IS_CURRPAR(de->d_name)) {
continue;
}
- BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
+ BLI_join_dirfile(path, sizeof(path), search_directory, de->d_name);
if (BLI_stat(path, &status) == -1) {
- continue; /* can't stat, don't bother with this file, could print debug info here */
+ CLOG_WARN(&LOG, "Cannot get file status (`stat()`) of '%s'", path);
+ continue;
}
- if (S_ISREG(status.st_mode)) { /* is file */
- if (BLI_path_ncmp(filename, de->d_name, FILE_MAX) == 0) { /* name matches */
- /* open the file to read its size */
+ if (S_ISREG(status.st_mode)) { /* It is a file. */
+ if (BLI_path_ncmp(filename_src, de->d_name, FILE_MAX) == 0) { /* Names match. */
size = status.st_size;
- if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */
+ if ((size > 0) && (size > *r_filesize)) { /* Find the biggest matching file. */
*r_filesize = size;
- BLI_strncpy(filename_new, path, FILE_MAX);
+ BLI_strncpy(r_filename_new, path, FILE_MAX);
found = true;
}
}
}
- else if (S_ISDIR(status.st_mode)) { /* is subdir */
- if (*r_recur_depth <= MAX_RECUR) {
- (*r_recur_depth)++;
+ else if (S_ISDIR(status.st_mode)) { /* It is a sub-directory. */
+ if (*r_recurse_depth <= MAX_DIR_RECURSE) {
+ (*r_recurse_depth)++;
found |= missing_files_find__recursive(
- filename_new, path, filename, r_filesize, r_recur_depth);
- (*r_recur_depth)--;
+ path, filename_src, r_filename_new, r_filesize, r_recurse_depth);
+ (*r_recurse_depth)--;
}
}
}
+
closedir(dir);
return found;
}
@@ -376,37 +327,37 @@ typedef struct BPathFind_Data {
const char *basedir;
const char *searchdir;
ReportList *reports;
- bool find_all;
+ bool find_all; /* Also search for files which current path is still valid. */
} BPathFind_Data;
-static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool missing_files_find_foreach_path_cb(BPathForeachPathData *bpath_data,
+ char *path_dst,
+ const char *path_src)
{
- BPathFind_Data *data = (BPathFind_Data *)userdata;
+ BPathFind_Data *data = (BPathFind_Data *)bpath_data->user_data;
char filename_new[FILE_MAX];
- int64_t filesize = -1;
- int recur_depth = 0;
- bool found;
+ int64_t filesize = FILESIZE_INVALID_DIRECTORY;
+ int recurse_depth = 0;
+ bool is_found;
- if (data->find_all == false) {
- if (BLI_exists(path_src)) {
- return false;
- }
+ if (!data->find_all && BLI_exists(path_src)) {
+ return false;
}
filename_new[0] = '\0';
- found = missing_files_find__recursive(
- filename_new, data->searchdir, BLI_path_basename(path_src), &filesize, &recur_depth);
+ is_found = missing_files_find__recursive(
+ data->searchdir, BLI_path_basename(path_src), filename_new, &filesize, &recurse_depth);
- if (filesize == -1) { /* could not open dir */
+ if (filesize == FILESIZE_INVALID_DIRECTORY) {
BKE_reportf(data->reports,
RPT_WARNING,
- "Could not open directory '%s'",
+ "Could not open the directory '%s'",
BLI_path_basename(data->searchdir));
return false;
}
- if (found == false) {
+ if (is_found == false) {
BKE_reportf(data->reports,
RPT_WARNING,
"Could not find '%s' in '%s'",
@@ -419,7 +370,7 @@ static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const c
BLI_strncpy(path_dst, filename_new, FILE_MAX);
- /* keep path relative if the previous one was relative */
+ /* Keep the path relative if the previous one was relative. */
if (was_relative) {
BLI_path_rel(path_dst, data->basedir);
}
@@ -433,480 +384,281 @@ void BKE_bpath_missing_files_find(Main *bmain,
const bool find_all)
{
struct BPathFind_Data data = {NULL};
- const int flag = BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_RELOAD_EDITED;
+ const int flag = BKE_BPATH_FOREACH_PATH_ABSOLUTE | BKE_BPATH_FOREACH_PATH_RELOAD_EDITED;
data.basedir = BKE_main_blendfile_path(bmain);
data.reports = reports;
data.searchdir = searchpath;
data.find_all = find_all;
- BKE_bpath_traverse_main(bmain, missing_files_find__visit_cb, flag, (void *)&data);
+ BKE_bpath_foreach_path_main(
+ &(BPathForeachPathData){.bmain = bmain,
+ .callback_function = missing_files_find_foreach_path_cb,
+ .flag = flag,
+ .user_data = &data});
}
+#undef MAX_DIR_RECURSE
+#undef FILESIZE_INVALID_DIRECTORY
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Generic File Path Traversal API
+/** \name Rebase Relative Paths
* \{ */
-/**
- * Run a visitor on a string, replacing the contents of the string as needed.
- */
-static bool rewrite_path_fixed(char *path,
- BPathVisitor visit_cb,
- const char *absbase,
- void *userdata)
+typedef struct BPathRebase_Data {
+ const char *basedir_src;
+ const char *basedir_dst;
+ ReportList *reports;
+
+ int count_tot;
+ int count_changed;
+ int count_failed;
+} BPathRebase_Data;
+
+static bool relative_rebase_foreach_path_cb(BPathForeachPathData *bpath_data,
+ char *path_dst,
+ const char *path_src)
{
- char path_src_buf[FILE_MAX];
- const char *path_src;
- char path_dst[FILE_MAX];
+ BPathRebase_Data *data = (BPathRebase_Data *)bpath_data->user_data;
- if (absbase) {
- BLI_strncpy(path_src_buf, path, sizeof(path_src_buf));
- BLI_path_abs(path_src_buf, absbase);
- path_src = path_src_buf;
+ data->count_tot++;
+
+ if (!BLI_path_is_rel(path_src)) {
+ /* Absolute, leave this as-is. */
+ return false;
}
- else {
- path_src = path;
+
+ char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
+ BLI_strncpy(filepath, path_src, FILE_MAX);
+ if (!BLI_path_abs(filepath, data->basedir_src)) {
+ BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
+ data->count_failed++;
+ return false;
}
- /* so functions can check old value */
- BLI_strncpy(path_dst, path, FILE_MAX);
+ BLI_path_normalize(NULL, filepath);
- if (visit_cb(userdata, path_dst, path_src)) {
- BLI_strncpy(path, path_dst, FILE_MAX);
- return true;
- }
+ /* This may fail, if so it's fine to leave absolute since the path is still valid. */
+ BLI_path_rel(filepath, data->basedir_dst);
- return false;
+ BLI_strncpy(path_dst, filepath, FILE_MAX);
+ data->count_changed++;
+ return true;
}
-static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
- char path_file[FILE_MAXFILE],
- BPathVisitor visit_cb,
- const char *absbase,
- void *userdata)
+void BKE_bpath_relative_rebase(Main *bmain,
+ const char *basedir_src,
+ const char *basedir_dst,
+ ReportList *reports)
{
- char path_src[FILE_MAX];
- char path_dst[FILE_MAX];
-
- BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
+ BPathRebase_Data data = {NULL};
+ const int flag = (BKE_BPATH_FOREACH_PATH_SKIP_LINKED | BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE);
- /* so functions can check old value */
- BLI_strncpy(path_dst, path_src, FILE_MAX);
+ BLI_assert(basedir_src[0] != '\0');
+ BLI_assert(basedir_dst[0] != '\0');
- if (absbase) {
- BLI_path_abs(path_src, absbase);
- }
+ data.basedir_src = basedir_src;
+ data.basedir_dst = basedir_dst;
+ data.reports = reports;
- if (visit_cb(userdata, path_dst, (const char *)path_src)) {
- BLI_split_dirfile(path_dst, path_dir, path_file, FILE_MAXDIR, FILE_MAXFILE);
- return true;
- }
+ BKE_bpath_foreach_path_main(
+ &(BPathForeachPathData){.bmain = bmain,
+ .callback_function = relative_rebase_foreach_path_cb,
+ .flag = flag,
+ .user_data = &data});
- return false;
+ BKE_reportf(reports,
+ data.count_failed ? RPT_WARNING : RPT_INFO,
+ "Total files %d | Changed %d | Failed %d",
+ data.count_tot,
+ data.count_changed,
+ data.count_failed);
}
-static bool rewrite_path_alloc(char **path,
- BPathVisitor visit_cb,
- const char *absbase,
- void *userdata)
-{
- char path_src_buf[FILE_MAX];
- const char *path_src;
- char path_dst[FILE_MAX];
-
- if (absbase) {
- BLI_strncpy(path_src_buf, *path, sizeof(path_src_buf));
- BLI_path_abs(path_src_buf, absbase);
- path_src = path_src_buf;
- }
- else {
- path_src = *path;
- }
+/** \} */
- if (visit_cb(userdata, path_dst, path_src)) {
- MEM_freeN(*path);
- (*path) = BLI_strdup(path_dst);
- return true;
- }
+/* -------------------------------------------------------------------- */
+/** \name Make Paths Relative Or Absolute
+ * \{ */
- return false;
-}
+typedef struct BPathRemap_Data {
+ const char *basedir;
+ ReportList *reports;
-typedef struct Seq_callback_data {
- const char *absbase;
- void *bpath_user_data;
- BPathVisitor visit_cb;
- const int flag;
-} Seq_callback_data;
+ int count_tot;
+ int count_changed;
+ int count_failed;
+} BPathRemap_Data;
-static bool seq_rewrite_path_callback(Sequence *seq, void *user_data)
+static bool relative_convert_foreach_path_cb(BPathForeachPathData *bpath_data,
+ char *path_dst,
+ const char *path_src)
{
- if (SEQ_HAS_PATH(seq)) {
- StripElem *se = seq->strip->stripdata;
- Seq_callback_data *cd = (Seq_callback_data *)user_data;
+ BPathRemap_Data *data = (BPathRemap_Data *)bpath_data->user_data;
- if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
- rewrite_path_fixed_dirfile(
- seq->strip->dir, se->name, cd->visit_cb, cd->absbase, cd->bpath_user_data);
- }
- else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
- /* might want an option not to loop over all strips */
- unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
- unsigned int i;
-
- if (cd->flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
- /* only operate on one path */
- len = MIN2(1u, len);
- }
+ data->count_tot++;
- for (i = 0; i < len; i++, se++) {
- rewrite_path_fixed_dirfile(
- seq->strip->dir, se->name, cd->visit_cb, cd->absbase, cd->bpath_user_data);
- }
- }
- else {
- /* simple case */
- rewrite_path_fixed(seq->strip->dir, cd->visit_cb, cd->absbase, cd->bpath_user_data);
- }
+ if (BLI_path_is_rel(path_src)) {
+ return false; /* Already relative. */
+ }
+
+ BLI_strncpy(path_dst, path_src, FILE_MAX);
+ BLI_path_rel(path_dst, data->basedir);
+ if (BLI_path_is_rel(path_dst)) {
+ data->count_changed++;
+ }
+ else {
+ BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src);
+ data->count_failed++;
}
return true;
}
-/**
- * Run visitor function 'visit' on all paths contained in 'id'.
- */
-void BKE_bpath_traverse_id(
- Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+static bool absolute_convert_foreach_path_cb(BPathForeachPathData *bpath_data,
+ char *path_dst,
+ const char *path_src)
{
- const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
+ BPathRemap_Data *data = (BPathRemap_Data *)bpath_data->user_data;
- if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && ID_IS_LINKED(id)) {
- return;
- }
+ data->count_tot++;
- if (id->library_weak_reference != NULL) {
- rewrite_path_fixed(
- id->library_weak_reference->library_filepath, visit_cb, absbase, bpath_user_data);
+ if (!BLI_path_is_rel(path_src)) {
+ return false; /* Already absolute. */
}
- switch (GS(id->name)) {
- case ID_IM: {
- Image *ima;
- ima = (Image *)id;
- if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- /* Skip empty file paths, these are typically from generated images and
- * don't make sense to add directories to until the image has been saved
- * once to give it a meaningful value. */
- if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED) &&
- ima->filepath[0]) {
- if (rewrite_path_fixed(ima->filepath, visit_cb, absbase, bpath_user_data)) {
- if (flag & BKE_BPATH_TRAVERSE_RELOAD_EDITED) {
- if (!BKE_image_has_packedfile(ima) &&
- /* image may have been painted onto (and not saved, T44543) */
- !BKE_image_is_dirty(ima)) {
- BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD);
- }
- }
- }
- }
- }
- break;
- }
- case ID_BR: {
- Brush *brush = (Brush *)id;
- if (brush->icon_filepath[0]) {
- rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, bpath_user_data);
- }
- break;
- }
- case ID_OB: {
- Object *ob = (Object *)id;
- ModifierData *md;
- ParticleSystem *psys;
-
-#define BPATH_TRAVERSE_POINTCACHE(ptcaches) \
- { \
- PointCache *cache; \
- for (cache = (ptcaches).first; cache; cache = cache->next) { \
- if (cache->flag & PTCACHE_DISK_CACHE) { \
- rewrite_path_fixed(cache->path, visit_cb, absbase, bpath_user_data); \
- } \
- } \
- } \
- (void)0
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Fluidsim) {
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
- if (fluidmd->fss) {
- rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data);
- }
- }
- else if (md->type == eModifierType_Fluid) {
- FluidModifierData *fmd = (FluidModifierData *)md;
- if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
- rewrite_path_fixed(fmd->domain->cache_directory, visit_cb, absbase, bpath_user_data);
- }
- }
- else if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData *)md;
- BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches);
- }
- else if (md->type == eModifierType_Ocean) {
- OceanModifierData *omd = (OceanModifierData *)md;
- rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
- }
- else if (md->type == eModifierType_MeshCache) {
- MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
- rewrite_path_fixed(mcmd->filepath, visit_cb, absbase, bpath_user_data);
- }
- }
-
- if (ob->soft) {
- BPATH_TRAVERSE_POINTCACHE(ob->soft->shared->ptcaches);
- }
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- BPATH_TRAVERSE_POINTCACHE(psys->ptcaches);
- }
-
-#undef BPATH_TRAVERSE_POINTCACHE
-
- break;
- }
- case ID_SO: {
- bSound *sound = (bSound *)id;
- if (sound->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- rewrite_path_fixed(sound->filepath, visit_cb, absbase, bpath_user_data);
- }
- break;
- }
- case ID_VO: {
- Volume *volume = (Volume *)id;
- if (volume->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- rewrite_path_fixed(volume->filepath, visit_cb, absbase, bpath_user_data);
- }
- break;
- }
- case ID_TXT:
- if (((Text *)id)->filepath) {
- rewrite_path_alloc(&((Text *)id)->filepath, visit_cb, absbase, bpath_user_data);
- }
- break;
- case ID_VF: {
- VFont *vfont = (VFont *)id;
- if (vfont->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- if (BKE_vfont_is_builtin(vfont) == false) {
- rewrite_path_fixed(((VFont *)id)->filepath, visit_cb, absbase, bpath_user_data);
- }
- }
- break;
- }
- case ID_MA: {
- Material *ma = (Material *)id;
- bNodeTree *ntree = ma->nodetree;
-
- if (ntree) {
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_SCRIPT) {
- NodeShaderScript *nss = (NodeShaderScript *)node->storage;
- rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
- }
- else if (node->type == SH_NODE_TEX_IES) {
- NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
- rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
- }
- }
- }
- break;
- }
- case ID_NT: {
- bNodeTree *ntree = (bNodeTree *)id;
- bNode *node;
-
- if (ntree->type == NTREE_SHADER) {
- /* same as lines above */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_SCRIPT) {
- NodeShaderScript *nss = (NodeShaderScript *)node->storage;
- rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
- }
- else if (node->type == SH_NODE_TEX_IES) {
- NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
- rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
- }
- }
- }
- break;
- }
- case ID_SCE: {
- Scene *scene = (Scene *)id;
- if (scene->ed) {
- Seq_callback_data user_data = {absbase, bpath_user_data, visit_cb, flag};
- SEQ_for_each_callback(&scene->ed->seqbase, seq_rewrite_path_callback, &user_data);
- }
- break;
- }
- case ID_ME: {
- Mesh *me = (Mesh *)id;
- if (me->ldata.external) {
- rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data);
- }
- break;
- }
- case ID_LI: {
- Library *lib = (Library *)id;
- /* keep packedfile paths always relative to the blend */
- if (lib->packedfile == NULL) {
- if (rewrite_path_fixed(lib->filepath, visit_cb, absbase, bpath_user_data)) {
- BKE_library_filepath_set(bmain, lib, lib->filepath);
- }
- }
- break;
- }
- case ID_MC: {
- MovieClip *clip = (MovieClip *)id;
- rewrite_path_fixed(clip->filepath, visit_cb, absbase, bpath_user_data);
- break;
- }
- case ID_CF: {
- CacheFile *cache_file = (CacheFile *)id;
- rewrite_path_fixed(cache_file->filepath, visit_cb, absbase, bpath_user_data);
- break;
- }
- default:
- /* Nothing to do for other IDs that don't contain file paths. */
- break;
+ BLI_strncpy(path_dst, path_src, FILENAME_MAX);
+ BLI_path_abs(path_dst, data->basedir);
+ if (BLI_path_is_rel(path_dst) == false) {
+ data->count_changed++;
+ }
+ else {
+ BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
+ data->count_failed++;
}
+ return true;
}
-void BKE_bpath_traverse_id_list(
- Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+static void bpath_absolute_relative_convert(Main *bmain,
+ const char *basedir,
+ ReportList *reports,
+ BPathForeachPathFunctionCallback callback_function)
{
- ID *id;
- for (id = lb->first; id; id = id->next) {
- BKE_bpath_traverse_id(bmain, id, visit_cb, flag, bpath_user_data);
+ BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_FOREACH_PATH_SKIP_LINKED;
+
+ BLI_assert(basedir[0] != '\0');
+ if (basedir[0] == '\0') {
+ CLOG_ERROR(&LOG, "basedir='', this is a bug");
+ return;
}
+
+ data.basedir = basedir;
+ data.reports = reports;
+
+ BKE_bpath_foreach_path_main(&(BPathForeachPathData){
+ .bmain = bmain, .callback_function = callback_function, .flag = flag, .user_data = &data});
+
+ BKE_reportf(reports,
+ data.count_failed ? RPT_WARNING : RPT_INFO,
+ "Total files %d | Changed %d | Failed %d",
+ data.count_tot,
+ data.count_changed,
+ data.count_failed);
}
-void BKE_bpath_traverse_main(Main *bmain,
- BPathVisitor visit_cb,
- const int flag,
- void *bpath_user_data)
+void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
{
- ListBase *lbarray[INDEX_ID_MAX];
- int a = set_listbasepointers(bmain, lbarray);
- while (a--) {
- BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
- }
+ bpath_absolute_relative_convert(bmain, basedir, reports, relative_convert_foreach_path_cb);
}
-/**
- * Rewrites a relative path to be relative to the main file - unless the path is
- * absolute, in which case it is not altered.
- */
-bool BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
+void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
{
- /* be sure there is low chance of the path being too short */
- char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
- const char *base_new = ((char **)pathbase_v)[0];
- const char *base_old = ((char **)pathbase_v)[1];
-
- if (BLI_path_is_rel(base_old)) {
- CLOG_ERROR(&LOG, "old base path '%s' is not absolute.", base_old);
- return false;
- }
-
- /* Make referenced file absolute. This would be a side-effect of
- * BLI_path_normalize, but we do it explicitly so we know if it changed. */
- BLI_strncpy(filepath, path_src, FILE_MAX);
- if (BLI_path_abs(filepath, base_old)) {
- /* Path was relative and is now absolute. Remap.
- * Important BLI_path_normalize runs before the path is made relative
- * because it won't work for paths that start with "//../" */
- BLI_path_normalize(base_new, filepath);
- BLI_path_rel(filepath, base_new);
- BLI_strncpy(path_dst, filepath, FILE_MAX);
- return true;
- }
-
- /* Path was not relative to begin with. */
- return false;
+ bpath_absolute_relative_convert(bmain, basedir, reports, absolute_convert_foreach_path_cb);
}
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Backup/Restore/Free functions,
+/** \name Backup/Restore/Free paths list functions.
*
- * \note These functions assume the data won't change order.
* \{ */
struct PathStore {
struct PathStore *next, *prev;
};
-static bool bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src)
+static bool bpath_list_append(BPathForeachPathData *bpath_data,
+ char *UNUSED(path_dst),
+ const char *path_src)
{
- /* store the path and string in a single alloc */
- ListBase *ls = userdata;
+ ListBase *path_list = bpath_data->user_data;
size_t path_size = strlen(path_src) + 1;
+
+ /* NOTE: the PathStore and its string are allocated together in a single alloc. */
struct PathStore *path_store = MEM_mallocN(sizeof(struct PathStore) + path_size, __func__);
char *filepath = (char *)(path_store + 1);
- memcpy(filepath, path_src, path_size);
- BLI_addtail(ls, path_store);
+ BLI_strncpy(filepath, path_src, path_size);
+ BLI_addtail(path_list, path_store);
return false;
}
-static bool bpath_list_restore(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_list_restore(BPathForeachPathData *bpath_data,
+ char *path_dst,
+ const char *path_src)
{
- /* assume ls->first won't be NULL because the number of paths can't change!
- * (if they do caller is wrong) */
- ListBase *ls = userdata;
- struct PathStore *path_store = ls->first;
+ ListBase *path_list = bpath_data->user_data;
+
+ /* `ls->first` should never be NULL, because the number of paths should not change.
+ * If this happens, there is a bug in caller code. */
+ BLI_assert(!BLI_listbase_is_empty(path_list));
+
+ struct PathStore *path_store = path_list->first;
const char *filepath = (char *)(path_store + 1);
- bool ret;
+ bool is_path_changed = false;
- if (STREQ(path_src, filepath)) {
- ret = false;
- }
- else {
+ if (!STREQ(path_src, filepath)) {
BLI_strncpy(path_dst, filepath, FILE_MAX);
- ret = true;
+ is_path_changed = true;
}
- BLI_freelinkN(ls, path_store);
- return ret;
+ BLI_freelinkN(path_list, path_store);
+ return is_path_changed;
}
-/* return ls_handle */
-void *BKE_bpath_list_backup(Main *bmain, const int flag)
+void *BKE_bpath_list_backup(Main *bmain, const eBPathForeachFlag flag)
{
- ListBase *ls = MEM_callocN(sizeof(ListBase), __func__);
+ ListBase *path_list = MEM_callocN(sizeof(ListBase), __func__);
- BKE_bpath_traverse_main(bmain, bpath_list_append, flag, ls);
+ BKE_bpath_foreach_path_main(&(BPathForeachPathData){.bmain = bmain,
+ .callback_function = bpath_list_append,
+ .flag = flag,
+ .user_data = path_list});
- return ls;
+ return path_list;
}
-void BKE_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
+void BKE_bpath_list_restore(Main *bmain, const eBPathForeachFlag flag, void *path_list_handle)
{
- ListBase *ls = ls_handle;
+ ListBase *path_list = path_list_handle;
- BKE_bpath_traverse_main(bmain, bpath_list_restore, flag, ls);
+ BKE_bpath_foreach_path_main(&(BPathForeachPathData){.bmain = bmain,
+ .callback_function = bpath_list_restore,
+ .flag = flag,
+ .user_data = path_list});
}
-void BKE_bpath_list_free(void *ls_handle)
+void BKE_bpath_list_free(void *path_list_handle)
{
- ListBase *ls = ls_handle;
- BLI_assert(BLI_listbase_is_empty(ls)); /* assumes we were used */
- BLI_freelistN(ls);
- MEM_freeN(ls);
+ ListBase *path_list = path_list_handle;
+ /* The whole list should have been consumed by #BKE_bpath_list_restore, see also comment in
+ * #bpath_list_restore. */
+ BLI_assert(BLI_listbase_is_empty(path_list));
+
+ BLI_freelistN(path_list);
+ MEM_freeN(path_list);
}
/** \} */
diff --git a/source/blender/blenkernel/intern/bpath_test.cc b/source/blender/blenkernel/intern/bpath_test.cc
new file mode 100644
index 00000000000..121d47af75f
--- /dev/null
+++ b/source/blender/blenkernel/intern/bpath_test.cc
@@ -0,0 +1,181 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ */
+#include "testing/testing.h"
+
+#include "CLG_log.h"
+
+#include "BKE_bpath.h"
+#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_text_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+namespace blender::bke::tests {
+
+#ifdef WIN32
+# define ABSOLUTE_ROOT "C:" SEP_STR
+#else
+# define ABSOLUTE_ROOT SEP_STR
+#endif
+
+#define RELATIVE_ROOT "//"
+#define BASE_DIR ABSOLUTE_ROOT "blendfiles" SEP_STR
+#define REBASE_DIR BASE_DIR "rebase" SEP_STR
+
+#define BLENDFILE_NAME "bpath.blend"
+#define BLENDFILE_PATH BASE_DIR BLENDFILE_NAME
+
+#define TEXT_PATH_ITEM "texts" SEP_STR "text.txt"
+#define TEXT_PATH_ABSOLUTE ABSOLUTE_ROOT TEXT_PATH_ITEM
+#define TEXT_PATH_ABSOLUTE_MADE_RELATIVE RELATIVE_ROOT ".." SEP_STR TEXT_PATH_ITEM
+#define TEXT_PATH_RELATIVE RELATIVE_ROOT TEXT_PATH_ITEM
+#define TEXT_PATH_RELATIVE_MADE_ABSOLUTE BASE_DIR TEXT_PATH_ITEM
+
+#define MOVIECLIP_PATH_ITEM "movieclips" SEP_STR "movieclip.avi"
+#define MOVIECLIP_PATH_ABSOLUTE ABSOLUTE_ROOT MOVIECLIP_PATH_ITEM
+#define MOVIECLIP_PATH_ABSOLUTE_MADE_RELATIVE RELATIVE_ROOT ".." SEP_STR MOVIECLIP_PATH_ITEM
+#define MOVIECLIP_PATH_RELATIVE RELATIVE_ROOT MOVIECLIP_PATH_ITEM
+#define MOVIECLIP_PATH_RELATIVE_MADE_ABSOLUTE BASE_DIR MOVIECLIP_PATH_ITEM
+
+class BPathTest : public testing::Test {
+ public:
+ static void SetUpTestSuite()
+ {
+ CLG_init();
+ BKE_idtype_init();
+ }
+ static void TearDownTestSuite()
+ {
+ CLG_exit();
+ }
+
+ void SetUp() override
+ {
+ bmain = BKE_main_new();
+ STRNCPY(bmain->filepath, BLENDFILE_PATH);
+
+ BKE_id_new(bmain, ID_TXT, nullptr);
+ BKE_id_new(bmain, ID_MC, nullptr);
+ }
+
+ void TearDown() override
+ {
+ BKE_main_free(bmain);
+ }
+
+ Main *bmain;
+};
+
+TEST_F(BPathTest, rebase_on_relative)
+{
+ // Test on relative paths, should be modified.
+ Text *text = reinterpret_cast<Text *>(bmain->texts.first);
+ text->filepath = BLI_strdup(TEXT_PATH_RELATIVE);
+
+ MovieClip *movie_clip = reinterpret_cast<MovieClip *>(bmain->movieclips.first);
+ BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_RELATIVE, sizeof(movie_clip->filepath));
+
+ BKE_bpath_relative_rebase(bmain, BASE_DIR, REBASE_DIR, nullptr);
+
+ EXPECT_STREQ(text->filepath, RELATIVE_ROOT ".." SEP_STR TEXT_PATH_ITEM);
+ EXPECT_STREQ(movie_clip->filepath, RELATIVE_ROOT ".." SEP_STR MOVIECLIP_PATH_ITEM);
+}
+
+TEST_F(BPathTest, rebase_on_absolute)
+{
+ // Test on absolute paths, should not be modified.
+ Text *text = reinterpret_cast<Text *>(bmain->texts.first);
+ text->filepath = BLI_strdup(TEXT_PATH_ABSOLUTE);
+
+ MovieClip *movie_clip = reinterpret_cast<MovieClip *>(bmain->movieclips.first);
+ BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE, sizeof(movie_clip->filepath));
+
+ BKE_bpath_relative_rebase(bmain, BASE_DIR, REBASE_DIR, nullptr);
+
+ EXPECT_STREQ(text->filepath, TEXT_PATH_ABSOLUTE);
+ EXPECT_STREQ(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE);
+}
+
+TEST_F(BPathTest, convert_to_relative)
+{
+ Text *text = reinterpret_cast<Text *>(bmain->texts.first);
+ text->filepath = BLI_strdup(TEXT_PATH_RELATIVE);
+
+ MovieClip *movie_clip = reinterpret_cast<MovieClip *>(bmain->movieclips.first);
+ BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE, sizeof(movie_clip->filepath));
+
+ BKE_bpath_relative_convert(bmain, BASE_DIR, nullptr);
+
+ // Already relative path should not be modified.
+ EXPECT_STREQ(text->filepath, TEXT_PATH_RELATIVE);
+ // Absolute path should be modified.
+ EXPECT_STREQ(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE_MADE_RELATIVE);
+}
+
+TEST_F(BPathTest, convert_to_absolute)
+{
+ Text *text = reinterpret_cast<Text *>(bmain->texts.first);
+ text->filepath = BLI_strdup(TEXT_PATH_RELATIVE);
+
+ MovieClip *movie_clip = reinterpret_cast<MovieClip *>(bmain->movieclips.first);
+ BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE, sizeof(movie_clip->filepath));
+
+ BKE_bpath_absolute_convert(bmain, BASE_DIR, nullptr);
+
+ // Relative path should be modified.
+ EXPECT_STREQ(text->filepath, TEXT_PATH_RELATIVE_MADE_ABSOLUTE);
+ // Already absolute path should not be modified.
+ EXPECT_STREQ(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE);
+}
+
+TEST_F(BPathTest, list_backup_restore)
+{
+ Text *text = reinterpret_cast<Text *>(bmain->texts.first);
+ text->filepath = BLI_strdup(TEXT_PATH_RELATIVE);
+
+ MovieClip *movie_clip = reinterpret_cast<MovieClip *>(bmain->movieclips.first);
+ BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE, sizeof(movie_clip->filepath));
+
+ void *path_list_handle = BKE_bpath_list_backup(bmain, static_cast<eBPathForeachFlag>(0));
+
+ ListBase *path_list = reinterpret_cast<ListBase *>(path_list_handle);
+ EXPECT_EQ(BLI_listbase_count(path_list), 2);
+
+ MEM_freeN(text->filepath);
+ text->filepath = BLI_strdup(TEXT_PATH_ABSOLUTE);
+ BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_RELATIVE, sizeof(movie_clip->filepath));
+
+ BKE_bpath_list_restore(bmain, static_cast<eBPathForeachFlag>(0), path_list_handle);
+
+ EXPECT_STREQ(text->filepath, TEXT_PATH_RELATIVE);
+ EXPECT_STREQ(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE);
+ EXPECT_EQ(BLI_listbase_count(path_list), 0);
+
+ BKE_bpath_list_free(path_list_handle);
+}
+
+} // namespace blender::bke::tests
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index dc3c2a8e55e..153a65d67db 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -33,6 +33,7 @@
#include "BLT_translation.h"
+#include "BKE_bpath.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -218,6 +219,14 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_texture_mtex_foreach_id(data, &brush->mask_mtex));
}
+static void brush_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Brush *brush = (Brush *)id;
+ if (brush->icon_filepath[0] != '\0') {
+ BKE_bpath_foreach_path_fixed_process(bpath_data, brush->icon_filepath);
+ }
+}
+
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Brush *brush = (Brush *)id;
@@ -414,6 +423,7 @@ IDTypeInfo IDType_ID_BR = {
.name_plural = "brushes",
.translation_context = BLT_I18NCONTEXT_ID_BRUSH,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = brush_init_data,
.copy_data = brush_copy_data,
@@ -421,6 +431,7 @@ IDTypeInfo IDType_ID_BR = {
.make_local = brush_make_local,
.foreach_id = brush_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = brush_foreach_path,
.owner_get = NULL,
.blend_write = brush_blend_write,
@@ -503,10 +514,6 @@ static void brush_defaults(Brush *brush)
/* Datablock add/copy/free/make_local */
-/**
- * \note Resulting brush will have two users: one as a fake user,
- * another is assumed to be used by the caller.
- */
Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
{
Brush *brush;
@@ -518,7 +525,6 @@ Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
return brush;
}
-/* add grease pencil settings */
void BKE_brush_init_gpencil_settings(Brush *brush)
{
if (brush->gpencil_settings == NULL) {
@@ -546,7 +552,6 @@ void BKE_brush_init_gpencil_settings(Brush *brush)
brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
-/* add a new gp-brush */
Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name, eObjectMode mode)
{
Paint *paint = NULL;
@@ -586,7 +591,6 @@ Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name, eO
return brush;
}
-/* Delete a Brush. */
bool BKE_brush_delete(Main *bmain, Brush *brush)
{
if (brush->id.tag & LIB_TAG_INDIRECT) {
@@ -1320,7 +1324,6 @@ static Brush *gpencil_brush_ensure(
return brush;
}
-/* Create a set of grease pencil Drawing presets. */
void BKE_brush_gpencil_paint_presets(Main *bmain, ToolSettings *ts, const bool reset)
{
bool r_new = false;
@@ -1422,7 +1425,6 @@ void BKE_brush_gpencil_paint_presets(Main *bmain, ToolSettings *ts, const bool r
}
}
-/* Create a set of grease pencil Vertex Paint presets. */
void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts, const bool reset)
{
bool r_new = false;
@@ -1469,7 +1471,6 @@ void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts, const bool
}
}
-/* Create a set of grease pencil Sculpt Paint presets. */
void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts, const bool reset)
{
bool r_new = false;
@@ -1544,7 +1545,6 @@ void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts, const bool
}
}
-/* Create a set of grease pencil Weight Paint presets. */
void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts, const bool reset)
{
bool r_new = false;
@@ -1946,9 +1946,6 @@ void BKE_brush_sculpt_reset(Brush *br)
}
}
-/**
- * Library Operations
- */
void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset)
{
CurveMapping *cumap = NULL;
@@ -1966,10 +1963,6 @@ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset)
BKE_curvemapping_changed(cumap, false);
}
-/* Generic texture sampler for 3D painting systems. point has to be either in
- * region space mouse coordinates, or 3d world coordinates for 3D mapping.
- *
- * rgba outputs straight alpha. */
float BKE_brush_sample_tex_3d(const Scene *scene,
const Brush *br,
const float point[3],
@@ -2362,7 +2355,6 @@ void BKE_brush_weight_set(const Scene *scene, Brush *brush, float value)
}
}
-/* scale unprojected radius to reflect a change in the brush's 2D size */
void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
int new_brush_size,
int old_brush_size)
@@ -2375,7 +2367,6 @@ void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
(*unprojected_radius) *= scale;
}
-/* scale brush size to reflect a change in the brush's unprojected radius */
void BKE_brush_scale_size(int *r_brush_size,
float new_unprojected_radius,
float old_unprojected_radius)
@@ -2426,7 +2417,6 @@ void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
}
}
-/* Uses the brush curve control to find a strength value */
float BKE_brush_curve_strength(const Brush *br, float p, const float len)
{
float strength = 1.0f;
@@ -2474,8 +2464,7 @@ float BKE_brush_curve_strength(const Brush *br, float p, const float len)
return strength;
}
-/* Uses the brush curve control to find a strength value between 0 and 1 */
-float BKE_brush_curve_strength_clamped(Brush *br, float p, const float len)
+float BKE_brush_curve_strength_clamped(const Brush *br, float p, const float len)
{
float strength = BKE_brush_curve_strength(br, p, len);
@@ -2517,7 +2506,6 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec
return texcache;
}
-/**** Radial Control ****/
struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool display_gradient)
{
ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc
index 1f92f834972..a68119fbc1d 100644
--- a/source/blender/blenkernel/intern/bvhutils.cc
+++ b/source/blender/blenkernel/intern/bvhutils.cc
@@ -125,7 +125,7 @@ bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
return false;
}
-BVHCache *bvhcache_init(void)
+BVHCache *bvhcache_init()
{
BVHCache *cache = (BVHCache *)MEM_callocN(sizeof(BVHCache), __func__);
BLI_mutex_init(&cache->mutex);
@@ -147,9 +147,6 @@ static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType typ
item->is_filled = true;
}
-/**
- * frees a bvhcache
- */
void bvhcache_free(BVHCache *bvh_cache)
{
for (int index = 0; index < BVHTREE_MAX_ITEM; index++) {
@@ -184,6 +181,7 @@ static void bvhtree_balance(BVHTree *tree, const bool isolate)
}
/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Local Callbacks
* \{ */
@@ -669,9 +667,6 @@ static void bvhtree_from_mesh_verts_setup_data(BVHTreeFromMesh *data,
data->vert_allocated = vert_allocated;
}
-/**
- * Builds a BVH-tree where nodes are the vertices of the given `em`.
- */
BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
BMEditMesh *em,
const BLI_bitmap *verts_mask,
@@ -727,13 +722,6 @@ BVHTree *bvhtree_from_editmesh_verts(
data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr);
}
-/**
- * Builds a BVH-tree where nodes are the given vertices (NOTE: does not copy given `vert`!).
- * \param vert_allocated: if true, vert freeing will be done when freeing data.
- * \param verts_mask: if not null, true elements give which vert to add to BVH-tree.
- * \param verts_num_active: if >= 0, number of active verts to add to BVH-tree
- * (else will be computed from mask).
- */
BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
const MVert *vert,
const int verts_num,
@@ -884,9 +872,6 @@ static void bvhtree_from_mesh_edges_setup_data(BVHTreeFromMesh *data,
data->edge_allocated = edge_allocated;
}
-/**
- * Builds a BVH-tree where nodes are the edges of the given `em`.
- */
BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
BMEditMesh *em,
const BLI_bitmap *edges_mask,
@@ -941,14 +926,6 @@ BVHTree *bvhtree_from_editmesh_edges(
data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr);
}
-/**
- * Builds a BVH-tree where nodes are the given edges.
- * \param vert, vert_allocated: if true, elem freeing will be done when freeing data.
- * \param edge, edge_allocated: if true, elem freeing will be done when freeing data.
- * \param edges_mask: if not null, true elements give which vert to add to BVH-tree.
- * \param edges_num_active: if >= 0, number of active edges to add to BVH-tree
- * (else will be computed from mask).
- */
BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
const MVert *vert,
const bool vert_allocated,
@@ -1075,15 +1052,6 @@ static void bvhtree_from_mesh_faces_setup_data(BVHTreeFromMesh *data,
data->face_allocated = face_allocated;
}
-/**
- * Builds a BVH-tree where nodes are the given tessellated faces
- * (NOTE: does not copy given mfaces!).
- * \param vert_allocated: if true, vert freeing will be done when freeing data.
- * \param face_allocated: if true, face freeing will be done when freeing data.
- * \param faces_mask: if not null, true elements give which faces to add to BVH-tree.
- * \param faces_num_active: if >= 0, number of active faces to add to BVH-tree
- * (else will be computed from mask).
- */
BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data,
const MVert *vert,
const bool vert_allocated,
@@ -1257,9 +1225,6 @@ static void bvhtree_from_mesh_looptri_setup_data(BVHTreeFromMesh *data,
data->looptri_allocated = looptri_allocated;
}
-/**
- * Builds a BVH-tree where nodes are the `looptri` faces of the given `bm`.
- */
BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
BMEditMesh *em,
const BLI_bitmap *looptri_mask,
@@ -1314,11 +1279,6 @@ BVHTree *bvhtree_from_editmesh_looptri(
data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr);
}
-/**
- * Builds a BVH-tree where nodes are the looptri faces of the given mesh.
- *
- * \note for edit-mesh this is currently a duplicate of #bvhtree_from_mesh_faces_ex
- */
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
const struct MVert *vert,
const bool vert_allocated,
@@ -1461,12 +1421,6 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly,
return looptri_mask;
}
-/**
- * Builds or queries a bvhcache for the cache bvhtree of the request type.
- *
- * \note This function only fills a cache, and therefore the mesh argument can
- * be considered logically const. Concurrent access is protected by a mutex.
- */
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
const struct Mesh *mesh,
const BVHCacheType bvh_cache_type,
@@ -1650,9 +1604,6 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
return tree;
}
-/**
- * Builds or queries a bvhcache for the cache bvhtree of the request type.
- */
BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const int tree_type,
@@ -1767,9 +1718,10 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
/** \} */
-/**
- * Frees data allocated by a call to `bvhtree_from_editmesh_*`.
- */
+/* -------------------------------------------------------------------- */
+/** \name Free Functions
+ * \{ */
+
void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
{
if (data->tree) {
@@ -1780,9 +1732,6 @@ void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
}
}
-/**
- * Frees data allocated by a call to `bvhtree_from_mesh_*`.
- */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
{
if (data->tree && !data->cached) {
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index e642bbc9e06..8833f3eabe9 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -40,6 +40,7 @@
#include "BLT_translation.h"
#include "BKE_anim_data.h"
+#include "BKE_bpath.h"
#include "BKE_cachefile.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
@@ -94,6 +95,12 @@ static void cache_file_free_data(ID *id)
BLI_freelistN(&cache_file->object_paths);
}
+static void cache_file_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ CacheFile *cache_file = (CacheFile *)id;
+ BKE_bpath_foreach_path_fixed_process(bpath_data, cache_file->filepath);
+}
+
static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
CacheFile *cache_file = (CacheFile *)id;
@@ -134,6 +141,7 @@ IDTypeInfo IDType_ID_CF = {
.name_plural = "cache_files",
.translation_context = BLT_I18NCONTEXT_ID_CACHEFILE,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = cache_file_init_data,
.copy_data = cache_file_copy_data,
@@ -141,6 +149,7 @@ IDTypeInfo IDType_ID_CF = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = cache_file_foreach_path,
.owner_get = NULL,
.blend_write = cache_file_blend_write,
@@ -411,12 +420,6 @@ float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, c
return cache_file->is_sequence ? frame : frame / fps - time_offset;
}
-/**
- * Determine whether the #CacheFile should use a render engine procedural. If so, data is not read
- * from the file and bounding boxes are used to represent the objects in the Scene.
- * Render engines will receive the bounding box as a placeholder but can instead
- * load the data directly if they support it.
- */
bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file,
Scene *scene,
const int dag_eval_mode)
diff --git a/source/blender/blenkernel/intern/callbacks.c b/source/blender/blenkernel/intern/callbacks.c
index 72dd51a940d..992eb896d2d 100644
--- a/source/blender/blenkernel/intern/callbacks.c
+++ b/source/blender/blenkernel/intern/callbacks.c
@@ -115,7 +115,6 @@ void BKE_callback_global_init(void)
callbacks_initialized = true;
}
-/* call on application exit */
void BKE_callback_global_finalize(void)
{
eCbEvent evt;
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index d355de73170..7940936b64a 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -182,6 +182,7 @@ IDTypeInfo IDType_ID_CA = {
.name_plural = "cameras",
.translation_context = BLT_I18NCONTEXT_ID_CAMERA,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = camera_init_data,
.copy_data = camera_copy_data,
@@ -189,6 +190,7 @@ IDTypeInfo IDType_ID_CA = {
.make_local = NULL,
.foreach_id = camera_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = camera_blend_write,
@@ -216,7 +218,6 @@ void *BKE_camera_add(Main *bmain, const char *name)
return cam;
}
-/* get the camera's dof value, takes the dof object into account */
float BKE_camera_object_dof_distance(Object *ob)
{
Camera *cam = (Camera *)ob->data;
@@ -425,7 +426,6 @@ void BKE_camera_params_compute_viewplane(
params->viewplane = viewplane;
}
-/* viewplane is assumed to be already computed */
void BKE_camera_params_compute_matrix(CameraParams *params)
{
rctf viewplane = params->viewplane;
@@ -756,8 +756,6 @@ static bool camera_frame_fit_calc_from_data(CameraParams *params,
return false;
}
-/* don't move the camera, just yield the fit location */
-/* r_scale only valid/useful for ortho cameras */
bool BKE_camera_view_frame_fit_to_scene(
Depsgraph *depsgraph, const Scene *scene, Object *camera_ob, float r_co[3], float *r_scale)
{
@@ -908,7 +906,6 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
}
-/* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
void BKE_camera_multiview_view_matrix(const RenderData *rd,
const Object *camera,
const bool is_left,
@@ -1031,7 +1028,6 @@ static Object *camera_multiview_advanced(const Scene *scene, Object *camera, con
return camera;
}
-/* returns the camera to be used for render */
Object *BKE_camera_multiview_render(const Scene *scene, Object *camera, const char *viewname)
{
const bool is_multiview = (camera != NULL) && (scene->r.scemode & R_MULTIVIEW) != 0;
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 080a7c90c46..42633ff3809 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -326,6 +326,7 @@ static int do_step_cloth(
/************************************************
* clothModifier_do - main simulation function
************************************************/
+
void clothModifier_do(ClothModifierData *clmd,
Depsgraph *depsgraph,
Scene *scene,
@@ -433,7 +434,6 @@ void clothModifier_do(ClothModifierData *clmd,
clmd->clothObject->last_frame = framenr;
}
-/* frees all */
void cloth_free_modifier(ClothModifierData *clmd)
{
Cloth *cloth = NULL;
@@ -504,7 +504,6 @@ void cloth_free_modifier(ClothModifierData *clmd)
}
}
-/* frees all */
void cloth_free_modifier_extern(ClothModifierData *clmd)
{
Cloth *cloth = NULL;
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 22b939d3cf9..21a9159004f 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -375,6 +375,7 @@ IDTypeInfo IDType_ID_GR = {
.name_plural = "collections",
.translation_context = BLT_I18NCONTEXT_ID_COLLECTION,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = collection_init_data,
.copy_data = collection_copy_data,
@@ -382,6 +383,7 @@ IDTypeInfo IDType_ID_GR = {
.make_local = NULL,
.foreach_id = collection_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = collection_owner_get,
.blend_write = collection_blend_write,
@@ -429,10 +431,6 @@ static Collection *collection_add(Main *bmain,
return collection;
}
-/**
- * Add a collection to a collection ListBase and synchronize all render layers
- * The ListBase is NULL when the collection is to be added to the master collection
- */
Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
{
Collection *collection = collection_add(bmain, collection_parent, name_custom);
@@ -440,12 +438,6 @@ Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const
return collection;
}
-/**
- * Add \a collection_dst to all scene collections that reference object \a ob_src is in.
- * Used to replace an instance object with a collection (library override operator).
- *
- * Logic is very similar to #BKE_collection_object_add_from().
- */
void BKE_collection_add_from_object(Main *bmain,
Scene *scene,
const Object *ob_src,
@@ -468,12 +460,6 @@ void BKE_collection_add_from_object(Main *bmain,
BKE_main_collection_sync(bmain);
}
-/**
- * Add \a collection_dst to all scene collections that reference collection \a collection_src is
- * in.
- *
- * Logic is very similar to #BKE_collection_object_add_from().
- */
void BKE_collection_add_from_collection(Main *bmain,
Scene *scene,
Collection *collection_src,
@@ -507,17 +493,12 @@ void BKE_collection_add_from_collection(Main *bmain,
/** \name Free and Delete Collection
* \{ */
-/** Free (or release) any data used by this collection (does not free the collection itself). */
void BKE_collection_free_data(Collection *collection)
{
BKE_libblock_free_data(&collection->id, false);
collection_free_data(&collection->id);
}
-/**
- * Remove a collection, optionally removing its child objects or moving
- * them to parent collections.
- */
bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
{
/* Master collection is not real datablock, can't be removed. */
@@ -678,14 +659,6 @@ static Collection *collection_duplicate_recursive(Main *bmain,
return collection_new;
}
-/**
- * Make a deep copy (aka duplicate) of the given collection and all of its children, recursively.
- *
- * \warning This functions will clear all \a bmain #ID.idnew pointers, unless \a
- * #LIB_ID_DUPLICATE_IS_SUBPROCESS duplicate option is passed on, in which case caller is
- * responsible to reconstruct collection dependencies information's
- * (i.e. call #BKE_main_collection_sync).
- */
Collection *BKE_collection_duplicate(Main *bmain,
Collection *parent,
Collection *collection,
@@ -744,9 +717,6 @@ Collection *BKE_collection_duplicate(Main *bmain,
/** \name Collection Naming
* \{ */
-/**
- * The automatic/fallback name of a new collection.
- */
void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
{
char *name;
@@ -769,9 +739,6 @@ void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
MEM_freeN(name);
}
-/**
- * The name to show in the interface.
- */
const char *BKE_collection_ui_name_get(struct Collection *collection)
{
if (collection->flag & COLLECTION_IS_MASTER) {
@@ -1127,9 +1094,6 @@ static bool collection_object_remove(Main *bmain,
return true;
}
-/**
- * Add object to collection
- */
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
{
if (ELEM(NULL, collection, ob)) {
@@ -1158,12 +1122,6 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
return true;
}
-/**
- * Add \a ob_dst to all scene collections that reference object \a ob_src is in.
- * Used for copying objects.
- *
- * Logic is very similar to #BKE_collection_add_from_object()
- */
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
{
bool is_instantiated = false;
@@ -1186,9 +1144,6 @@ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, O
BKE_main_collection_sync(bmain);
}
-/**
- * Remove object from collection.
- */
bool BKE_collection_object_remove(Main *bmain,
Collection *collection,
Object *ob,
@@ -1236,9 +1191,6 @@ static bool scene_collections_object_remove(
return removed;
}
-/**
- * Remove object from all collections of scene
- */
bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
return scene_collections_object_remove(bmain, scene, ob, free_us, NULL);
@@ -1302,18 +1254,6 @@ static void collection_missing_parents_remove(Collection *collection)
}
}
-/**
- * Remove all NULL children from parent collections of changed \a collection.
- * This is used for library remapping, where these pointers have been set to NULL.
- * Otherwise this should never happen.
- *
- * \note caller must ensure #BKE_main_collection_sync_remap() is called afterwards!
- *
- * \param parent_collection: The collection owning the pointers that were remapped. May be \a NULL,
- * in which case whole \a bmain database of collections is checked.
- * \param child_collection: The collection that was remapped to another pointer. May be \a NULL,
- * in which case whole \a bmain database of collections is checked.
- */
void BKE_collections_child_remove_nulls(Main *bmain,
Collection *parent_collection,
Collection *child_collection)
@@ -1358,11 +1298,6 @@ void BKE_collections_child_remove_nulls(Main *bmain,
}
}
-/**
- * Move object from a collection into another
- *
- * If source collection is NULL move it from all the existing collections.
- */
void BKE_collection_object_move(
Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
{
@@ -1437,15 +1372,6 @@ static bool collection_instance_find_recursive(Collection *collection,
return false;
}
-/**
- * Find potential cycles in collections.
- *
- * \param new_ancestor: the potential new owner of given \a collection,
- * or the collection to check if the later is NULL.
- * \param collection: the collection we want to add to \a new_ancestor,
- * may be NULL if we just want to ensure \a new_ancestor does not already have cycles.
- * \return true if a cycle is found.
- */
bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection)
{
if (collection == new_ancestor) {
@@ -1509,12 +1435,6 @@ static bool collection_cycle_fix_recursive(Main *bmain,
return cycles_found;
}
-/**
- * Find and fix potential cycles in collections.
- *
- * \param collection: The collection to check for existing cycles.
- * \return true if cycles are found and fixed.
- */
bool BKE_collection_cycles_fix(Main *bmain, Collection *collection)
{
return collection_cycle_fix_recursive(bmain, collection, collection) ||
@@ -1627,11 +1547,6 @@ bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *ch
return true;
}
-/**
- * Rebuild parent relationships from child ones, for all children of given \a collection.
- *
- * \note Given collection is assumed to already have valid parents.
- */
void BKE_collection_parent_relations_rebuild(Collection *collection)
{
LISTBASE_FOREACH_MUTABLE (CollectionChild *, child, &collection->children) {
@@ -1680,9 +1595,6 @@ static void collection_parents_rebuild_recursive(Collection *collection)
}
}
-/**
- * Rebuild parent relationships from child ones, for all collections in given \a bmain.
- */
void BKE_main_collections_parent_relations_rebuild(Main *bmain)
{
/* Only collections not in bmain (master ones in scenes) have no parent... */
@@ -1743,11 +1655,6 @@ static Collection *collection_from_index_recursive(Collection *collection,
return NULL;
}
-/**
- * Return Scene Collection for a given index.
- *
- * The index is calculated from top to bottom counting the children before the siblings.
- */
Collection *BKE_collection_from_index(Scene *scene, const int index)
{
int index_current = 0;
@@ -1791,10 +1698,6 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect
return changed;
}
-/**
- * Select all the objects in this Collection (and its nested collections) for this ViewLayer.
- * Return true if any object was selected.
- */
bool BKE_collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
{
LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer,
@@ -1920,10 +1823,6 @@ static void scene_collections_array(Scene *scene,
scene_collection_callback(collection, scene_collections_build_array, &array);
}
-/**
- * Only use this in non-performance critical situations
- * (it iterates over all scene collections twice)
- */
void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
{
Scene *scene = data_in;
@@ -2065,13 +1964,6 @@ void BKE_scene_objects_iterator_end(BLI_Iterator *iter)
}
}
-/**
- * Generate a new GSet (or extend given `objects_gset` if not NULL) with all objects referenced by
- * all collections of given `scene`.
- *
- * \note This will include objects without a base currently
- * (because they would belong to excluded collections only e.g.).
- */
GSet *BKE_scene_objects_as_gset(Scene *scene, GSet *objects_gset)
{
BLI_Iterator iter;
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 03957d54629..671c6530685 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -78,7 +78,6 @@ typedef struct SelfColDetectData {
* Collision modifier code start
***********************************/
-/* step is limited from 0 (frame start position) to 1 (frame end position) */
void collision_move_object(CollisionModifierData *collmd,
const float step,
const float prevstep,
@@ -1261,9 +1260,6 @@ static void add_collision_object(ListBase *relations,
}
}
-/* Create list of collision relations in the collection or entire scene.
- * This is used by the depsgraph to build relations, as well as faster
- * lookup of colliders during evaluation. */
ListBase *BKE_collision_relations_create(Depsgraph *depsgraph,
Collection *collection,
unsigned int modifier_type)
@@ -1292,8 +1288,6 @@ void BKE_collision_relations_free(ListBase *relations)
}
}
-/* Create effective list of colliders from relations built beforehand.
- * Self will be excluded. */
Object **BKE_collision_objects_create(Depsgraph *depsgraph,
Object *self,
Collection *collection,
@@ -1341,8 +1335,6 @@ void BKE_collision_objects_free(Object **objects)
}
}
-/* Create effective list of colliders from relations built beforehand.
- * Self will be excluded. */
ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collection *collection)
{
ListBase *relations = DEG_get_collision_relations(
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 62b817487fc..b12b19453ae 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -183,7 +183,6 @@ void BKE_curvemapping_set_black_white(CurveMapping *cumap,
/* ***************** operations on single curve ************* */
/* ********** NOTE: requires BKE_curvemapping_changed() call after ******** */
-/* remove specified point */
bool BKE_curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point)
{
CurveMapPoint *cmp;
@@ -213,7 +212,6 @@ bool BKE_curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point)
return (removed != 0);
}
-/* removes with flag set */
void BKE_curvemap_remove(CurveMap *cuma, const short flag)
{
CurveMapPoint *cmp = MEM_mallocN((cuma->totpoint) * sizeof(CurveMapPoint), "curve points");
@@ -439,9 +437,6 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
}
}
-/**
- * \param type: eBezTriple_Handle
- */
void BKE_curvemap_handle_set(CurveMap *cuma, int type)
{
int a;
@@ -800,10 +795,10 @@ static void curvemap_make_table(const CurveMapping *cumap, CurveMap *cuma)
cuma->table = cmp;
}
-/* call when you do images etc, needs restore too. also verifies tables */
-/* it uses a flag to prevent premul or free to happen twice */
-void BKE_curvemapping_premultiply(CurveMapping *cumap, int restore)
+void BKE_curvemapping_premultiply(CurveMapping *cumap, bool restore)
{
+ /* It uses a flag to prevent pre-multiply or free to happen twice. */
+
int a;
if (restore) {
@@ -873,7 +868,6 @@ static int sort_curvepoints(const void *a1, const void *a2)
/* ************************ more CurveMapping calls *************** */
-/* NOTE: only does current curvemap! */
void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
{
CurveMap *cuma = cumap->cm + cumap->cur;
@@ -965,13 +959,11 @@ void BKE_curvemapping_changed_all(CurveMapping *cumap)
cumap->cur = cur;
}
-/* Reset the view for current curve. */
void BKE_curvemapping_reset_view(CurveMapping *cumap)
{
cumap->curr = cumap->clipr;
}
-/* table should be verified */
float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value)
{
/* index in table */
@@ -994,7 +986,6 @@ float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, fl
return (1.0f - fi) * cuma->table[i].y + (fi)*cuma->table[i + 1].y;
}
-/* works with curve 'cur' */
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
{
const CurveMap *cuma = cumap->cm + cur;
@@ -1013,7 +1004,6 @@ float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value
return val;
}
-/* vector case */
void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3])
{
vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], vecin[0]);
@@ -1021,7 +1011,6 @@ void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], con
vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], vecin[2]);
}
-/* RGB case, no black/white points, no premult */
void BKE_curvemapping_evaluateRGBF(const CurveMapping *cumap,
float vecout[3],
const float vecin[3])
@@ -1052,16 +1041,6 @@ static void curvemapping_evaluateRGBF_filmlike(const CurveMapping *cumap,
vecout[channel_offset[2]] = v2;
}
-/**
- * Same as #BKE_curvemapping_evaluate_premulRGBF
- * but black/bwmul are passed as args for the compositor
- * where they can change per pixel.
- *
- * Use in conjunction with #BKE_curvemapping_set_black_white_ex
- *
- * \param black: Use instead of cumap->black
- * \param bwmul: Use instead of cumap->bwmul
- */
void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap,
float vecout[3],
const float vecin[3],
@@ -1127,7 +1106,6 @@ void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap,
}
}
-/* RGB with black/white points and premult. tables are checked */
void BKE_curvemapping_evaluate_premulRGBF(const CurveMapping *cumap,
float vecout[3],
const float vecin[3])
@@ -1135,7 +1113,6 @@ void BKE_curvemapping_evaluate_premulRGBF(const CurveMapping *cumap,
BKE_curvemapping_evaluate_premulRGBF_ex(cumap, vecout, vecin, cumap->black, cumap->bwmul);
}
-/* same as above, byte version */
void BKE_curvemapping_evaluate_premulRGB(const CurveMapping *cumap,
unsigned char vecout_byte[3],
const unsigned char vecin_byte[3])
@@ -1262,7 +1239,6 @@ void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping
}
}
-/* cumap itself has been read already. */
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
{
/* flag seems to be able to hang? Maybe old files... not bad to clear anyway */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 3455baa9292..d284c32b1df 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -123,7 +123,6 @@ static bConstraint *constraint_find_original_for_update(bConstraintOb *cob, bCon
/* -------------- Naming -------------- */
-/* Find the first available, non-duplicate name for a given constraint */
void BKE_constraint_unique_name(bConstraint *con, ListBase *list)
{
BLI_uniquename(list, con, DATA_("Const"), '.', offsetof(bConstraint, name), sizeof(con->name));
@@ -132,8 +131,6 @@ void BKE_constraint_unique_name(bConstraint *con, ListBase *list)
/* ----------------- Evaluation Loop Preparation --------------- */
/* package an object/bone for use in constraint evaluation */
-/* This function MEM_calloc's a bConstraintOb struct,
- * that will need to be freed after evaluation */
bConstraintOb *BKE_constraints_make_evalob(
Depsgraph *depsgraph, Scene *scene, Object *ob, void *subdata, short datatype)
{
@@ -211,7 +208,6 @@ bConstraintOb *BKE_constraints_make_evalob(
return cob;
}
-/* cleanup after constraint evaluation */
void BKE_constraints_clear_evalob(bConstraintOb *cob)
{
float delta[4][4], imat[4][4];
@@ -261,10 +257,6 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
/* -------------- Space-Conversion API -------------- */
-/* This function is responsible for the correct transformations/conversions
- * of a matrix from one space to another for constraint evaluation.
- * For now, this is only implemented for Objects and PoseChannels.
- */
void BKE_constraint_mat_convertspace(Object *ob,
bPoseChannel *pchan,
bConstraintOb *cob,
@@ -5556,9 +5548,6 @@ static void constraints_init_typeinfo(void)
constraintsTypeInfo[30] = &CTI_ARMATURE; /* Armature Constraint */
}
-/* This function should be used for getting the appropriate type-info when only
- * a constraint type is known
- */
const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type)
{
/* initialize the type-info list? */
@@ -5578,9 +5567,6 @@ const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type)
return NULL;
}
-/* This function should always be used to get the appropriate type-info, as it
- * has checks which prevent segfaults in some weird cases.
- */
const bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con)
{
/* only return typeinfo for valid constraints */
@@ -5611,11 +5597,6 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con),
}
}
-/**
- * Free data of a specific constraint if it has any info.
- * be sure to run #BIK_clear_data() when freeing an IK constraint,
- * unless DAG_relations_tag_update is called.
- */
void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user)
{
if (con->data) {
@@ -5643,7 +5624,6 @@ void BKE_constraint_free_data(bConstraint *con)
BKE_constraint_free_data_ex(con, true);
}
-/* Free all constraints from a constraint-stack */
void BKE_constraints_free_ex(ListBase *list, bool do_id_user)
{
/* Free constraint data and also any extra data */
@@ -5660,7 +5640,6 @@ void BKE_constraints_free(ListBase *list)
BKE_constraints_free_ex(list, true);
}
-/* Remove the specified constraint from the given constraint stack */
bool BKE_constraint_remove(ListBase *list, bConstraint *con)
{
if (con) {
@@ -5686,7 +5665,6 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool
return false;
}
-/* Apply the specified constraint in the given constraint stack */
bool BKE_constraint_apply_for_object(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -5920,7 +5898,6 @@ bool BKE_constraint_target_uses_bbone(struct bConstraint *con,
/* ......... */
-/* Add new constraint for the given bone */
bConstraint *BKE_constraint_add_for_pose(Object *ob,
bPoseChannel *pchan,
const char *name,
@@ -5933,7 +5910,6 @@ bConstraint *BKE_constraint_add_for_pose(Object *ob,
return add_new_constraint(ob, pchan, name, type);
}
-/* Add new constraint for the given object */
bConstraint *BKE_constraint_add_for_object(Object *ob, const char *name, short type)
{
return add_new_constraint(ob, NULL, name, type);
@@ -5941,7 +5917,6 @@ bConstraint *BKE_constraint_add_for_object(Object *ob, const char *name, short t
/* ......... */
-/* Run the given callback on all ID-blocks in list of constraints */
void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *userdata)
{
LISTBASE_FOREACH (bConstraint *, con, conlist) {
@@ -6016,7 +5991,6 @@ static void constraint_copy_data_ex(bConstraint *dst,
}
}
-/** Allocate and duplicate a single constraint, outside of any object/pose context. */
bConstraint *BKE_constraint_duplicate_ex(bConstraint *src, const int flag, const bool do_extern)
{
bConstraint *dst = MEM_dupallocN(src);
@@ -6025,7 +5999,6 @@ bConstraint *BKE_constraint_duplicate_ex(bConstraint *src, const int flag, const
return dst;
}
-/* Add a copy of the given constraint for the given bone */
bConstraint *BKE_constraint_copy_for_pose(Object *ob, bPoseChannel *pchan, bConstraint *src)
{
if (pchan == NULL) {
@@ -6037,7 +6010,6 @@ bConstraint *BKE_constraint_copy_for_pose(Object *ob, bPoseChannel *pchan, bCons
return new_con;
}
-/* Add a copy of the given constraint for the given object */
bConstraint *BKE_constraint_copy_for_object(Object *ob, bConstraint *src)
{
bConstraint *new_con = BKE_constraint_duplicate_ex(src, 0, !ID_IS_LINKED(ob));
@@ -6045,7 +6017,6 @@ bConstraint *BKE_constraint_copy_for_object(Object *ob, bConstraint *src)
return new_con;
}
-/* duplicate all of the constraints in a constraint stack */
void BKE_constraints_copy_ex(ListBase *dst, const ListBase *src, const int flag, bool do_extern)
{
bConstraint *con, *srccon;
@@ -6074,7 +6045,6 @@ bConstraint *BKE_constraints_find_name(ListBase *list, const char *name)
return BLI_findstring(list, name, offsetof(bConstraint, name));
}
-/* finds the 'active' constraint in a constraint stack */
bConstraint *BKE_constraints_active_get(ListBase *list)
{
@@ -6091,7 +6061,6 @@ bConstraint *BKE_constraints_active_get(ListBase *list)
return NULL;
}
-/* Set the given constraint as the active one (clearing all the others) */
void BKE_constraints_active_set(ListBase *list, bConstraint *con)
{
@@ -6127,7 +6096,6 @@ static bConstraint *constraint_list_find_from_target(ListBase *constraints, bCon
return NULL;
}
-/* Finds the constraint that owns the given target within the object. */
bConstraint *BKE_constraint_find_from_target(Object *ob,
bConstraintTarget *tgt,
bPoseChannel **r_pchan)
@@ -6225,12 +6193,6 @@ static bConstraint *constraint_find_original_for_update(bConstraintOb *cob, bCon
return orig_con;
}
-/**
- * Check whether given constraint is not local (i.e. from linked data) when the object is a library
- * override.
- *
- * \param con: May be NULL, in which case we consider it as a non-local constraint case.
- */
bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstraint *con)
{
return (ID_IS_OVERRIDE_LIBRARY(ob) &&
@@ -6239,8 +6201,6 @@ bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstrai
/* -------- Constraints and Proxies ------- */
-/* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL
- * (i.e. added to bone that's proxy-synced in this file) */
void BKE_constraints_proxylocal_extract(ListBase *dst, ListBase *src)
{
bConstraint *con, *next;
@@ -6257,7 +6217,6 @@ void BKE_constraints_proxylocal_extract(ListBase *dst, ListBase *src)
}
}
-/* Returns if the owner of the constraint is proxy-protected */
bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
{
/* Currently, constraints can only be on object or bone level */
@@ -6281,13 +6240,6 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
/* -------- Target-Matrix Stuff ------- */
-/* This function is a relic from the prior implementations of the constraints system, when all
- * constraints either had one or no targets. It used to be called during the main constraint
- * solving loop, but is now only used for the remaining cases for a few constraints.
- *
- * None of the actual calculations of the matrices should be done here! Also, this function is
- * not to be used by any new constraints, particularly any that have multiple targets.
- */
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
Scene *scene,
bConstraint *con,
@@ -6364,7 +6316,6 @@ void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
}
}
-/* Get the list of targets required for solving a constraint */
void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph,
bConstraint *con,
bConstraintOb *cob,
@@ -6434,12 +6385,6 @@ void BKE_constraint_custom_object_space_get(float r_mat[4][4], bConstraint *con)
/* ---------- Evaluation ----------- */
-/* This function is called whenever constraints need to be evaluated. Currently, all
- * constraints that can be evaluated are every time this gets run.
- *
- * BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and
- * after running this function, to sort out cob
- */
void BKE_constraints_solve(struct Depsgraph *depsgraph,
ListBase *conlist,
bConstraintOb *cob,
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index c235a1bbb6a..ceaed5d2bba 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -547,12 +547,6 @@ static void data_dir_add(ListBase *lb, const char *member, const bool use_all)
BLI_addtail(lb, link);
}
-/**
- * \param C: Context
- * \param use_store: Use 'C->wm.store'
- * \param use_rna: Use Include the properties from 'RNA_Context'
- * \param use_all: Don't skip values (currently only "scene")
- */
ListBase CTX_data_dir_get_ex(const bContext *C,
const bool use_store,
const bool use_rna,
@@ -1127,13 +1121,6 @@ RenderEngineType *CTX_data_engine_type(const bContext *C)
return RE_engines_find(scene->r.engine);
}
-/**
- * This is tricky. Sometimes the user overrides the render_layer
- * but not the scene_collection. In this case what to do?
- *
- * If the scene_collection is linked to the ViewLayer we use it.
- * Otherwise we fallback to the active one of the ViewLayer.
- */
LayerCollection *CTX_data_layer_collection(const bContext *C)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 26894495777..6bbb9957b03 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -98,7 +98,6 @@ static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob)
return disabled;
}
-/* disable subsurf temporal, get mapped cos, and enable it */
float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, Object *obedit))[3]
{
Scene *scene = DEG_get_input_scene(depsgraph);
@@ -243,10 +242,6 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
}
}
-/**
- * Returns an array of deform matrices for crazy-space correction,
- * and the number of modifiers left.
- */
int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc
index 1ff0ca92306..d532ed9e4b2 100644
--- a/source/blender/blenkernel/intern/cryptomatte.cc
+++ b/source/blender/blenkernel/intern/cryptomatte.cc
@@ -139,7 +139,7 @@ std::optional<std::string> CryptomatteSession::operator[](float encoded_hash) co
return std::nullopt;
}
-CryptomatteSession *BKE_cryptomatte_init(void)
+CryptomatteSession *BKE_cryptomatte_init()
{
CryptomatteSession *session = new CryptomatteSession();
return session;
@@ -212,7 +212,6 @@ float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash)
return blender::bke::cryptomatte::CryptomatteHash(cryptomatte_hash).float_encoded();
}
-/* Find an ID in the given main that matches the given encoded float. */
bool BKE_cryptomatte_find_name(const CryptomatteSession *session,
const float encoded_hash,
char *r_name,
@@ -489,10 +488,6 @@ std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name, const Stri
return "cryptomatte/" + cryptomatte_layer_name_hash(layer_name) + "/" + key_name;
}
-/* Extracts the cryptomatte name from a render pass name.
- *
- * Example: A render pass could be named `CryptoObject00`. This
- * function would remove the trailing digits and return `CryptoObject`. */
StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name)
{
int64_t last_token = render_pass_name.size();
@@ -525,16 +520,6 @@ std::string CryptomatteHash::hex_encoded() const
return encoded.str();
}
-/* Convert a cryptomatte hash to a float.
- *
- * Cryptomatte hashes are stored in float textures and images. The conversion is taken from the
- * cryptomatte specification. See Floating point conversion section in
- * https://github.com/Psyop/Cryptomatte/blob/master/specification/cryptomatte_specification.pdf.
- *
- * The conversion uses as many 32 bit floating point values as possible to minimize hash
- * collisions. Unfortunately not all 32 bits can be used as NaN and Inf can be problematic.
- *
- * Note that this conversion assumes to be running on a L-endian system. */
float CryptomatteHash::float_encoded() const
{
uint32_t mantissa = hash & ((1 << 23) - 1);
@@ -626,7 +611,6 @@ void CryptomatteStampDataCallbackData::extract_layer_names(void *_data,
data->hash_to_layer_name.add(layer_hash, propvalue);
}
-/* C type callback function (StampCallback). */
void CryptomatteStampDataCallbackData::extract_layer_manifest(void *_data,
const char *propname,
char *propvalue,
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.cc
index aae9ac383a4..dc2527f9b62 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -21,9 +21,9 @@
* \ingroup bke
*/
-#include <math.h> /* floor */
-#include <stdlib.h>
-#include <string.h>
+#include <cmath> /* floor */
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -43,7 +43,7 @@
#include "DNA_defaults.h"
#include "DNA_material_types.h"
-/* for dereferencing pointers */
+/* For dereferencing pointers. */
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_vfont_types.h"
@@ -89,12 +89,12 @@ static void curve_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
BLI_listbase_clear(&curve_dst->nurb);
BKE_nurbList_duplicate(&(curve_dst->nurb), &(curve_src->nurb));
- curve_dst->mat = MEM_dupallocN(curve_src->mat);
+ curve_dst->mat = (Material **)MEM_dupallocN(curve_src->mat);
- curve_dst->str = MEM_dupallocN(curve_src->str);
- curve_dst->strinfo = MEM_dupallocN(curve_src->strinfo);
- curve_dst->tb = MEM_dupallocN(curve_src->tb);
- curve_dst->batch_cache = NULL;
+ curve_dst->str = (char *)MEM_dupallocN(curve_src->str);
+ curve_dst->strinfo = (CharInfo *)MEM_dupallocN(curve_src->strinfo);
+ curve_dst->tb = (TextBox *)MEM_dupallocN(curve_src->tb);
+ curve_dst->batch_cache = nullptr;
curve_dst->bevel_profile = BKE_curveprofile_copy(curve_src->bevel_profile);
@@ -104,8 +104,8 @@ static void curve_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
curve_dst->key->from = &curve_dst->id;
}
- curve_dst->editnurb = NULL;
- curve_dst->editfont = NULL;
+ curve_dst->editnurb = nullptr;
+ curve_dst->editfont = nullptr;
}
static void curve_free_data(ID *id)
@@ -148,9 +148,9 @@ static void curve_blend_write(BlendWriter *writer, ID *id, const void *id_addres
Curve *cu = (Curve *)id;
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
- cu->editnurb = NULL;
- cu->editfont = NULL;
- cu->batch_cache = NULL;
+ cu->editnurb = nullptr;
+ cu->editfont = nullptr;
+ cu->batch_cache = nullptr;
/* write LibData */
BLO_write_id_struct(writer, Curve, id_address, &cu->id);
@@ -188,7 +188,7 @@ static void curve_blend_write(BlendWriter *writer, ID *id, const void *id_addres
}
}
- if (cu->bevel_profile != NULL) {
+ if (cu->bevel_profile != nullptr) {
BKE_curveprofile_blend_write(writer, cu->bevel_profile);
}
}
@@ -218,13 +218,13 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &cu->strinfo);
BLO_read_data_address(reader, &cu->tb);
- if (cu->vfont == NULL) {
+ if (cu->vfont == nullptr) {
BLO_read_list(reader, &(cu->nurb));
}
else {
- cu->nurb.first = cu->nurb.last = NULL;
+ cu->nurb.first = cu->nurb.last = nullptr;
- TextBox *tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "TextBoxread");
+ TextBox *tb = (TextBox *)MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "TextBoxread");
if (cu->tb) {
memcpy(tb, cu->tb, cu->totbox * sizeof(TextBox));
MEM_freeN(cu->tb);
@@ -241,16 +241,16 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
}
}
- cu->editnurb = NULL;
- cu->editfont = NULL;
- cu->batch_cache = NULL;
+ cu->editnurb = nullptr;
+ cu->editfont = nullptr;
+ cu->batch_cache = nullptr;
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
BLO_read_data_address(reader, &nu->bezt);
BLO_read_data_address(reader, &nu->bp);
BLO_read_data_address(reader, &nu->knotsu);
BLO_read_data_address(reader, &nu->knotsv);
- if (cu->vfont == NULL) {
+ if (cu->vfont == nullptr) {
nu->charidx = 0;
}
@@ -261,7 +261,7 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
cu->texflag &= ~CU_AUTOSPACE_EVALUATED;
BLO_read_data_address(reader, &cu->bevel_profile);
- if (cu->bevel_profile != NULL) {
+ if (cu->bevel_profile != nullptr) {
BKE_curveprofile_blend_read(reader, cu->bevel_profile);
}
}
@@ -304,34 +304,35 @@ static void curve_blend_read_expand(BlendExpander *expander, ID *id)
}
IDTypeInfo IDType_ID_CU = {
- .id_code = ID_CU,
- .id_filter = FILTER_ID_CU,
- .main_listbase_index = INDEX_ID_CU,
- .struct_size = sizeof(Curve),
- .name = "Curve",
- .name_plural = "curves",
- .translation_context = BLT_I18NCONTEXT_ID_CURVE,
- .flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
-
- .init_data = curve_init_data,
- .copy_data = curve_copy_data,
- .free_data = curve_free_data,
- .make_local = NULL,
- .foreach_id = curve_foreach_id,
- .foreach_cache = NULL,
- .owner_get = NULL,
-
- .blend_write = curve_blend_write,
- .blend_read_data = curve_blend_read_data,
- .blend_read_lib = curve_blend_read_lib,
- .blend_read_expand = curve_blend_read_expand,
-
- .blend_read_undo_preserve = NULL,
-
- .lib_override_apply_post = NULL,
+ /* id_code */ ID_CU,
+ /* id_filter */ FILTER_ID_CU,
+ /* main_listbase_index */ INDEX_ID_CU,
+ /* struct_size */ sizeof(Curve),
+ /* name */ "Curve",
+ /* name_plural */ "curves",
+ /* translation_context */ BLT_I18NCONTEXT_ID_CURVE,
+ /* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ /* asset_type_info */ nullptr,
+
+ /* init_data */ curve_init_data,
+ /* copy_data */ curve_copy_data,
+ /* free_data */ curve_free_data,
+ /* make_local */ nullptr,
+ /* foreach_id */ curve_foreach_id,
+ /* foreach_cache */ nullptr,
+ /* foreach_path */ nullptr,
+ /* owner_get */ nullptr,
+
+ /* blend_write */ curve_blend_write,
+ /* blend_read_data */ curve_blend_read_data,
+ /* blend_read_lib */ curve_blend_read_lib,
+ /* blend_read_expand */ curve_blend_read_expand,
+
+ /* blend_read_undo_preserve */ nullptr,
+
+ /* lib_override_apply_post */ nullptr,
};
-/* frees editcurve entirely */
void BKE_curve_editfont_free(Curve *cu)
{
if (cu->editfont) {
@@ -348,21 +349,21 @@ void BKE_curve_editfont_free(Curve *cu)
}
MEM_freeN(ef);
- cu->editfont = NULL;
+ cu->editfont = nullptr;
}
}
static void curve_editNurb_keyIndex_cv_free_cb(void *val)
{
- CVKeyIndex *index = val;
+ CVKeyIndex *index = (CVKeyIndex *)val;
MEM_freeN(index->orig_cv);
MEM_freeN(val);
}
void BKE_curve_editNurb_keyIndex_delCV(GHash *keyindex, const void *cv)
{
- BLI_assert(keyindex != NULL);
- BLI_ghash_remove(keyindex, cv, NULL, curve_editNurb_keyIndex_cv_free_cb);
+ BLI_assert(keyindex != nullptr);
+ BLI_ghash_remove(keyindex, cv, nullptr, curve_editNurb_keyIndex_cv_free_cb);
}
void BKE_curve_editNurb_keyIndex_free(GHash **keyindex)
@@ -370,8 +371,8 @@ void BKE_curve_editNurb_keyIndex_free(GHash **keyindex)
if (!(*keyindex)) {
return;
}
- BLI_ghash_free(*keyindex, NULL, curve_editNurb_keyIndex_cv_free_cb);
- *keyindex = NULL;
+ BLI_ghash_free(*keyindex, nullptr, curve_editNurb_keyIndex_cv_free_cb);
+ *keyindex = nullptr;
}
void BKE_curve_editNurb_free(Curve *cu)
@@ -380,7 +381,7 @@ void BKE_curve_editNurb_free(Curve *cu)
BKE_nurbList_free(&cu->editnurb->nurbs);
BKE_curve_editNurb_keyIndex_free(&cu->editnurb->keyindex);
MEM_freeN(cu->editnurb);
- cu->editnurb = NULL;
+ cu->editnurb = nullptr;
}
}
@@ -394,12 +395,12 @@ void BKE_curve_init(Curve *cu, const short curve_type)
cu->flag |= CU_FRONT | CU_BACK;
cu->vfont = cu->vfontb = cu->vfonti = cu->vfontbi = BKE_vfont_builtin_get();
cu->vfont->id.us += 4;
- cu->str = MEM_malloc_arrayN(12, sizeof(unsigned char), "str");
+ cu->str = (char *)MEM_malloc_arrayN(12, sizeof(unsigned char), "str");
BLI_strncpy(cu->str, "Text", 12);
cu->len = cu->len_char32 = cu->pos = 4;
- cu->strinfo = MEM_calloc_arrayN(12, sizeof(CharInfo), "strinfo new");
+ cu->strinfo = (CharInfo *)MEM_calloc_arrayN(12, sizeof(CharInfo), "strinfo new");
cu->totbox = cu->actbox = 1;
- cu->tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "textbox");
+ cu->tb = (TextBox *)MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "textbox");
cu->tb[0].w = cu->tb[0].h = 0.0;
}
else if (cu->type == OB_SURF) {
@@ -407,7 +408,7 @@ void BKE_curve_init(Curve *cu, const short curve_type)
cu->resolu = 4;
cu->resolv = 4;
}
- cu->bevel_profile = NULL;
+ cu->bevel_profile = nullptr;
}
Curve *BKE_curve_add(Main *bmain, const char *name, int type)
@@ -415,21 +416,20 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
Curve *cu;
/* We cannot use #BKE_id_new here as we need some custom initialization code. */
- cu = BKE_libblock_alloc(bmain, ID_CU, name, 0);
+ cu = (Curve *)BKE_libblock_alloc(bmain, ID_CU, name, 0);
BKE_curve_init(cu, type);
return cu;
}
-/* Get list of nurbs from editnurbs structure */
ListBase *BKE_curve_editNurbs_get(Curve *cu)
{
if (cu->editnurb) {
return &cu->editnurb->nurbs;
}
- return NULL;
+ return nullptr;
}
const ListBase *BKE_curve_editNurbs_get_for_read(const Curve *cu)
@@ -438,7 +438,7 @@ const ListBase *BKE_curve_editNurbs_get_for_read(const Curve *cu)
return &cu->editnurb->nurbs;
}
- return NULL;
+ return nullptr;
}
short BKE_curve_type_get(const Curve *cu)
@@ -481,10 +481,10 @@ void BKE_curve_dimension_update(Curve *cu)
void BKE_curve_type_test(Object *ob)
{
- ob->type = BKE_curve_type_get(ob->data);
+ ob->type = BKE_curve_type_get((Curve *)ob->data);
if (ob->type == OB_CURVE) {
- Curve *cu = ob->data;
+ Curve *cu = (Curve *)ob->data;
if (CU_IS_2D(cu)) {
BKE_curve_dimension_update(cu);
}
@@ -495,15 +495,15 @@ BoundBox *BKE_curve_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) {
- Curve *cu = ob->data;
+ if (ob->runtime.bb == nullptr || ob->runtime.bb->flag & BOUNDBOX_DIRTY) {
+ Curve *cu = (Curve *)ob->data;
float min[3], max[3];
INIT_MINMAX(min, max);
BKE_curve_minmax(cu, true, min, max);
- 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;
@@ -618,26 +618,26 @@ int BKE_nurbList_verts_count_without_handles(const ListBase *nurb)
void BKE_nurb_free(Nurb *nu)
{
- if (nu == NULL) {
+ if (nu == nullptr) {
return;
}
if (nu->bezt) {
MEM_freeN(nu->bezt);
}
- nu->bezt = NULL;
+ nu->bezt = nullptr;
if (nu->bp) {
MEM_freeN(nu->bp);
}
- nu->bp = NULL;
+ nu->bp = nullptr;
if (nu->knotsu) {
MEM_freeN(nu->knotsu);
}
- nu->knotsu = NULL;
+ nu->knotsu = nullptr;
if (nu->knotsv) {
MEM_freeN(nu->knotsv);
}
- nu->knotsv = NULL;
+ nu->knotsv = nullptr;
// if (nu->trim.first) freeNurblist(&(nu->trim));
MEM_freeN(nu);
@@ -645,7 +645,7 @@ void BKE_nurb_free(Nurb *nu)
void BKE_nurbList_free(ListBase *lb)
{
- if (lb == NULL) {
+ if (lb == nullptr) {
return;
}
@@ -661,8 +661,8 @@ Nurb *BKE_nurb_duplicate(const Nurb *nu)
int len;
newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "duplicateNurb");
- if (newnu == NULL) {
- return NULL;
+ if (newnu == nullptr) {
+ return nullptr;
}
memcpy(newnu, nu, sizeof(Nurb));
@@ -675,19 +675,19 @@ Nurb *BKE_nurb_duplicate(const Nurb *nu)
newnu->bp = (BPoint *)MEM_malloc_arrayN(len, sizeof(BPoint), "duplicateNurb3");
memcpy(newnu->bp, nu->bp, len * sizeof(BPoint));
- newnu->knotsu = newnu->knotsv = NULL;
+ newnu->knotsu = newnu->knotsv = nullptr;
if (nu->knotsu) {
len = KNOTSU(nu);
if (len) {
- newnu->knotsu = MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb4");
+ newnu->knotsu = (float *)MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb4");
memcpy(newnu->knotsu, nu->knotsu, sizeof(float) * len);
}
}
if (nu->pntsv > 1 && nu->knotsv) {
len = KNOTSV(nu);
if (len) {
- newnu->knotsv = MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb5");
+ newnu->knotsv = (float *)MEM_malloc_arrayN(len, sizeof(float), "duplicateNurb5");
memcpy(newnu->knotsv, nu->knotsv, sizeof(float) * len);
}
}
@@ -695,7 +695,6 @@ Nurb *BKE_nurb_duplicate(const Nurb *nu)
return newnu;
}
-/* copy the nurb but allow for different number of points (to be copied after this) */
Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
{
Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb");
@@ -708,8 +707,8 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
newnu->pntsv = pntsv;
/* caller can manually handle these arrays */
- newnu->knotsu = NULL;
- newnu->knotsv = NULL;
+ newnu->knotsu = nullptr;
+ newnu->knotsv = nullptr;
if (src->bezt) {
newnu->bezt = (BezTriple *)MEM_malloc_arrayN(pntsu * pntsv, sizeof(BezTriple), "copyNurb2");
@@ -757,10 +756,6 @@ void BKE_nurb_project_2d(Nurb *nu)
}
}
-/**
- * if use_radius is truth, minmax will take points' radius into account,
- * which will make boundbox closer to beveled curve.
- */
void BKE_nurb_minmax(const Nurb *nu, bool use_radius, float min[3], float max[3])
{
BezTriple *bezt;
@@ -842,7 +837,7 @@ float BKE_nurb_calc_length(const Nurb *nu, int resolution)
}
}
else if (nu->type == CU_BEZIER) {
- points = MEM_mallocN(sizeof(float[3]) * (resolu + 1), "getLength_bezier");
+ points = (float *)MEM_mallocN(sizeof(float[3]) * (resolu + 1), "getLength_bezier");
a = nu->pntsu - 1;
bezt = nu->bezt;
if (nu->flagu & CU_NURB_CYCLIC) {
@@ -886,9 +881,9 @@ float BKE_nurb_calc_length(const Nurb *nu, int resolution)
else if (nu->type == CU_NURBS) {
if (nu->pntsv == 1) {
/* important to zero for BKE_nurb_makeCurve. */
- points = MEM_callocN(sizeof(float[3]) * pntsu * resolu, "getLength_nurbs");
+ points = (float *)MEM_callocN(sizeof(float[3]) * pntsu * resolu, "getLength_nurbs");
- BKE_nurb_makeCurve(nu, points, NULL, NULL, NULL, resolu, sizeof(float[3]));
+ BKE_nurb_makeCurve(nu, points, nullptr, nullptr, nullptr, resolu, sizeof(float[3]));
if (nu->flagu & CU_NURB_CYCLIC) {
b = pntsu * resolu + 1;
@@ -914,10 +909,9 @@ float BKE_nurb_calc_length(const Nurb *nu, int resolution)
return length;
}
-/* be sure to call makeknots after this */
void BKE_nurb_points_add(Nurb *nu, int number)
{
- nu->bp = MEM_recallocN(nu->bp, (nu->pntsu + number) * sizeof(BPoint));
+ nu->bp = (BPoint *)MEM_recallocN(nu->bp, (nu->pntsu + number) * sizeof(BPoint));
BPoint *bp;
int i;
@@ -933,7 +927,7 @@ void BKE_nurb_bezierPoints_add(Nurb *nu, int number)
BezTriple *bezt;
int i;
- nu->bezt = MEM_recallocN(nu->bezt, (nu->pntsu + number) * sizeof(BezTriple));
+ nu->bezt = (BezTriple *)MEM_recallocN(nu->bezt, (nu->pntsu + number) * sizeof(BezTriple));
for (i = 0, bezt = &nu->bezt[nu->pntsu]; i < number; i++, bezt++) {
bezt->radius = 1.0f;
@@ -984,7 +978,7 @@ BezTriple *BKE_nurb_bezt_get_next(Nurb *nu, BezTriple *bezt)
bezt_next = nu->bezt;
}
else {
- bezt_next = NULL;
+ bezt_next = nullptr;
}
}
else {
@@ -1005,7 +999,7 @@ BPoint *BKE_nurb_bpoint_get_next(Nurb *nu, BPoint *bp)
bp_next = nu->bp;
}
else {
- bp_next = NULL;
+ bp_next = nullptr;
}
}
else {
@@ -1027,7 +1021,7 @@ BezTriple *BKE_nurb_bezt_get_prev(Nurb *nu, BezTriple *bezt)
bezt_prev = &nu->bezt[nu->pntsu - 1];
}
else {
- bezt_prev = NULL;
+ bezt_prev = nullptr;
}
}
else {
@@ -1049,7 +1043,7 @@ BPoint *BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp)
bp_prev = &nu->bp[nu->pntsu - 1];
}
else {
- bp_prev = NULL;
+ bp_prev = nullptr;
}
}
else {
@@ -1217,7 +1211,7 @@ static void makecyclicknots(float *knots, int pnts, short order)
{
int a, b, order2, c;
- if (knots == NULL) {
+ if (knots == nullptr) {
return;
}
@@ -1252,7 +1246,7 @@ static void makeknots(Nurb *nu, short uv)
MEM_freeN(nu->knotsu);
}
if (BKE_nurb_check_valid_u(nu)) {
- nu->knotsu = MEM_calloc_arrayN(KNOTSU(nu) + 1, sizeof(float), "makeknots");
+ nu->knotsu = (float *)MEM_calloc_arrayN(KNOTSU(nu) + 1, sizeof(float), "makeknots");
if (nu->flagu & CU_NURB_CYCLIC) {
calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */
makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
@@ -1262,7 +1256,7 @@ static void makeknots(Nurb *nu, short uv)
}
}
else {
- nu->knotsu = NULL;
+ nu->knotsu = nullptr;
}
}
else if (uv == 2) {
@@ -1270,7 +1264,7 @@ static void makeknots(Nurb *nu, short uv)
MEM_freeN(nu->knotsv);
}
if (BKE_nurb_check_valid_v(nu)) {
- nu->knotsv = MEM_calloc_arrayN(KNOTSV(nu) + 1, sizeof(float), "makeknots");
+ nu->knotsv = (float *)MEM_calloc_arrayN(KNOTSV(nu) + 1, sizeof(float), "makeknots");
if (nu->flagv & CU_NURB_CYCLIC) {
calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */
makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
@@ -1280,7 +1274,7 @@ static void makeknots(Nurb *nu, short uv)
}
}
else {
- nu->knotsv = NULL;
+ nu->knotsv = nullptr;
}
}
}
@@ -1374,9 +1368,6 @@ static void basisNurb(
}
}
-/**
- * \param coord_array: has to be (3 * 4 * resolu * resolv) in size, and zero-ed.
- */
void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
{
BPoint *bp;
@@ -1387,7 +1378,7 @@ void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int r
int totu = nu->pntsu * resolu, totv = nu->pntsv * resolv;
- if (nu->knotsu == NULL || nu->knotsv == NULL) {
+ if (nu->knotsu == nullptr || nu->knotsv == nullptr) {
return;
}
if (nu->orderu > nu->pntsu) {
@@ -1396,7 +1387,7 @@ void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int r
if (nu->orderv > nu->pntsv) {
return;
}
- if (coord_array == NULL) {
+ if (coord_array == nullptr) {
return;
}
@@ -1447,7 +1438,7 @@ void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int r
jstart = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces4");
jend = (int *)MEM_malloc_arrayN(totv, sizeof(float), "makeNurbfaces5");
- /* precalculation of basisv and jstart, jend */
+ /* Pre-calculation of `basisv` and `jstart`, `jend`. */
if (nu->flagv & CU_NURB_CYCLIC) {
cycl = nu->orderv - 1;
}
@@ -1569,11 +1560,6 @@ void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int r
MEM_freeN(jend);
}
-/**
- * \param coord_array: Has to be 3 * 4 * pntsu * resolu in size and zero-ed
- * \param tilt_array: set when non-NULL
- * \param radius_array: set when non-NULL
- */
void BKE_nurb_makeCurve(const Nurb *nu,
float *coord_array,
float *tilt_array,
@@ -1590,13 +1576,13 @@ void BKE_nurb_makeCurve(const Nurb *nu,
*weight_fp = weight_array;
int i, len, istart, iend, cycl;
- if (nu->knotsu == NULL) {
+ if (nu->knotsu == nullptr) {
return;
}
if (nu->orderu > nu->pntsu) {
return;
}
- if (coord_array == NULL) {
+ if (coord_array == nullptr) {
return;
}
@@ -1690,16 +1676,16 @@ void BKE_nurb_makeCurve(const Nurb *nu,
}
}
- coord_fp = POINTER_OFFSET(coord_fp, stride);
+ coord_fp = (float *)POINTER_OFFSET(coord_fp, stride);
if (tilt_fp) {
- tilt_fp = POINTER_OFFSET(tilt_fp, stride);
+ tilt_fp = (float *)POINTER_OFFSET(tilt_fp, stride);
}
if (radius_fp) {
- radius_fp = POINTER_OFFSET(radius_fp, stride);
+ radius_fp = (float *)POINTER_OFFSET(radius_fp, stride);
}
if (weight_fp) {
- weight_fp = POINTER_OFFSET(weight_fp, stride);
+ weight_fp = (float *)POINTER_OFFSET(weight_fp, stride);
}
u += ustep;
@@ -1710,9 +1696,6 @@ void BKE_nurb_makeCurve(const Nurb *nu,
MEM_freeN(basisu);
}
-/**
- * Calculate the length for arrays filled in by #BKE_curve_calc_coords_axis.
- */
unsigned int BKE_curve_calc_coords_axis_len(const unsigned int bezt_array_len,
const unsigned int resolu,
const bool is_cyclic,
@@ -1724,12 +1707,6 @@ unsigned int BKE_curve_calc_coords_axis_len(const unsigned int bezt_array_len,
return points_len;
}
-/**
- * Calculate an array for the entire curve (cyclic or non-cyclic).
- * \note Call for each axis.
- *
- * \param use_cyclic_duplicate_endpoint: Duplicate values at the beginning & end of the array.
- */
void BKE_curve_calc_coords_axis(const BezTriple *bezt_array,
const unsigned int bezt_array_len,
const unsigned int resolu,
@@ -1757,7 +1734,7 @@ void BKE_curve_calc_coords_axis(const BezTriple *bezt_array,
r_points_offset,
(int)resolu,
stride);
- r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride);
+ r_points_offset = (float *)POINTER_OFFSET(r_points_offset, resolu_stride);
}
if (is_cyclic) {
@@ -1770,23 +1747,22 @@ void BKE_curve_calc_coords_axis(const BezTriple *bezt_array,
r_points_offset,
(int)resolu,
stride);
- r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride);
+ r_points_offset = (float *)POINTER_OFFSET(r_points_offset, resolu_stride);
if (use_cyclic_duplicate_endpoint) {
*r_points_offset = *r_points;
- r_points_offset = POINTER_OFFSET(r_points_offset, stride);
+ r_points_offset = (float *)POINTER_OFFSET(r_points_offset, stride);
}
}
else {
- float *r_points_last = POINTER_OFFSET(r_points, bezt_array_last * resolu_stride);
+ float *r_points_last = (float *)POINTER_OFFSET(r_points, bezt_array_last * resolu_stride);
*r_points_last = bezt_array[bezt_array_last].vec[1][axis];
- r_points_offset = POINTER_OFFSET(r_points_offset, stride);
+ r_points_offset = (float *)POINTER_OFFSET(r_points_offset, stride);
}
- BLI_assert(POINTER_OFFSET(r_points, points_len * stride) == r_points_offset);
+ BLI_assert((float *)POINTER_OFFSET(r_points, points_len * stride) == r_points_offset);
UNUSED_VARS_NDEBUG(points_len);
}
-/* forward differencing method for bezier curve */
void BKE_curve_forward_diff_bezier(
float q0, float q1, float q2, float q3, float *p, int it, int stride)
{
@@ -1808,14 +1784,13 @@ void BKE_curve_forward_diff_bezier(
for (a = 0; a <= it; a++) {
*p = q0;
- p = POINTER_OFFSET(p, stride);
+ p = (float *)POINTER_OFFSET(p, stride);
q0 += q1;
q1 += q2;
q2 += q3;
}
}
-/* forward differencing method for first derivative of cubic bezier curve */
void BKE_curve_forward_diff_tangent_bezier(
float q0, float q1, float q2, float q3, float *p, int it, int stride)
{
@@ -1834,7 +1809,7 @@ void BKE_curve_forward_diff_tangent_bezier(
for (a = 0; a <= it; a++) {
*p = q0;
- p = POINTER_OFFSET(p, stride);
+ p = (float *)POINTER_OFFSET(p, stride);
q0 += q1;
q1 += q2;
}
@@ -1860,7 +1835,7 @@ static void forward_diff_bezier_cotangent(const float p0[3],
(-18.0f * t + 6.0f) * p2[i] + (6.0f * t) * p3[i];
}
normalize_v3(p);
- p = POINTER_OFFSET(p, stride);
+ p = (float *)POINTER_OFFSET(p, stride);
}
}
@@ -1973,7 +1948,7 @@ struct BevelSort {
static int vergxcobev(const void *a1, const void *a2)
{
- const struct BevelSort *x1 = a1, *x2 = a2;
+ const struct BevelSort *x1 = (BevelSort *)a1, *x2 = (BevelSort *)a2;
if (x1->left > x2->left) {
return 1;
@@ -2047,7 +2022,7 @@ static void tilt_bezpart(const BezTriple *prevbezt,
float fac, dfac, t[4];
int a;
- if (tilt_array == NULL && radius_array == NULL) {
+ if (tilt_array == nullptr && radius_array == nullptr) {
return;
}
@@ -2095,7 +2070,7 @@ static void tilt_bezpart(const BezTriple *prevbezt,
t[3] * next->tilt;
}
- tilt_array = POINTER_OFFSET(tilt_array, stride);
+ tilt_array = (float *)POINTER_OFFSET(tilt_array, stride);
}
if (radius_array) {
@@ -2109,14 +2084,14 @@ static void tilt_bezpart(const BezTriple *prevbezt,
else {
/* reuse interpolation from tilt if we can */
- if (tilt_array == NULL || nu->tilt_interp != nu->radius_interp) {
+ if (tilt_array == nullptr || nu->tilt_interp != nu->radius_interp) {
key_curve_position_weights(fac, t, nu->radius_interp);
}
*radius_array = t[0] * pprev->radius + t[1] * prevbezt->radius + t[2] * bezt->radius +
t[3] * next->radius;
}
- radius_array = POINTER_OFFSET(radius_array, stride);
+ radius_array = (float *)POINTER_OFFSET(radius_array, stride);
}
if (weight_array) {
@@ -2124,15 +2099,15 @@ static void tilt_bezpart(const BezTriple *prevbezt,
*weight_array = prevbezt->weight + (bezt->weight - prevbezt->weight) *
(3.0f * fac * fac - 2.0f * fac * fac * fac);
- weight_array = POINTER_OFFSET(weight_array, stride);
+ weight_array = (float *)POINTER_OFFSET(weight_array, stride);
}
}
}
-/* make_bevel_list_3D_* funcs, at a minimum these must
- * fill in the bezp->quat and bezp->dir values */
+/* `make_bevel_list_3D_*` functions, at a minimum these must
+ * fill in the #BevPoint.quat and #BevPoint.dir values. */
-/* utility for make_bevel_list_3D_* funcs */
+/** Utility for `make_bevel_list_3D_*` functions. */
static void bevel_list_calc_bisect(BevList *bl)
{
BevPoint *bevp2, *bevp1, *bevp0;
@@ -2354,14 +2329,14 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
/* Need to correct for the start/end points not matching
* do this by calculating the tilt angle difference, then apply
- * the rotation gradually over the entire curve
+ * the rotation gradually over the entire curve.
*
- * note that the split is between last and second last, rather than first/last as youd expect.
+ * Note that the split is between last and second last, rather than first/last as you'd expect.
*
* real order is like this
* 0,1,2,3,4 --> 1,2,3,4,0
*
- * this is why we compare last with second last
+ * This is why we compare last with second last.
*/
float vec_1[3] = {0, 1, 0}, vec_2[3] = {0, 1, 0}, angle, ang_fac, cross_tmp[3];
@@ -2622,13 +2597,13 @@ static void bevlist_firstlast_direction_calc_from_bpoint(const Nurb *nu, BevList
void BKE_curve_bevelList_free(ListBase *bev)
{
LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) {
- if (bl->seglen != NULL) {
+ if (bl->seglen != nullptr) {
MEM_freeN(bl->seglen);
}
- if (bl->segbevcount != NULL) {
+ if (bl->segbevcount != nullptr) {
MEM_freeN(bl->segbevcount);
}
- if (bl->bevpoints != NULL) {
+ if (bl->bevpoints != nullptr) {
MEM_freeN(bl->bevpoints);
}
MEM_freeN(bl);
@@ -2639,22 +2614,21 @@ void BKE_curve_bevelList_free(ListBase *bev)
void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_render)
{
- /*
- * - convert all curves to polys, with indication of resol and flags for double-vertices
- * - possibly; do a smart vertice removal (in case Nurb)
- * - separate in individual blocks with BoundBox
- * - AutoHole detection
+ /* - Convert all curves to polys, with indication of resolution and flags for double-vertices.
+ * - Possibly; do a smart vertex removal (in case #Nurb).
+ * - Separate in individual blocks with #BoundBox.
+ * - Auto-hole detection.
*/
- /* this function needs an object, because of tflag and upflag */
- Curve *cu = ob->data;
+ /* This function needs an object, because of `tflag` and `upflag`. */
+ Curve *cu = (Curve *)ob->data;
BezTriple *bezt, *prevbezt;
BPoint *bp;
BevList *blnew;
- BevPoint *bevp2, *bevp1 = NULL, *bevp0;
+ BevPoint *bevp2, *bevp1 = nullptr, *bevp0;
const float threshold = 0.00001f;
float min, inp;
- float *seglen = NULL;
+ float *seglen = nullptr;
struct BevelSort *sortdata, *sd, *sd1;
int a, b, nr, poly, resolu = 0, len = 0, segcount;
int *segbevcount;
@@ -2662,7 +2636,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
bool is_editmode = false;
ListBase *bev;
- /* segbevcount alsp requires seglen. */
+ /* segbevcount also requires seglen. */
const bool need_seglen = ELEM(
cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) ||
ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE);
@@ -2679,7 +2653,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
if (cu->editnurb && ob->type != OB_FONT) {
- is_editmode = 1;
+ is_editmode = true;
}
LISTBASE_FOREACH (const Nurb *, nu, nurbs) {
@@ -2690,8 +2664,8 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
/* check we are a single point? also check we are not a surface and that the orderu is sane,
* enforced in the UI but can go wrong possibly */
if (!BKE_nurb_check_valid_u(nu)) {
- BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList1");
- bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1");
+ BevList *bl = (BevList *)MEM_callocN(sizeof(BevList), "makeBevelList1");
+ bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1");
BLI_addtail(bev, bl);
bl->nr = 0;
bl->charidx = nu->charidx;
@@ -2720,11 +2694,11 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
if (nu->type == CU_POLY) {
len = nu->pntsu;
- BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList2");
- bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2");
+ BevList *bl = (BevList *)MEM_callocN(sizeof(BevList), __func__);
+ bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(len, sizeof(BevPoint), __func__);
if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
- bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen");
- bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList2_segbevcount");
+ bl->seglen = (float *)MEM_malloc_arrayN(segcount, sizeof(float), __func__);
+ bl->segbevcount = (int *)MEM_malloc_arrayN(segcount, sizeof(int), __func__);
}
BLI_addtail(bev, bl);
@@ -2744,7 +2718,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
bevp->radius = bp->radius;
bevp->weight = bp->weight;
bp++;
- if (seglen != NULL && len != 0) {
+ if (seglen != nullptr && len != 0) {
*seglen = len_v3v3(bevp->vec, bp->vec);
bevp++;
bevp->offset = *seglen;
@@ -2770,11 +2744,11 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
/* in case last point is not cyclic */
len = segcount * resolu + 1;
- BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints");
- bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints");
+ BevList *bl = (BevList *)MEM_callocN(sizeof(BevList), __func__);
+ bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(len, sizeof(BevPoint), __func__);
if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
- bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen");
- bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelBPoints_segbevcount");
+ bl->seglen = (float *)MEM_malloc_arrayN(segcount, sizeof(float), __func__);
+ bl->segbevcount = (int *)MEM_malloc_arrayN(segcount, sizeof(int), __func__);
}
BLI_addtail(bev, bl);
@@ -2786,7 +2760,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
segbevcount = bl->segbevcount;
bevp->offset = 0;
- if (seglen != NULL) {
+ if (seglen != nullptr) {
*seglen = 0;
*segbevcount = 0;
}
@@ -2818,7 +2792,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
bevp++;
bl->nr++;
bl->dupe_nr = 1;
- if (seglen != NULL) {
+ if (seglen != nullptr) {
*seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]);
bevp->offset = *seglen;
seglen++;
@@ -2830,10 +2804,10 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
}
}
else {
- /* always do all three, to prevent data hanging around */
+ /* Always do all three, to prevent data hanging around. */
int j;
- /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */
+ /* #BevPoint must stay aligned to 4 so `sizeof(BevPoint) / sizeof(float)` works. */
for (j = 0; j < 3; j++) {
BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
prevbezt->vec[2][j],
@@ -2844,13 +2818,13 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
sizeof(BevPoint));
}
- /* if both arrays are NULL do nothiong */
+ /* If both arrays are `nullptr` do nothing. */
tilt_bezpart(prevbezt,
bezt,
nu,
- do_tilt ? &bevp->tilt : NULL,
- do_radius ? &bevp->radius : NULL,
- do_weight ? &bevp->weight : NULL,
+ do_tilt ? &bevp->tilt : nullptr,
+ do_radius ? &bevp->radius : nullptr,
+ do_weight ? &bevp->weight : nullptr,
resolu,
sizeof(BevPoint));
@@ -2864,15 +2838,15 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
sizeof(BevPoint));
}
- /* seglen */
- if (seglen != NULL) {
+ /* `seglen`. */
+ if (seglen != nullptr) {
*seglen = 0;
*segbevcount = 0;
for (j = 0; j < resolu; j++) {
bevp0 = bevp;
bevp++;
bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
- /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
+ /* Match `seglen` and `segbevcount` to the cleaned up bevel lists (see STEP 2). */
if (bevp->offset > threshold) {
*seglen += bevp->offset;
*segbevcount += 1;
@@ -2906,11 +2880,11 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
if (nu->pntsv == 1) {
len = (resolu * segcount);
- BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList3");
- bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3");
+ BevList *bl = (BevList *)MEM_callocN(sizeof(BevList), __func__);
+ bl->bevpoints = (BevPoint *)MEM_calloc_arrayN(len, sizeof(BevPoint), __func__);
if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
- bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen");
- bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList3_segbevcount");
+ bl->seglen = (float *)MEM_malloc_arrayN(segcount, sizeof(float), __func__);
+ bl->segbevcount = (int *)MEM_malloc_arrayN(segcount, sizeof(int), __func__);
}
BLI_addtail(bev, bl);
bl->nr = len;
@@ -2924,14 +2898,14 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
BKE_nurb_makeCurve(nu,
&bevp->vec[0],
- do_tilt ? &bevp->tilt : NULL,
- do_radius ? &bevp->radius : NULL,
- do_weight ? &bevp->weight : NULL,
+ do_tilt ? &bevp->tilt : nullptr,
+ do_radius ? &bevp->radius : nullptr,
+ do_weight ? &bevp->weight : nullptr,
resolu,
sizeof(BevPoint));
/* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
- if (seglen != NULL) {
+ if (seglen != nullptr) {
nr = segcount;
bevp0 = bevp;
bevp++;
@@ -2983,7 +2957,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
}
nr--;
while (nr--) {
- if (seglen != NULL) {
+ if (seglen != nullptr) {
if (fabsf(bevp1->offset) < threshold) {
bevp0->dupe_tag = true;
bl->dupe_nr++;
@@ -3005,10 +2979,10 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
continue;
}
- nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */
- blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4");
+ nr = bl->nr - bl->dupe_nr + 1; /* +1 because vector-bezier sets flag too. */
+ blnew = (BevList *)MEM_mallocN(sizeof(BevList), "makeBevelList4");
memcpy(blnew, bl, sizeof(BevList));
- blnew->bevpoints = MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4");
+ blnew->bevpoints = (BevPoint *)MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4");
if (!blnew->bevpoints) {
MEM_freeN(blnew);
break;
@@ -3017,7 +2991,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
blnew->seglen = bl->seglen;
blnew->nr = 0;
BLI_remlink(bev, bl);
- BLI_insertlinkbefore(bev, bl->next, blnew); /* to make sure bevlist is tuned with nurblist */
+ BLI_insertlinkbefore(bev, bl->next, blnew); /* Ensure `bevlist` is tuned with `nurblist`. */
bevp0 = bl->bevpoints;
bevp1 = blnew->bevpoints;
nr = bl->nr;
@@ -3029,7 +3003,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
}
bevp0++;
}
- if (bl->bevpoints != NULL) {
+ if (bl->bevpoints != nullptr) {
MEM_freeN(bl->bevpoints);
}
MEM_freeN(bl);
@@ -3048,7 +3022,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
/* find extreme left points, also test (turning) direction */
if (poly > 0) {
- sd = sortdata = MEM_malloc_arrayN(poly, sizeof(struct BevelSort), "makeBevelList5");
+ sd = sortdata = (BevelSort *)MEM_malloc_arrayN(poly, sizeof(struct BevelSort), __func__);
LISTBASE_FOREACH (BevList *, bl, bev) {
if (bl->poly > 0) {
BevPoint *bevp;
@@ -3139,7 +3113,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
BevPoint *bevp = bl->bevpoints;
unit_qt(bevp->quat);
}
- else if (bl->nr == 2) { /* 2 pnt, treat separate */
+ else if (bl->nr == 2) { /* 2 points, treat separately. */
make_bevel_list_segment_2D(bl);
}
else {
@@ -3154,7 +3128,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
BevPoint *bevp = bl->bevpoints;
unit_qt(bevp->quat);
}
- else if (bl->nr == 2) { /* 2 pnt, treat separate */
+ else if (bl->nr == 2) { /* 2 points, treat separately. */
make_bevel_list_segment_3D(bl);
}
else {
@@ -3194,7 +3168,7 @@ static void calchandleNurb_intern(BezTriple *bezt,
p2 = bezt->vec[1];
- if (prev == NULL) {
+ if (prev == nullptr) {
p3 = next->vec[1];
pt[0] = 2.0f * p2[0] - p3[0];
pt[1] = 2.0f * p2[1] - p3[1];
@@ -3205,7 +3179,7 @@ static void calchandleNurb_intern(BezTriple *bezt,
p1 = prev->vec[1];
}
- if (next == NULL) {
+ if (next == nullptr) {
pt[0] = 2.0f * p2[0] - p1[0];
pt[1] = 2.0f * p2[1] - p1[1];
pt[2] = 2.0f * p2[2] - p1[2];
@@ -3283,13 +3257,13 @@ static void calchandleNurb_intern(BezTriple *bezt,
if (ydiff1 <= 0.0f) {
if (prev->vec[1][1] > bezt->vec[0][1]) {
bezt->vec[0][1] = prev->vec[1][1];
- leftviolate = 1;
+ leftviolate = true;
}
}
else {
if (prev->vec[1][1] < bezt->vec[0][1]) {
bezt->vec[0][1] = prev->vec[1][1];
- leftviolate = 1;
+ leftviolate = true;
}
}
}
@@ -3310,13 +3284,13 @@ static void calchandleNurb_intern(BezTriple *bezt,
if (ydiff1 <= 0.0f) {
if (next->vec[1][1] < bezt->vec[2][1]) {
bezt->vec[2][1] = next->vec[1][1];
- rightviolate = 1;
+ rightviolate = true;
}
}
else {
if (next->vec[1][1] > bezt->vec[2][1]) {
bezt->vec[2][1] = next->vec[1][1];
- rightviolate = 1;
+ rightviolate = true;
}
}
}
@@ -3346,13 +3320,13 @@ static void calchandleNurb_intern(BezTriple *bezt,
}
if (skip_align ||
- /* when one handle is free, alignming makes no sense, see: T35952 */
+ /* When one handle is free, aligning makes no sense, see: T35952 */
ELEM(HD_FREE, bezt->h1, bezt->h2) ||
- /* also when no handles are aligned, skip this step */
+ /* Also when no handles are aligned, skip this step. */
(!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) {
- /* handles need to be updated during animation and applying stuff like hooks,
+ /* Handles need to be updated during animation and applying stuff like hooks,
* but in such situations it's quite difficult to distinguish in which order
- * align handles should be aligned so skip them for now */
+ * align handles should be aligned so skip them for now. */
return;
}
@@ -3427,19 +3401,19 @@ static void calchandlesNurb_intern(Nurb *nu, eBezTriple_Flag handle_sel_flag, bo
prev = bezt + (a - 1);
}
else {
- prev = NULL;
+ prev = nullptr;
}
next = bezt + 1;
while (a--) {
- calchandleNurb_intern(bezt, prev, next, handle_sel_flag, 0, skip_align, 0);
+ calchandleNurb_intern(bezt, prev, next, handle_sel_flag, false, skip_align, 0);
prev = bezt;
if (a == 1) {
if (nu->flagu & CU_NURB_CYCLIC) {
next = nu->bezt;
}
else {
- next = NULL;
+ next = nullptr;
}
}
else {
@@ -3455,7 +3429,8 @@ static void calchandlesNurb_intern(Nurb *nu, eBezTriple_Flag handle_sel_flag, bo
* with easy error checking and de-allocation, and an easy way to add or remove
* arrays that are processed in this way when changing code.
*
- * floats, chars: NULL-terminated arrays of pointers to array pointers that need to be allocated.
+ * floats, chars: null-terminated arrays of pointers to array pointers that need to be
+ * allocated.
*
* Returns: pointer to the buffer that contains all of the arrays.
*/
@@ -3474,10 +3449,10 @@ static void *allocate_arrays(int count, float ***floats, char ***chars, const ch
void *buffer = (float *)MEM_malloc_arrayN(count, (sizeof(float) * num_floats + num_chars), name);
if (!buffer) {
- return NULL;
+ return nullptr;
}
- float *fptr = buffer;
+ float *fptr = (float *)buffer;
for (int i = 0; i < num_floats; i++, fptr += count) {
*floats[i] = fptr;
@@ -3546,9 +3521,9 @@ static bool tridiagonal_solve_with_limits(float *a,
int solve_count)
{
float *a0, *b0, *c0, *d0;
- float **arrays[] = {&a0, &b0, &c0, &d0, NULL};
+ float **arrays[] = {&a0, &b0, &c0, &d0, nullptr};
char *is_locked, *num_unlocks;
- char **flagarrays[] = {&is_locked, &num_unlocks, NULL};
+ char **flagarrays[] = {&is_locked, &num_unlocks, nullptr};
void *tmps = allocate_arrays(solve_count, arrays, flagarrays, "tridiagonal_solve_with_limits");
if (!tmps) {
@@ -3815,7 +3790,7 @@ static void bezier_handle_calc_smooth_fcurve(
BezTriple *bezt, int total, int start, int count, bool cycle)
{
float *dx, *dy, *l, *a, *b, *c, *d, *h, *hmax, *hmin;
- float **arrays[] = {&dx, &dy, &l, &a, &b, &c, &d, &h, &hmax, &hmin, NULL};
+ float **arrays[] = {&dx, &dy, &l, &a, &b, &c, &d, &h, &hmax, &hmin, nullptr};
int solve_count = count;
@@ -3844,7 +3819,7 @@ static void bezier_handle_calc_smooth_fcurve(
/* allocate all */
- void *tmp_buffer = allocate_arrays(count, arrays, NULL, "bezier_calc_smooth_tmp");
+ void *tmp_buffer = allocate_arrays(count, arrays, nullptr, "bezier_calc_smooth_tmp");
if (!tmp_buffer) {
return;
}
@@ -4020,8 +3995,8 @@ void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cyclic)
}
}
- /* Find continuous subsequences of free auto handles and smooth them, starting at
- * search_base. In cyclic mode these subsequences can span the cycle boundary. */
+ /* Find continuous sub-sequences of free auto handles and smooth them, starting at search_base.
+ * In cyclic mode these sub-sequences can span the cycle boundary. */
int start = search_base, count = 1;
for (int i = 1, j = start + 1; i < total; i++, j++) {
@@ -4046,23 +4021,12 @@ void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cyclic)
}
}
-/**
- * Recalculate the handles of a nurb bezier-triple. Acts based on handle selection with `SELECT`
- * flag. To use a different flag, use #BKE_nurb_handle_calc_ex().
- */
void BKE_nurb_handle_calc(
BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing)
{
- calchandleNurb_intern(bezt, prev, next, SELECT, is_fcurve, false, smoothing);
+ calchandleNurb_intern(bezt, prev, next, (eBezTriple_Flag)SELECT, is_fcurve, false, smoothing);
}
-/**
- * Variant of #BKE_nurb_handle_calc() that allows calculating based on a different select flag.
- *
- * \param handle_sel_flag: The flag (bezt.f1/2/3) value to use to determine selection.
- * Usually #SELECT, but may want to use a different one at times
- * (if caller does not operate on selection).
- */
void BKE_nurb_handle_calc_ex(BezTriple *bezt,
BezTriple *prev,
BezTriple *next,
@@ -4070,12 +4034,13 @@ void BKE_nurb_handle_calc_ex(BezTriple *bezt,
const bool is_fcurve,
const char smoothing)
{
- calchandleNurb_intern(bezt, prev, next, handle_sel_flag, is_fcurve, false, smoothing);
+ calchandleNurb_intern(
+ bezt, prev, next, (eBezTriple_Flag)handle_sel_flag, is_fcurve, false, smoothing);
}
void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
{
- calchandlesNurb_intern(nu, SELECT, false);
+ calchandlesNurb_intern(nu, (eBezTriple_Flag)SELECT, false);
}
/**
@@ -4103,14 +4068,12 @@ static void nurb_handles_calc__align_selected(Nurb *nu)
nurbList_handles_swap_select(nu);
}
-/* similar to BKE_nurb_handle_calc but for curves and
- * figures out the previous and next for us */
void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
{
if (nu->pntsu > 1) {
BezTriple *prev = BKE_nurb_bezt_get_prev(nu, bezt);
BezTriple *next = BKE_nurb_bezt_get_next(nu, bezt);
- BKE_nurb_handle_calc(bezt, prev, next, 0, 0);
+ BKE_nurb_handle_calc(bezt, prev, next, false, 0);
}
}
@@ -4129,19 +4092,6 @@ void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt)
}
}
-/**
- * Update selected handle types to ensure valid state, e.g. deduce "Auto" types to concrete ones.
- * Thereby \a sel_flag defines what qualifies as selected.
- * Use when something has changed handle positions.
- *
- * The caller needs to recalculate handles.
- *
- * \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
- * but may want to use a different one at times (if caller does not operate on
- * selection).
- * \param use_handle: Check selection state of individual handles, otherwise always update both
- * handles if the key is selected.
- */
void BKE_nurb_bezt_handle_test(BezTriple *bezt,
const eBezTriple_Flag__Alias sel_flag,
const bool use_handle,
@@ -4223,7 +4173,7 @@ void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag)
const float eps = 0.0001f;
const float eps_sq = eps * eps;
- if (nu == NULL || nu->bezt == NULL) {
+ if (nu == nullptr || nu->bezt == nullptr) {
return;
}
@@ -4238,13 +4188,13 @@ void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag)
/* left handle: */
if (flag == 0 || (bezt1->f1 & flag)) {
bezt1->h1 = HD_FREE;
- /* distance too short: vectorhandle */
+ /* Distance too short: vector-handle. */
if (len_squared_v3v3(bezt1->vec[1], bezt0->vec[1]) < eps_sq) {
bezt1->h1 = HD_VECT;
leftsmall = true;
}
else {
- /* aligned handle? */
+ /* Aligned handle? */
if (dist_squared_to_line_v3(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < eps_sq) {
align = true;
bezt1->h1 = HD_ALIGN;
@@ -4258,13 +4208,13 @@ void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag)
/* right handle: */
if (flag == 0 || (bezt1->f3 & flag)) {
bezt1->h2 = HD_FREE;
- /* distance too short: vectorhandle */
+ /* Distance too short: vector-handle. */
if (len_squared_v3v3(bezt1->vec[1], bezt2->vec[1]) < eps_sq) {
bezt1->h2 = HD_VECT;
rightsmall = true;
}
else {
- /* aligned handle? */
+ /* Aligned handle? */
if (align) {
bezt1->h2 = HD_ALIGN;
}
@@ -4305,15 +4255,6 @@ void BKE_nurbList_handles_autocalc(ListBase *editnurb, uint8_t flag)
}
}
-/**
- * \param code:
- * - 1 (#HD_AUTO): set auto-handle.
- * - 2 (#HD_VECT): set vector-handle.
- * - 3 (#HD_ALIGN) it toggle, vector-handles become #HD_FREE.
- *
- * - 5: Set align, like 3 but no toggle.
- * - 6: Clear align (setting #HD_FREE), like 3 but no toggle.
- */
void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
{
BezTriple *bezt;
@@ -4491,9 +4432,6 @@ void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set)
}
}
-/**
- * Set \a flag for every point that already has \a from_flag set.
- */
bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, uint8_t from_flag, uint8_t flag)
{
bool changed = false;
@@ -4608,7 +4546,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
/* and make in increasing order again */
a = KNOTSU(nu);
fp1 = nu->knotsu;
- fp2 = tempf = MEM_malloc_arrayN(a, sizeof(float), "switchdirect");
+ fp2 = tempf = (float *)MEM_malloc_arrayN(a, sizeof(float), "switchdirect");
a--;
fp2[a] = fp1[a];
while (a--) {
@@ -4678,7 +4616,8 @@ void BKE_curve_nurbs_vert_coords_get(const ListBase *lb, float (*vert_coords)[3]
float (*BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
{
const int vert_len = BKE_nurbList_verts_count(lb);
- float(*vert_coords)[3] = MEM_malloc_arrayN(vert_len, sizeof(*vert_coords), __func__);
+ float(*vert_coords)[3] = (float(*)[3])MEM_malloc_arrayN(
+ vert_len, sizeof(*vert_coords), __func__);
BKE_curve_nurbs_vert_coords_get(lb, vert_coords, vert_len);
*r_vert_len = vert_len;
return vert_coords;
@@ -4717,7 +4656,7 @@ void BKE_curve_nurbs_vert_coords_apply_with_mat4(ListBase *lb,
BKE_nurb_project_2d(nu);
}
- calchandlesNurb_intern(nu, SELECT, true);
+ calchandlesNurb_intern(nu, (eBezTriple_Flag)SELECT, true);
}
}
@@ -4753,14 +4692,14 @@ void BKE_curve_nurbs_vert_coords_apply(ListBase *lb,
BKE_nurb_project_2d(nu);
}
- calchandlesNurb_intern(nu, SELECT, true);
+ calchandlesNurb_intern(nu, (eBezTriple_Flag)SELECT, true);
}
}
float (*BKE_curve_nurbs_key_vert_coords_alloc(const ListBase *lb, float *key, int *r_vert_len))[3]
{
int vert_len = BKE_nurbList_verts_count(lb);
- float(*cos)[3] = MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__);
+ float(*cos)[3] = (float(*)[3])MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__);
float *co = cos[0];
LISTBASE_FOREACH (const Nurb *, nu, lb) {
@@ -4910,9 +4849,6 @@ bool BKE_nurb_order_clamp_v(struct Nurb *nu)
return changed;
}
-/**
- * \note caller must ensure active vertex remains valid.
- */
bool BKE_nurb_type_convert(Nurb *nu,
const short type,
const bool use_handles,
@@ -4923,7 +4859,7 @@ bool BKE_nurb_type_convert(Nurb *nu,
int a, c, nr;
if (nu->type == CU_POLY) {
- if (type == CU_BEZIER) { /* To Bezier with vecthandles. */
+ if (type == CU_BEZIER) { /* To Bezier with vector-handles. */
nr = nu->pntsu;
bezt = (BezTriple *)MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2");
nu->bezt = bezt;
@@ -4939,7 +4875,7 @@ bool BKE_nurb_type_convert(Nurb *nu,
bezt++;
}
MEM_freeN(nu->bp);
- nu->bp = NULL;
+ nu->bp = nullptr;
nu->pntsu = nr;
nu->pntsv = 0;
nu->type = CU_BEZIER;
@@ -4961,7 +4897,7 @@ bool BKE_nurb_type_convert(Nurb *nu,
else if (nu->type == CU_BEZIER) { /* Bezier */
if (ELEM(type, CU_POLY, CU_NURBS)) {
nr = use_handles ? (3 * nu->pntsu) : nu->pntsu;
- nu->bp = MEM_calloc_arrayN(nr, sizeof(BPoint), "setsplinetype");
+ nu->bp = (BPoint *)MEM_calloc_arrayN(nr, sizeof(BPoint), "setsplinetype");
a = nu->pntsu;
bezt = nu->bezt;
bp = nu->bp;
@@ -4993,7 +4929,7 @@ bool BKE_nurb_type_convert(Nurb *nu,
bezt++;
}
MEM_freeN(nu->bezt);
- nu->bezt = NULL;
+ nu->bezt = nullptr;
nu->pntsu = nr;
nu->pntsv = 1;
nu->orderu = 4;
@@ -5013,20 +4949,20 @@ bool BKE_nurb_type_convert(Nurb *nu,
if (nu->knotsu) {
MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
}
- nu->knotsu = NULL;
+ nu->knotsu = nullptr;
MEM_SAFE_FREE(nu->knotsv);
}
else if (type == CU_BEZIER) { /* to Bezier */
nr = nu->pntsu / 3;
if (nr < 2) {
- if (r_err_msg != NULL) {
+ if (r_err_msg != nullptr) {
*r_err_msg = "At least 6 points required for conversion";
}
return false; /* conversion impossible */
}
- bezt = MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2");
+ bezt = (BezTriple *)MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2");
nu->bezt = bezt;
a = nr;
bp = nu->bp;
@@ -5045,9 +4981,9 @@ bool BKE_nurb_type_convert(Nurb *nu,
bezt++;
}
MEM_freeN(nu->bp);
- nu->bp = NULL;
+ nu->bp = nullptr;
MEM_freeN(nu->knotsu);
- nu->knotsu = NULL;
+ nu->knotsu = nullptr;
nu->pntsu = nr;
nu->type = CU_BEZIER;
}
@@ -5056,7 +4992,6 @@ bool BKE_nurb_type_convert(Nurb *nu,
return true;
}
-/* Get edit nurbs or normal nurbs list */
ListBase *BKE_curve_nurbs_get(Curve *cu)
{
if (cu->editnurb) {
@@ -5077,7 +5012,7 @@ const ListBase *BKE_curve_nurbs_get_for_read(const Curve *cu)
void BKE_curve_nurb_active_set(Curve *cu, const Nurb *nu)
{
- if (nu == NULL) {
+ if (nu == nullptr) {
cu->actnu = CU_ACT_NONE;
}
else {
@@ -5090,14 +5025,13 @@ void BKE_curve_nurb_active_set(Curve *cu, const Nurb *nu)
Nurb *BKE_curve_nurb_active_get(Curve *cu)
{
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- return BLI_findlink(nurbs, cu->actnu);
+ return (Nurb *)BLI_findlink(nurbs, cu->actnu);
}
-/* Get active vert for curve */
void *BKE_curve_vert_active_get(Curve *cu)
{
- Nurb *nu = NULL;
- void *vert = NULL;
+ Nurb *nu = nullptr;
+ void *vert = nullptr;
BKE_curve_nurb_vert_active_get(cu, &nu, &vert);
return vert;
@@ -5114,7 +5048,6 @@ int BKE_curve_nurb_vert_index_get(const Nurb *nu, const void *vert)
return (BPoint *)vert - nu->bp;
}
-/* Set active nurb and active vert for curve */
void BKE_curve_nurb_vert_active_set(Curve *cu, const Nurb *nu, const void *vert)
{
if (nu) {
@@ -5132,15 +5065,14 @@ void BKE_curve_nurb_vert_active_set(Curve *cu, const Nurb *nu, const void *vert)
}
}
-/* Get points to the active nurb and active vert for curve. */
bool BKE_curve_nurb_vert_active_get(Curve *cu, Nurb **r_nu, void **r_vert)
{
- Nurb *nu = NULL;
- void *vert = NULL;
+ Nurb *nu = nullptr;
+ void *vert = nullptr;
if (cu->actvert != CU_ACT_NONE) {
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- nu = BLI_findlink(nurbs, cu->actnu);
+ nu = (Nurb *)BLI_findlink(nurbs, cu->actnu);
if (nu) {
if (nu->type == CU_BEZIER) {
@@ -5157,7 +5089,7 @@ bool BKE_curve_nurb_vert_active_get(Curve *cu, Nurb **r_nu, void **r_vert)
*r_nu = nu;
*r_vert = vert;
- return (*r_vert != NULL);
+ return (*r_vert != nullptr);
}
void BKE_curve_nurb_vert_active_validate(Curve *cu)
@@ -5167,13 +5099,13 @@ void BKE_curve_nurb_vert_active_validate(Curve *cu)
if (BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
if (nu->type == CU_BEZIER) {
- BezTriple *bezt = vert;
+ BezTriple *bezt = (BezTriple *)vert;
if (BEZT_ISSEL_ANY(bezt) == 0) {
cu->actvert = CU_ACT_NONE;
}
}
else {
- BPoint *bp = vert;
+ BPoint *bp = (BPoint *)vert;
if ((bp->f1 & SELECT) == 0) {
cu->actvert = CU_ACT_NONE;
}
@@ -5185,11 +5117,10 @@ void BKE_curve_nurb_vert_active_validate(Curve *cu)
}
}
-/* basic vertex data functions */
bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
- ListBase temp_nurb_lb = {NULL, NULL};
+ ListBase temp_nurb_lb = {nullptr, nullptr};
const bool is_font = (BLI_listbase_is_empty(nurb_lb)) && (cu->len != 0);
/* For font curves we generate temp list of splines.
*
@@ -5198,7 +5129,7 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
*/
if (is_font) {
nurb_lb = &temp_nurb_lb;
- BKE_vfont_to_curve_ex(NULL, cu, FO_EDIT, nurb_lb, NULL, NULL, NULL, NULL);
+ BKE_vfont_to_curve_ex(nullptr, cu, FO_EDIT, nurb_lb, nullptr, nullptr, nullptr, nullptr);
use_radius = false;
}
/* Do bounding box based on splines. */
@@ -5303,7 +5234,7 @@ void BKE_curve_transform_ex(Curve *cu,
if (do_keys && cu->key) {
LISTBASE_FOREACH (KeyBlock *, kb, &cu->key->block) {
- float *fp = kb->data;
+ float *fp = (float *)kb->data;
int n = kb->totelem;
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
@@ -5361,7 +5292,7 @@ void BKE_curve_translate(Curve *cu, const float offset[3], const bool do_keys)
if (do_keys && cu->key) {
LISTBASE_FOREACH (KeyBlock *, kb, &cu->key->block) {
- float *fp = kb->data;
+ float *fp = (float *)kb->data;
int n = kb->totelem;
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
@@ -5513,11 +5444,10 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int
}
}
else {
- Nurb *nu;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
if (nurbs) {
- for (nu = nurbs->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurbs) {
MAT_NR_REMAP(nu->mat_nr);
}
}
@@ -5551,8 +5481,6 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu,
r_rect->ymin = r_rect->ymax - tb->h;
}
-/* This function is almost the same as BKE_fcurve_correct_bezpart(), but doesn't allow as large a
- * tangent. */
void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2])
{
float h1[2], h2[2], len1, len2, len, fac;
@@ -5609,8 +5537,8 @@ void BKE_curve_eval_geometry(Depsgraph *depsgraph, Curve *curve)
}
/* Draw Engine */
-void (*BKE_curve_batch_cache_dirty_tag_cb)(Curve *cu, int mode) = NULL;
-void (*BKE_curve_batch_cache_free_cb)(Curve *cu) = NULL;
+void (*BKE_curve_batch_cache_dirty_tag_cb)(Curve *cu, int mode) = nullptr;
+void (*BKE_curve_batch_cache_free_cb)(Curve *cu) = nullptr;
void BKE_curve_batch_cache_dirty_tag(Curve *cu, int mode)
{
diff --git a/source/blender/blenkernel/intern/curve_bevel.c b/source/blender/blenkernel/intern/curve_bevel.c
index d205d8cca46..18e4ab3ade1 100644
--- a/source/blender/blenkernel/intern/curve_bevel.c
+++ b/source/blender/blenkernel/intern/curve_bevel.c
@@ -64,8 +64,8 @@ static void bevel_quarter_fill(const Curve *curve,
float angle = 0.0f;
const float dangle = (float)M_PI_2 / (curve->bevresol + 1);
for (int i = 0; i < curve->bevresol + 1; i++) {
- quarter_coords_x[i] = (float)(cosf(angle) * (curve->ext2));
- quarter_coords_y[i] = (float)(sinf(angle) * (curve->ext2));
+ quarter_coords_x[i] = (float)(cosf(angle) * (curve->bevel_radius));
+ quarter_coords_y[i] = (float)(sinf(angle) * (curve->bevel_radius));
angle += dangle;
}
}
@@ -76,11 +76,11 @@ static void bevel_quarter_fill(const Curve *curve,
/* If there aren't enough samples, the curveprofile won't
* sample the start vertex, so set it manually instead. */
- quarter_coords_x[0] = curve->ext2;
+ quarter_coords_x[0] = curve->bevel_radius;
quarter_coords_y[0] = 0.0f;
for (int i = 1; i < curve->bevresol + 1; i++) {
- quarter_coords_x[i] = (float)(curve->bevel_profile->segments[i].x * (curve->ext2));
- quarter_coords_y[i] = (float)(curve->bevel_profile->segments[i].y * (curve->ext2));
+ quarter_coords_x[i] = (float)(curve->bevel_profile->segments[i].x * (curve->bevel_radius));
+ quarter_coords_y[i] = (float)(curve->bevel_profile->segments[i].y * (curve->bevel_radius));
}
}
}
@@ -133,13 +133,13 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu,
/* Add the bottom vertex. */
fp[0] = 0.0f;
fp[1] = 0.0f;
- fp[2] = -cu->ext1 - cu->ext2;
+ fp[2] = -cu->extrude - cu->bevel_radius;
fp += 3;
for (int i = cu->bevresol; i >= 0; i--) {
fp[0] = 0.0f;
fp[1] = quarter_coords_x[i];
- fp[2] = -quarter_coords_y[i] - cu->ext1;
+ fp[2] = -quarter_coords_y[i] - cu->extrude;
fp += 3;
}
}
@@ -147,8 +147,8 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu,
/* Add the extrusion if we're only building either the back or the front. */
if (use_extrude && ELEM(fill_type, FRONT, BACK)) {
fp[0] = 0.0f;
- fp[1] = cu->ext2;
- fp[2] = (fill_type == FRONT) ? -cu->ext1 : cu->ext1;
+ fp[1] = cu->bevel_radius;
+ fp[2] = (fill_type == FRONT) ? -cu->extrude : cu->extrude;
fp += 3;
}
@@ -159,13 +159,13 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu,
for (int i = front_start; i < cu->bevresol + 1; i++) {
fp[0] = 0.0f;
fp[1] = quarter_coords_x[i];
- fp[2] = quarter_coords_y[i] + cu->ext1;
+ fp[2] = quarter_coords_y[i] + cu->extrude;
fp += 3;
}
/* Add the top vertex. */
fp[0] = 0.0f;
fp[1] = 0.0f;
- fp[2] = cu->ext1 + cu->ext2;
+ fp[2] = cu->extrude + cu->bevel_radius;
fp += 3;
}
@@ -174,22 +174,22 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu,
for (int i = cu->bevresol; i > 0; i--) {
fp[0] = 0.0f;
fp[1] = -quarter_coords_x[i];
- fp[2] = quarter_coords_y[i] + cu->ext1;
+ fp[2] = quarter_coords_y[i] + cu->extrude;
fp += 3;
}
if (use_extrude) {
/* Add the extrusion. */
fp[0] = 0.0f;
- fp[1] = -cu->ext2;
- fp[2] = cu->ext1;
+ fp[1] = -cu->bevel_radius;
+ fp[2] = cu->extrude;
fp += 3;
}
for (int i = 0; i < cu->bevresol + 1; i++) {
fp[0] = 0.0f;
fp[1] = -quarter_coords_x[i];
- fp[2] = -quarter_coords_y[i] - cu->ext1;
+ fp[2] = -quarter_coords_y[i] - cu->extrude;
fp += 3;
}
}
@@ -213,8 +213,8 @@ static void curve_bevel_make_full_circle(const Curve *cu, ListBase *disp)
for (int i = 0; i < nr; i++) {
fp[0] = 0.0;
- fp[1] = (cosf(angle) * (cu->ext2));
- fp[2] = (sinf(angle) * (cu->ext2)) - cu->ext1;
+ fp[1] = (cosf(angle) * (cu->bevel_radius));
+ fp[2] = (sinf(angle) * (cu->bevel_radius)) - cu->extrude;
angle += dangle;
fp += 3;
}
@@ -232,9 +232,9 @@ static void curve_bevel_make_only_extrude(const Curve *cu, ListBase *disp)
float *fp = dl->verts;
fp[0] = fp[1] = 0.0;
- fp[2] = -cu->ext1;
+ fp[2] = -cu->extrude;
fp[3] = fp[4] = 0.0;
- fp[5] = cu->ext1;
+ fp[5] = cu->extrude;
}
static void curve_bevel_make_from_object(const Curve *cu, ListBase *disp)
@@ -247,7 +247,7 @@ static void curve_bevel_make_from_object(const Curve *cu, ListBase *disp)
}
Curve *bevcu = cu->bevobj->data;
- if (bevcu->ext1 == 0.0f && bevcu->ext2 == 0.0f) {
+ if (bevcu->extrude == 0.0f && bevcu->bevel_radius == 0.0f) {
ListBase bevdisp = {NULL, NULL};
float facx = cu->bevobj->scale[0];
float facy = cu->bevobj->scale[1];
@@ -299,8 +299,8 @@ ListBase BKE_curve_bevel_make(const Curve *curve)
}
}
else {
- const bool use_extrude = curve->ext1 != 0.0f;
- const bool use_bevel = curve->ext2 != 0.0f;
+ const bool use_extrude = curve->extrude != 0.0f;
+ const bool use_bevel = curve->bevel_radius != 0.0f;
/* Pass. */
if (use_extrude && !use_bevel) {
curve_bevel_make_only_extrude(curve, &bevel_shape);
diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c
index b8b8506d681..d754f8cc27d 100644
--- a/source/blender/blenkernel/intern/curve_deform.c
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -410,12 +410,6 @@ void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve,
em_target);
}
-/**
- * \param orco: Input vec and orco = local coord in curve space
- * orco is original not-animated or deformed reference point.
- *
- * The result written in vec and r_mat.
- */
void BKE_curve_deform_co(const Object *ob_curve,
const Object *ob_target,
const float orco[3],
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index ff0478f2543..38f736e6907 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -50,12 +50,6 @@ blender::MutableSpan<SplinePtr> CurveEval::splines()
return splines_;
}
-/**
- * \return True if the curve contains a spline with the given type.
- *
- * \note If you are looping over all of the splines in the same scope anyway,
- * it's better to avoid calling this function, in case there are many splines.
- */
bool CurveEval::has_spline_with_type(const Spline::Type type) const
{
for (const SplinePtr &spline : this->splines()) {
@@ -72,14 +66,18 @@ void CurveEval::resize(const int size)
attributes.reallocate(size);
}
-/**
- * \warning Call #reallocate on the spline's attributes after adding all splines.
- */
void CurveEval::add_spline(SplinePtr spline)
{
splines_.append(std::move(spline));
}
+void CurveEval::add_splines(MutableSpan<SplinePtr> splines)
+{
+ for (SplinePtr &spline : splines) {
+ this->add_spline(std::move(spline));
+ }
+}
+
void CurveEval::remove_splines(blender::IndexMask mask)
{
for (int i = mask.size() - 1; i >= 0; i--) {
@@ -109,13 +107,24 @@ void CurveEval::bounds_min_max(float3 &min, float3 &max, const bool use_evaluate
}
}
-/**
- * Return the start indices for each of the curve spline's control points, if they were part
- * of a flattened array. This can be used to facilitate parallelism by avoiding the need to
- * accumulate an offset while doing more complex calculations.
- *
- * \note The result array is one longer than the spline count; the last element is the total size.
- */
+float CurveEval::total_length() const
+{
+ float length = 0.0f;
+ for (const SplinePtr &spline : this->splines()) {
+ length += spline->length();
+ }
+ return length;
+}
+
+int CurveEval::total_control_point_size() const
+{
+ int count = 0;
+ for (const SplinePtr &spline : this->splines()) {
+ count += spline->size();
+ }
+ return count;
+}
+
blender::Array<int> CurveEval::control_point_offsets() const
{
Array<int> offsets(splines_.size() + 1);
@@ -128,9 +137,6 @@ blender::Array<int> CurveEval::control_point_offsets() const
return offsets;
}
-/**
- * Exactly like #control_point_offsets, but uses the number of evaluated points instead.
- */
blender::Array<int> CurveEval::evaluated_point_offsets() const
{
Array<int> offsets(splines_.size() + 1);
@@ -143,11 +149,6 @@ blender::Array<int> CurveEval::evaluated_point_offsets() const
return offsets;
}
-/**
- * Return the accumulated length at the start of every spline in the curve.
- *
- * \note The result is one longer than the spline count; the last element is the total length.
- */
blender::Array<float> CurveEval::accumulated_spline_lengths() const
{
Array<float> spline_lengths(splines_.size() + 1);
@@ -343,13 +344,6 @@ std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
return curve_eval_from_dna_curve(dna_curve, *BKE_curve_nurbs_get_for_read(&dna_curve));
}
-/**
- * Check the invariants that curve control point attributes should always uphold, necessary
- * because attributes are stored on splines rather than in a flat array on the curve:
- * - The same set of attributes exists on every spline.
- * - Attributes with the same name have the same type on every spline.
- * - Attributes are in the same order on every spline.
- */
void CurveEval::assert_valid_point_attributes() const
{
#ifdef DEBUG
diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
index 03525e32a52..5522a84d094 100644
--- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
+++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
@@ -691,16 +691,6 @@ static void copy_spline_domain_attributes_to_mesh(const CurveEval &curve,
}
}
-/**
- * Extrude all splines in the profile curve along the path of every spline in the curve input.
- * Transfer curve attributes to the mesh.
- *
- * \note Normal calculation is by far the slowest part of calculations relating to the result mesh.
- * Although it would be a sensible decision to use the better topology information available while
- * generating the mesh to also generate the normals, that work may wasted if the output mesh is
- * changed anyway in a way that affects the normals. So currently this code uses the safer /
- * simpler solution of deferring normal calculation to the rest of Blender.
- */
Mesh *curve_to_mesh_sweep(const CurveEval &curve, const CurveEval &profile, const bool fill_caps)
{
Span<SplinePtr> profiles = profile.splines();
@@ -776,10 +766,6 @@ static CurveEval get_curve_single_vert()
return curve;
}
-/**
- * Create a loose-edge mesh based on the evaluated path of the curve's splines.
- * Transfer curve attributes to the mesh.
- */
Mesh *curve_to_wire_mesh(const CurveEval &curve)
{
static const CurveEval vert_curve = get_curve_single_vert();
diff --git a/source/blender/blenkernel/intern/curveprofile.cc b/source/blender/blenkernel/intern/curveprofile.cc
index 7f2a2bc342d..387709fca29 100644
--- a/source/blender/blenkernel/intern/curveprofile.cc
+++ b/source/blender/blenkernel/intern/curveprofile.cc
@@ -44,9 +44,6 @@
/** \name Data Handling
* \{ */
-/**
- * Returns a pointer to a newly allocated curve profile, using the given preset.
- */
struct CurveProfile *BKE_curveprofile_add(eCurveProfilePresets preset)
{
CurveProfile *profile = (CurveProfile *)MEM_callocN(sizeof(CurveProfile), __func__);
@@ -104,7 +101,6 @@ void BKE_curveprofile_blend_write(struct BlendWriter *writer, const struct Curve
BLO_write_struct_array(writer, CurveProfilePoint, profile->path_len, profile->path);
}
-/* Expects that the curve profile itself has been read already. */
void BKE_curveprofile_blend_read(struct BlendDataReader *reader, struct CurveProfile *profile)
{
BLO_read_data_address(reader, &profile->path);
@@ -125,14 +121,6 @@ void BKE_curveprofile_blend_read(struct BlendDataReader *reader, struct CurvePro
/** \name Editing
* \{ */
-/**
- * Move a point's handle, accounting for the alignment of handles with the #HD_ALIGN type.
- *
- * \param handle_1: Whether to move the 1st or 2nd control point.
- * \param delta: The *relative* change in the handle's position.
- * \note Requires #BKE_curveprofile_update call after.
- * \return Whether the handle moved from its start position.
- */
bool BKE_curveprofile_move_handle(struct CurveProfilePoint *point,
const bool handle_1,
const bool snap,
@@ -173,14 +161,6 @@ bool BKE_curveprofile_move_handle(struct CurveProfilePoint *point,
return false;
}
-/**
- * Moves a control point, accounting for clipping and snapping, and moving free handles.
- *
- * \param snap: Whether to snap the point to the grid
- * \param delta: The *relative* change of the point's location.
- * \return Whether the point moved from its start position.
- * \note Requires #BKE_curveprofile_update call after.
- */
bool BKE_curveprofile_move_point(struct CurveProfile *profile,
struct CurveProfilePoint *point,
const bool snap,
@@ -228,10 +208,6 @@ bool BKE_curveprofile_move_point(struct CurveProfile *profile,
return false;
}
-/**
- * Removes a specific point from the path of control points.
- * \note Requires #BKE_curveprofile_update call after.
- */
bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *point)
{
/* Must have 2 points minimum. */
@@ -262,13 +238,6 @@ bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *poi
return true;
}
-/**
- * Removes every point in the widget with the supplied flag set, except for the first and last.
- *
- * \param flag: #CurveProfilePoint.flag.
- *
- * \note Requires #BKE_curveprofile_update call after.
- */
void BKE_curveprofile_remove_by_flag(CurveProfile *profile, const short flag)
{
/* Copy every point without the flag into the new path. */
@@ -308,13 +277,6 @@ static void point_init(CurveProfilePoint *point, float x, float y, short flag, c
point->h2 = h2;
}
-/**
- * Adds a new point at the specified location. The choice for which points to place the new vertex
- * between is made by checking which control point line segment is closest to the new point and
- * placing the new vertex in between that segment's points.
- *
- * \note Requires #BKE_curveprofile_update call after.
- */
CurveProfilePoint *BKE_curveprofile_insert(CurveProfile *profile, float x, float y)
{
const float new_loc[2] = {x, y};
@@ -370,11 +332,6 @@ CurveProfilePoint *BKE_curveprofile_insert(CurveProfile *profile, float x, float
return new_pt;
}
-/**
- * Sets the handle type of the selected control points.
- * \param type_1, type_2: Handle type for the first handle. HD_VECT, HD_AUTO, HD_FREE, or HD_ALIGN.
- * \note Requires #BKE_curveprofile_update call after.
- */
void BKE_curveprofile_selected_handle_set(CurveProfile *profile, int type_1, int type_2)
{
for (int i = 0; i < profile->path_len; i++) {
@@ -397,11 +354,6 @@ static CurveProfilePoint mirror_point(const CurveProfilePoint *point)
return new_point;
}
-/**
- * Flips the profile across the diagonal so that its orientation is reversed.
- *
- * \note Requires #BKE_curveprofile_update call after.
- */
void BKE_curveprofile_reverse(CurveProfile *profile)
{
/* When there are only two points, reversing shouldn't do anything. */
@@ -478,19 +430,11 @@ static void curveprofile_build_steps(CurveProfile *profile)
}
}
-/**
- * Reset the view to the clipping rectangle.
- */
void BKE_curveprofile_reset_view(CurveProfile *profile)
{
profile->view_rect = profile->clip_rect;
}
-/**
- * Resets the profile to the current preset.
- *
- * \note Requires #BKE_curveprofile_update call after.
- */
void BKE_curveprofile_reset(CurveProfile *profile)
{
MEM_SAFE_FREE(profile->path);
@@ -871,10 +815,6 @@ static void create_samples(CurveProfile *profile,
MEM_freeN(n_samples);
}
-/**
- * Sets the default settings and clip range for the profile widget.
- * Does not generate either table.
- */
void BKE_curveprofile_set_defaults(CurveProfile *profile)
{
profile->flag = PROF_USE_CLIP;
@@ -895,12 +835,6 @@ void BKE_curveprofile_set_defaults(CurveProfile *profile)
profile->changed_timestamp = 0;
}
-/**
- * Refreshes the higher resolution table sampled from the input points. A call to this or
- * #BKE_curveprofile_update is needed before evaluation functions that use the table.
- * Also sets the number of segments used for the display preview of the locations
- * of the sampled points.
- */
void BKE_curveprofile_init(CurveProfile *profile, short segments_len)
{
if (segments_len != profile->segments_len) {
@@ -1044,12 +978,6 @@ static void curveprofile_make_segments_table(CurveProfile *profile)
profile->segments = new_table;
}
-/**
- * Should be called after the widget is changed. Does profile and remove double checks and more
- * importantly, recreates the display / evaluation and segments tables.
- * \param update_flags: Bitfield with fields defined in header file. Controls removing doubles and
- * clipping.
- */
void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
{
CurveProfilePoint *points = profile->path;
@@ -1105,13 +1033,6 @@ void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
}
}
-/**
- * Does a single evaluation along the profile's path.
- * Travels down (length_portion * path) length and returns the position at that point.
- *
- * \param length_portion: The portion (0 to 1) of the path's full length to sample at.
- * \note Requires #BKE_curveprofile_init or #BKE_curveprofile_update call before to fill table.
- */
void BKE_curveprofile_evaluate_length_portion(const CurveProfile *profile,
float length_portion,
float *x_out,
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 743d5471aa7..090de26c230 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -73,7 +73,6 @@ BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "siz
static CLG_LogRef LOG = {"bke.customdata"};
-/** Update mask_dst with layers defined in mask_src (equivalent to a bitwise OR). */
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
const CustomData_MeshMasks *mask_src)
{
@@ -84,7 +83,6 @@ void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
mask_dst->lmask |= mask_src->lmask;
}
-/** Return True if all layers set in \a mask_required are also set in \a mask_ref */
bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
const CustomData_MeshMasks *mask_required)
{
@@ -2182,7 +2180,6 @@ bool CustomData_merge(const struct CustomData *source,
return changed;
}
-/* NOTE: Take care of referenced layers by yourself! */
void CustomData_realloc(CustomData *data, int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
@@ -2444,8 +2441,6 @@ void CustomData_set_layer_stencil(CustomData *data, int type, int n)
}
}
-/* For using with an index from CustomData_get_active_layer_index and
- * CustomData_get_render_layer_index. */
void CustomData_set_layer_active_index(CustomData *data, int type, int n)
{
for (int i = 0; i < data->totlayer; i++) {
@@ -2648,7 +2643,6 @@ void *CustomData_add_layer(
return NULL;
}
-/* Same as above but accepts a name. */
void *CustomData_add_layer_named(CustomData *data,
int type,
eCDAllocType alloctype,
@@ -3068,18 +3062,6 @@ void CustomData_free_elem(CustomData *data, int index, int count)
#define SOURCE_BUF_SIZE 100
-/**
- * Interpolate given custom data source items into a single destination one.
- *
- * \param src_indices: Indices of every source items to interpolate into the destination one.
- * \param weights: The weight to apply to each source value individually. If NULL, they will be
- * averaged.
- * \param sub_weights: The weights of sub-items, only used to affect each corners of a
- * tessellated face data (should always be and array of four values).
- * \param count: The number of source items to interpolate.
- * \param dest_index: Index of the destination item, in which to put the result of the
- * interpolation.
- */
void CustomData_interp(const CustomData *source,
CustomData *dest,
const int *src_indices,
@@ -3162,13 +3144,6 @@ void CustomData_interp(const CustomData *source,
}
}
-/**
- * Swap data inside each item, for all layers.
- * This only applies to item types that may store several sub-item data
- * (e.g. corner data [UVs, VCol, ...] of tessellated faces).
- *
- * \param corner_indices: A mapping 'new_index -> old_index' of sub-item data.
- */
void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices)
{
for (int i = 0; i < data->totlayer; i++) {
@@ -3182,9 +3157,6 @@ void CustomData_swap_corners(struct CustomData *data, int index, const int *corn
}
}
-/**
- * Swap two items of given custom data, in all available layers.
- */
void CustomData_swap(struct CustomData *data, const int index_a, const int index_b)
{
char buff_static[256];
@@ -3362,7 +3334,7 @@ void CustomData_set(const CustomData *data, int index, int type, const void *sou
}
/* BMesh functions */
-/* needed to convert to/from different face reps */
+
void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
{
for (int i = 0; i < fdata->totlayer; i++) {
@@ -3418,12 +3390,6 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *ldata, int total)
}
#ifndef NDEBUG
-/**
- * Debug check, used to assert when we expect layers to be in/out of sync.
- *
- * \param fallback: Use when there are no layers to handle,
- * since callers may expect success or failure.
- */
bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback)
{
int a_num = 0, b_num = 0;
@@ -3491,11 +3457,6 @@ void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata)
}
}
-/* update active indices for active/render/clone/stencil custom data layers
- * based on indices from fdata layers
- * used by do_versions in readfile.c when creating pdata and ldata for pre-bmesh
- * meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files
- */
void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
@@ -3677,9 +3638,6 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
*block = NULL;
}
-/**
- * Same as #CustomData_bmesh_free_block but zero the memory rather than freeing.
- */
void CustomData_bmesh_free_block_data(CustomData *data, void *block)
{
if (block == NULL) {
@@ -3713,9 +3671,6 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
}
}
-/**
- * A selective version of #CustomData_bmesh_free_block_data.
- */
void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
void *block,
const CustomDataMask mask_exclude)
@@ -3832,9 +3787,6 @@ void CustomData_bmesh_copy_data(const CustomData *source,
CustomData_bmesh_copy_data_exclude_by_type(source, dest, src_block, dest_block, 0);
}
-/* BMesh Custom Data Functions.
- * Should replace edit-mesh ones with these as well, due to more efficient memory alloc.
- */
void *CustomData_bmesh_get(const CustomData *data, void *block, int type)
{
/* get the layer index of the first layer of type */
@@ -3857,7 +3809,6 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
}
-/* Gets from the layer at physical index n, NOTE: doesn't check type. */
void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
{
if (n < 0 || n >= data->totlayer) {
@@ -3902,7 +3853,6 @@ bool CustomData_has_math(const struct CustomData *data)
return false;
}
-/* a non bmesh version would have to check layer->data */
bool CustomData_bmesh_has_free(const struct CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
@@ -3938,8 +3888,6 @@ bool CustomData_has_referenced(const struct CustomData *data)
return false;
}
-/* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
- * another, while not overwriting anything else (e.g. flags). */
void CustomData_data_copy_value(int type, const void *source, void *dest)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -3956,8 +3904,6 @@ void CustomData_data_copy_value(int type, const void *source, void *dest)
}
}
-/* Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into
- * another, while not overwriting anything else (e.g. flags). */
void CustomData_data_mix_value(
int type, const void *source, void *dest, const int mixmode, const float mixfactor)
{
@@ -4074,10 +4020,6 @@ void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, const vo
}
}
-/**
- * \note src_blocks_ofs & dst_block_ofs
- * must be pointers to the data, offset by layer->offset already.
- */
void CustomData_bmesh_interp_n(CustomData *data,
const void **src_blocks_ofs,
const float *weights,
@@ -4146,11 +4088,6 @@ void CustomData_bmesh_interp(CustomData *data,
}
}
-/**
- * \param use_default_init: initializes data which can't be copied,
- * typically you'll want to use this if the BM_xxx create function
- * is called with BM_CREATE_SKIP_CD flag
- */
void CustomData_to_bmesh_block(const CustomData *source,
CustomData *dest,
int src_index,
@@ -4265,25 +4202,6 @@ void CustomData_file_write_info(int type, const char **r_struct_name, int *r_str
*r_struct_num = typeInfo->structnum;
}
-/**
- * Prepare given custom data for file writing.
- *
- * \param data: the customdata to tweak for .blend file writing (modified in place).
- * \param r_write_layers: contains a reduced set of layers to be written to file,
- * use it with writestruct_at_address()
- * (caller must free it if != \a write_layers_buff).
- *
- * \param write_layers_buff: an optional buffer for r_write_layers (to avoid allocating it).
- * \param write_layers_size: the size of pre-allocated \a write_layer_buff.
- *
- * \warning After this func has ran, given custom data is no more valid from Blender PoV
- * (its totlayer is invalid). This func shall always be called with localized data
- * (as it is in write_meshes()).
- *
- * \note data->typemap is not updated here, since it is always rebuilt on file read anyway.
- * This means written typemap does not match written layers (as returned by \a r_write_layers).
- * Trivial to fix is ever needed.
- */
void CustomData_blend_write_prepare(CustomData *data,
CustomDataLayer **r_write_layers,
CustomDataLayer *write_layers_buff,
@@ -4337,20 +4255,12 @@ const char *CustomData_layertype_name(int type)
return layerType_getName(type);
}
-/**
- * Can only ever be one of these.
- */
bool CustomData_layertype_is_singleton(int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
return typeInfo->defaultname == NULL;
}
-/**
- * Has dynamically allocated members.
- * This is useful to know if operations such as #memcmp are
- * valid when comparing data from two layers.
- */
bool CustomData_layertype_is_dynamic(int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -4358,9 +4268,6 @@ bool CustomData_layertype_is_dynamic(int type)
return (typeInfo->free != NULL);
}
-/**
- * \return Maximum number of layers of given \a type, -1 means 'no limit'.
- */
int CustomData_layertype_layers_max(const int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@@ -4502,12 +4409,6 @@ bool CustomData_verify_versions(struct CustomData *data, int index)
return keeplayer;
}
-/**
- * Validate and fix data of \a layer,
- * if possible (needs relevant callback in layer's type to be defined).
- *
- * \return True if some errors were found.
- */
bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
@@ -4971,7 +4872,6 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
MEM_freeN(tmp_dst);
}
-/* Normals are special, we need to take care of source & destination spaces... */
void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLayerMap *laymap,
void *data_dst,
const void **sources,
@@ -5118,9 +5018,6 @@ static void write_grid_paint_mask(BlendWriter *writer, int count, GridPaintMask
}
}
-/**
- * \param layers: The layers argument assigned by #CustomData_blend_write_prepare.
- */
void CustomData_blend_write(BlendWriter *writer,
CustomData *data,
CustomDataLayer *layers,
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index b83621e8b79..f036f1ced87 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -93,10 +93,6 @@ void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types,
}
}
-/**
- * Check what can do each layer type
- * (if it is actually handled by transfer-data, if it supports advanced mixing.
- */
bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types,
bool *r_advanced_mixing,
bool *r_threshold)
@@ -1232,12 +1228,6 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
return false;
}
-/**
- * Transfer data *layout* of selected types from source to destination object.
- * By default, it only creates new data layers if needed on \a ob_dst.
- * If \a use_delete is true, it will also delete data layers on \a ob_dst that do not match those
- * from \a ob_src, to get (as much as possible) exact copy of source data layout.
- */
void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob_src,
diff --git a/source/blender/blenkernel/intern/data_transfer_intern.h b/source/blender/blenkernel/intern/data_transfer_intern.h
index c5d7dd42cb8..e40b4946f52 100644
--- a/source/blender/blenkernel/intern/data_transfer_intern.h
+++ b/source/blender/blenkernel/intern/data_transfer_intern.h
@@ -68,6 +68,10 @@ bool data_transfer_layersmapping_vgroups(struct ListBase *r_map,
const int tolayers);
/* Defined in customdata.c */
+
+/**
+ * Normals are special, we need to take care of source & destination spaces.
+ */
void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLayerMap *laymap,
void *data_dst,
const void **sources,
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 13222747a52..6b429a146d4 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -107,11 +107,6 @@ bDeformGroup *BKE_defgroup_duplicate(const bDeformGroup *ingroup)
return outgroup;
}
-/**
- * Overwrite weights filtered by vgroup_subset.
- * - do nothing if neither are set.
- * - add destination weight if needed
- */
void BKE_defvert_copy_subset(MDeformVert *dvert_dst,
const MDeformVert *dvert_src,
const bool *vgroup_subset,
@@ -125,11 +120,6 @@ void BKE_defvert_copy_subset(MDeformVert *dvert_dst,
}
}
-/**
- * Overwrite weights filtered by vgroup_subset and with mirroring specified by the flip map
- * - do nothing if neither are set.
- * - add destination weight if needed
- */
void BKE_defvert_mirror_subset(MDeformVert *dvert_dst,
const MDeformVert *dvert_src,
const bool *vgroup_subset,
@@ -168,11 +158,6 @@ void BKE_defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
}
}
-/**
- * Copy an index from one dvert to another.
- * - do nothing if neither are set.
- * - add destination weight if needed.
- */
void BKE_defvert_copy_index(MDeformVert *dvert_dst,
const int defgroup_dst,
const MDeformVert *dvert_src,
@@ -197,10 +182,6 @@ void BKE_defvert_copy_index(MDeformVert *dvert_dst,
}
}
-/**
- * Only sync over matching weights, don't add or remove groups
- * warning, loop within loop.
- */
void BKE_defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool use_ensure)
{
if (dvert_src->totweight && dvert_dst->totweight) {
@@ -221,9 +202,6 @@ void BKE_defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, cons
}
}
-/**
- * be sure all flip_map values are valid
- */
void BKE_defvert_sync_mapped(MDeformVert *dvert_dst,
const MDeformVert *dvert_src,
const int *flip_map,
@@ -250,9 +228,6 @@ void BKE_defvert_sync_mapped(MDeformVert *dvert_dst,
}
}
-/**
- * be sure all flip_map values are valid
- */
void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len)
{
MDeformWeight *dw = dvert->dw;
@@ -265,9 +240,6 @@ void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len)
}
}
-/**
- * Same as #BKE_defvert_normalize but takes a bool array.
- */
void BKE_defvert_normalize_subset(MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot)
@@ -334,9 +306,6 @@ void BKE_defvert_normalize(MDeformVert *dvert)
}
}
-/**
- * Same as BKE_defvert_normalize() if the locked vgroup is not a member of the subset
- */
void BKE_defvert_normalize_lock_single(MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
@@ -391,9 +360,6 @@ void BKE_defvert_normalize_lock_single(MDeformVert *dvert,
}
}
-/**
- * Same as BKE_defvert_normalize() if no locked vgroup is a member of the subset
- */
void BKE_defvert_normalize_lock_map(MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
@@ -557,11 +523,35 @@ bDeformGroup *BKE_object_defgroup_find_name(const Object *ob, const char *name)
int BKE_id_defgroup_name_index(const ID *id, const char *name)
{
- if (name == NULL || name[0] == '\0') {
+ int index;
+ if (!BKE_id_defgroup_name_find(id, name, &index, NULL)) {
return -1;
}
+ return index;
+}
+
+bool BKE_id_defgroup_name_find(const struct ID *id,
+ const char *name,
+ int *r_index,
+ struct bDeformGroup **r_group)
+{
+ if (name == NULL || name[0] == '\0') {
+ return false;
+ }
const ListBase *defbase = BKE_id_defgroup_list_get(id);
- return BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name));
+ int index;
+ LISTBASE_FOREACH_INDEX (bDeformGroup *, group, defbase, index) {
+ if (STREQ(name, group->name)) {
+ if (r_index != NULL) {
+ *r_index = index;
+ }
+ if (r_group != NULL) {
+ *r_group = group;
+ }
+ return true;
+ }
+ }
+ return false;
}
const ListBase *BKE_object_defgroup_list(const Object *ob)
@@ -586,17 +576,11 @@ int BKE_object_defgroup_count(const Object *ob)
return BLI_listbase_count(BKE_object_defgroup_list(ob));
}
-/**
- * \note For historical reasons, the index starts at 1 rather than 0.
- */
int BKE_object_defgroup_active_index_get(const Object *ob)
{
return *object_defgroup_active_index_get_p(ob);
}
-/**
- * \note For historical reasons, the index starts at 1 rather than 0.
- */
void BKE_object_defgroup_active_index_set(Object *ob, const int new_index)
{
/* Cast away const just for the accessor. */
@@ -604,9 +588,6 @@ void BKE_object_defgroup_active_index_set(Object *ob, const int new_index)
*index = new_index;
}
-/**
- * \note caller must free.
- */
int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default)
{
const ListBase *defbase = BKE_object_defgroup_list(ob);
@@ -646,9 +627,6 @@ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const boo
return map;
}
-/**
- * \note caller must free.
- */
int *BKE_object_defgroup_flip_map_single(const Object *ob,
int *flip_map_len,
const bool use_default,
@@ -745,13 +723,6 @@ float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgrou
return dw ? dw->weight : 0.0f;
}
-/**
- * Take care with this the rationale is:
- * - if the object has no vertex group. act like vertex group isn't set and return 1.0,
- * - if the vertex group exists but the 'defgroup' isn't found on this vertex, _still_ return 0.0
- *
- * This is a bit confusing, just saves some checks from the caller.
- */
float BKE_defvert_array_find_weight_safe(const struct MDeformVert *dvert,
const int index,
const int defgroup)
@@ -790,11 +761,6 @@ MDeformWeight *BKE_defvert_find_index(const MDeformVert *dvert, const int defgro
return NULL;
}
-/**
- * Ensures that mv has a deform weight entry for the specified defweight group.
- *
- * \note this function is mirrored in editmesh_tools.c, for use for editvertices.
- */
MDeformWeight *BKE_defvert_ensure_index(MDeformVert *dvert, const int defgroup)
{
MDeformWeight *dw_new;
@@ -826,15 +792,10 @@ MDeformWeight *BKE_defvert_ensure_index(MDeformVert *dvert, const int defgroup)
return dw_new;
}
-/* TODO: merge with code above! */
-
-/**
- * Adds the given vertex to the specified vertex group, with given weight.
- *
- * \warning this does NOT check for existing, assume caller already knows its not there.
- */
void BKE_defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weight)
{
+ /* TODO: merge with #BKE_defvert_ensure_index! */
+
MDeformWeight *dw_new;
/* do this check always, this function is used to check for it */
@@ -856,11 +817,6 @@ void BKE_defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float
dvert->totweight++;
}
-/**
- * Removes the given vertex from the vertex group.
- *
- * \warning This function frees the given MDeformWeight, do not use it afterward!
- */
void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
{
if (dvert && dw) {
@@ -899,10 +855,6 @@ void BKE_defvert_clear(MDeformVert *dvert)
dvert->totweight = 0;
}
-/**
- * \return The first group index shared by both deform verts
- * or -1 if none are found.
- */
int BKE_defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b)
{
if (dvert_a->totweight && dvert_b->totweight) {
@@ -919,9 +871,6 @@ int BKE_defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert
return -1;
}
-/**
- * return true if has no weights
- */
bool BKE_defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_tot)
{
MDeformWeight *dw = dvert->dw;
@@ -936,9 +885,6 @@ bool BKE_defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgr
return true;
}
-/**
- * \return The total weight in all groups marked in the selection mask.
- */
float BKE_defvert_total_selected_weight(const struct MDeformVert *dv,
int defbase_tot,
const bool *defbase_sel)
@@ -961,14 +907,6 @@ float BKE_defvert_total_selected_weight(const struct MDeformVert *dv,
return total;
}
-/**
- * \return The representative weight of a multipaint group, used for
- * viewport colors and actual painting.
- *
- * Result equal to sum of weights with auto normalize, and average otherwise.
- * Value is not clamped, since painting relies on multiplication being always
- * commutative with the collective weight function.
- */
float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv,
int defbase_tot,
const bool *defbase_sel,
@@ -986,11 +924,6 @@ float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv,
return total;
}
-/**
- * Computes the display weight for the lock relative weight paint mode.
- *
- * \return weight divided by 1-locked_weight with division by zero check
- */
float BKE_defvert_calc_lock_relative_weight(float weight,
float locked_weight,
float unlocked_weight)
@@ -1019,11 +952,6 @@ float BKE_defvert_calc_lock_relative_weight(float weight,
return weight / (1.0f - locked_weight);
}
-/**
- * Computes the display weight for the lock relative weight paint mode, using weight data.
- *
- * \return weight divided by unlocked, or 1-locked_weight with division by zero check.
- */
float BKE_defvert_lock_relative_weight(float weight,
const struct MDeformVert *dv,
int defbase_tot,
@@ -1115,10 +1043,6 @@ void BKE_defvert_extract_vgroup_to_vertweights(MDeformVert *dvert,
}
}
-/**
- * The following three make basic interpolation,
- * using temp vert_weights array to avoid looking up same weight several times.
- */
void BKE_defvert_extract_vgroup_to_edgeweights(MDeformVert *dvert,
const int defgroup,
const int num_verts,
@@ -1451,7 +1375,7 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
* and even have to support NULL data_src in transfer data code
* (we always create a data_dst, though).
*
- * Note: Above comment is outdated, but this function was written when that was true.
+ * NOTE: Above comment is outdated, but this function was written when that was true.
*/
const ListBase *src_defbase = BKE_object_defgroup_list(ob_src);
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index 0bf436aa8b2..edf043de63f 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -66,8 +66,6 @@
using blender::IndexRange;
-static void boundbox_displist_object(Object *ob);
-
static void displist_elem_free(DispList *dl)
{
if (dl) {
@@ -404,12 +402,6 @@ static void curve_to_displist(const Curve *cu,
}
}
-/**
- * \param normal_proj: Optional normal that's used to project the scanfill verts into 2d coords.
- * Pass this along if known since it saves time calculating the normal.
- * This is also used to initialize #DispList.nors (one normal per display list).
- * \param flipnormal: Flip the normal (same as passing \a normal_proj negated)
- */
void BKE_displist_fill(const ListBase *dispbase,
ListBase *to,
const float normal_proj[3],
@@ -832,7 +824,7 @@ static bool do_curve_implicit_mesh_conversion(const Curve *curve,
}
/* Curve objects with implicit "tube" meshes should convert implicitly to a mesh. */
- if (curve->ext1 != 0.0f || curve->ext2 != 0.0f) {
+ if (curve->extrude != 0.0f || curve->bevel_radius != 0.0f) {
return true;
}
@@ -1312,11 +1304,11 @@ static GeometrySet evaluate_curve_type_object(Depsgraph *depsgraph,
ListBase dlbev = BKE_curve_bevel_make(cu);
/* no bevel or extrude, and no width correction? */
- if (BLI_listbase_is_empty(&dlbev) && cu->width == 1.0f) {
+ if (BLI_listbase_is_empty(&dlbev) && cu->offset == 1.0f) {
curve_to_displist(cu, deformed_nurbs, for_render, r_dispbase);
}
else {
- const float widfac = cu->width - 1.0f;
+ const float widfac = cu->offset - 1.0f;
const BevList *bl = (BevList *)ob->runtime.curve_cache->bev.first;
const Nurb *nu = (Nurb *)deformed_nurbs->first;
@@ -1528,7 +1520,7 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
ob->runtime.geometry_set_eval = new GeometrySet(std::move(geometry));
}
- boundbox_displist_object(ob);
+ BKE_object_boundbox_calc_from_evaluated_geometry(ob);
}
void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
@@ -1536,7 +1528,7 @@ void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
bool doit = false;
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
- const int tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
+ const int tot = (ELEM(dl->type, DL_INDEX3, DL_INDEX4)) ? dl->nr : dl->nr * dl->parts;
for (const int i : IndexRange(tot)) {
minmax_v3v3_v3(min, max, &dl->verts[i * 3]);
}
@@ -1551,30 +1543,3 @@ void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
zero_v3(max);
}
}
-
-/* this is confusing, there's also min_max_object, applying the obmat... */
-static void boundbox_displist_object(Object *ob)
-{
- BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT));
- /* Curve's BB is already calculated as a part of modifier stack,
- * here we only calculate object BB based on final display list. */
-
- /* object's BB is calculated from final displist */
- if (ob->runtime.bb == nullptr) {
- ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__);
- }
-
- const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval) {
- BKE_object_boundbox_calc_from_mesh(ob, mesh_eval);
- }
- else {
- float min[3], max[3];
-
- INIT_MINMAX(min, max);
- BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
- BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
-
- ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
- }
-}
diff --git a/source/blender/blenkernel/intern/displist_tangent.c b/source/blender/blenkernel/intern/displist_tangent.c
index 5c969d52aea..4451961ad94 100644
--- a/source/blender/blenkernel/intern/displist_tangent.c
+++ b/source/blender/blenkernel/intern/displist_tangent.c
@@ -29,6 +29,10 @@
/* interface */
#include "mikktspace.h"
+/* -------------------------------------------------------------------- */
+/** \name Internal Types
+ * \{ */
+
typedef struct {
const DispList *dl;
float (*tangent)[4]; /* destination */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 05f1e9b286f..ce92a34de47 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -327,7 +327,6 @@ static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface)
return 0;
}
-/* get currently active surface (in user interface) */
DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas)
{
return BLI_findlink(&canvas->surfaces, canvas->active_sur);
@@ -420,7 +419,6 @@ void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char
surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
}
-/* change surface data to defaults on new type */
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface)
{
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
@@ -855,7 +853,6 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
/***************************** Freeing data ******************************/
-/* Free brush data */
void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
{
if (pmd->brush) {
@@ -992,7 +989,6 @@ void dynamicPaint_freeSurface(const DynamicPaintModifierData *pmd, DynamicPaintS
MEM_freeN(surface);
}
-/* Free canvas data */
void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
{
if (pmd->canvas) {
@@ -1011,7 +1007,6 @@ void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
}
}
-/* Free whole dp modifier */
void dynamicPaint_Modifier_free(DynamicPaintModifierData *pmd)
{
if (pmd == NULL) {
@@ -1024,11 +1019,6 @@ void dynamicPaint_Modifier_free(DynamicPaintModifierData *pmd)
/***************************** Initialize and reset ******************************/
-/*
- * Creates a new surface and adds it to the list
- * If scene is null, frame range of 1-250 is used
- * A pointer to this surface is returned
- */
DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas,
Scene *scene)
{
@@ -1106,9 +1096,6 @@ DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *c
return surface;
}
-/*
- * Initialize modifier data
- */
bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene)
{
if (pmd) {
@@ -1721,7 +1708,6 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
}
}
-/* clears surface data back to zero */
void dynamicPaint_clearSurface(const Scene *scene, DynamicPaintSurface *surface)
{
PaintSurfaceData *sData = surface->data;
@@ -1751,7 +1737,6 @@ void dynamicPaint_clearSurface(const Scene *scene, DynamicPaintSurface *surface)
}
}
-/* Completely (re)initializes surface (only for point cache types). */
bool dynamicPaint_resetSurface(const Scene *scene, DynamicPaintSurface *surface)
{
int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
@@ -2079,7 +2064,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
return result;
}
-/* update cache frame range */
void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface)
{
if (surface->pointcache) {
@@ -2189,7 +2173,6 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd,
}
}
-/* Modifier call. Processes dynamic paint modifier step. */
Mesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd,
struct Depsgraph *depsgraph,
Scene *scene,
@@ -6369,9 +6352,6 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph,
return ret;
}
-/**
- * Calculate a single frame and included sub-frames for surface.
- */
int dynamicPaint_calculateFrame(DynamicPaintSurface *surface,
struct Depsgraph *depsgraph,
Scene *scene,
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 83e03ef44f5..805d3cdb5e3 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -39,10 +39,6 @@
#include "BKE_mesh_wrapper.h"
#include "BKE_object.h"
-/**
- * \note The caller is responsible for ensuring triangulation data,
- * typically by calling #BKE_editmesh_looptri_calc.
- */
BMEditMesh *BKE_editmesh_create(BMesh *bm)
{
BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
@@ -75,12 +71,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em)
return em_copy;
}
-/**
- * \brief Return the BMEditMesh for a given object
- *
- * \note this function assumes this is a mesh object,
- * don't add NULL data check here. caller must do that
- */
BMEditMesh *BKE_editmesh_from_object(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -158,10 +148,6 @@ void BKE_editmesh_looptri_calc(BMEditMesh *em)
});
}
-/**
- * Performing the face normal calculation at the same time as tessellation
- * gives a reasonable performance boost (approx ~20% faster).
- */
void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em)
{
BKE_editmesh_looptri_calc_ex(em,
@@ -221,7 +207,6 @@ void BKE_editmesh_free_derived_caches(BMEditMesh *em)
MEM_SAFE_FREE(em->bb_cage);
}
-/* Does not free the #BMEditMesh struct itself. */
void BKE_editmesh_free_data(BMEditMesh *em)
{
BKE_editmesh_free_derived_caches(em);
@@ -342,7 +327,6 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me)
BM_lnorspace_update(bm);
}
-/* If autosmooth not already set, set it */
void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me)
{
if (!(me->flag & ME_AUTOSMOOTH)) {
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 5058863912f..e200a504b5d 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -565,9 +565,6 @@ static bool bmbvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSE
((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
}
-/**
- * Overlap indices reference the looptri's
- */
BVHTreeOverlap *BKE_bmbvh_overlap(const BMBVHTree *bmtree_a,
const BMBVHTree *bmtree_b,
unsigned int *r_overlap_tot)
@@ -591,9 +588,6 @@ static bool bmbvh_overlap_self_cb(void *userdata, int index_a, int index_b, int
return false;
}
-/**
- * Overlap indices reference the looptri's
- */
BVHTreeOverlap *BKE_bmbvh_overlap_self(const BMBVHTree *bmtree, unsigned int *r_overlap_tot)
{
struct BMBVHTree_OverlapData data;
diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c
index da4ea742656..ff0d47e534e 100644
--- a/source/blender/blenkernel/intern/editmesh_tangent.c
+++ b/source/blender/blenkernel/intern/editmesh_tangent.c
@@ -273,13 +273,6 @@ static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), vo
}
}
-/**
- * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
- *
- * \note This function is not so normal, its using #BMesh.ldata as input,
- * but output's to #Mesh.ldata.
- * This is done because #CD_TANGENT is cache data used only for drawing.
- */
void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index a88339082fe..8229228976c 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -221,9 +221,6 @@ static void add_effector_evaluation(ListBase **effectors,
precalculate_effector(depsgraph, eff);
}
-/* Create list of effector relations in the collection or entire scene.
- * This is used by the depsgraph to build relations, as well as faster
- * lookup of effectors during evaluation. */
ListBase *BKE_effector_relations_create(Depsgraph *depsgraph,
ViewLayer *view_layer,
Collection *collection)
@@ -329,7 +326,6 @@ static bool is_effector_relevant(PartDeflect *pd, EffectorWeights *weights, bool
is_effector_nonzero_strength(pd);
}
-/* Create effective list of effectors from relations built beforehand. */
ListBase *BKE_effectors_create(Depsgraph *depsgraph,
Object *ob_src,
ParticleSystem *psys_src,
@@ -656,11 +652,11 @@ float effector_falloff(EffectorCache *eff,
return falloff;
}
-int closest_point_on_surface(SurfaceModifierData *surmd,
- const float co[3],
- float surface_co[3],
- float surface_nor[3],
- float surface_vel[3])
+bool closest_point_on_surface(SurfaceModifierData *surmd,
+ const float co[3],
+ float surface_co[3],
+ float surface_nor[3],
+ float surface_vel[3])
{
BVHTreeNearest nearest;
@@ -687,18 +683,18 @@ int closest_point_on_surface(SurfaceModifierData *surmd,
mul_v3_fl(surface_vel, (1.0f / 3.0f));
}
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int get_effector_data(EffectorCache *eff,
- EffectorData *efd,
- EffectedPoint *point,
- int real_velocity)
+bool get_effector_data(EffectorCache *eff,
+ EffectorData *efd,
+ EffectedPoint *point,
+ int real_velocity)
{
float cfra = DEG_get_ctime(eff->depsgraph);
- int ret = 0;
+ bool ret = false;
/* In case surface object is in Edit mode when loading the .blend,
* surface modifier is never executed and bvhtree never built, see T48415. */
@@ -730,7 +726,7 @@ int get_effector_data(EffectorCache *eff,
efd->size = 0.0f;
- ret = 1;
+ ret = true;
}
}
else if (eff->psys) {
@@ -798,7 +794,7 @@ int get_effector_data(EffectorCache *eff,
zero_v3(efd->vel);
efd->size = 0.0f;
- ret = 1;
+ ret = true;
}
if (ret) {
@@ -1130,20 +1126,6 @@ static void do_physical_effector(EffectorCache *eff,
}
}
-/* -------- BKE_effectors_apply() --------
- * generic force/speed system, now used for particles and softbodies
- * scene = scene where it runs in, for time and stuff
- * lb = listbase with objects that take part in effecting
- * opco = global coord, as input
- * force = accumulator for force
- * wind_force = accumulator for force only acting perpendicular to a surface
- * speed = actual current speed which can be altered
- * cur_time = "external" time in frames, is constant for static particles
- * loc_time = "local" time in frames, range <0-1> for the lifetime of particle
- * par_layer = layer the caller is in
- * flags = only used for softbody wind now
- * guide = old speed of particle
- */
void BKE_effectors_apply(ListBase *effectors,
ListBase *colliders,
EffectorWeights *weights,
@@ -1152,6 +1134,22 @@ void BKE_effectors_apply(ListBase *effectors,
float *wind_force,
float *impulse)
{
+ /* WARNING(@campbellbarton): historic comment?
+ * Many of these parameters don't exist!
+ *
+ * scene = scene where it runs in, for time and stuff.
+ * lb = listbase with objects that take part in effecting.
+ * opco = global coord, as input.
+ * force = accumulator for force.
+ * wind_force = accumulator for force only acting perpendicular to a surface.
+ * speed = actual current speed which can be altered.
+ * cur_time = "external" time in frames, is constant for static particles.
+ * loc_time = "local" time in frames, range <0-1> for the lifetime of particle.
+ * par_layer = layer the caller is in.
+ * flags = only used for soft-body wind now.
+ * guide = old speed of particle.
+ */
+
/*
* Modifies the force on a particle according to its
* relation with the effector object
diff --git a/source/blender/blenkernel/intern/extern_implementations.cc b/source/blender/blenkernel/intern/extern_implementations.cc
deleted file mode 100644
index 07a4b6fc455..00000000000
--- a/source/blender/blenkernel/intern/extern_implementations.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "BKE_attribute_access.hh"
-
-namespace blender::bke {
-
-template class OutputAttribute_Typed<float>;
-template class OutputAttribute_Typed<int>;
-template class OutputAttribute_Typed<float3>;
-template class OutputAttribute_Typed<bool>;
-template class OutputAttribute_Typed<ColorGeometry4f>;
-
-} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index bbf61c51bfb..5bbfc0913a1 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -77,7 +77,6 @@ FCurve *BKE_fcurve_create(void)
/** \name F-Curve Data Free
* \{ */
-/* Frees the F-Curve itself too, so make sure BLI_remlink is called before calling this... */
void BKE_fcurve_free(FCurve *fcu)
{
if (fcu == NULL) {
@@ -99,7 +98,6 @@ void BKE_fcurve_free(FCurve *fcu)
MEM_freeN(fcu);
}
-/* Frees a list of F-Curves. */
void BKE_fcurves_free(ListBase *list)
{
FCurve *fcu, *fcn;
@@ -128,7 +126,6 @@ void BKE_fcurves_free(ListBase *list)
/** \name F-Curve Data Copy
* \{ */
-/* Duplicate a F-Curve. */
FCurve *BKE_fcurve_copy(const FCurve *fcu)
{
FCurve *fcu_d;
@@ -161,7 +158,6 @@ FCurve *BKE_fcurve_copy(const FCurve *fcu)
return fcu_d;
}
-/* Duplicate a list of F-Curves. */
void BKE_fcurves_copy(ListBase *dst, ListBase *src)
{
FCurve *dfcu, *sfcu;
@@ -181,10 +177,6 @@ void BKE_fcurves_copy(ListBase *dst, ListBase *src)
}
}
-/**
- * Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
- * `IDTypeInfo` structure).
- */
void BKE_fcurve_foreach_id(FCurve *fcu, LibraryForeachIDData *data)
{
ChannelDriver *driver = fcu->driver;
@@ -221,7 +213,6 @@ void BKE_fcurve_foreach_id(FCurve *fcu, LibraryForeachIDData *data)
/* ----------------- Finding F-Curves -------------------------- */
-/* High level function to get an fcurve from C without having the RNA. */
FCurve *id_data_find_fcurve(
ID *id, void *data, StructRNA *type, const char *prop_name, int index, bool *r_driven)
{
@@ -273,8 +264,6 @@ FCurve *id_data_find_fcurve(
return fcu;
}
-/* Find the F-Curve affecting the given RNA-access path + index,
- * in the list of F-Curves provided. */
FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_index)
{
FCurve *fcu;
@@ -304,7 +293,6 @@ FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_i
/** \name FCurve Iteration
* \{ */
-/* Quick way to loop over all fcurves of a given 'path'. */
FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
{
FCurve *fcu;
@@ -325,18 +313,6 @@ FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
return NULL;
}
-/**
- * Get list of LinkData's containing pointers to the F-Curves
- * which control the types of data indicated.
- *
- * Lists...
- * - dst: list of LinkData's matching the criteria returned.
- * List must be freed after use, and is assumed to be empty when passed.
- * - src: list of F-Curves to search through
- * Filters...
- * - dataPrefix: i.e. 'pose.bones[' or 'nodes['
- * - dataName: name of entity within "" immediately following the prefix
- */
int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName)
{
FCurve *fcu;
@@ -601,9 +577,6 @@ static int BKE_fcurve_bezt_binarysearch_index_ex(const BezTriple array[],
return start;
}
-/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve)
- * Returns the index to insert at (data already at that index will be offset if replace is 0)
- */
int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[],
const float frame,
const int arraylen,
@@ -667,7 +640,6 @@ static short get_fcurve_end_keyframes(FCurve *fcu,
return found;
}
-/* Calculate the extents of F-Curve's data. */
bool BKE_fcurve_calc_bounds(FCurve *fcu,
float *xmin,
float *xmax,
@@ -798,7 +770,6 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu,
return foundvert;
}
-/* Calculate the extents of F-Curve's keyframes. */
bool BKE_fcurve_calc_range(
FCurve *fcu, float *start, float *end, const bool do_sel_only, const bool do_min_length)
{
@@ -846,14 +817,6 @@ bool BKE_fcurve_calc_range(
return foundvert;
}
-/**
- * Return an array of keyed frames, rounded to `interval`.
- *
- * \param interval: Set to 1.0 to round to whole keyframes, 0.5 for in-between key-frames, etc.
- *
- * \note An interval of zero could be supported (this implies no rounding at all),
- * however this risks very small differences in float values being treated as separate keyframes.
- */
float *BKE_fcurves_calc_keyed_frames_ex(FCurve **fcurve_array,
int fcurve_array_len,
const float interval,
@@ -902,10 +865,6 @@ float *BKE_fcurves_calc_keyed_frames(FCurve **fcurve_array,
/** \name Active Keyframe
* \{ */
-/**
- * Set the index that stores the FCurve's active keyframe, assuming that \a active_bezt
- * is already part of `fcu->bezt`. If NULL, set active keyframe index to "none."
- */
void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt)
{
if (active_bezt == NULL) {
@@ -927,9 +886,6 @@ void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt)
fcu->active_keyframe_index = (int)offset;
}
-/**
- * Get the active keyframe index, with sanity checks for point bounds.
- */
int BKE_fcurve_active_keyframe_index(const FCurve *fcu)
{
const int active_keyframe_index = fcu->active_keyframe_index;
@@ -963,10 +919,6 @@ void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, con
/** \name Status Checks
* \{ */
-/* Are keyframes on F-Curve of any use?
- * Usability of keyframes refers to whether they should be displayed,
- * and also whether they will have any influence on the final result.
- */
bool BKE_fcurve_are_keyframes_usable(FCurve *fcu)
{
/* F-Curve must exist. */
@@ -1032,9 +984,6 @@ bool BKE_fcurve_is_protected(FCurve *fcu)
return ((fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)));
}
-/* Can keyframes be added to F-Curve?
- * Keyframes can only be added if they are already visible.
- */
bool BKE_fcurve_is_keyframable(FCurve *fcu)
{
/* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
@@ -1057,7 +1006,6 @@ bool BKE_fcurve_is_keyframable(FCurve *fcu)
/** \name Keyframe Column Tools
* \{ */
-/* Add a BezTriple to a column. */
static void UNUSED_FUNCTION(bezt_add_to_cfra_elem)(ListBase *lb, BezTriple *bezt)
{
CfraElem *ce, *cen;
@@ -1100,18 +1048,12 @@ static void UNUSED_FUNCTION(bezt_add_to_cfra_elem)(ListBase *lb, BezTriple *bezt
* which BezTriples/Keyframe data are ill equipped to do.
*/
-/* Basic sampling callback which acts as a wrapper for evaluate_fcurve()
- * 'data' arg here is unneeded here...
- */
float fcurve_samplingcb_evalcurve(FCurve *fcu, void *UNUSED(data), float evaltime)
{
/* Assume any interference from drivers on the curve is intended... */
return evaluate_fcurve(fcu, evaltime);
}
-/* Main API function for creating a set of sampled curve data, given some callback function
- * used to retrieve the values to store.
- */
void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb)
{
FPoint *fpt, *new_fpt;
@@ -1159,7 +1101,6 @@ static void init_unbaked_bezt_data(BezTriple *bezt)
bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
}
-/* Convert baked/sampled fcurves into bezt/regular fcurves. */
void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end)
{
@@ -1235,7 +1176,6 @@ void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end)
* that the handles are correct.
*/
-/* Checks if the F-Curve has a Cycles modifier, and returns the type of the cycle behavior. */
eFCU_Cycle_Type BKE_fcurve_get_cycle_type(FCurve *fcu)
{
FModifier *fcm = fcu->modifiers.first;
@@ -1269,8 +1209,6 @@ eFCU_Cycle_Type BKE_fcurve_get_cycle_type(FCurve *fcu)
return FCU_CYCLE_NONE;
}
-/* Checks if the F-Curve has a Cycles modifier with simple settings
- * that warrant transition smoothing. */
bool BKE_fcurve_is_cyclic(FCurve *fcu)
{
return BKE_fcurve_get_cycle_type(fcu) != FCU_CYCLE_NONE;
@@ -1299,13 +1237,6 @@ static BezTriple *cycle_offset_triple(
return out;
}
-/**
- * Variant of #calchandles_fcurve() that allows calculating based on a different select flag.
- *
- * \param handle_sel_flag: The flag (bezt.f1/2/3) value to use to determine selection.
- * Usually `SELECT`, but may want to use a different one at times
- * (if caller does not operate on selection).
- */
void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
{
BezTriple *bezt, *prev, *next;
@@ -1389,28 +1320,11 @@ void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
}
}
-/**
- * This function recalculates the handles of an F-Curve. Acts based on selection with `SELECT`
- * flag. To use a different flag, use #calchandles_fcurve_ex().
- *
- * If the BezTriples have been rearranged, sort them first before using this.
- */
void calchandles_fcurve(FCurve *fcu)
{
calchandles_fcurve_ex(fcu, SELECT);
}
-/**
- * Update handles, making sure the handle-types are valid (e.g. correctly deduced from an "Auto"
- * type), and recalculating their position vectors.
- * Use when something has changed handle positions.
- *
- * \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
- * but may want to use a different one at times (if caller does not operate on
- * selection).
- * \param use_handle: Check selection state of individual handles, otherwise always update both
- * handles if the key is selected.
- */
void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_handle)
{
BezTriple *bezt;
@@ -1430,9 +1344,6 @@ void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_ha
calchandles_fcurve_ex(fcu, sel_flag);
}
-/* This function sorts BezTriples so that they are arranged in chronological order,
- * as tools working on F-Curves expect that the BezTriples are in order.
- */
void sort_time_fcurve(FCurve *fcu)
{
if (fcu->bezt == NULL) {
@@ -1475,7 +1386,6 @@ void sort_time_fcurve(FCurve *fcu)
}
}
-/* This function tests if any BezTriples are out of order, thus requiring a sort. */
bool test_time_fcurve(FCurve *fcu)
{
unsigned int a;
@@ -1517,14 +1427,6 @@ bool test_time_fcurve(FCurve *fcu)
/** \name F-Curve Calculations
* \{ */
-/**
- * The length of each handle is not allowed to be more
- * than the horizontal distance between (v1-v4).
- * This is to prevent curve loops.
- *
- * This function is very similar to BKE_curve_correct_bezpart(), but allows a steeper tangent for
- * more snappy animations. This is not desired for other areas in which curves are used, though.
- */
void BKE_fcurve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2])
{
float h1[2], h2[2], len1, len2, len, fac;
@@ -1709,14 +1611,6 @@ static void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
}
}
-/**
- * Adjust Bezier handles of all three given BezTriples, so that `bezt` can be inserted between
- * `prev` and `next` without changing the resulting curve shape.
- *
- * \param r_pdelta: return Y difference between `bezt` and the original curve value at its X
- * position.
- * \return Whether the split was successful.
- */
bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt,
struct BezTriple *prev,
struct BezTriple *next,
@@ -2252,14 +2146,12 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna,
return evaluate_fcurve_ex(fcu, evaltime, cvalue);
}
-/* Checks if the curve has valid keys, drivers or modifiers that produce an actual curve. */
bool BKE_fcurve_is_empty(FCurve *fcu)
{
return (fcu->totvert == 0) && (fcu->driver == NULL) &&
!list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE);
}
-/* Calculate the value of the given F-Curve at the given frame, and set its curval. */
float calculate_fcurve(PathResolvedRNA *anim_rna,
FCurve *fcu,
const AnimationEvalContext *anim_eval_context)
diff --git a/source/blender/blenkernel/intern/fcurve_cache.c b/source/blender/blenkernel/intern/fcurve_cache.c
index 8142b871edd..4f27bad5b91 100644
--- a/source/blender/blenkernel/intern/fcurve_cache.c
+++ b/source/blender/blenkernel/intern/fcurve_cache.c
@@ -155,11 +155,6 @@ FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
return NULL;
}
-/**
- * Fill in an array of F-Curve, leave NULL when not found.
- *
- * \return The number of F-Curves found.
- */
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
const char *rna_path,
FCurve **fcurve_result,
diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c
index 3ac64dbf84b..5496519e53b 100644
--- a/source/blender/blenkernel/intern/fcurve_driver.c
+++ b/source/blender/blenkernel/intern/fcurve_driver.c
@@ -199,9 +199,6 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return value;
}
-/**
- * Same as 'dtar_get_prop_val'. but get the RNA property.
- */
bool driver_get_variable_property(ChannelDriver *driver,
DriverTarget *dtar,
PointerRNA *r_ptr,
@@ -621,7 +618,6 @@ static void quaternion_to_angles(float quat[4], int channel)
}
}
-/* Compute channel values for a rotational Transform Channel driver variable. */
void BKE_driver_target_matrix_to_rot_channels(
float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
{
@@ -720,7 +716,6 @@ static const DriverVarTypeInfo *get_dvar_typeinfo(int type)
/** \name Driver API
* \{ */
-/* Perform actual freeing driver variable and remove it from the given list */
void driver_free_variable(ListBase *variables, DriverVar *dvar)
{
/* Sanity checks. */
@@ -745,7 +740,6 @@ void driver_free_variable(ListBase *variables, DriverVar *dvar)
BLI_freelinkN(variables, dvar);
}
-/* Free the driver variable and do extra updates */
void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar)
{
/* Remove and free the driver variable. */
@@ -755,7 +749,6 @@ void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar)
BKE_driver_invalidate_expression(driver, false, true);
}
-/* Copy driver variables from src_vars list to dst_vars list */
void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars)
{
BLI_assert(BLI_listbase_is_empty(dst_vars));
@@ -773,7 +766,6 @@ void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars)
}
}
-/* Change the type of driver variable */
void driver_change_variable_type(DriverVar *dvar, int type)
{
const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type);
@@ -803,7 +795,6 @@ void driver_change_variable_type(DriverVar *dvar, int type)
DRIVER_TARGETS_LOOPER_END;
}
-/* Validate driver name (after being renamed) */
void driver_variable_name_validate(DriverVar *dvar)
{
/* Special character blacklist */
@@ -873,7 +864,6 @@ void driver_variable_name_validate(DriverVar *dvar)
}
}
-/* Add a new driver variable */
DriverVar *driver_add_new_variable(ChannelDriver *driver)
{
DriverVar *dvar;
@@ -906,7 +896,6 @@ DriverVar *driver_add_new_variable(ChannelDriver *driver)
return dvar;
}
-/* This frees the driver itself */
void fcurve_free_driver(FCurve *fcu)
{
ChannelDriver *driver;
@@ -939,7 +928,6 @@ void fcurve_free_driver(FCurve *fcu)
fcu->driver = NULL;
}
-/* This makes a copy of the given driver */
ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver)
{
ChannelDriver *ndriver;
@@ -1082,7 +1070,6 @@ static bool driver_try_evaluate_simple_expr(ChannelDriver *driver,
driver_evaluate_simple_expr(driver, driver_orig->expr_simple, result, time);
}
-/* Check if the expression in the driver conforms to the simple subset. */
bool BKE_driver_has_simple_expression(ChannelDriver *driver)
{
return driver_compile_simple_expr(driver) && BLI_expr_pylike_is_valid(driver->expr_simple);
@@ -1109,7 +1096,6 @@ static bool python_driver_exression_depends_on_time(const char *expression)
return false;
}
-/* Check if the expression in the driver may depend on the current frame. */
bool BKE_driver_expression_depends_on_time(ChannelDriver *driver)
{
if (driver->type != DRIVER_TYPE_PYTHON) {
@@ -1125,7 +1111,6 @@ bool BKE_driver_expression_depends_on_time(ChannelDriver *driver)
return python_driver_exression_depends_on_time(driver->expression);
}
-/* Reset cached compiled expression data */
void BKE_driver_invalidate_expression(ChannelDriver *driver,
bool expr_changed,
bool varname_changed)
@@ -1152,7 +1137,6 @@ void BKE_driver_invalidate_expression(ChannelDriver *driver,
/** \name Driver Evaluation
* \{ */
-/* Evaluate a Driver Variable to get a value that contributes to the final */
float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
{
const DriverVarTypeInfo *dvti;
@@ -1269,14 +1253,6 @@ static void evaluate_driver_python(PathResolvedRNA *anim_rna,
}
}
-/**
- * Evaluate an Channel-Driver to get a 'time' value to use
- * instead of `anim_eval_context->eval_time`.
- *
- * - `anim_eval_context->eval_time` is the frame at which F-Curve is being evaluated.
- * - Has to return a float value.
- * - \a driver_orig is where we cache Python expressions, in case of COW
- */
float evaluate_driver(PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
@@ -1309,3 +1285,5 @@ float evaluate_driver(PathResolvedRNA *anim_rna,
/* Return value for driver. */
return driver->curval;
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 9d26a1528f3..39122b33683 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -4437,8 +4437,6 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v
}
}
-/* Get fluid velocity and density at given coordinates
- * Returns fluid density or -1.0f if outside domain. */
float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3])
{
FluidModifierData *fmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
@@ -4575,10 +4573,10 @@ void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_typ
}
}
-#endif /* WITH_FLUID */
-
/** \} */
+#endif /* WITH_FLUID */
+
/* -------------------------------------------------------------------- */
/** \name Public Data Access API
*
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 121927513cc..d140e70978a 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1065,10 +1065,6 @@ static void fmods_init_typeinfo(void)
fmodifiersTypeInfo[9] = &FMI_STEPPED; /* Stepped F-Curve Modifier */
}
-/**
- * This function should be used for getting the appropriate type-info when only
- * a F-Curve modifier type is known.
- */
const FModifierTypeInfo *get_fmodifier_typeinfo(const int type)
{
/* initialize the type-info list? */
@@ -1088,10 +1084,6 @@ const FModifierTypeInfo *get_fmodifier_typeinfo(const int type)
return NULL;
}
-/**
- * This function should always be used to get the appropriate type-info,
- * as it has checks which prevent segfaults in some weird cases.
- */
const FModifierTypeInfo *fmodifier_get_typeinfo(const FModifier *fcm)
{
/* only return typeinfo for valid modifiers */
@@ -1108,9 +1100,6 @@ const FModifierTypeInfo *fmodifier_get_typeinfo(const FModifier *fcm)
/** \name F-Curve Modifier Public API
* \{ */
-/**
- * Add a new F-Curve Modifier to the given F-Curve of a certain type.
- */
FModifier *add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
{
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
@@ -1161,9 +1150,6 @@ FModifier *add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
return fcm;
}
-/**
- * Make a copy of the specified F-Modifier.
- */
FModifier *copy_fmodifier(const FModifier *src)
{
const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src);
@@ -1191,9 +1177,6 @@ FModifier *copy_fmodifier(const FModifier *src)
return dst;
}
-/**
- * Duplicate all of the F-Modifiers in the Modifier stacks.
- */
void copy_fmodifiers(ListBase *dst, const ListBase *src)
{
FModifier *fcm, *srcfcm;
@@ -1220,9 +1203,6 @@ void copy_fmodifiers(ListBase *dst, const ListBase *src)
}
}
-/**
- * Remove and free the given F-Modifier from the given stack.
- */
bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
{
const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
@@ -1263,9 +1243,6 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
return false;
}
-/**
- * Remove all of a given F-Curve's modifiers.
- */
void free_fmodifiers(ListBase *modifiers)
{
FModifier *fcm, *fmn;
@@ -1282,9 +1259,6 @@ void free_fmodifiers(ListBase *modifiers)
}
}
-/**
- * Find the active F-Modifier.
- */
FModifier *find_active_fmodifier(ListBase *modifiers)
{
FModifier *fcm;
@@ -1305,9 +1279,6 @@ FModifier *find_active_fmodifier(ListBase *modifiers)
return NULL;
}
-/**
- * Set the active F-Modifier.
- */
void set_active_fmodifier(ListBase *modifiers, FModifier *fcm)
{
FModifier *fm;
@@ -1328,12 +1299,6 @@ void set_active_fmodifier(ListBase *modifiers, FModifier *fcm)
}
}
-/**
- * Do we have any modifiers which match certain criteria.
- *
- * \param mtype: Type of modifier (if 0, doesn't matter).
- * \param acttype: Type of action to perform (if -1, doesn't matter).
- */
bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
{
FModifier *fcm;
@@ -1443,19 +1408,6 @@ static float eval_fmodifier_influence(FModifier *fcm, float evaltime)
return influence;
}
-/**
- * Evaluate time modifications imposed by some F-Curve Modifiers.
- *
- * - This step acts as an optimization to prevent the F-Curve stack being evaluated
- * several times by modifiers requesting the time be modified, as the final result
- * would have required using the modified time
- * - Modifiers only ever receive the unmodified time, as subsequent modifiers should be
- * working on the 'global' result of the modified curve, not some localized segment,
- * so \a evaltime gets set to whatever the last time-modifying modifier likes.
- * - We start from the end of the stack, as only the last one matters for now.
- *
- * \param fcu: Can be NULL.
- */
float evaluate_time_fmodifiers(FModifiersStackStorage *storage,
ListBase *modifiers,
FCurve *fcu,
@@ -1513,10 +1465,6 @@ float evaluate_time_fmodifiers(FModifiersStackStorage *storage,
return evaltime;
}
-/**
- * Evaluates the given set of F-Curve Modifiers using the given data
- * Should only be called after evaluate_time_fmodifiers() has been called.
- */
void evaluate_value_fmodifiers(FModifiersStackStorage *storage,
ListBase *modifiers,
FCurve *fcu,
@@ -1565,10 +1513,6 @@ void evaluate_value_fmodifiers(FModifiersStackStorage *storage,
/* ---------- */
-/**
- * Bake modifiers for given F-Curve to curve sample data, in the frame range defined
- * by start and end (inclusive).
- */
void fcurve_bake_modifiers(FCurve *fcu, int start, int end)
{
ChannelDriver *driver;
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index d9b3faf8623..68b7e274970 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -152,10 +152,6 @@ bool BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig
return true;
}
-/**
- * Reinsert \a module_conf offset by \a direction from current position.
- * \return if position of \a module_conf changed.
- */
bool BKE_freestyle_module_move(FreestyleConfig *config,
FreestyleModuleConfig *module_conf,
int direction)
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index 598c61fd877..1e24b29038d 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -77,7 +77,6 @@ bool CurveComponent::has_curve() const
return curve_ != nullptr;
}
-/* Clear the component and replace it with the new curve. */
void CurveComponent::replace(CurveEval *curve, GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
@@ -128,10 +127,6 @@ void CurveComponent::ensure_owns_direct_data()
}
}
-/**
- * Create empty curve data used for rendering the spline's wire edges.
- * \note See comment on #curve_for_render_ for further explanation.
- */
const Curve *CurveComponent::get_curve_for_render() const
{
if (curve_ == nullptr) {
@@ -391,14 +386,14 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen
/** \} */
+namespace blender::bke {
+
/* -------------------------------------------------------------------- */
/** \name Builtin Spline Attributes
*
* Attributes with a value for every spline, stored contiguously or in every spline separately.
* \{ */
-namespace blender::bke {
-
class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
using AsReadAttribute = GVArray (*)(const CurveEval &data);
using AsWriteAttribute = GVMutableArray (*)(CurveEval &data);
@@ -714,46 +709,15 @@ 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 VArrayImpl<T> {
- private:
- const Array<Span<T>> data_;
- Array<int> offsets_;
-
- public:
- VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets)
- : VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
- {
- }
-
- 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(const IndexMask mask, MutableSpan<T> r_span) const final
- {
- point_attribute_materialize(data_.as_span(), offsets_, mask, r_span);
- }
-
- 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);
- }
-};
-
-/**
* Mutable virtual array for any control point data accessed with spans and an offset array.
*/
-template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> {
+template<typename T> class VArrayImpl_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)
+ VArrayImpl_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
: VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
{
}
@@ -791,16 +755,17 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl
}
};
-template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets)
+template<typename T> VArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
{
- return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets));
+ return VArray<T>::template For<VArrayImpl_For_SplinePoints<T>>(std::move(spans),
+ std::move(offsets));
}
template<typename T>
-VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
+VMutableArray<T> point_data_varray_mutable(Array<MutableSpan<T>> spans, Array<int> offsets)
{
- return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans),
- std::move(offsets));
+ return VMutableArray<T>::template For<VArrayImpl_For_SplinePoints<T>>(std::move(spans),
+ std::move(offsets));
}
/**
@@ -811,13 +776,13 @@ VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offse
* \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 VMutableArrayImpl<float3> {
+class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
public:
- VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
+ VArrayImpl_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
: VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
{
}
@@ -889,104 +854,16 @@ class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3>
}
};
-class VArray_For_BezierHandle final : public VArrayImpl<float3> {
- private:
- Span<SplinePtr> splines_;
- Array<int> offsets_;
- bool is_right_;
-
- public:
- VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right)
- : VArrayImpl<float3>(offsets.last()),
- splines_(std::move(splines)),
- offsets_(std::move(offsets)),
- is_right_(is_right)
- {
- }
-
- static float3 get_internal(const int64_t index,
- Span<SplinePtr> splines,
- Span<int> offsets,
- const bool is_right)
- {
- const PointIndices indices = lookup_point_indices(offsets, index);
- const Spline &spline = *splines[indices.spline_index];
- if (spline.type() == Spline::Type::Bezier) {
- const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline);
- return is_right ? bezier_spline.handle_positions_right()[indices.point_index] :
- bezier_spline.handle_positions_left()[indices.point_index];
- }
- return float3(0);
- }
-
- float3 get(const int64_t index) const final
- {
- return get_internal(index, splines_, offsets_, is_right_);
- }
-
- /**
- * Utility so we can pass handle positions to the materialize functions above.
- *
- * \note This relies on the ability of the materialize implementations to
- * handle empty spans, since only Bezier splines have handles.
- */
- static Array<Span<float3>> get_handle_spans(Span<SplinePtr> splines, const bool is_right)
- {
- Array<Span<float3>> spans(splines.size());
- for (const int i : spans.index_range()) {
- if (splines[i]->type() == Spline::Type::Bezier) {
- BezierSpline &bezier_spline = static_cast<BezierSpline &>(*splines[i]);
- spans[i] = is_right ? bezier_spline.handle_positions_right() :
- bezier_spline.handle_positions_left();
- }
- else {
- spans[i] = {};
- }
- }
- return spans;
- }
-
- static void materialize_internal(const IndexMask mask,
- Span<SplinePtr> splines,
- Span<int> offsets,
- const bool is_right,
- MutableSpan<float3> r_span)
- {
- Array<Span<float3>> spans = get_handle_spans(splines, is_right);
- point_attribute_materialize(spans.as_span(), offsets, mask, r_span);
- }
-
- static void materialize_to_uninitialized_internal(const IndexMask mask,
- Span<SplinePtr> splines,
- Span<int> offsets,
- const bool is_right,
- MutableSpan<float3> r_span)
- {
- Array<Span<float3>> spans = get_handle_spans(splines, is_right);
- point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span);
- }
-
- void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
- {
- materialize_internal(mask, splines_, offsets_, is_right_, r_span);
- }
-
- 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 VMutableArrayImpl<float3> {
+class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
private:
MutableSpan<SplinePtr> splines_;
Array<int> offsets_;
bool is_right_;
public:
- VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines,
- Array<int> offsets,
- const bool is_right)
+ VArrayImpl_For_BezierHandles(MutableSpan<SplinePtr> splines,
+ Array<int> offsets,
+ const bool is_right)
: VMutableArrayImpl<float3>(offsets.last()),
splines_(splines),
offsets_(std::move(offsets)),
@@ -996,7 +873,14 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
float3 get(const int64_t index) const final
{
- return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_);
+ const PointIndices indices = lookup_point_indices(offsets_, index);
+ const Spline &spline = *splines_[indices.spline_index];
+ if (spline.type() == Spline::Type::Bezier) {
+ const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline);
+ return is_right_ ? bezier_spline.handle_positions_right()[indices.point_index] :
+ bezier_spline.handle_positions_left()[indices.point_index];
+ }
+ return float3(0);
}
void set(const int64_t index, float3 value) final
@@ -1040,13 +924,36 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
{
- VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span);
+ Array<Span<float3>> spans = get_handle_spans(splines_, is_right_);
+ point_attribute_materialize(spans.as_span(), offsets_, mask, r_span);
}
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);
+ Array<Span<float3>> spans = get_handle_spans(splines_, is_right_);
+ point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span);
+ }
+
+ /**
+ * Utility so we can pass handle positions to the materialize functions above.
+ *
+ * \note This relies on the ability of the materialize implementations to
+ * handle empty spans, since only Bezier splines have handles.
+ */
+ static Array<Span<float3>> get_handle_spans(Span<SplinePtr> splines, const bool is_right)
+ {
+ Array<Span<float3>> spans(splines.size());
+ for (const int i : spans.index_range()) {
+ if (splines[i]->type() == Spline::Type::Bezier) {
+ BezierSpline &bezier_spline = static_cast<BezierSpline &>(*splines[i]);
+ spans[i] = is_right ? bezier_spline.handle_positions_right() :
+ bezier_spline.handle_positions_left();
+ }
+ else {
+ spans[i] = {};
+ }
+ }
+ return spans;
}
};
@@ -1102,9 +1009,12 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
}
Array<int> offsets = curve->control_point_offsets();
- Array<Span<T>> spans(splines.size());
+ Array<MutableSpan<T>> spans(splines.size());
for (const int i : splines.index_range()) {
- spans[i] = get_span_(*splines[i]);
+ Span<T> span = get_span_(*splines[i]);
+ /* Use const-cast because the underlying virtual array implementation is shared between const
+ * and non const data. */
+ spans[i] = MutableSpan<T>(const_cast<T *>(span.data()), span.size());
}
return point_data_varray(spans, offsets);
@@ -1143,7 +1053,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
spans[i] = get_mutable_span_(*splines[i]);
}
- return {point_data_varray(spans, offsets), domain_, tag_modified_fn};
+ return {point_data_varray_mutable(spans, offsets), domain_, tag_modified_fn};
}
bool try_delete(GeometryComponent &component) const final
@@ -1235,8 +1145,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
};
Array<int> offsets = curve->control_point_offsets();
- return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(),
- std::move(offsets)),
+ return {VMutableArray<float3>::For<VArrayImpl_For_SplinePosition>(curve->splines(),
+ std::move(offsets)),
domain_,
tag_modified_fn};
}
@@ -1270,8 +1180,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
}
Array<int> offsets = curve->control_point_offsets();
- return VArray<float3>::For<VArray_For_BezierHandle>(
- curve->splines(), std::move(offsets), is_right_);
+ /* Use const-cast because the underlying virtual array implementation is shared between const
+ * and non const data. */
+ return VArray<float3>::For<VArrayImpl_For_BezierHandles>(
+ const_cast<CurveEval *>(curve)->splines(), std::move(offsets), is_right_);
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
@@ -1288,7 +1200,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); };
Array<int> offsets = curve->control_point_offsets();
- return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>(
+ return {VMutableArray<float3>::For<VArrayImpl_For_BezierHandles>(
curve->splines(), std::move(offsets), is_right_),
domain_,
tag_modified_fn};
@@ -1377,9 +1289,12 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
Array<int> offsets = curve->control_point_offsets();
attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) {
using T = decltype(dummy);
- Array<Span<T>> data(splines.size());
+ Array<MutableSpan<T>> data(splines.size());
for (const int i : splines.index_range()) {
- data[i] = spans[i].typed<T>();
+ Span<T> span = spans[i].typed<T>();
+ /* Use const-cast because the underlying virtual array implementation is shared between
+ * const and non const data. */
+ data[i] = MutableSpan<T>(const_cast<T *>(span.data()), span.size());
BLI_assert(data[i].data() != nullptr);
}
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
@@ -1435,7 +1350,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
data[i] = spans[i].typed<T>();
BLI_assert(data[i].data() != nullptr);
}
- attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
+ attribute = {point_data_varray_mutable(data, offsets), ATTR_DOMAIN_POINT};
});
return attribute;
}
@@ -1570,6 +1485,8 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
{&spline_custom_data, &point_custom_data});
}
+/** \} */
+
} // namespace blender::bke
const blender::bke::ComponentAttributeProviders *CurveComponent::get_attribute_providers() const
@@ -1578,5 +1495,3 @@ const blender::bke::ComponentAttributeProviders *CurveComponent::get_attribute_p
blender::bke::create_attribute_providers_for_curve();
return &providers;
}
-
-/** \} */
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 9a30c86c1e5..93a7646fed0 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -31,12 +31,17 @@
#include "attribute_access_intern.hh"
+#include "FN_cpp_type_make.hh"
+
using blender::float4x4;
using blender::Map;
using blender::MutableSpan;
using blender::Set;
using blender::Span;
using blender::VectorSet;
+using blender::fn::GSpan;
+
+MAKE_CPP_TYPE(InstanceReference, InstanceReference, CPPTypeFlags::None)
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
@@ -51,8 +56,8 @@ GeometryComponent *InstancesComponent::copy() const
InstancesComponent *new_component = new InstancesComponent();
new_component->instance_reference_handles_ = instance_reference_handles_;
new_component->instance_transforms_ = instance_transforms_;
- new_component->instance_ids_ = instance_ids_;
new_component->references_ = references_;
+ new_component->attributes_ = attributes_;
return new_component;
}
@@ -60,32 +65,21 @@ void InstancesComponent::reserve(int min_capacity)
{
instance_reference_handles_.reserve(min_capacity);
instance_transforms_.reserve(min_capacity);
- if (!instance_ids_.is_empty()) {
- this->instance_ids_ensure();
- }
+ attributes_.reallocate(min_capacity);
}
-/**
- * Resize the transform, handles, and ID vectors to the specified capacity.
- *
- * \note This function should be used carefully, only when it's guaranteed
- * that the data will be filled.
- */
void InstancesComponent::resize(int capacity)
{
instance_reference_handles_.resize(capacity);
instance_transforms_.resize(capacity);
- if (!instance_ids_.is_empty()) {
- this->instance_ids_ensure();
- }
+ attributes_.reallocate(capacity);
}
void InstancesComponent::clear()
{
instance_reference_handles_.clear();
instance_transforms_.clear();
- instance_ids_.clear();
-
+ attributes_.clear();
references_.clear();
}
@@ -95,9 +89,7 @@ void InstancesComponent::add_instance(const int instance_handle, const float4x4
BLI_assert(instance_handle < references_.size());
instance_reference_handles_.append(instance_handle);
instance_transforms_.append(transform);
- if (!instance_ids_.is_empty()) {
- this->instance_ids_ensure();
- }
+ attributes_.reallocate(this->instances_amount());
}
blender::Span<int> InstancesComponent::instance_reference_handles() const
@@ -119,36 +111,6 @@ blender::Span<blender::float4x4> InstancesComponent::instance_transforms() const
return instance_transforms_;
}
-blender::MutableSpan<int> InstancesComponent::instance_ids()
-{
- return instance_ids_;
-}
-blender::Span<int> InstancesComponent::instance_ids() const
-{
- return instance_ids_;
-}
-
-/**
- * Make sure the ID storage size matches the number of instances. By directly resizing the
- * component's vectors internally, it is possible to be in a situation where the IDs are not
- * empty but they do not have the correct size; this function resolves that.
- */
-blender::MutableSpan<int> InstancesComponent::instance_ids_ensure()
-{
- instance_ids_.append_n_times(0, this->instances_amount() - instance_ids_.size());
- return instance_ids_;
-}
-
-void InstancesComponent::instance_ids_clear()
-{
- instance_ids_.clear_and_make_inline();
-}
-
-/**
- * With write access to the instances component, the data in the instanced geometry sets can be
- * changed. This is a function on the component rather than each reference to ensure `const`
- * correctness for that reason.
- */
GeometrySet &InstancesComponent::geometry_set_from_reference(const int reference_index)
{
/* If this assert fails, it means #ensure_geometry_instances must be called first or that the
@@ -160,11 +122,6 @@ GeometrySet &InstancesComponent::geometry_set_from_reference(const int reference
return const_cast<GeometrySet &>(references_[reference_index].geometry_set());
}
-/**
- * Returns a handle for the given reference.
- * If the reference exists already, the handle of the existing reference is returned.
- * Otherwise a new handle is added.
- */
int InstancesComponent::add_reference(const InstanceReference &reference)
{
return references_.index_of_or_add_as(reference);
@@ -347,15 +304,17 @@ static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids)
blender::Span<int> InstancesComponent::almost_unique_ids() const
{
std::lock_guard lock(almost_unique_ids_mutex_);
- if (instance_ids().is_empty()) {
- almost_unique_ids_.reinitialize(this->instances_amount());
- for (const int i : almost_unique_ids_.index_range()) {
- almost_unique_ids_[i] = i;
+ std::optional<GSpan> instance_ids_gspan = attributes_.get_for_read("id");
+ if (instance_ids_gspan) {
+ Span<int> instance_ids = instance_ids_gspan->typed<int>();
+ if (almost_unique_ids_.size() != instance_ids.size()) {
+ almost_unique_ids_ = generate_unique_instance_ids(instance_ids);
}
}
else {
- if (almost_unique_ids_.size() != instance_ids_.size()) {
- almost_unique_ids_ = generate_unique_instance_ids(instance_ids_);
+ almost_unique_ids_.reinitialize(this->instances_amount());
+ for (const int i : almost_unique_ids_.index_range()) {
+ almost_unique_ids_[i] = i;
}
}
return almost_unique_ids_;
@@ -434,81 +393,21 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
}
};
-class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
- public:
- InstanceIDAttributeProvider()
- : BuiltinAttributeProvider(
- "id", ATTR_DOMAIN_INSTANCE, CD_PROP_INT32, Creatable, Writable, Deletable)
- {
- }
-
- 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 VArray<int>::ForSpan(instances.instance_ids());
- }
-
- WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
- {
- InstancesComponent &instances = static_cast<InstancesComponent &>(component);
- if (instances.instance_ids().is_empty()) {
- return {};
- }
- return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_};
- }
-
- bool try_delete(GeometryComponent &component) const final
- {
- InstancesComponent &instances = static_cast<InstancesComponent &>(component);
- if (instances.instance_ids().is_empty()) {
- return false;
- }
- instances.instance_ids_clear();
- return true;
- }
-
- bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final
- {
- InstancesComponent &instances = static_cast<InstancesComponent &>(component);
- if (instances.instances_amount() == 0) {
- return false;
- }
- MutableSpan<int> ids = instances.instance_ids_ensure();
- switch (initializer.type) {
- case AttributeInit::Type::Default: {
- ids.fill(0);
- break;
- }
- case AttributeInit::Type::VArray: {
- const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
- varray.materialize_to_uninitialized(varray.index_range(), ids.data());
- break;
- }
- case AttributeInit::Type::MoveArray: {
- void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
- ids.copy_from({static_cast<int *>(source_data), instances.instances_amount()});
- MEM_freeN(source_data);
- break;
- }
- }
- return true;
- }
+template<typename T>
+static GVArray make_array_read_attribute(const void *data, const int domain_size)
+{
+ return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
+}
- bool exists(const GeometryComponent &component) const final
- {
- const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
- return !instances.instance_ids().is_empty();
- }
-};
+template<typename T>
+static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
+{
+ return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
+}
static ComponentAttributeProviders create_attribute_providers_for_instances()
{
static InstancePositionAttributeProvider position;
- static InstanceIDAttributeProvider id;
-
static CustomDataAccessInfo instance_custom_data_access = {
[](GeometryComponent &component) -> CustomData * {
InstancesComponent &inst = static_cast<InstancesComponent &>(component);
@@ -520,6 +419,24 @@ static ComponentAttributeProviders create_attribute_providers_for_instances()
},
nullptr};
+ /**
+ * IDs of the instances. They are used for consistency over multiple frames for things like
+ * motion blur. Proper stable ID data that actually helps when rendering can only be generated
+ * in some situations, so this vector is allowed to be empty, in which case the index of each
+ * instance will be used for the final ID.
+ */
+ static BuiltinCustomDataLayerProvider id("id",
+ ATTR_DOMAIN_INSTANCE,
+ CD_PROP_INT32,
+ CD_PROP_INT32,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ instance_custom_data_access,
+ make_array_read_attribute<int>,
+ make_array_write_attribute<int>,
+ nullptr);
+
static CustomDataAttributeProvider instance_custom_data(ATTR_DOMAIN_INSTANCE,
instance_custom_data_access);
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 86a52b420b6..cc15e6d7b84 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -29,7 +29,6 @@
#include "attribute_access_intern.hh"
-/* 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);
/* -------------------------------------------------------------------- */
@@ -71,7 +70,6 @@ bool MeshComponent::has_mesh() const
return mesh_ != nullptr;
}
-/* Clear the component and replace it with the new mesh. */
void MeshComponent::replace(Mesh *mesh, GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
@@ -80,8 +78,6 @@ void MeshComponent::replace(Mesh *mesh, GeometryOwnershipType ownership)
ownership_ = ownership;
}
-/* Return the mesh and clear the component. The caller takes over responsibility for freeing the
- * mesh (if the component was responsible before). */
Mesh *MeshComponent::release()
{
BLI_assert(this->is_mutable());
@@ -90,15 +86,11 @@ Mesh *MeshComponent::release()
return mesh;
}
-/* Get the mesh from this component. This method can be used by multiple threads at the same
- * time. Therefore, the returned mesh should not be modified. No ownership is transferred. */
const Mesh *MeshComponent::get_for_read() const
{
return mesh_;
}
-/* Get the mesh from this component. This method can only be used when the component is mutable,
- * i.e. it is not shared. The returned mesh can be modified. No ownership is transferred. */
Mesh *MeshComponent::get_for_write()
{
BLI_assert(this->is_mutable());
@@ -996,57 +988,36 @@ static void set_crease(MEdge &edge, float value)
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
}
-class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
+class VArrayImpl_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)
+ VArrayImpl_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
: VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
{
}
float get(const int64_t index) const override
{
- return get_internal(dverts_, dvert_index_, index);
- }
-
- void set(const int64_t index, const float value) override
- {
- MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
- weight->weight = value;
- }
-
- static float get_internal(const MDeformVert *dverts, const int dvert_index, const int64_t index)
- {
- if (dverts == nullptr) {
+ if (dverts_ == nullptr) {
return 0.0f;
}
- const MDeformVert &dvert = dverts[index];
+ const MDeformVert &dvert = dverts_[index];
for (const MDeformWeight &weight : Span(dvert.dw, dvert.totweight)) {
- if (weight.def_nr == dvert_index) {
+ if (weight.def_nr == dvert_index_) {
return weight.weight;
}
}
return 0.0f;
+ ;
}
-};
-
-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)
- : VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
- {
- }
-
- float get(const int64_t index) const override
+ void set(const int64_t index, const float value) override
{
- return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index);
+ MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
+ weight->weight = value;
}
};
@@ -1077,7 +1048,7 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
static const float default_value = 0.0f;
return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT};
}
- return {VArray<float>::For<VArray_For_VertexWeights>(
+ return {VArray<float>::For<VArrayImpl_For_VertexWeights>(
mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}
@@ -1109,7 +1080,7 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
}
- return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>(
+ return {VMutableArray<float>::For<VArrayImpl_For_VertexWeights>(
mesh->dvert, mesh->totvert, vertex_group_index),
ATTR_DOMAIN_POINT};
}
@@ -1127,16 +1098,19 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
}
const std::string name = attribute_id.name();
- const int vertex_group_index = BLI_findstringindex(
- &mesh->vertex_group_names, name.c_str(), offsetof(bDeformGroup, name));
- if (vertex_group_index < 0) {
+
+ int index;
+ bDeformGroup *group;
+ if (!BKE_id_defgroup_name_find(&mesh->id, name.c_str(), &index, &group)) {
return false;
}
+ BLI_remlink(&mesh->vertex_group_names, group);
+ MEM_freeN(group);
if (mesh->dvert == nullptr) {
return true;
}
for (MDeformVert &dvert : MutableSpan(mesh->dvert, mesh->totvert)) {
- MDeformWeight *weight = BKE_defvert_find_index(&dvert, vertex_group_index);
+ MDeformWeight *weight = BKE_defvert_find_index(&dvert, index);
BKE_defvert_remove_group(&dvert, weight);
}
return true;
diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
index c6a1c61a96d..80c09a7ed4a 100644
--- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
+++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc
@@ -62,7 +62,6 @@ bool PointCloudComponent::has_pointcloud() const
return pointcloud_ != nullptr;
}
-/* Clear the component and replace it with the new point cloud. */
void PointCloudComponent::replace(PointCloud *pointcloud, GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
@@ -71,8 +70,6 @@ void PointCloudComponent::replace(PointCloud *pointcloud, GeometryOwnershipType
ownership_ = ownership;
}
-/* Return the point cloud and clear the component. The caller takes over responsibility for freeing
- * the point cloud (if the component was responsible before). */
PointCloud *PointCloudComponent::release()
{
BLI_assert(this->is_mutable());
@@ -81,17 +78,11 @@ PointCloud *PointCloudComponent::release()
return pointcloud;
}
-/* Get the point cloud from this component. This method can be used by multiple threads at the same
- * time. Therefore, the returned point cloud should not be modified. No ownership is transferred.
- */
const PointCloud *PointCloudComponent::get_for_read() const
{
return pointcloud_;
}
-/* Get the point cloud from this component. This method can only be used when the component is
- * mutable, i.e. it is not shared. The returned point cloud can be modified. No ownership is
- * transferred. */
PointCloud *PointCloudComponent::get_for_write()
{
BLI_assert(this->is_mutable());
diff --git a/source/blender/blenkernel/intern/geometry_component_volume.cc b/source/blender/blenkernel/intern/geometry_component_volume.cc
index 94ed07a63de..e9874153b4c 100644
--- a/source/blender/blenkernel/intern/geometry_component_volume.cc
+++ b/source/blender/blenkernel/intern/geometry_component_volume.cc
@@ -59,7 +59,6 @@ bool VolumeComponent::has_volume() const
return volume_ != nullptr;
}
-/* Clear the component and replace it with the new volume. */
void VolumeComponent::replace(Volume *volume, GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
@@ -68,8 +67,6 @@ void VolumeComponent::replace(Volume *volume, GeometryOwnershipType ownership)
ownership_ = ownership;
}
-/* Return the volume and clear the component. The caller takes over responsibility for freeing the
- * volume (if the component was responsible before). */
Volume *VolumeComponent::release()
{
BLI_assert(this->is_mutable());
@@ -78,15 +75,11 @@ Volume *VolumeComponent::release()
return volume;
}
-/* Get the volume from this component. This method can be used by multiple threads at the same
- * time. Therefore, the returned volume should not be modified. No ownership is transferred. */
const Volume *VolumeComponent::get_for_read() const
{
return volume_;
}
-/* Get the volume from this component. This method can only be used when the component is mutable,
- * i.e. it is not shared. The returned volume can be modified. No ownership is transferred. */
Volume *VolumeComponent::get_for_write()
{
BLI_assert(this->is_mutable());
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index c250c14f1d7..ef5609ec9a8 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -105,7 +105,6 @@ bool GeometryComponent::is_empty() const
/** \name Geometry Set
* \{ */
-/* The methods are defaulted here so that they are not instantiated in every translation unit. */
GeometrySet::GeometrySet() = default;
GeometrySet::GeometrySet(const GeometrySet &other) = default;
GeometrySet::GeometrySet(GeometrySet &&other) = default;
@@ -113,36 +112,24 @@ GeometrySet::~GeometrySet() = default;
GeometrySet &GeometrySet::operator=(const GeometrySet &other) = default;
GeometrySet &GeometrySet::operator=(GeometrySet &&other) = default;
-/* This method can only be used when the geometry set is mutable. It returns a mutable geometry
- * component of the given type.
- */
GeometryComponent &GeometrySet::get_component_for_write(GeometryComponentType component_type)
{
- return components_.add_or_modify(
- component_type,
- [&](GeometryComponentPtr *value_ptr) -> GeometryComponent & {
- /* If the component did not exist before, create a new one. */
- new (value_ptr) GeometryComponentPtr(GeometryComponent::create(component_type));
- return **value_ptr;
- },
- [&](GeometryComponentPtr *value_ptr) -> GeometryComponent & {
- GeometryComponentPtr &value = *value_ptr;
- if (value->is_mutable()) {
- /* If the referenced component is already mutable, return it directly. */
- return *value;
- }
- /* If the referenced component is shared, make a copy. The copy is not shared and is
- * therefore mutable. */
- GeometryComponent *copied_component = value->copy();
- value = GeometryComponentPtr{copied_component};
- return *copied_component;
- });
+ GeometryComponentPtr &component_ptr = components_[component_type];
+ if (!component_ptr) {
+ /* If the component did not exist before, create a new one. */
+ component_ptr = GeometryComponent::create(component_type);
+ return *component_ptr;
+ }
+ if (component_ptr->is_mutable()) {
+ /* If the referenced component is already mutable, return it directly. */
+ return *component_ptr;
+ }
+ /* If the referenced component is shared, make a copy. The copy is not shared and is
+ * therefore mutable. */
+ component_ptr = component_ptr->copy();
+ return *component_ptr;
}
-/**
- * Retrieve the pointer to a component without creating it if it does not exist,
- * unlike #get_component_for_write.
- */
GeometryComponent *GeometrySet::get_component_ptr(GeometryComponentType type)
{
if (this->has(type)) {
@@ -151,56 +138,47 @@ GeometryComponent *GeometrySet::get_component_ptr(GeometryComponentType type)
return nullptr;
}
-/* Get the component of the given type. Might return null if the component does not exist yet. */
const GeometryComponent *GeometrySet::get_component_for_read(
GeometryComponentType component_type) const
{
- const GeometryComponentPtr *component = components_.lookup_ptr(component_type);
- if (component != nullptr) {
- return component->get();
- }
- return nullptr;
+ return components_[component_type].get();
}
bool GeometrySet::has(const GeometryComponentType component_type) const
{
- return components_.contains(component_type);
+ return components_[component_type].has_value();
}
void GeometrySet::remove(const GeometryComponentType component_type)
{
- components_.remove(component_type);
+ components_[component_type].reset();
}
-/**
- * Remove all geometry components with types that are not in the provided list.
- */
void GeometrySet::keep_only(const blender::Span<GeometryComponentType> component_types)
{
- for (auto it = components_.keys().begin(); it != components_.keys().end(); ++it) {
- const GeometryComponentType type = *it;
- if (!component_types.contains(type)) {
- components_.remove(it);
+ for (GeometryComponentPtr &component_ptr : components_) {
+ if (component_ptr) {
+ if (!component_types.contains(component_ptr->type())) {
+ component_ptr.reset();
+ }
}
}
}
void GeometrySet::add(const GeometryComponent &component)
{
- BLI_assert(!components_.contains(component.type()));
+ BLI_assert(!components_[component.type()]);
component.user_add();
- GeometryComponentPtr component_ptr{const_cast<GeometryComponent *>(&component)};
- components_.add_new(component.type(), std::move(component_ptr));
+ components_[component.type()] = const_cast<GeometryComponent *>(&component);
}
-/**
- * Get all geometry components in this geometry set for read-only access.
- */
Vector<const GeometryComponent *> GeometrySet::get_components_for_read() const
{
Vector<const GeometryComponent *> components;
- for (const GeometryComponentPtr &ptr : components_.values()) {
- components.append(ptr.get());
+ for (const GeometryComponentPtr &component_ptr : components_) {
+ if (component_ptr) {
+ components.append(component_ptr.get());
+ }
}
return components;
}
@@ -233,122 +211,111 @@ std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
return stream;
}
-/* Remove all geometry components from the geometry set. */
void GeometrySet::clear()
{
- components_.clear();
+ for (GeometryComponentPtr &component_ptr : components_) {
+ component_ptr.reset();
+ }
}
-/* Make sure that the geometry can be cached. This does not ensure ownership of object/collection
- * instances. */
void GeometrySet::ensure_owns_direct_data()
{
- for (GeometryComponentType type : components_.keys()) {
- const GeometryComponent *component = this->get_component_for_read(type);
- if (!component->owns_direct_data()) {
- GeometryComponent &component_for_write = this->get_component_for_write(type);
- component_for_write.ensure_owns_direct_data();
+ for (GeometryComponentPtr &component_ptr : components_) {
+ if (!component_ptr) {
+ continue;
}
+ if (component_ptr->owns_direct_data()) {
+ continue;
+ }
+ GeometryComponent &component_for_write = this->get_component_for_write(component_ptr->type());
+ component_for_write.ensure_owns_direct_data();
}
}
bool GeometrySet::owns_direct_data() const
{
- for (const GeometryComponentPtr &component : components_.values()) {
- if (!component->owns_direct_data()) {
- return false;
+ for (const GeometryComponentPtr &component_ptr : components_) {
+ if (component_ptr) {
+ if (!component_ptr->owns_direct_data()) {
+ return false;
+ }
}
}
return true;
}
-/* Returns a read-only mesh or null. */
const Mesh *GeometrySet::get_mesh_for_read() const
{
const MeshComponent *component = this->get_component_for_read<MeshComponent>();
return (component == nullptr) ? nullptr : component->get_for_read();
}
-/* Returns true when the geometry set has a mesh component that has a mesh. */
bool GeometrySet::has_mesh() const
{
const MeshComponent *component = this->get_component_for_read<MeshComponent>();
return component != nullptr && component->has_mesh();
}
-/* Returns a read-only point cloud of null. */
const PointCloud *GeometrySet::get_pointcloud_for_read() const
{
const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
return (component == nullptr) ? nullptr : component->get_for_read();
}
-/* Returns a read-only volume or null. */
const Volume *GeometrySet::get_volume_for_read() const
{
const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
return (component == nullptr) ? nullptr : component->get_for_read();
}
-/* Returns a read-only curve or null. */
const CurveEval *GeometrySet::get_curve_for_read() const
{
const CurveComponent *component = this->get_component_for_read<CurveComponent>();
return (component == nullptr) ? nullptr : component->get_for_read();
}
-/* Returns true when the geometry set has a point cloud component that has a point cloud. */
bool GeometrySet::has_pointcloud() const
{
const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
return component != nullptr && component->has_pointcloud();
}
-/* Returns true when the geometry set has an instances component that has at least one instance. */
bool GeometrySet::has_instances() const
{
const InstancesComponent *component = this->get_component_for_read<InstancesComponent>();
return component != nullptr && component->instances_amount() >= 1;
}
-/* Returns true when the geometry set has a volume component that has a volume. */
bool GeometrySet::has_volume() const
{
const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
return component != nullptr && component->has_volume();
}
-/* Returns true when the geometry set has a curve component that has a curve. */
bool GeometrySet::has_curve() const
{
const CurveComponent *component = this->get_component_for_read<CurveComponent>();
return component != nullptr && component->has_curve();
}
-/* Returns true when the geometry set has any data that is not an instance. */
bool GeometrySet::has_realized_data() const
{
- if (components_.is_empty()) {
- return false;
- }
- if (components_.size() > 1) {
- return true;
+ for (const GeometryComponentPtr &component_ptr : components_) {
+ if (component_ptr) {
+ if (component_ptr->type() != GEO_COMPONENT_TYPE_INSTANCES) {
+ return true;
+ }
+ }
}
- /* Check if the only component is an #InstancesComponent. */
- return this->get_component_for_read<InstancesComponent>() == nullptr;
+ return false;
}
-/* Return true if the geometry set has any component that isn't empty. */
bool GeometrySet::is_empty() const
{
- if (components_.is_empty()) {
- return true;
- }
- return !(this->has_mesh() || this->has_curve() || this->has_pointcloud() ||
+ return !(this->has_mesh() || this->has_curve() || this->has_pointcloud() || this->has_volume() ||
this->has_instances());
}
-/* Create a new geometry set that only contains the given mesh. */
GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
@@ -359,7 +326,6 @@ GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType owne
return geometry_set;
}
-/* Create a new geometry set that only contains the given point cloud. */
GeometrySet GeometrySet::create_with_pointcloud(PointCloud *pointcloud,
GeometryOwnershipType ownership)
{
@@ -371,7 +337,6 @@ GeometrySet GeometrySet::create_with_pointcloud(PointCloud *pointcloud,
return geometry_set;
}
-/* Create a new geometry set that only contains the given curve. */
GeometrySet GeometrySet::create_with_curve(CurveEval *curve, GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
@@ -382,76 +347,80 @@ GeometrySet GeometrySet::create_with_curve(CurveEval *curve, GeometryOwnershipTy
return geometry_set;
}
-/* Clear the existing mesh and replace it with the given one. */
void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership)
{
if (mesh == nullptr) {
this->remove<MeshComponent>();
+ return;
}
- else {
- MeshComponent &component = this->get_component_for_write<MeshComponent>();
- component.replace(mesh, ownership);
+ if (mesh == this->get_mesh_for_read()) {
+ return;
}
+ this->remove<MeshComponent>();
+ MeshComponent &component = this->get_component_for_write<MeshComponent>();
+ component.replace(mesh, ownership);
}
-/* Clear the existing curve and replace it with the given one. */
void GeometrySet::replace_curve(CurveEval *curve, GeometryOwnershipType ownership)
{
if (curve == nullptr) {
this->remove<CurveComponent>();
+ return;
}
- else {
- CurveComponent &component = this->get_component_for_write<CurveComponent>();
- component.replace(curve, ownership);
+ if (curve == this->get_curve_for_read()) {
+ return;
}
+ this->remove<CurveComponent>();
+ CurveComponent &component = this->get_component_for_write<CurveComponent>();
+ component.replace(curve, ownership);
}
-/* Clear the existing point cloud and replace with the given one. */
void GeometrySet::replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership)
{
if (pointcloud == nullptr) {
this->remove<PointCloudComponent>();
+ return;
}
- else {
- PointCloudComponent &component = this->get_component_for_write<PointCloudComponent>();
- component.replace(pointcloud, ownership);
+ if (pointcloud == this->get_pointcloud_for_read()) {
+ return;
}
+ this->remove<PointCloudComponent>();
+ PointCloudComponent &component = this->get_component_for_write<PointCloudComponent>();
+ component.replace(pointcloud, ownership);
}
-/* Clear the existing volume and replace with the given one. */
void GeometrySet::replace_volume(Volume *volume, GeometryOwnershipType ownership)
{
if (volume == nullptr) {
this->remove<VolumeComponent>();
+ return;
}
- else {
- VolumeComponent &component = this->get_component_for_write<VolumeComponent>();
- component.replace(volume, ownership);
+ if (volume == this->get_volume_for_read()) {
+ return;
}
+ this->remove<VolumeComponent>();
+ VolumeComponent &component = this->get_component_for_write<VolumeComponent>();
+ component.replace(volume, ownership);
}
-/* Returns a mutable mesh or null. No ownership is transferred. */
Mesh *GeometrySet::get_mesh_for_write()
{
MeshComponent *component = this->get_component_ptr<MeshComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
-/* Returns a mutable point cloud or null. No ownership is transferred. */
PointCloud *GeometrySet::get_pointcloud_for_write()
{
PointCloudComponent *component = this->get_component_ptr<PointCloudComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
-/* Returns a mutable volume or null. No ownership is transferred. */
Volume *GeometrySet::get_volume_for_write()
{
VolumeComponent *component = this->get_component_ptr<VolumeComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
-/* Returns a mutable curve or null. No ownership is transferred. */
CurveEval *GeometrySet::get_curve_for_write()
{
CurveComponent *component = this->get_component_ptr<CurveComponent>();
@@ -512,13 +481,18 @@ void GeometrySet::gather_attributes_for_propagation(
return;
}
+ AttributeDomain domain = meta_data.domain;
+ if (dst_component_type != GEO_COMPONENT_TYPE_INSTANCES && domain == ATTR_DOMAIN_INSTANCE) {
+ domain = ATTR_DOMAIN_POINT;
+ }
+
auto add_info = [&](AttributeKind *attribute_kind) {
- attribute_kind->domain = meta_data.domain;
+ attribute_kind->domain = domain;
attribute_kind->data_type = meta_data.data_type;
};
auto modify_info = [&](AttributeKind *attribute_kind) {
attribute_kind->domain = bke::attribute_domain_highest_priority(
- {attribute_kind->domain, meta_data.domain});
+ {attribute_kind->domain, domain});
attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
{attribute_kind->data_type, meta_data.data_type});
};
@@ -581,10 +555,6 @@ static void gather_mutable_geometry_sets(GeometrySet &geometry_set,
}
}
-/**
- * Modify every (recursive) instance separately. This is often more efficient than realizing all
- * instances just to change the same thing on all of them.
- */
void GeometrySet::modify_geometry_sets(ForeachSubGeometryCallback callback)
{
Vector<GeometrySet *> geometry_sets;
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index c73da7d9659..4d84d5d899d 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -53,9 +53,6 @@ static void add_final_mesh_as_geometry_component(const Object &object, GeometryS
}
}
-/**
- * \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
- */
GeometrySet object_get_evaluated_geometry_set(const Object &object)
{
if (object.type == OB_MESH && object.mode == OB_MODE_EDIT) {
@@ -77,7 +74,7 @@ GeometrySet object_get_evaluated_geometry_set(const Object &object)
add_final_mesh_as_geometry_component(object, geometry_set);
}
- /* TODO: Cover the case of point-clouds without modifiers-- they may not be covered by the
+ /* TODO: Cover the case of point clouds without modifiers-- they may not be covered by the
* #geometry_set_eval case above. */
/* TODO: Add volume support. */
@@ -169,16 +166,6 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
}
}
-/**
- * Return flattened vector of the geometry component's recursive instances. I.e. all collection
- * instances and object instances will be expanded into the instances of their geometry components.
- * Even the instances in those geometry components' will be included.
- *
- * \note For convenience (to avoid duplication in the caller), the returned vector also contains
- * the argument geometry set.
- *
- * \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
- */
void geometry_set_gather_instances(const GeometrySet &geometry_set,
Vector<GeometryInstanceGroup> &r_instance_groups)
{
@@ -220,375 +207,6 @@ void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> se
}
}
-static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups)
-{
- int totverts = 0;
- int totloops = 0;
- int totedges = 0;
- int totpolys = 0;
- int64_t cd_dirty_vert = 0;
- int64_t cd_dirty_poly = 0;
- int64_t cd_dirty_edge = 0;
- int64_t cd_dirty_loop = 0;
- VectorSet<Material *> materials;
-
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- const int tot_transforms = set_group.transforms.size();
- if (set.has_mesh()) {
- const Mesh &mesh = *set.get_mesh_for_read();
- totverts += mesh.totvert * tot_transforms;
- totloops += mesh.totloop * tot_transforms;
- totedges += mesh.totedge * tot_transforms;
- totpolys += mesh.totpoly * tot_transforms;
- cd_dirty_vert |= mesh.runtime.cd_dirty_vert;
- cd_dirty_poly |= mesh.runtime.cd_dirty_poly;
- cd_dirty_edge |= mesh.runtime.cd_dirty_edge;
- cd_dirty_loop |= mesh.runtime.cd_dirty_loop;
- for (const int slot_index : IndexRange(mesh.totcol)) {
- Material *material = mesh.mat[slot_index];
- materials.add(material);
- }
- }
- }
-
- /* Don't create an empty mesh. */
- if ((totverts + totloops + totedges + totpolys) == 0) {
- return nullptr;
- }
-
- Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys);
- /* Copy settings from the first input geometry set with a mesh. */
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- if (set.has_mesh()) {
- const Mesh &mesh = *set.get_mesh_for_read();
- BKE_mesh_copy_parameters_for_eval(new_mesh, &mesh);
- break;
- }
- }
- for (const int i : IndexRange(materials.size())) {
- Material *material = materials[i];
- BKE_id_material_eval_assign(&new_mesh->id, i + 1, material);
- }
- new_mesh->runtime.cd_dirty_vert = cd_dirty_vert;
- new_mesh->runtime.cd_dirty_poly = cd_dirty_poly;
- new_mesh->runtime.cd_dirty_edge = cd_dirty_edge;
- new_mesh->runtime.cd_dirty_loop = cd_dirty_loop;
-
- int vert_offset = 0;
- int loop_offset = 0;
- int edge_offset = 0;
- int poly_offset = 0;
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- if (set.has_mesh()) {
- const Mesh &mesh = *set.get_mesh_for_read();
-
- Array<int> material_index_map(mesh.totcol);
- for (const int i : IndexRange(mesh.totcol)) {
- Material *material = mesh.mat[i];
- const int new_material_index = materials.index_of(material);
- material_index_map[i] = new_material_index;
- }
-
- for (const float4x4 &transform : set_group.transforms) {
- for (const int i : IndexRange(mesh.totvert)) {
- const MVert &old_vert = mesh.mvert[i];
- MVert &new_vert = new_mesh->mvert[vert_offset + i];
-
- new_vert = old_vert;
-
- const float3 new_position = transform * float3(old_vert.co);
- copy_v3_v3(new_vert.co, new_position);
- }
- for (const int i : IndexRange(mesh.totedge)) {
- const MEdge &old_edge = mesh.medge[i];
- MEdge &new_edge = new_mesh->medge[edge_offset + i];
- new_edge = old_edge;
- new_edge.v1 += vert_offset;
- new_edge.v2 += vert_offset;
- }
- for (const int i : IndexRange(mesh.totloop)) {
- const MLoop &old_loop = mesh.mloop[i];
- MLoop &new_loop = new_mesh->mloop[loop_offset + i];
- new_loop = old_loop;
- new_loop.v += vert_offset;
- new_loop.e += edge_offset;
- }
- for (const int i : IndexRange(mesh.totpoly)) {
- const MPoly &old_poly = mesh.mpoly[i];
- MPoly &new_poly = new_mesh->mpoly[poly_offset + i];
- new_poly = old_poly;
- new_poly.loopstart += loop_offset;
- if (old_poly.mat_nr >= 0 && old_poly.mat_nr < mesh.totcol) {
- new_poly.mat_nr = material_index_map[new_poly.mat_nr];
- }
- else {
- /* The material index was invalid before. */
- new_poly.mat_nr = 0;
- }
- }
-
- vert_offset += mesh.totvert;
- loop_offset += mesh.totloop;
- edge_offset += mesh.totedge;
- poly_offset += mesh.totpoly;
- }
- }
- }
-
- /* A possible optimization is to only tag the normals dirty when there are transforms that change
- * normals. */
- BKE_mesh_normals_tag_dirty(new_mesh);
-
- return new_mesh;
-}
-
-static void join_attributes(Span<GeometryInstanceGroup> set_groups,
- Span<GeometryComponentType> component_types,
- const Map<AttributeIDRef, AttributeKind> &attribute_info,
- GeometryComponent &result)
-{
- for (Map<AttributeIDRef, AttributeKind>::Item entry : attribute_info.items()) {
- const AttributeIDRef attribute_id = entry.key;
- const AttributeDomain domain_output = entry.value.domain;
- const CustomDataType data_type_output = entry.value.data_type;
- const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type_output);
- BLI_assert(cpp_type != nullptr);
-
- 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 ||
- write_attribute.domain != domain_output) {
- continue;
- }
-
- fn::GVMutableArray_GSpan dst_span{write_attribute.varray};
-
- int offset = 0;
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- for (const GeometryComponentType component_type : component_types) {
- if (set.has(component_type)) {
- const GeometryComponent &component = *set.get_component_for_read(component_type);
- const int domain_size = component.attribute_domain_size(domain_output);
- if (domain_size == 0) {
- continue; /* Domain size is 0, so no need to increment the offset. */
- }
- 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};
- const void *src_buffer = src_span.data();
- for (const int UNUSED(i) : set_group.transforms.index_range()) {
- void *dst_buffer = dst_span[offset];
- cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size);
- offset += domain_size;
- }
- }
- else {
- offset += domain_size * set_group.transforms.size();
- }
- }
- }
- }
-
- dst_span.save();
- }
-}
-
-static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup> set_groups)
-{
- /* Count the total number of points. */
- int totpoint = 0;
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- if (set.has<PointCloudComponent>()) {
- const PointCloudComponent &component = *set.get_component_for_read<PointCloudComponent>();
- totpoint += component.attribute_domain_size(ATTR_DOMAIN_POINT);
- }
- }
- if (totpoint == 0) {
- return nullptr;
- }
-
- PointCloud *new_pointcloud = BKE_pointcloud_new_nomain(totpoint);
- MutableSpan new_positions{(float3 *)new_pointcloud->co, new_pointcloud->totpoint};
-
- /* Transform each instance's point locations into the new point cloud. */
- int offset = 0;
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- const PointCloud *pointcloud = set.get_pointcloud_for_read();
- if (pointcloud == nullptr) {
- continue;
- }
- for (const float4x4 &transform : set_group.transforms) {
- for (const int i : IndexRange(pointcloud->totpoint)) {
- new_positions[offset + i] = transform * float3(pointcloud->co[i]);
- }
- offset += pointcloud->totpoint;
- }
- }
-
- return new_pointcloud;
-}
-
-static CurveEval *join_curve_splines_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups)
-{
- Vector<SplinePtr> new_splines;
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- if (!set.has_curve()) {
- continue;
- }
-
- const CurveEval &source_curve = *set.get_curve_for_read();
- for (const SplinePtr &source_spline : source_curve.splines()) {
- for (const float4x4 &transform : set_group.transforms) {
- SplinePtr new_spline = source_spline->copy_without_attributes();
- new_spline->transform(transform);
- new_splines.append(std::move(new_spline));
- }
- }
- }
- if (new_splines.is_empty()) {
- return nullptr;
- }
-
- CurveEval *new_curve = new CurveEval();
- for (SplinePtr &new_spline : new_splines) {
- new_curve->add_spline(std::move(new_spline));
- }
-
- new_curve->attributes.reallocate(new_curve->splines().size());
- return new_curve;
-}
-
-static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, GeometrySet &result)
-{
- Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups);
- if (new_mesh == nullptr) {
- return;
- }
-
- MeshComponent &dst_component = result.get_component_for_write<MeshComponent>();
- dst_component.replace(new_mesh);
-
- /* Don't copy attributes that are stored directly in the mesh data structs. */
- Map<AttributeIDRef, AttributeKind> attributes;
- geometry_set_gather_instances_attribute_info(
- set_groups,
- {GEO_COMPONENT_TYPE_MESH},
- {"position", "material_index", "normal", "shade_smooth", "crease"},
- attributes);
- join_attributes(set_groups,
- {GEO_COMPONENT_TYPE_MESH},
- attributes,
- static_cast<GeometryComponent &>(dst_component));
-}
-
-static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_groups,
- GeometrySet &result)
-{
- PointCloud *new_pointcloud = join_pointcloud_position_attribute(set_groups);
- if (new_pointcloud == nullptr) {
- return;
- }
-
- PointCloudComponent &dst_component = result.get_component_for_write<PointCloudComponent>();
- dst_component.replace(new_pointcloud);
-
- Map<AttributeIDRef, AttributeKind> attributes;
- geometry_set_gather_instances_attribute_info(
- set_groups, {GEO_COMPONENT_TYPE_POINT_CLOUD}, {"position"}, attributes);
- join_attributes(set_groups,
- {GEO_COMPONENT_TYPE_POINT_CLOUD},
- attributes,
- static_cast<GeometryComponent &>(dst_component));
-}
-
-static void join_instance_groups_volume(Span<GeometryInstanceGroup> set_groups,
- GeometrySet &result)
-{
- /* Not yet supported; for now only return the first volume. Joining volume grids with the same
- * name requires resampling of at least one of the grids. The cell size of the resulting volume
- * has to be determined somehow. */
- for (const GeometryInstanceGroup &set_group : set_groups) {
- const GeometrySet &set = set_group.geometry_set;
- if (set.has<VolumeComponent>()) {
- result.add(*set.get_component_for_read<VolumeComponent>());
- return;
- }
- }
-}
-
-/**
- * Curve point domain attributes must be in the same order on every spline. The order might have
- * been different on separate instances, so ensure that all splines have the same order. Note that
- * because #Map is used, the order is not necessarily consistent every time, but it is the same for
- * every spline, and that's what matters.
- */
-static void sort_curve_point_attributes(const Map<AttributeIDRef, AttributeKind> &info,
- MutableSpan<SplinePtr> splines)
-{
- Vector<AttributeIDRef> new_order;
- for (Map<AttributeIDRef, AttributeKind>::Item item : info.items()) {
- if (item.value.domain == ATTR_DOMAIN_POINT) {
- /* Only sort attributes stored on splines. */
- new_order.append(item.key);
- }
- }
- for (SplinePtr &spline : splines) {
- spline->attributes.reorder(new_order);
- }
-}
-
-static void join_instance_groups_curve(Span<GeometryInstanceGroup> set_groups, GeometrySet &result)
-{
- CurveEval *curve = join_curve_splines_and_builtin_attributes(set_groups);
- if (curve == nullptr) {
- return;
- }
-
- CurveComponent &dst_component = result.get_component_for_write<CurveComponent>();
- dst_component.replace(curve);
-
- Map<AttributeIDRef, AttributeKind> attributes;
- geometry_set_gather_instances_attribute_info(
- set_groups,
- {GEO_COMPONENT_TYPE_CURVE},
- {"position", "radius", "tilt", "handle_left", "handle_right", "cyclic", "resolution"},
- attributes);
- join_attributes(set_groups,
- {GEO_COMPONENT_TYPE_CURVE},
- attributes,
- static_cast<GeometryComponent &>(dst_component));
- sort_curve_point_attributes(attributes, curve->splines());
- curve->assert_valid_point_attributes();
-}
-
-GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
-{
- if (!geometry_set.has_instances()) {
- return geometry_set;
- }
-
- GeometrySet new_geometry_set;
-
- Vector<GeometryInstanceGroup> set_groups;
- geometry_set_gather_instances(geometry_set, set_groups);
- join_instance_groups_mesh(set_groups, new_geometry_set);
- join_instance_groups_pointcloud(set_groups, new_geometry_set);
- join_instance_groups_volume(set_groups, new_geometry_set);
- join_instance_groups_curve(set_groups, new_geometry_set);
-
- return new_geometry_set;
-}
-
} // namespace blender::bke
void InstancesComponent::foreach_referenced_geometry(
@@ -624,11 +242,6 @@ void InstancesComponent::foreach_referenced_geometry(
}
}
-/**
- * If references have a collection or object type, convert them into geometry instances
- * recursively. After that, the geometry sets can be edited. There may still be instances of other
- * types of they can't be converted to geometry sets.
- */
void InstancesComponent::ensure_geometry_instances()
{
using namespace blender;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index bea65030c06..13338f33bd6 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -320,6 +320,7 @@ IDTypeInfo IDType_ID_GD = {
.name_plural = "grease_pencils",
.translation_context = BLT_I18NCONTEXT_ID_GPENCIL,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = greasepencil_copy_data,
@@ -327,6 +328,7 @@ IDTypeInfo IDType_ID_GD = {
.make_local = NULL,
.foreach_id = greasepencil_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = greasepencil_blend_write,
@@ -363,7 +365,6 @@ void BKE_gpencil_batch_cache_free(bGPdata *gpd)
/* ************************************************** */
/* Memory Management */
-/* clean vertex groups weights */
void BKE_gpencil_free_point_weights(MDeformVert *dvert)
{
if (dvert == NULL) {
@@ -402,7 +403,6 @@ void BKE_gpencil_free_stroke_editcurve(bGPDstroke *gps)
gps->editcurve = NULL;
}
-/* free stroke, doesn't unlink from any listbase */
void BKE_gpencil_free_stroke(bGPDstroke *gps)
{
if (gps == NULL) {
@@ -426,7 +426,6 @@ void BKE_gpencil_free_stroke(bGPDstroke *gps)
MEM_freeN(gps);
}
-/* Free strokes belonging to a gp-frame */
bool BKE_gpencil_free_strokes(bGPDframe *gpf)
{
bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
@@ -440,7 +439,6 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf)
return changed;
}
-/* Free all of a gp-layer's frames */
void BKE_gpencil_free_frames(bGPDlayer *gpl)
{
bGPDframe *gpf_next;
@@ -470,7 +468,6 @@ void BKE_gpencil_free_layer_masks(bGPDlayer *gpl)
BLI_freelinkN(&gpl->mask_layers, mask);
}
}
-/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
void BKE_gpencil_free_layers(ListBase *list)
{
bGPDlayer *gpl_next;
@@ -494,7 +491,6 @@ void BKE_gpencil_free_layers(ListBase *list)
}
}
-/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
void BKE_gpencil_free_data(bGPdata *gpd, bool free_all)
{
/* free layers */
@@ -512,10 +508,6 @@ void BKE_gpencil_free_data(bGPdata *gpd, bool free_all)
}
}
-/**
- * Delete grease pencil evaluated data
- * \param gpd_eval: Grease pencil data-block
- */
void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
{
BKE_gpencil_free_data(gpd_eval, true);
@@ -524,11 +516,6 @@ void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
MEM_freeN(gpd_eval);
}
-/**
- * Tag data-block for depsgraph update.
- * Wrapper to avoid include Depsgraph tag functions in other modules.
- * \param gpd: Grease pencil data-block.
- */
void BKE_gpencil_tag(bGPdata *gpd)
{
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -537,12 +524,6 @@ void BKE_gpencil_tag(bGPdata *gpd)
/* ************************************************** */
/* Container Creation */
-/**
- * Add a new gp-frame to the given layer.
- * \param gpl: Grease pencil layer
- * \param cframe: Frame number
- * \return Pointer to new frame
- */
bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
{
bGPDframe *gpf = NULL, *gf = NULL;
@@ -596,12 +577,6 @@ bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
return gpf;
}
-/**
- * Add a copy of the active gp-frame to the given layer.
- * \param gpl: Grease pencil layer
- * \param cframe: Frame number
- * \return Pointer to new frame
- */
bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
{
bGPDframe *new_frame;
@@ -656,14 +631,6 @@ bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
return new_frame;
}
-/**
- * Add a new gp-layer and make it the active layer.
- * \param gpd: Grease pencil data-block
- * \param name: Name of the layer
- * \param setactive: Set as active
- * \param add_to_header: Used to force the layer added at header
- * \return Pointer to new layer
- */
bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd,
const char *name,
const bool setactive,
@@ -748,12 +715,6 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd,
return gpl;
}
-/**
- * Add a new grease pencil data-block.
- * \param bmain: Main pointer
- * \param name: Name of the datablock
- * \return Pointer to new data-block
- */
bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
{
bGPdata *gpd;
@@ -805,13 +766,6 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
/* Primitive Creation */
/* Utilities for easier bulk-creation of geometry */
-/**
- * Create a new stroke, with pre-allocated data buffers.
- * \param mat_idx: Index of the material
- * \param totpoints: Total points
- * \param thickness: Stroke thickness
- * \return Pointer to new stroke
- */
bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
{
/* allocate memory for a new stroke */
@@ -848,15 +802,6 @@ bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
return gps;
}
-/**
- * Create a new stroke and add to frame.
- * \param gpf: Grease pencil frame
- * \param mat_idx: Material index
- * \param totpoints: Total points
- * \param thickness: Stroke thickness
- * \param insert_at_head: Add to the head of the strokes list
- * \return Pointer to new stroke
- */
bGPDstroke *BKE_gpencil_stroke_add(
bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
{
@@ -875,16 +820,6 @@ bGPDstroke *BKE_gpencil_stroke_add(
return gps;
}
-/**
- * Add a stroke and copy the temporary drawing color value
- * from one of the existing stroke.
- * \param gpf: Grease pencil frame
- * \param existing: Stroke with the style to copy
- * \param mat_idx: Material index
- * \param totpoints: Total points
- * \param thickness: Stroke thickness
- * \return Pointer to new stroke
- */
bGPDstroke *BKE_gpencil_stroke_add_existing_style(
bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
{
@@ -909,11 +844,6 @@ bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points)
/* ************************************************** */
/* Data Duplication */
-/**
- * Make a copy of a given gpencil weights.
- * \param gps_src: Source grease pencil stroke
- * \param gps_dst: Destination grease pencil stroke
- */
void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
{
if (gps_src == NULL) {
@@ -924,7 +854,6 @@ void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_d
BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
}
-/* Make a copy of a given gpencil stroke editcurve */
bGPDcurve *BKE_gpencil_stroke_curve_duplicate(bGPDcurve *gpc_src)
{
bGPDcurve *gpc_dst = MEM_dupallocN(gpc_src);
@@ -936,13 +865,6 @@ bGPDcurve *BKE_gpencil_stroke_curve_duplicate(bGPDcurve *gpc_src)
return gpc_dst;
}
-/**
- * Make a copy of a given grease-pencil stroke.
- * \param gps_src: Source grease pencil strokes.
- * \param dup_points: Duplicate points data.
- * \param dup_curve: Duplicate curve data.
- * \return Pointer to new stroke.
- */
bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src,
const bool dup_points,
const bool dup_curve)
@@ -980,11 +902,6 @@ bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src,
return gps_dst;
}
-/**
- * Make a copy of a given gpencil frame.
- * \param gpf_src: Source grease pencil frame
- * \return Pointer to new frame
- */
bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes)
{
bGPDstroke *gps_dst = NULL;
@@ -1013,11 +930,6 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_
return gpf_dst;
}
-/**
- * Make a copy of strokes between gpencil frames.
- * \param gpf_src: Source grease pencil frame
- * \param gpf_dst: Destination grease pencil frame
- */
void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
{
bGPDstroke *gps_dst = NULL;
@@ -1035,11 +947,6 @@ void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_ds
}
}
-/**
- * Make a copy of a given gpencil layer.
- * \param gpl_src: Source grease pencil layer
- * \return Pointer to new layer
- */
bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src,
const bool dup_frames,
const bool dup_strokes)
@@ -1078,9 +985,6 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src,
return gpl_dst;
}
-/**
- * Make a copy of a given gpencil layer settings.
- */
void BKE_gpencil_layer_copy_settings(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst)
{
gpl_dst->line_change = gpl_src->line_change;
@@ -1102,11 +1006,6 @@ void BKE_gpencil_layer_copy_settings(const bGPDlayer *gpl_src, bGPDlayer *gpl_ds
gpl_dst->flag = gpl_src->flag;
}
-/**
- * Make a copy of a given gpencil data-block.
- *
- * XXX: Should this be deprecated?
- */
bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
{
bGPdata *gpd_dst;
@@ -1139,10 +1038,6 @@ bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool in
/* ************************************************** */
/* GP Stroke API */
-/**
- * Ensure selection status of stroke is in sync with its points.
- * \param gps: Grease pencil stroke
- */
void BKE_gpencil_stroke_sync_selection(bGPdata *gpd, bGPDstroke *gps)
{
bGPDspoint *pt;
@@ -1206,14 +1101,12 @@ void BKE_gpencil_curve_sync_selection(bGPdata *gpd, bGPDstroke *gps)
}
}
-/* Assign unique stroke ID for selection. */
void BKE_gpencil_stroke_select_index_set(bGPdata *gpd, bGPDstroke *gps)
{
gpd->select_last_index++;
gps->select_index = gpd->select_last_index;
}
-/* Reset unique stroke ID for selection. */
void BKE_gpencil_stroke_select_index_reset(bGPDstroke *gps)
{
gps->select_index = 0;
@@ -1222,11 +1115,6 @@ void BKE_gpencil_stroke_select_index_reset(bGPDstroke *gps)
/* ************************************************** */
/* GP Frame API */
-/**
- * Delete the last stroke of the given frame.
- * \param gpl: Grease pencil layer
- * \param gpf: Grease pencil frame
- */
void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
{
bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
@@ -1258,11 +1146,6 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
/* ************************************************** */
/* GP Layer API */
-/**
- * Check if the given layer is able to be edited or not.
- * \param gpl: Grease pencil layer
- * \return True if layer is editable
- */
bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
{
/* Sanity check */
@@ -1279,12 +1162,6 @@ bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
return false;
}
-/**
- * Look up the gp-frame on the requested frame number, but don't add a new one.
- * \param gpl: Grease pencil layer
- * \param cframe: Frame number
- * \return Pointer to frame
- */
bGPDframe *BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
{
bGPDframe *gpf;
@@ -1301,16 +1178,6 @@ bGPDframe *BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
return NULL;
}
-/**
- * Get the appropriate gp-frame from a given layer
- * - this sets the layer's actframe var (if allowed to)
- * - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
- *
- * \param gpl: Grease pencil layer
- * \param cframe: Frame number
- * \param addnew: Add option
- * \return Pointer to new frame
- */
bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
{
bGPDframe *gpf = NULL;
@@ -1465,12 +1332,6 @@ bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_
return gpl->actframe;
}
-/**
- * Delete the given frame from a layer.
- * \param gpl: Grease pencil layer
- * \param gpf: Grease pencil frame
- * \return True if delete was done
- */
bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
{
bool changed = false;
@@ -1494,12 +1355,6 @@ bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
return changed;
}
-/**
- * Get layer by name
- * \param gpd: Grease pencil data-block
- * \param name: Layer name
- * \return Pointer to layer
- */
bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
{
if (name[0] == '\0') {
@@ -1508,12 +1363,6 @@ bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
return BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info));
}
-/**
- * Get mask layer by name.
- * \param gpl: Grease pencil layer
- * \param name: Mask name
- * \return Pointer to mask layer
- */
bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(bGPDlayer *gpl, const char *name)
{
if (name[0] == '\0') {
@@ -1522,12 +1371,6 @@ bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(bGPDlayer *gpl, const char *nam
return BLI_findstring(&gpl->mask_layers, name, offsetof(bGPDlayer_Mask, name));
}
-/**
- * Add grease pencil mask layer.
- * \param gpl: Grease pencil layer
- * \param name: Name of the mask
- * \return Pointer to new mask layer
- */
bGPDlayer_Mask *BKE_gpencil_layer_mask_add(bGPDlayer *gpl, const char *name)
{
@@ -1539,11 +1382,6 @@ bGPDlayer_Mask *BKE_gpencil_layer_mask_add(bGPDlayer *gpl, const char *name)
return mask;
}
-/**
- * Remove grease pencil mask layer.
- * \param gpl: Grease pencil layer
- * \param mask: Grease pencil mask layer
- */
void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask)
{
BLI_freelinkN(&gpl->mask_layers, mask);
@@ -1551,11 +1389,6 @@ void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask)
CLAMP_MIN(gpl->act_mask, 0);
}
-/**
- * Remove any reference to mask layer.
- * \param gpd: Grease pencil data-block
- * \param name: Name of the mask layer
- */
void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
{
bGPDlayer_Mask *mask_next;
@@ -1587,11 +1420,6 @@ static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
return val;
}
-/**
- * Sort grease pencil mask layers.
- * \param gpd: Grease pencil data-block
- * \param gpl: Grease pencil layer
- */
void BKE_gpencil_layer_mask_sort(bGPdata *gpd, bGPDlayer *gpl)
{
/* Update sort index. */
@@ -1607,10 +1435,6 @@ void BKE_gpencil_layer_mask_sort(bGPdata *gpd, bGPDlayer *gpl)
BLI_listbase_sort(&gpl->mask_layers, gpencil_cb_sort_masks);
}
-/**
- * Sort all grease pencil mask layer.
- * \param gpd: Grease pencil data-block
- */
void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
{
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
@@ -1618,9 +1442,6 @@ void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
}
}
-/**
- * Make a copy of a given gpencil mask layers.
- */
void BKE_gpencil_layer_mask_copy(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst)
{
BLI_listbase_clear(&gpl_dst->mask_layers);
@@ -1631,9 +1452,6 @@ void BKE_gpencil_layer_mask_copy(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst)
}
}
-/**
- * Clean any invalid mask layer.
- */
void BKE_gpencil_layer_mask_cleanup(bGPdata *gpd, bGPDlayer *gpl)
{
LISTBASE_FOREACH_MUTABLE (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
@@ -1643,9 +1461,6 @@ void BKE_gpencil_layer_mask_cleanup(bGPdata *gpd, bGPDlayer *gpl)
}
}
-/**
- * Clean any invalid mask layer for all layers.
- */
void BKE_gpencil_layer_mask_cleanup_all_layers(bGPdata *gpd)
{
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
@@ -1674,21 +1489,11 @@ static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
return 0;
}
-/**
- * Sort grease pencil frames.
- * \param gpl: Grease pencil layer
- * \param r_has_duplicate_frames: Duplicated frames flag
- */
void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames)
{
BLI_listbase_sort_r(&gpl->frames, gpencil_cb_cmp_frame, r_has_duplicate_frames);
}
-/**
- * Get the active grease pencil layer for editing.
- * \param gpd: Grease pencil data-block
- * \return Pointer to layer
- */
bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
{
/* error checking */
@@ -1732,11 +1537,6 @@ bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_
return NULL;
}
-/**
- * Set active grease pencil layer.
- * \param gpd: Grease pencil data-block
- * \param active: Grease pencil layer to set as active
- */
void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
{
/* error checking */
@@ -1759,11 +1559,6 @@ void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
}
}
-/**
- * Set locked layers for autolock mode.
- * \param gpd: Grease pencil data-block
- * \param unlock: Unlock flag
- */
void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
{
BLI_assert(gpd != NULL);
@@ -1794,11 +1589,6 @@ void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
}
}
-/**
- * Delete grease pencil layer.
- * \param gpd: Grease pencil data-block
- * \param gpl: Grease pencil layer
- */
void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
{
/* error checking */
@@ -1821,11 +1611,6 @@ void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
BLI_freelinkN(&gpd->layers, gpl);
}
-/**
- * Get grease pencil material from brush.
- * \param brush: Brush
- * \return Pointer to material
- */
Material *BKE_gpencil_brush_material_get(Brush *brush)
{
Material *ma = NULL;
@@ -1838,11 +1623,6 @@ Material *BKE_gpencil_brush_material_get(Brush *brush)
return ma;
}
-/**
- * Set grease pencil brush material.
- * \param brush: Brush
- * \param ma: Material
- */
void BKE_gpencil_brush_material_set(Brush *brush, Material *ma)
{
BLI_assert(brush);
@@ -1858,13 +1638,6 @@ void BKE_gpencil_brush_material_set(Brush *brush, Material *ma)
}
}
-/**
- * Adds the pinned material to the object if necessary.
- * \param bmain: Main pointer
- * \param ob: Grease pencil object
- * \param brush: Brush
- * \return Pointer to material
- */
Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob, Brush *brush)
{
if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
@@ -1883,13 +1656,6 @@ Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob,
return BKE_object_material_get(ob, ob->actcol);
}
-/**
- * Assigns the material to object (if not already present) and returns its index (mat_nr).
- * \param bmain: Main pointer
- * \param ob: Grease pencil object
- * \param material: Material
- * \return Index of the material
- */
int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *material)
{
if (!material) {
@@ -1904,14 +1670,6 @@ int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *materi
return index;
}
-/**
- * Creates a new grease-pencil material and assigns it to object.
- * \param bmain: Main pointer
- * \param ob: Grease pencil object
- * \param name: Material name
- * \param r_index: value is set to zero based index of the new material if \a r_index is not NULL.
- * \return Material pointer.
- */
Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
{
Material *ma = BKE_gpencil_material_add(bmain, name);
@@ -1926,12 +1684,6 @@ Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *n
return ma;
}
-/**
- * Returns the material for a brush with respect to its pinned state.
- * \param ob: Grease pencil object
- * \param brush: Brush
- * \return Material pointer
- */
Material *BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush)
{
if ((brush) && (brush->gpencil_settings) &&
@@ -1943,12 +1695,6 @@ Material *BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush)
return BKE_object_material_get(ob, ob->actcol);
}
-/**
- * Returns the material index for a brush with respect to its pinned state.
- * \param ob: Grease pencil object
- * \param brush: Brush
- * \return Material index.
- */
int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
{
if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
@@ -1958,12 +1704,6 @@ int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
return ob->actcol - 1;
}
-/**
- * Guaranteed to return a material assigned to object. Returns never NULL.
- * \param bmain: Main pointer
- * \param ob: Grease pencil object
- * \return Material pointer.
- */
Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main *bmain,
Object *ob,
ToolSettings *ts)
@@ -1976,13 +1716,6 @@ Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main
return BKE_gpencil_object_material_ensure_from_active_input_brush(bmain, ob, NULL);
}
-/**
- * Guaranteed to return a material assigned to object. Returns never NULL.
- * \param bmain: Main pointer
- * \param ob: Grease pencil object.
- * \param brush: Brush
- * \return Material pointer
- */
Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain,
Object *ob,
Brush *brush)
@@ -2000,12 +1733,6 @@ Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain
return BKE_gpencil_object_material_ensure_from_active_input_material(ob);
}
-/**
- * Guaranteed to return a material assigned to object. Returns never NULL.
- * Only use this for materials unrelated to user input.
- * \param ob: Grease pencil object
- * \return Material pointer
- */
Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob)
{
Material *ma = BKE_object_material_get(ob, ob->actcol);
@@ -2016,11 +1743,6 @@ Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *
return BKE_material_default_gpencil();
}
-/**
- * Get active color, and add all default settings if we don't find anything.
- * \param ob: Grease pencil object
- * \return Material pointer
- */
Material *BKE_gpencil_object_material_ensure_active(Object *ob)
{
Material *ma = NULL;
@@ -2039,11 +1761,6 @@ Material *BKE_gpencil_object_material_ensure_active(Object *ob)
}
/* ************************************************** */
-/**
- * Check if stroke has any point selected
- * \param gps: Grease pencil stroke
- * \return True if selected
- */
bool BKE_gpencil_stroke_select_check(const bGPDstroke *gps)
{
const bGPDspoint *pt;
@@ -2059,11 +1776,6 @@ bool BKE_gpencil_stroke_select_check(const bGPDstroke *gps)
/* ************************************************** */
/* GP Object - Vertex Groups */
-/**
- * Remove a vertex group.
- * \param ob: Grease pencil object
- * \param defgroup: deform group
- */
void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
{
bGPdata *gpd = ob->data;
@@ -2103,10 +1815,6 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
-/**
- * Ensure stroke has vertex group.
- * \param gps: Grease pencil stroke
- */
void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
{
if (gps->dvert == NULL) {
@@ -2116,14 +1824,6 @@ void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
/* ************************************************** */
-/**
- * Get range of selected frames in layer.
- * Always the active frame is considered as selected, so if no more selected the range
- * will be equal to the current active frame.
- * \param gpl: Layer.
- * \param r_initframe: Number of first selected frame.
- * \param r_endframe: Number of last selected frame.
- */
void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
{
*r_initframe = gpl->actframe->framenum;
@@ -2141,14 +1841,6 @@ void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_e
}
}
-/**
- * Get Falloff factor base on frame range
- * \param gpf: Frame.
- * \param actnum: Number of active frame in layer.
- * \param f_init: Number of first selected frame.
- * \param f_end: Number of last selected frame.
- * \param cur_falloff: Curve with falloff factors.
- */
float BKE_gpencil_multiframe_falloff_calc(
bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
{
@@ -2180,12 +1872,6 @@ float BKE_gpencil_multiframe_falloff_calc(
return value;
}
-/**
- * Reassign strokes using a material.
- * \param gpd: Grease pencil data-block
- * \param totcol: Total materials
- * \param index: Index of the material
- */
void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
{
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
@@ -2201,12 +1887,6 @@ void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
}
}
-/**
- * Remove strokes using a material.
- * \param gpd: Grease pencil data-block
- * \param index: Index of the material
- * \return True if removed
- */
bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
{
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
@@ -2222,12 +1902,6 @@ bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
return false;
}
-/**
- * Remap material
- * \param gpd: Grease pencil data-block
- * \param remap: Remap index
- * \param remap_len: Remap length
- */
void BKE_gpencil_material_remap(struct bGPdata *gpd,
const unsigned int *remap,
unsigned int remap_len)
@@ -2253,15 +1927,6 @@ void BKE_gpencil_material_remap(struct bGPdata *gpd,
#undef MAT_NR_REMAP
}
-/**
- * Load a table with material conversion index for merged materials.
- * \param ob: Grease pencil object.
- * \param hue_threshold: Threshold for Hue.
- * \param sat_threshold: Threshold for Saturation.
- * \param val_threshold: Threshold for Value.
- * \param r_mat_table: return material table.
- * \return True if done.
- */
bool BKE_gpencil_merge_materials_table_get(Object *ob,
const float hue_threshold,
const float sat_threshold,
@@ -2381,15 +2046,6 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
return changed;
}
-/**
- * Merge similar materials
- * \param ob: Grease pencil object
- * \param hue_threshold: Threshold for Hue
- * \param sat_threshold: Threshold for Saturation
- * \param val_threshold: Threshold for Value
- * \param r_removed: Number of materials removed
- * \return True if done
- */
bool BKE_gpencil_merge_materials(Object *ob,
const float hue_threshold,
const float sat_threshold,
@@ -2448,10 +2104,6 @@ bool BKE_gpencil_merge_materials(Object *ob,
return changed;
}
-/**
- * Calc grease pencil statistics functions.
- * \param gpd: Grease pencil data-block
- */
void BKE_gpencil_stats_update(bGPdata *gpd)
{
gpd->totlayer = 0;
@@ -2471,12 +2123,6 @@ void BKE_gpencil_stats_update(bGPdata *gpd)
}
}
-/**
- * Get material index (0-based like mat_nr not actcol).
- * \param ob: Grease pencil object
- * \param ma: Material
- * \return Index of the material
- */
int BKE_gpencil_object_material_index_get(Object *ob, Material *ma)
{
short *totcol = BKE_object_material_len_p(ob);
@@ -2519,11 +2165,6 @@ Material *BKE_gpencil_object_material_ensure_by_name(Main *bmain,
return BKE_gpencil_object_material_new(bmain, ob, name, r_index);
}
-/**
- * Create a default palette.
- * \param bmain: Main pointer
- * \param scene: Scene
- */
void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
{
const char *hexcol[] = {
@@ -2573,15 +2214,6 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
BKE_paint_palette_set(&ts->gp_vertexpaint->paint, palette);
}
-/**
- * Create grease pencil strokes from image
- * \param sima: Image
- * \param gpd: Grease pencil data-block
- * \param gpf: Grease pencil frame
- * \param size: Size
- * \param mask: Mask
- * \return True if done
- */
bool BKE_gpencil_from_image(
SpaceImage *sima, bGPdata *gpd, bGPDframe *gpf, const float size, const bool mask)
{
@@ -2713,6 +2345,8 @@ void BKE_gpencil_visible_stroke_iter(bGPdata *gpd,
}
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Advanced Iterator
*
@@ -2917,11 +2551,6 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer,
}
}
-/**
- * Update original pointers in evaluated frame.
- * \param gpf_orig: Original grease-pencil frame.
- * \param gpf_eval: Evaluated grease pencil frame.
- */
void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
const struct bGPDframe *gpf_eval)
{
@@ -2950,11 +2579,6 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig
}
}
-/**
- * Update pointers of eval data to original data to keep references.
- * \param ob_orig: Original grease pencil object
- * \param ob_eval: Evaluated grease pencil object
- */
void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
{
bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
@@ -2985,13 +2609,6 @@ void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_ev
}
}
-/**
- * Get parent matrix, including layer parenting.
- * \param depsgraph: Depsgraph
- * \param obact: Grease pencil object
- * \param gpl: Grease pencil layer
- * \param diff_mat: Result parent matrix
- */
void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
Object *obact,
bGPDlayer *gpl,
@@ -3040,11 +2657,6 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
unit_m4(diff_mat); /* not defined type */
}
-/**
- * Update parent matrix and local transforms.
- * \param depsgraph: Depsgraph
- * \param ob: Grease pencil object
- */
void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
{
if (ob->type != OB_GPENCIL) {
@@ -3104,12 +2716,6 @@ void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
}
}
-/**
- * Find material by name prefix.
- * \param ob: Object pointer
- * \param name_prefix: Prefix name of the material
- * \return Index
- */
int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_prefix)
{
const int name_prefix_len = strlen(name_prefix);
@@ -3124,7 +2730,6 @@ int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_
return -1;
}
-/* Create a hash with the list of selected frame number. */
void BKE_gpencil_frame_selected_hash(bGPdata *gpd, struct GHash *r_list)
{
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index 98e481e6ea8..d633678b873 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -477,17 +477,6 @@ static void gpencil_editstroke_deselect_all(bGPDcurve *gpc)
gpc->flag &= ~GP_CURVE_SELECT;
}
-/**
- * Convert a curve object to grease pencil stroke.
- *
- * \param bmain: Main thread pointer
- * \param scene: Original scene.
- * \param ob_gp: Grease pencil object to add strokes.
- * \param ob_cu: Curve to convert.
- * \param use_collections: Create layers using collection names.
- * \param scale_thickness: Scale thickness factor.
- * \param sample: Sample distance, zero to disable.
- */
void BKE_gpencil_convert_curve(Main *bmain,
Scene *scene,
Object *ob_gp,
@@ -639,9 +628,6 @@ static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps,
return NULL;
}
-/**
- * Creates a bGPDcurve by doing a cubic curve fitting on the grease pencil stroke points.
- */
bGPDcurve *BKE_gpencil_stroke_editcurve_generate(bGPDstroke *gps,
const float error_threshold,
const float corner_angle,
@@ -753,9 +739,6 @@ bGPDcurve *BKE_gpencil_stroke_editcurve_generate(bGPDstroke *gps,
return editcurve;
}
-/**
- * Updates the editcurve for a stroke. Frees the old curve if one exists and generates a new one.
- */
void BKE_gpencil_stroke_editcurve_update(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
{
if (gps == NULL || gps->totpoints < 0) {
@@ -778,9 +761,6 @@ void BKE_gpencil_stroke_editcurve_update(bGPdata *gpd, bGPDlayer *gpl, bGPDstrok
gps->editcurve = editcurve;
}
-/**
- * Sync the selection from stroke to editcurve
- */
void BKE_gpencil_editcurve_stroke_sync_selection(bGPdata *UNUSED(gpd),
bGPDstroke *gps,
bGPDcurve *gpc)
@@ -807,9 +787,6 @@ void BKE_gpencil_editcurve_stroke_sync_selection(bGPdata *UNUSED(gpd),
}
}
-/**
- * Sync the selection from editcurve to stroke
- */
void BKE_gpencil_stroke_editcurve_sync_selection(bGPdata *gpd, bGPDstroke *gps, bGPDcurve *gpc)
{
if (gpc->flag & GP_CURVE_SELECT) {
@@ -1055,9 +1032,6 @@ static float *gpencil_stroke_points_from_editcurve_fixed_resolu(bGPDcurve_point
return (float(*))r_points;
}
-/**
- * Recalculate stroke points with the editcurve of the stroke.
- */
void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps,
const uint resolution,
const bool adaptive)
@@ -1142,9 +1116,6 @@ void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps,
MEM_freeN(points);
}
-/**
- * Recalculate the handles of the edit curve of a grease pencil stroke
- */
void BKE_gpencil_editcurve_recalculate_handles(bGPDstroke *gps)
{
if (gps == NULL || gps->editcurve == NULL) {
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index fffc13c49a8..b5190f598c6 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -67,15 +67,10 @@
using blender::float3;
using blender::Span;
-/* GP Object - Boundbox Support */
-/**
- *Get min/max coordinate bounds for single stroke.
- * \param gps: Grease pencil stroke
- * \param use_select: Include only selected points
- * \param r_min: Result minimum coordinates
- * \param r_max: Result maximum coordinates
- * \return True if it was possible to calculate
- */
+/* -------------------------------------------------------------------- */
+/** \name Grease Pencil Object: Bound-box Support
+ * \{ */
+
bool BKE_gpencil_stroke_minmax(const bGPDstroke *gps,
const bool use_select,
float r_min[3],
@@ -104,13 +99,6 @@ bool BKE_gpencil_stroke_minmax(const bGPDstroke *gps,
return changed;
}
-/**
- * Get min/max bounds of all strokes in grease pencil data-block.
- * \param gpd: Grease pencil datablock
- * \param r_min: Result minimum coordinates
- * \param r_max: Result maximum coordinates
- * \return True if it was possible to calculate
- */
bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
{
bool changed = false;
@@ -134,11 +122,6 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
return changed;
}
-/**
- * Compute center of bounding box.
- * \param gpd: Grease pencil data-block
- * \param r_centroid: Location of the center
- */
void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
{
float3 min;
@@ -149,10 +132,6 @@ void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
mul_v3_v3fl(r_centroid, tot, 0.5f);
}
-/**
- * Compute stroke bounding box.
- * \param gps: Grease pencil Stroke
- */
void BKE_gpencil_stroke_boundingbox_calc(bGPDstroke *gps)
{
INIT_MINMAX(gps->boundbox_min, gps->boundbox_max);
@@ -184,11 +163,6 @@ static void boundbox_gpencil(Object *ob)
bb->flag &= ~BOUNDBOX_DIRTY;
}
-/**
- * Get grease pencil object bounding box.
- * \param ob: Grease pencil object
- * \return Bounding box
- */
BoundBox *BKE_gpencil_boundbox_get(Object *ob)
{
if (ELEM(nullptr, ob, ob->data)) {
@@ -218,7 +192,11 @@ BoundBox *BKE_gpencil_boundbox_get(Object *ob)
return ob->runtime.bb;
}
-/* ************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Sample
+ * \{ */
static int stroke_march_next_point(const bGPDstroke *gps,
const int index_next_pt,
@@ -431,12 +409,6 @@ static void stroke_interpolate_deform_weights(
}
}
-/**
- * Resample a stroke
- * \param gpd: Grease pencil data-block
- * \param gps: Stroke to sample
- * \param dist: Distance of one segment
- */
bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select)
{
bGPDspoint *pt = gps->points;
@@ -594,15 +566,6 @@ static bool BKE_gpencil_stroke_extra_points(bGPDstroke *gps,
return true;
}
-/**
- * Backbone stretch similar to Freestyle.
- * \param gps: Stroke to sample.
- * \param dist: Length of the added section.
- * \param overshoot_fac: Relative length of the curve which is used to determine the extension.
- * \param mode: Affect to Start, End or Both extremes (0->Both, 1->Start, 2->End)
- * \param follow_curvature: True for approximating curvature of given overshoot.
- * \param extra_point_count: When follow_curvature is true, use this amount of extra points
- */
bool BKE_gpencil_stroke_stretch(bGPDstroke *gps,
const float dist,
const float overshoot_fac,
@@ -779,12 +742,12 @@ bool BKE_gpencil_stroke_stretch(bGPDstroke *gps,
return true;
}
-/**
- * Trim stroke to needed segments
- * \param gps: Target stroke
- * \param index_from: the index of the first point to be used in the trimmed result
- * \param index_to: the index of the last point to be used in the trimmed result
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Trim
+ * \{ */
+
bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const int index_to)
{
bGPDspoint *pt = gps->points, *new_pt;
@@ -837,15 +800,12 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
return true;
}
-/**
- * Split stroke.
- * \param gpd: Grease pencil data-block
- * \param gpf: Grease pencil frame
- * \param gps: Grease pencil original stroke
- * \param before_index: Position of the point to split
- * \param remaining_gps: Secondary stroke after split.
- * \return True if the split was done
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Split
+ * \{ */
+
bool BKE_gpencil_stroke_split(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps,
@@ -898,12 +858,12 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
return true;
}
-/**
- * Shrink the stroke by length.
- * \param gps: Stroke to shrink
- * \param dist: delta length
- * \param mode: 1->Start, 2->End
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Shrink
+ * \{ */
+
bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mode)
{
#define START 1
@@ -976,13 +936,14 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo
return true;
}
-/**
- * Apply smooth position to stroke point.
- * \param gps: Stroke to smooth
- * \param i: Point index
- * \param inf: Amount of smoothing to apply
- */
-bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf)
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Smooth Positions
+ * \{ */
+
+bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf, const bool smooth_caps)
{
bGPDspoint *pt = &gps->points[i];
float sco[3] = {0.0f};
@@ -996,7 +957,7 @@ bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf)
/* Only affect endpoints by a fraction of the normal strength,
* to prevent the stroke from shrinking too much
*/
- if (!is_cyclic && ELEM(i, 0, gps->totpoints - 1)) {
+ if ((!smooth_caps) && (!is_cyclic && ELEM(i, 0, gps->totpoints - 1))) {
inf *= 0.1f;
}
@@ -1054,12 +1015,12 @@ bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf)
return true;
}
-/**
- * Apply smooth strength to stroke point.
- * \param gps: Stroke to smooth
- * \param point_index: Point index
- * \param influence: Amount of smoothing to apply
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Smooth Strength
+ * \{ */
+
bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -1132,12 +1093,12 @@ bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float
return true;
}
-/**
- * Apply smooth for thickness to stroke point (use pressure).
- * \param gps: Stroke to smooth
- * \param point_index: Point index
- * \param influence: Amount of smoothing to apply
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Smooth Thickness
+ * \{ */
+
bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -1209,12 +1170,12 @@ bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float
return true;
}
-/**
- * Apply smooth for UV rotation to stroke point (use pressure).
- * \param gps: Stroke to smooth
- * \param point_index: Point index
- * \param influence: Amount of smoothing to apply
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Smooth UV
+ * \{ */
+
bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -1266,14 +1227,6 @@ bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influe
return true;
}
-/**
- * Get points of stroke always flat to view not affected
- * by camera view or view position.
- * \param points: Array of grease pencil points (3D)
- * \param totpoints: Total of points
- * \param points2d: Result array of 2D points
- * \param r_direction: Return Concave (-1), Convex (1), or Auto-detect (0)
- */
void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points,
int totpoints,
float (*points2d)[2],
@@ -1348,17 +1301,6 @@ void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points,
*r_direction = (cross >= 0.0f) ? 1 : -1;
}
-/**
- * Get points of stroke always flat to view not affected by camera view or view position
- * using another stroke as reference.
- * \param ref_points: Array of reference points (3D)
- * \param ref_totpoints: Total reference points
- * \param points: Array of points to flat (3D)
- * \param totpoints: Total points
- * \param points2d: Result array of 2D points
- * \param scale: Scale factor
- * \param r_direction: Return Concave (-1), Convex (1), or Auto-detect (0)
- */
void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points,
int ref_totpoints,
const bGPDspoint *points,
@@ -1482,10 +1424,12 @@ static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2],
}
}
-/**
- * Triangulate stroke to generate data for filling areas.
- * \param gps: Grease pencil stroke
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Fill Triangulate
+ * \{ */
+
void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
{
BLI_assert(gps->totpoints >= 3);
@@ -1545,10 +1489,6 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
MEM_SAFE_FREE(uv);
}
-/**
- * Update Stroke UV data.
- * \param gps: Grease pencil stroke
- */
void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
{
if (gps == nullptr || gps->totpoints == 0) {
@@ -1564,11 +1504,6 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
}
}
-/**
- * Recalc all internal geometry data for the stroke
- * \param gpd: Grease pencil data-block
- * \param gps: Grease pencil stroke
- */
void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps)
{
if (gps == nullptr) {
@@ -1606,12 +1541,6 @@ void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps)
BKE_gpencil_stroke_boundingbox_calc(gps);
}
-/**
- * Calculate grease pencil stroke length.
- * \param gps: Grease pencil stroke
- * \param use_3d: Set to true to use 3D points
- * \return Length of the stroke
- */
float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
{
if (!gps->points || gps->totpoints < 2) {
@@ -1632,7 +1561,6 @@ float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
return total_length;
}
-/** Calculate grease pencil stroke length between points. */
float BKE_gpencil_stroke_segment_length(const struct bGPDstroke *gps,
const int start_index,
const int end_index,
@@ -1660,10 +1588,6 @@ float BKE_gpencil_stroke_segment_length(const struct bGPDstroke *gps,
return total_length;
}
-/**
- * Trim stroke to the first intersection or loop.
- * \param gps: Stroke data
- */
bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
{
if (gps->totpoints < 4) {
@@ -1756,10 +1680,6 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
return intersect;
}
-/**
- * Close grease pencil stroke.
- * \param gps: Stroke to close
- */
bool BKE_gpencil_stroke_close(bGPDstroke *gps)
{
bGPDspoint *pt1 = nullptr;
@@ -1845,13 +1765,12 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
return true;
}
-/**
- * Dissolve points in stroke.
- * \param gpd: Grease pencil data-block
- * \param gpf: Grease pencil frame
- * \param gps: Grease pencil stroke
- * \param tag: Type of tag for point
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve Points
+ * \{ */
+
void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, const short tag)
{
bGPDspoint *pt;
@@ -1934,11 +1853,12 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps,
}
}
-/**
- * Calculate stroke normals.
- * \param gps: Grease pencil stroke
- * \param r_normal: Return Normal vector normalized
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Normal Calculation
+ * \{ */
+
void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
{
if (gps->totpoints < 3) {
@@ -1969,18 +1889,12 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
normalize_v3(r_normal);
}
-/* Stroke Simplify ------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Simplify
+ * \{ */
-/**
- * Reduce a series of points to a simplified version, but
- * maintains the general shape of the series
- *
- * Ramer - Douglas - Peucker algorithm
- * by http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
- * \param gpd: Grease pencil data-block
- * \param gps: Grease pencil stroke
- * \param epsilon: Epsilon value to define precision of the algorithm
- */
void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float epsilon)
{
bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points);
@@ -2085,11 +1999,6 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
MEM_SAFE_FREE(marked);
}
-/**
- * Simplify alternate vertex of stroke except extremes.
- * \param gpd: Grease pencil data-block
- * \param gps: Grease pencil stroke
- */
void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
{
if (gps->totpoints < 5) {
@@ -2150,13 +2059,6 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
MEM_SAFE_FREE(old_dvert);
}
-/**
- * Subdivide a stroke
- * \param gpd: Grease pencil data-block
- * \param gps: Stroke
- * \param level: Level of subdivision
- * \param type: Type of subdivision
- */
void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int type)
{
bGPDspoint *temp_points;
@@ -2269,19 +2171,12 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
-/* Merge by distance ------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Merge by Distance
+ * \{ */
-/**
- * Reduce a series of points when the distance is below a threshold.
- * Special case for first and last points (both are kept) for other points,
- * the merge point always is at first point.
- *
- * \param gpd: Grease pencil data-block.
- * \param gpf: Grease Pencil frame.
- * \param gps: Grease Pencil stroke.
- * \param threshold: Distance between points.
- * \param use_unselected: Set to true to analyze all stroke and not only selected points.
- */
void BKE_gpencil_stroke_merge_distance(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps,
@@ -2639,22 +2534,6 @@ static void make_element_name(const char *obname, const char *name, const int ma
BLI_strncpy_utf8(r_name, str, maxlen);
}
-/**
- * Convert a mesh object to grease pencil stroke.
- *
- * \param bmain: Main thread pointer.
- * \param depsgraph: Original depsgraph.
- * \param scene: Original scene.
- * \param ob_gp: Grease pencil object to add strokes.
- * \param ob_mesh: Mesh to convert.
- * \param angle: Limit angle to consider a edge-loop ends.
- * \param thickness: Thickness of the strokes.
- * \param offset: Offset along the normals.
- * \param matrix: Transformation matrix.
- * \param frame_offset: Destination frame number offset.
- * \param use_seams: Only export seam edges.
- * \param use_faces: Export faces as filled strokes.
- */
bool BKE_gpencil_convert_mesh(Main *bmain,
Depsgraph *depsgraph,
Scene *scene,
@@ -2807,11 +2686,6 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
return true;
}
-/**
- * Apply grease pencil Transforms.
- * \param gpd: Grease pencil data-block
- * \param mat: Transformation matrix
- */
void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4])
{
if (gpd == nullptr) {
@@ -2845,7 +2719,6 @@ void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4])
}
}
-/* Used for "move only origins" in object_data_transform.c */
int BKE_gpencil_stroke_point_count(const bGPdata *gpd)
{
int total_points = 0;
@@ -2872,7 +2745,6 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd)
return total_points;
}
-/* Used for "move only origins" in object_data_transform.c */
void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_data)
{
if (gpd == nullptr) {
@@ -2903,7 +2775,6 @@ void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_da
}
}
-/* Used for "move only origins" in object_data_transform.c */
void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates *elem_data)
{
if (gpd == nullptr) {
@@ -2937,7 +2808,6 @@ void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates
}
}
-/* Used for "move only origins" in object_data_transform.c */
void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd,
const GPencilPointCoordinates *elem_data,
const float mat[4][4])
@@ -2974,10 +2844,6 @@ void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd,
}
}
-/**
- * Set a random color to stroke using vertex color.
- * \param gps: Stroke
- */
void BKE_gpencil_stroke_set_random_color(bGPDstroke *gps)
{
BLI_assert(gps->totpoints > 0);
@@ -2993,7 +2859,6 @@ void BKE_gpencil_stroke_set_random_color(bGPDstroke *gps)
}
}
-/* Flip stroke. */
void BKE_gpencil_stroke_flip(bGPDstroke *gps)
{
/* Reverse points. */
@@ -3103,20 +2968,6 @@ static void gpencil_stroke_join_islands(bGPdata *gpd,
BKE_gpencil_free_stroke(gps_last);
}
-/* Split the given stroke into several new strokes, partitioning
- * it based on whether the stroke points have a particular flag
- * is set (e.g. "GP_SPOINT_SELECT" in most cases, but not always)
- *
- * The algorithm used here is as follows:
- * 1) We firstly identify the number of "islands" of non-tagged points
- * which will all end up being in new strokes.
- * - In the most extreme case (i.e. every other vert is a 1-vert island),
- * we have at most n / 2 islands
- * - Once we start having larger islands than that, the number required
- * becomes much less
- * 2) Each island gets converted to a new stroke
- * If the number of points is <= limit, the stroke is deleted
- */
bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps,
@@ -3126,6 +2977,16 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
const bool flat_cap,
const int limit)
{
+ /* The algorithm used here is as follows:
+ * 1) We firstly identify the number of "islands" of non-tagged points
+ * which will all end up being in new strokes.
+ * - In the most extreme case (i.e. every other vert is a 1-vert island),
+ * we have at most `n / 2` islands
+ * - Once we start having larger islands than that, the number required
+ * becomes much less
+ * 2) Each island gets converted to a new stroke
+ * If the number of points is <= limit, the stroke is deleted. */
+
tGPDeleteIsland *islands = (tGPDeleteIsland *)MEM_callocN(
sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
bool in_island = false;
@@ -3430,7 +3291,6 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps,
}
}
-/* Join two strokes using the shortest distance (reorder stroke if necessary ) */
void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
bGPDstroke *gps_b,
const bool leave_gaps,
@@ -3548,7 +3408,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
for (i = start; i < end; i++) {
pt = &gps_a->points[i];
pt->pressure += (avg_pressure - pt->pressure) * ratio;
- BKE_gpencil_stroke_smooth_point(gps_a, i, ratio * 0.6f);
+ BKE_gpencil_stroke_smooth_point(gps_a, i, ratio * 0.6f, false);
ratio += step;
/* In the center, reverse the ratio. */
@@ -3560,7 +3420,6 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
}
}
-/* Copy the stroke of the frame to all frames selected (except current). */
void BKE_gpencil_stroke_copy_to_keyframes(
bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const bool tail)
{
@@ -3599,7 +3458,11 @@ void BKE_gpencil_stroke_copy_to_keyframes(
BLI_ghash_free(frame_list, nullptr, nullptr);
}
-/* Stroke Uniform Subdivide ------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Uniform Subdivide
+ * \{ */
struct tSamplePoint {
struct tSamplePoint *next, *prev;
@@ -3649,15 +3512,6 @@ static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamp
return new_edge;
}
-/**
- * Subdivide the grease pencil stroke so the number of points is target_number.
- * Does not change the shape of the stroke. The new points will be distributed as
- * uniformly as possible by repeatedly subdividing the current longest edge.
- *
- * \param gps: The stroke to be up-sampled.
- * \param target_number: The number of points the up-sampled stroke should have.
- * \param select: Select/Deselect the stroke.
- */
void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
bGPDstroke *gps,
const uint32_t target_number,
@@ -3793,12 +3647,6 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
-/**
- * Stroke to view space
- * Transforms a stroke to view space. This allows for manipulations in 2D but also easy conversion
- * back to 3D.
- * NOTE: also takes care of parent space transform
- */
void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
bGPDstroke *gps,
const float diff_mat[4][4])
@@ -3812,12 +3660,6 @@ void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
}
}
-/**
- * Stroke from view space
- * Transforms a stroke from view space back to world space. Inverse of
- * BKE_gpencil_stroke_to_view_space
- * NOTE: also takes care of parent space transform
- */
void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
bGPDstroke *gps,
const float diff_mat[4][4])
@@ -3832,8 +3674,11 @@ void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
}
}
-/* ----------------------------------------------------------------------------- */
-/* Stroke to perimeter */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke to Perimeter
+ * \{ */
struct tPerimeterPoint {
struct tPerimeterPoint *next, *prev;
@@ -4238,12 +4083,6 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
return perimeter_list;
}
-/**
- * Calculates the perimeter of a stroke projected from the view and
- * returns it as a new stroke.
- * \param subdivisions: Number of subdivisions for the start and end caps
- * \return: bGPDstroke pointer to stroke perimeter
- */
bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
bGPdata *gpd,
const bGPDlayer *gpl,
@@ -4310,7 +4149,6 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
return perimeter_stroke;
}
-/** Get average pressure. */
float BKE_gpencil_stroke_average_pressure_get(bGPDstroke *gps)
{
@@ -4327,7 +4165,6 @@ float BKE_gpencil_stroke_average_pressure_get(bGPDstroke *gps)
return tot / (float)gps->totpoints;
}
-/** Check if the thickness of the stroke is constant. */
bool BKE_gpencil_stroke_is_pressure_constant(bGPDstroke *gps)
{
if (gps->totpoints == 1) {
@@ -4344,4 +4181,5 @@ bool BKE_gpencil_stroke_is_pressure_constant(bGPDstroke *gps)
return true;
}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index a6164340477..62604286b43 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -36,6 +36,7 @@
#include "DNA_armature_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -50,7 +51,9 @@
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_material.h"
+#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_shrinkwrap.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -77,43 +80,83 @@ static GpencilVirtualModifierData virtualModifierCommonData;
*/
/**
- * Init grease pencil lattice deform data.
+ * Init grease pencil cache deform data.
* \param ob: Grease pencil object
*/
-void BKE_gpencil_lattice_init(Object *ob)
+void BKE_gpencil_cache_data_init(Depsgraph *depsgraph, Object *ob)
{
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
- if (md->type == eGpencilModifierType_Lattice) {
- LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
- Object *latob = NULL;
+ switch (md->type) {
+ case eGpencilModifierType_Lattice: {
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ Object *latob = NULL;
+
+ latob = mmd->object;
+ if ((!latob) || (latob->type != OB_LATTICE)) {
+ return;
+ }
+ if (mmd->cache_data) {
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
+ }
- latob = mmd->object;
- if ((!latob) || (latob->type != OB_LATTICE)) {
- return;
+ /* init deform data */
+ mmd->cache_data = BKE_lattice_deform_data_create(latob, ob);
+ break;
}
- if (mmd->cache_data) {
- BKE_lattice_deform_data_destroy(mmd->cache_data);
+ case eGpencilModifierType_Shrinkwrap: {
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+ ob = mmd->target;
+ if (!ob) {
+ return;
+ }
+ if (mmd->cache_data) {
+ BKE_shrinkwrap_free_tree(mmd->cache_data);
+ MEM_SAFE_FREE(mmd->cache_data);
+ }
+ Object *ob_target = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false);
+ mmd->cache_data = MEM_callocN(sizeof(ShrinkwrapTreeData), __func__);
+ if (BKE_shrinkwrap_init_tree(
+ mmd->cache_data, target, mmd->shrink_type, mmd->shrink_mode, false)) {
+ }
+ else {
+ MEM_SAFE_FREE(mmd->cache_data);
+ }
+ break;
}
- /* init deform data */
- mmd->cache_data = BKE_lattice_deform_data_create(latob, ob);
+ default:
+ break;
}
}
}
/**
- * Clear grease pencil lattice deform data.
+ * Clear grease pencil cache deform data.
* \param ob: Grease pencil object
*/
-void BKE_gpencil_lattice_clear(Object *ob)
+void BKE_gpencil_cache_data_clear(Object *ob)
{
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
- if (md->type == eGpencilModifierType_Lattice) {
- LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
- if ((mmd) && (mmd->cache_data)) {
- BKE_lattice_deform_data_destroy(mmd->cache_data);
- mmd->cache_data = NULL;
+ switch (md->type) {
+ case eGpencilModifierType_Lattice: {
+ LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
+ if ((mmd) && (mmd->cache_data)) {
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
+ mmd->cache_data = NULL;
+ }
+ break;
}
+ case eGpencilModifierType_Shrinkwrap: {
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+ if ((mmd) && (mmd->cache_data)) {
+ BKE_shrinkwrap_free_tree(mmd->cache_data);
+ MEM_SAFE_FREE(mmd->cache_data);
+ }
+ break;
+ }
+ default:
+ break;
}
}
}
@@ -121,8 +164,6 @@ void BKE_gpencil_lattice_clear(Object *ob)
/* *************************************************** */
/* Modifier Methods - Evaluation Loops, etc. */
-/* This is to include things that are not modifiers in the evaluation of the modifier stack, for
- * example parenting to an armature or lattice without having a real modifier. */
GpencilModifierData *BKE_gpencil_modifiers_get_virtual_modifierlist(
const Object *ob, GpencilVirtualModifierData *UNUSED(virtualModifierData))
{
@@ -150,11 +191,6 @@ GpencilModifierData *BKE_gpencil_modifiers_get_virtual_modifierlist(
return md;
}
-/**
- * Check if object has grease pencil Geometry modifiers.
- * \param ob: Grease pencil object
- * \return True if exist
- */
bool BKE_gpencil_has_geometry_modifiers(Object *ob)
{
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
@@ -167,11 +203,6 @@ bool BKE_gpencil_has_geometry_modifiers(Object *ob)
return false;
}
-/**
- * Check if object has grease pencil Time modifiers.
- * \param ob: Grease pencil object
- * \return True if exist
- */
bool BKE_gpencil_has_time_modifiers(Object *ob)
{
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
@@ -184,11 +215,6 @@ bool BKE_gpencil_has_time_modifiers(Object *ob)
return false;
}
-/**
- * Check if object has grease pencil transform stroke modifiers.
- * \param ob: Grease pencil object
- * \return True if exist
- */
bool BKE_gpencil_has_transform_modifiers(Object *ob)
{
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
@@ -258,7 +284,6 @@ bool BKE_gpencil_is_first_lineart_in_stack(const Object *ob, const GpencilModifi
return false;
}
-/* Get Time modifier frame number. */
int BKE_gpencil_time_modifier_cfra(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -292,11 +317,6 @@ int BKE_gpencil_time_modifier_cfra(Depsgraph *depsgraph,
return nfra;
}
-/**
- * Set current grease pencil active frame.
- * \param depsgraph: Current depsgraph
- * \param gpd: Grease pencil data-block.
- */
void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd)
{
DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd);
@@ -320,9 +340,6 @@ void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd)
}
}
-/**
- * Initialize grease pencil modifier.
- */
void BKE_gpencil_modifier_init(void)
{
/* Initialize modifier types */
@@ -346,11 +363,6 @@ void BKE_gpencil_modifier_init(void)
#endif
}
-/**
- * Create new grease pencil modifier.
- * \param type: Type of modifier
- * \return New modifier pointer
- */
GpencilModifierData *BKE_gpencil_modifier_new(int type)
{
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type);
@@ -386,11 +398,6 @@ static void modifier_free_data_id_us_cb(void *UNUSED(userData),
}
}
-/**
- * Free grease pencil modifier data
- * \param md: Modifier data
- * \param flag: Flags
- */
void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag)
{
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
@@ -411,16 +418,11 @@ void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag)
MEM_freeN(md);
}
-/**
- * Free grease pencil modifier data
- * \param md: Modifier data
- */
void BKE_gpencil_modifier_free(GpencilModifierData *md)
{
BKE_gpencil_modifier_free_ex(md, 0);
}
-/* check unique name */
bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *gmd)
{
if (modifiers && gmd) {
@@ -435,11 +437,6 @@ bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *
return false;
}
-/**
- * Check if grease pencil modifier depends on time.
- * \param md: Modifier data
- * \return True if depends on time
- */
bool BKE_gpencil_modifier_depends_ontime(GpencilModifierData *md)
{
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
@@ -447,11 +444,6 @@ bool BKE_gpencil_modifier_depends_ontime(GpencilModifierData *md)
return mti->dependsOnTime && mti->dependsOnTime(md);
}
-/**
- * Get grease pencil modifier information.
- * \param type: Type of modifier
- * \return Pointer to type
- */
const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type)
{
/* type unsigned, no need to check < 0 */
@@ -463,12 +455,6 @@ const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType
return NULL;
}
-/**
- * Get the idname of the modifier type's panel, which was defined in the #panelRegister callback.
- *
- * \param type: Type of modifier
- * \param r_idname: ID name
- */
void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname)
{
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type);
@@ -482,11 +468,6 @@ void BKE_gpencil_modifier_panel_expand(GpencilModifierData *md)
md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
}
-/**
- * Generic grease pencil modifier copy data.
- * \param md_src: Source modifier data
- * \param md_dst: Target modifier data
- */
void BKE_gpencil_modifier_copydata_generic(const GpencilModifierData *md_src,
GpencilModifierData *md_dst)
{
@@ -516,12 +497,6 @@ static void gpencil_modifier_copy_data_id_us_cb(void *UNUSED(userData),
}
}
-/**
- * Copy grease pencil modifier data.
- * \param md: Source modifier data
- * \param target: Target modifier data
- * \param flag: Flags
- */
void BKE_gpencil_modifier_copydata_ex(GpencilModifierData *md,
GpencilModifierData *target,
const int flag)
@@ -543,11 +518,6 @@ void BKE_gpencil_modifier_copydata_ex(GpencilModifierData *md,
}
}
-/**
- * Copy grease pencil modifier data.
- * \param md: Source modifier data
- * \param target: Target modifier data
- */
void BKE_gpencil_modifier_copydata(GpencilModifierData *md, GpencilModifierData *target)
{
BKE_gpencil_modifier_copydata_ex(md, target, 0);
@@ -566,19 +536,14 @@ GpencilModifierData *BKE_gpencil_modifiers_findby_type(Object *ob, GpencilModifi
return md;
}
-/**
- * Set grease pencil modifier error.
- * \param md: Modifier data
- * \param _format: Format
- */
-void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *_format, ...)
+void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *format, ...)
{
char buffer[512];
va_list ap;
- const char *format = TIP_(_format);
+ const char *format_tip = TIP_(format);
- va_start(ap, _format);
- vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format_tip, ap);
va_end(ap);
buffer[sizeof(buffer) - 1] = '\0';
@@ -591,12 +556,6 @@ void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *_format
CLOG_STR_ERROR(&LOG, md->error);
}
-/**
- * Check whether given modifier is not local (i.e. from linked data) when the object is a library
- * override.
- *
- * \param gmd: May be NULL, in which case we consider it as a non-local modifier case.
- */
bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const Object *ob,
const GpencilModifierData *gmd)
{
@@ -604,12 +563,6 @@ bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const Object *ob,
(gmd == NULL || (gmd->flag & eGpencilModifierFlag_OverrideLibrary_Local) == 0));
}
-/**
- * Link grease pencil modifier related IDs.
- * \param ob: Grease pencil object
- * \param walk: Walk option
- * \param userData: User data
- */
void BKE_gpencil_modifiers_foreach_ID_link(Object *ob, GreasePencilIDWalkFunc walk, void *userData)
{
GpencilModifierData *md = ob->greasepencil_modifiers.first;
@@ -623,12 +576,6 @@ void BKE_gpencil_modifiers_foreach_ID_link(Object *ob, GreasePencilIDWalkFunc wa
}
}
-/**
- * Link grease pencil modifier related Texts.
- * \param ob: Grease pencil object
- * \param walk: Walk option
- * \param userData: User data
- */
void BKE_gpencil_modifiers_foreach_tex_link(Object *ob,
GreasePencilTexWalkFunc walk,
void *userData)
@@ -644,12 +591,6 @@ void BKE_gpencil_modifiers_foreach_tex_link(Object *ob,
}
}
-/**
- * Find grease pencil modifier by name.
- * \param ob: Grease pencil object
- * \param name: Name to find
- * \return Pointer to modifier
- */
GpencilModifierData *BKE_gpencil_modifiers_findby_name(Object *ob, const char *name)
{
return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name));
@@ -677,14 +618,6 @@ static int gpencil_remap_time_get(Depsgraph *depsgraph, Scene *scene, Object *ob
return remap_cfra;
}
-/**
- * Get the current frame re-timed with time modifiers.
- * \param depsgraph: Current depsgraph.
- * \param scene: Current scene
- * \param ob: Grease pencil object
- * \param gpl: Grease pencil layer
- * \return New frame number
- */
bGPDframe *BKE_gpencil_frame_retime_get(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -753,12 +686,6 @@ static bGPdata *gpencil_copy_for_eval(bGPdata *gpd)
return result;
}
-/**
- * Prepare grease pencil eval data for modifiers
- * \param depsgraph: Current depsgraph
- * \param scene: Current scene
- * \param ob: Grease pencil object
- */
void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
bGPdata *gpd_eval = (bGPdata *)ob->data;
@@ -808,12 +735,6 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
BKE_gpencil_update_orig_pointers(ob_orig, ob);
}
-/**
- * Calculate gpencil modifiers.
- * \param depsgraph: Current depsgraph
- * \param scene: Current scene
- * \param ob: Grease pencil object
- */
void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
@@ -829,7 +750,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
}
/* Init general modifiers data. */
- BKE_gpencil_lattice_init(ob);
+ BKE_gpencil_cache_data_init(depsgraph, ob);
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
bool is_first_lineart = true;
@@ -872,8 +793,8 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
}
}
- /* Clear any lattice data. */
- BKE_gpencil_lattice_clear(ob);
+ /* Clear any cache data. */
+ BKE_gpencil_cache_data_clear(ob);
MOD_lineart_clear_cache(&gpd->runtime.lineart_cache);
}
@@ -1031,6 +952,10 @@ void BKE_gpencil_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
gpmd->segments[i].dmd = gpmd;
}
}
+ if (md->type == eGpencilModifierType_Shrinkwrap) {
+ ShrinkwrapGpencilModifierData *gpmd = (ShrinkwrapGpencilModifierData *)md;
+ gpmd->cache_data = NULL;
+ }
}
}
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 7433ee7ac29..f2a5146422e 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -80,7 +80,7 @@ static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, co
{
Hair *hair_dst = (Hair *)id_dst;
const Hair *hair_src = (const Hair *)id_src;
- hair_dst->mat = MEM_dupallocN(hair_dst->mat);
+ hair_dst->mat = MEM_dupallocN(hair_src->mat);
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, alloc_type, hair_dst->totpoint);
@@ -182,6 +182,7 @@ IDTypeInfo IDType_ID_HA = {
.name_plural = "hairs",
.translation_context = BLT_I18NCONTEXT_ID_HAIR,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = hair_init_data,
.copy_data = hair_copy_data,
@@ -189,6 +190,7 @@ IDTypeInfo IDType_ID_HA = {
.make_local = NULL,
.foreach_id = hair_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = hair_blend_write,
@@ -406,6 +408,7 @@ void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Obje
}
/* Draw Cache */
+
void (*BKE_hair_batch_cache_dirty_tag_cb)(Hair *hair, int mode) = NULL;
void (*BKE_hair_batch_cache_free_cb)(Hair *hair) = NULL;
diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc
index ffc39028400..059caaa27f9 100644
--- a/source/blender/blenkernel/intern/icons.cc
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -210,7 +210,7 @@ void BKE_icons_init(int first_dyn_id)
}
}
-void BKE_icons_free(void)
+void BKE_icons_free()
{
BLI_assert(BLI_thread_is_main());
@@ -227,7 +227,7 @@ void BKE_icons_free(void)
BLI_linklist_lockfree_free(&g_icon_delete_queue, MEM_freeN);
}
-void BKE_icons_deferred_free(void)
+void BKE_icons_deferred_free()
{
std::scoped_lock lock(gIconMutex);
@@ -251,7 +251,7 @@ static PreviewImage *previewimg_create_ex(size_t deferred_data_size)
}
for (int i = 0; i < NUM_ICON_SIZES; i++) {
- prv_img->flag[i] |= (PRV_CHANGED | PRV_UNFINISHED);
+ prv_img->flag[i] |= PRV_CHANGED;
prv_img->changed_timestamp[i] = 0;
}
return prv_img;
@@ -271,7 +271,7 @@ static PreviewImage *previewimg_deferred_create(const char *path, int source)
return prv;
}
-PreviewImage *BKE_previewimg_create(void)
+PreviewImage *BKE_previewimg_create()
{
return previewimg_create_ex(0);
}
@@ -308,7 +308,7 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size)
GPU_texture_free(prv->gputexture[size]);
}
prv->h[size] = prv->w[size] = 0;
- prv->flag[size] |= (PRV_CHANGED | PRV_UNFINISHED);
+ prv->flag[size] |= PRV_CHANGED;
prv->flag[size] &= ~PRV_USER_EDITED;
prv->changed_timestamp[size] = 0;
}
@@ -336,10 +336,6 @@ PreviewImage *BKE_previewimg_copy(const PreviewImage *prv)
return prv_img;
}
-/**
- * Duplicate preview image from \a id and clear icon_id,
- * to be used by datablock copy functions.
- */
void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
{
PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id);
@@ -360,31 +356,23 @@ void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
PreviewImage **BKE_previewimg_id_get_p(const ID *id)
{
switch (GS(id->name)) {
- case ID_OB: {
- Object *ob = (Object *)id;
- /* Currently, only object types with real geometry can be rendered as preview. */
- if (!OB_TYPE_IS_GEOMETRY(ob->type)) {
- return nullptr;
- }
- return &ob->preview;
- }
-
#define ID_PRV_CASE(id_code, id_struct) \
case id_code: { \
return &((id_struct *)id)->preview; \
} \
((void)0)
- ID_PRV_CASE(ID_MA, Material);
- ID_PRV_CASE(ID_TE, Tex);
- ID_PRV_CASE(ID_WO, World);
- ID_PRV_CASE(ID_LA, Light);
- ID_PRV_CASE(ID_IM, Image);
- ID_PRV_CASE(ID_BR, Brush);
- ID_PRV_CASE(ID_GR, Collection);
- ID_PRV_CASE(ID_SCE, Scene);
- ID_PRV_CASE(ID_SCR, bScreen);
- ID_PRV_CASE(ID_AC, bAction);
- ID_PRV_CASE(ID_NT, bNodeTree);
+ ID_PRV_CASE(ID_OB, Object);
+ ID_PRV_CASE(ID_MA, Material);
+ ID_PRV_CASE(ID_TE, Tex);
+ ID_PRV_CASE(ID_WO, World);
+ ID_PRV_CASE(ID_LA, Light);
+ ID_PRV_CASE(ID_IM, Image);
+ ID_PRV_CASE(ID_BR, Brush);
+ ID_PRV_CASE(ID_GR, Collection);
+ 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;
@@ -468,9 +456,6 @@ PreviewImage *BKE_previewimg_cached_get(const char *name)
return (PreviewImage *)BLI_ghash_lookup(gCachedPreviews, name);
}
-/**
- * Generate an empty PreviewImage, if not yet existing.
- */
PreviewImage *BKE_previewimg_cached_ensure(const char *name)
{
BLI_assert(BLI_thread_is_main());
@@ -488,10 +473,6 @@ PreviewImage *BKE_previewimg_cached_ensure(const char *name)
return prv;
}
-/**
- * Generate a PreviewImage from given file path, using thumbnails management, if not yet existing.
- * Does not actually generate the preview, #BKE_previewimg_ensure() must be called for that.
- */
PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name,
const char *path,
const int source,
@@ -546,10 +527,6 @@ void BKE_previewimg_cached_release(const char *name)
BKE_previewimg_deferred_release(prv);
}
-/**
- * Handle deferred (lazy) loading/generation of preview image, if needed.
- * For now, only used with file thumbnails.
- */
void BKE_previewimg_ensure(PreviewImage *prv, const int size)
{
if ((prv->tag & PRV_TAG_DEFFERED) != 0) {
@@ -573,7 +550,7 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
prv->w[ICON_SIZE_PREVIEW] = thumb->x;
prv->h[ICON_SIZE_PREVIEW] = thumb->y;
prv->rect[ICON_SIZE_PREVIEW] = (uint *)MEM_dupallocN(thumb->rect);
- prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_UNFINISHED);
+ prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_RENDERING);
}
if (do_icon) {
if (thumb->x > thumb->y) {
@@ -592,7 +569,7 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
prv->w[ICON_SIZE_ICON] = icon_w;
prv->h[ICON_SIZE_ICON] = icon_h;
prv->rect[ICON_SIZE_ICON] = (uint *)MEM_dupallocN(thumb->rect);
- prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_UNFINISHED);
+ prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_RENDERING);
}
IMB_freeImBuf(thumb);
}
@@ -600,10 +577,6 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
}
}
-/**
- * Create an #ImBuf holding a copy of the preview image buffer in \a prv.
- * \note The returned image buffer has to be free'd (#IMB_freeImBuf()).
- */
ImBuf *BKE_previewimg_to_imbuf(PreviewImage *prv, const int size)
{
const unsigned int w = prv->w[size];
@@ -624,12 +597,12 @@ ImBuf *BKE_previewimg_to_imbuf(PreviewImage *prv, const int size)
void BKE_previewimg_finish(PreviewImage *prv, const int size)
{
/* Previews may be calculated on a thread. */
- atomic_fetch_and_and_int16(&prv->flag[size], ~PRV_UNFINISHED);
+ atomic_fetch_and_and_int16(&prv->flag[size], ~PRV_RENDERING);
}
bool BKE_previewimg_is_finished(const PreviewImage *prv, const int size)
{
- return (prv->flag[size] & PRV_UNFINISHED) == 0;
+ return (prv->flag[size] & PRV_RENDERING) == 0;
}
void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
@@ -663,16 +636,11 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
BLO_read_data_address(reader, &prv->rect[i]);
}
prv->gputexture[i] = nullptr;
- /* For now consider previews read from file as finished to not confuse File Browser preview
- * loading. That could be smarter and check if there's a preview job running instead.
- * If the preview is tagged as changed, it needs to be updated anyway, so don't remove the tag.
- */
- if ((prv->flag[i] & PRV_CHANGED) == 0) {
- BKE_previewimg_finish(prv, i);
- }
- else {
- /* Only for old files that didn't write the flag. */
- prv->flag[i] |= PRV_UNFINISHED;
+
+ /* PRV_RENDERING is a runtime only flag currently, but don't mess with it on undo! It gets
+ * special handling in #memfile_undosys_restart_unfinished_id_previews() then. */
+ if (!BLO_read_data_is_undo(reader)) {
+ prv->flag[i] &= ~PRV_RENDERING;
}
}
prv->icon_id = 0;
@@ -702,7 +670,7 @@ void BKE_icon_changed(const int icon_id)
/* If we have previews, they all are now invalid changed. */
if (p_prv && *p_prv) {
for (int i = 0; i < NUM_ICON_SIZES; i++) {
- (*p_prv)->flag[i] |= (PRV_CHANGED | PRV_UNFINISHED);
+ (*p_prv)->flag[i] |= PRV_CHANGED;
(*p_prv)->changed_timestamp[i]++;
}
}
@@ -809,9 +777,6 @@ int BKE_icon_gplayer_color_ensure(bGPDlayer *gpl)
return icon_gplayer_color_ensure_create_icon(gpl);
}
-/**
- * Return icon id of given preview, or create new icon if not found.
- */
int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
{
if (!preview || G.background) {
@@ -852,11 +817,6 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
return preview->icon_id;
}
-/**
- * Create an icon as owner or \a ibuf. The icon-ID is not stored in \a ibuf, it needs to be stored
- * separately.
- * \note Transforms ownership of \a ibuf to the newly created icon.
- */
int BKE_icon_imbuf_create(ImBuf *ibuf)
{
int icon_id = get_next_free_id();
@@ -938,9 +898,6 @@ void BKE_icon_id_delete(struct ID *id)
BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), nullptr, icon_free);
}
-/**
- * Remove icon and free data.
- */
bool BKE_icon_delete(const int icon_id)
{
if (icon_id == 0) {
@@ -1065,4 +1022,5 @@ int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type)
icon->id_type = id_type;
return icon_id;
}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index f7411f541b7..bb6458331da 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -76,10 +76,6 @@ static size_t idp_size_table[] = {
/* --------- property array type -------------*/
-/**
- * \note as a start to move away from the stupid IDP_New function, this type
- * has its own allocation function.
- */
IDProperty *IDP_NewIDPArray(const char *name)
{
IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty prop array");
@@ -127,7 +123,6 @@ static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user)
}
}
-/* shallow copies item */
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
{
BLI_assert(prop->type == IDP_IDPARRAY);
@@ -229,7 +224,6 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
}
}
-/* This function works for strings too! */
void IDP_ResizeArray(IDProperty *prop, int newlen)
{
const bool is_grow = newlen >= prop->len;
@@ -351,19 +345,13 @@ static IDProperty *IDP_CopyArray(const IDProperty *prop, const int flag)
return newp;
}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name String Functions (IDProperty String API)
* \{ */
-/**
- *
- * \param st: The string to assign.
- * \param name: The property name.
- * \param maxlen: The size of the new string (including the \0 terminator).
- * \return The new string property.
- */
IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
{
IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
@@ -457,6 +445,7 @@ void IDP_FreeString(IDProperty *prop)
MEM_freeN(prop->data.pointer);
}
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -514,8 +503,6 @@ static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag)
return newp;
}
-/* use for syncing proxies.
- * When values name and types match, copy the values, else ignore */
void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
{
BLI_assert(dest->type == IDP_GROUP);
@@ -565,9 +552,6 @@ void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_a
}
}
-/**
- * Replaces all properties with the same name in a destination group from a source group.
- */
void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
{
BLI_assert(dest->type == IDP_GROUP);
@@ -592,10 +576,6 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
}
}
-/**
- * Checks if a property with the same name as prop exists, and if so replaces it.
- * Use this to preserve order!
- */
void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist)
{
BLI_assert(group->type == IDP_GROUP);
@@ -618,10 +598,6 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
IDP_ReplaceInGroup_ex(group, prop, prop_exist);
}
-/**
- * If a property is missing in \a dest, add it.
- * Do it recursively.
- */
void IDP_MergeGroup_ex(IDProperty *dest,
const IDProperty *src,
const bool do_overwrite,
@@ -663,25 +639,11 @@ void IDP_MergeGroup_ex(IDProperty *dest,
}
}
-/**
- * If a property is missing in \a dest, add it.
- * Do it recursively.
- */
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite)
{
IDP_MergeGroup_ex(dest, src, do_overwrite, 0);
}
-/**
- * This function has a sanity check to make sure ID properties with the same name don't
- * get added to the group.
- *
- * The sanity check just means the property is not added to the group if another property
- * exists with the same name; the client code using ID properties then needs to detect this
- * (the function that adds new properties to groups, #IDP_AddToGroup,
- * returns false if a property can't be added to the group, and true if it can)
- * and free the property.
- */
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop)
{
BLI_assert(group->type == IDP_GROUP);
@@ -695,10 +657,6 @@ bool IDP_AddToGroup(IDProperty *group, IDProperty *prop)
return false;
}
-/**
- * This is the same as IDP_AddToGroup, only you pass an item
- * in the group list to be inserted after.
- */
bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
{
BLI_assert(group->type == IDP_GROUP);
@@ -712,12 +670,6 @@ bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew
return false;
}
-/**
- * \note this does not free the property!!
- *
- * To free the property, you have to do:
- * IDP_FreeProperty(prop);
- */
void IDP_RemoveFromGroup(IDProperty *group, IDProperty *prop)
{
BLI_assert(group->type == IDP_GROUP);
@@ -727,9 +679,6 @@ void IDP_RemoveFromGroup(IDProperty *group, IDProperty *prop)
BLI_remlink(&group->data.group, prop);
}
-/**
- * Removes the property from the group and frees it.
- */
void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop)
{
IDP_RemoveFromGroup(group, prop);
@@ -742,7 +691,6 @@ IDProperty *IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name)
return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name));
}
-/** same as above but ensure type match */
IDProperty *IDP_GetPropertyTypeFromGroup(const IDProperty *prop, const char *name, const char type)
{
IDProperty *idprop = IDP_GetPropertyFromGroup(prop, name);
@@ -762,16 +710,13 @@ static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
}
BLI_freelistN(&prop->data.group);
}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Main Functions (IDProperty Main API)
* \{ */
-/**
- * Return an int from an IDProperty with a compatible type. This should be avoided, but
- * it's sometimes necessary, for example when legacy files have incorrect property types.
- */
int IDP_coerce_to_int_or_zero(const IDProperty *prop)
{
switch (prop->type) {
@@ -786,10 +731,6 @@ int IDP_coerce_to_int_or_zero(const IDProperty *prop)
}
}
-/**
- * Return a double from an IDProperty with a compatible type. This should be avoided, but
- * it's sometimes necessary, for example when legacy files have incorrect property types.
- */
double IDP_coerce_to_double_or_zero(const IDProperty *prop)
{
switch (prop->type) {
@@ -804,10 +745,6 @@ double IDP_coerce_to_double_or_zero(const IDProperty *prop)
}
}
-/**
- * Return a float from an IDProperty with a compatible type. This should be avoided, but
- * it's sometimes necessary, for example when legacy files have incorrect property types.
- */
float IDP_coerce_to_float_or_zero(const IDProperty *prop)
{
switch (prop->type) {
@@ -845,10 +782,6 @@ IDProperty *IDP_CopyProperty(const IDProperty *prop)
return IDP_CopyProperty_ex(prop, 0);
}
-/**
- * Copy content from source IDProperty into destination one, freeing destination property's content
- * first.
- */
void IDP_CopyPropertyContent(IDProperty *dst, IDProperty *src)
{
IDProperty *idprop_tmp = IDP_CopyProperty(src);
@@ -858,11 +791,6 @@ void IDP_CopyPropertyContent(IDProperty *dst, IDProperty *src)
IDP_FreeProperty(idprop_tmp);
}
-/**
- * Get the Group property that contains the id properties for ID id. Set create_if_needed
- * to create the Group property and attach it to id if it doesn't exist; otherwise
- * the function will return NULL if there's no Group property attached to the ID.
- */
IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed)
{
if (id->properties) {
@@ -880,8 +808,6 @@ IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed)
return id->properties;
}
-/**
- * \param is_strict: When false treat missing items as a match */
bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict)
{
if (prop1 == NULL && prop2 == NULL) {
@@ -974,33 +900,6 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
return IDP_EqualsProperties_ex(prop1, prop2, true);
}
-/**
- * Allocate a new ID.
- *
- * This function takes three arguments: the ID property type, a union which defines
- * its initial value, and a name.
- *
- * The union is simple to use; see the top of BKE_idprop.h for its definition.
- * An example of using this function:
- *
- * \code{.c}
- * IDPropertyTemplate val;
- * IDProperty *group, *idgroup, *color;
- * group = IDP_New(IDP_GROUP, val, "group1"); // groups don't need a template.
- *
- * val.array.len = 4
- * val.array.type = IDP_FLOAT;
- * color = IDP_New(IDP_ARRAY, val, "color1");
- *
- * idgroup = IDP_GetProperties(some_id, 1);
- * IDP_AddToGroup(idgroup, color);
- * IDP_AddToGroup(idgroup, group);
- * \endcode
- *
- * Note that you MUST either attach the id property to an id property group with
- * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
- * a memory leak.
- */
IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name)
{
IDProperty *prop = NULL;
@@ -1096,11 +995,6 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
return prop;
}
-/**
- * Free allocated pointers in the UI data that isn't shared with the UI data in the #other
- * argument. Useful for returning early on failure when updating UI data in place, or when
- * replacing a subset of the UI data's allocated pointers.
- */
void IDP_ui_data_free_unique_contents(IDPropertyUIData *ui_data,
const eIDPropertyUIDataType type,
const IDPropertyUIData *other)
@@ -1175,10 +1069,6 @@ void IDP_ui_data_free(IDProperty *prop)
prop->ui_data = NULL;
}
-/**
- * \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
- * But it does not free the actual IDProperty struct itself.
- */
void IDP_FreePropertyContent_ex(IDProperty *prop, const bool do_id_user)
{
switch (prop->type) {
@@ -1241,14 +1131,6 @@ void IDP_Reset(IDProperty *prop, const IDProperty *reference)
}
}
-/**
- * Loop through all ID properties in hierarchy of given \a id_property_root included.
- *
- * \note Container types (groups and arrays) are processed after applying the callback on them.
- *
- * \param type_filter: If not 0, only apply callback on properties of matching types, see
- * IDP_TYPE_FILTER_ enum in DNA_ID.h.
- */
void IDP_foreach_property(IDProperty *id_property_root,
const int type_filter,
IDPForeachPropertyCallback callback,
diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c
index d9dc68b1a4f..e6fd6c14d42 100644
--- a/source/blender/blenkernel/intern/idtype.c
+++ b/source/blender/blenkernel/intern/idtype.c
@@ -158,13 +158,6 @@ static const IDTypeInfo *idtype_get_info_from_name(const char *idtype_name)
/* Various helpers/wrappers around #IDTypeInfo structure. */
-/**
- * Convert an \a idcode into a name.
- *
- * \param idcode: The code to convert.
- * \return A static string representing the name of
- * the code.
- */
const char *BKE_idtype_idcode_to_name(const short idcode)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(idcode);
@@ -172,13 +165,6 @@ const char *BKE_idtype_idcode_to_name(const short idcode)
return id_type != NULL ? id_type->name : NULL;
}
-/**
- * Convert an \a idcode into a name (plural).
- *
- * \param idcode: The code to convert.
- * \return A static string representing the name of
- * the code.
- */
const char *BKE_idtype_idcode_to_name_plural(const short idcode)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(idcode);
@@ -186,12 +172,6 @@ const char *BKE_idtype_idcode_to_name_plural(const short idcode)
return id_type != NULL ? id_type->name_plural : NULL;
}
-/**
- * Convert an \a idcode into its translations' context.
- *
- * \param idcode: The code to convert.
- * \return A static string representing the i18n context of the code.
- */
const char *BKE_idtype_idcode_to_translation_context(const short idcode)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(idcode);
@@ -199,12 +179,6 @@ const char *BKE_idtype_idcode_to_translation_context(const short idcode)
return id_type != NULL ? id_type->translation_context : BLT_I18NCONTEXT_DEFAULT;
}
-/**
- * Convert an ID-type name into an \a idcode (ie. #ID_SCE)
- *
- * \param idtype_name: The ID-type's "user visible name" to convert.
- * \return The \a idcode for the name, or 0 if invalid.
- */
short BKE_idtype_idcode_from_name(const char *idtype_name)
{
const IDTypeInfo *id_type = idtype_get_info_from_name(idtype_name);
@@ -212,23 +186,11 @@ short BKE_idtype_idcode_from_name(const char *idtype_name)
return id_type != NULL ? id_type->id_code : 0;
}
-/**
- * Return if the ID code is a valid ID code.
- *
- * \param idcode: The code to check.
- * \return Boolean, 0 when invalid.
- */
bool BKE_idtype_idcode_is_valid(const short idcode)
{
return BKE_idtype_get_info_from_idcode(idcode) != NULL ? true : false;
}
-/**
- * Check if an ID type is linkable.
- *
- * \param idcode: The IDType code to check.
- * \return Boolean, false when non linkable, true otherwise.
- */
bool BKE_idtype_idcode_is_linkable(const short idcode)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(idcode);
@@ -236,12 +198,6 @@ bool BKE_idtype_idcode_is_linkable(const short idcode)
return id_type != NULL ? (id_type->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0 : false;
}
-/**
- * Check if an ID type is only appendable.
- *
- * \param idcode: The IDType code to check.
- * \return Boolean, false when also linkable, true when only appendable.
- */
bool BKE_idtype_idcode_is_only_appendable(const short idcode)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(idcode);
@@ -254,12 +210,6 @@ bool BKE_idtype_idcode_is_only_appendable(const short idcode)
return false;
}
-/**
- * Check if an ID type can try to reuse and existing matching local one when being appended again.
- *
- * \param idcode: The IDType code to check.
- * \return Boolean, false when it cannot be re-used, true otherwise.
- */
bool BKE_idtype_idcode_append_is_reusable(const short idcode)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(idcode);
@@ -272,9 +222,6 @@ bool BKE_idtype_idcode_append_is_reusable(const short idcode)
return false;
}
-/**
- * Convert an \a idcode into an \a idfilter (e.g. ID_OB -> FILTER_ID_OB).
- */
uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
{
#define CASE_IDFILTER(_id) \
@@ -324,9 +271,6 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
#undef CASE_IDFILTER
}
-/**
- * Convert an \a idfilter into an \a idcode (e.g. #FILTER_ID_OB -> #ID_OB).
- */
short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
{
#define CASE_IDFILTER(_id) \
@@ -375,9 +319,6 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
#undef CASE_IDFILTER
}
-/**
- * Convert an \a idcode into an index (e.g. #ID_OB -> #INDEX_ID_OB).
- */
int BKE_idtype_idcode_to_index(const short idcode)
{
#define CASE_IDINDEX(_id) \
@@ -437,9 +378,6 @@ int BKE_idtype_idcode_to_index(const short idcode)
#undef CASE_IDINDEX
}
-/**
- * Get an \a idcode from an index (e.g. #INDEX_ID_OB -> #ID_OB).
- */
short BKE_idtype_idcode_from_index(const int index)
{
#define CASE_IDCODE(_id) \
@@ -499,20 +437,11 @@ short BKE_idtype_idcode_from_index(const int index)
#undef CASE_IDCODE
}
-/**
- * Return an ID code and steps the index forward 1.
- *
- * \param index: start as 0.
- * \return the code, 0 when all codes have been returned.
- */
short BKE_idtype_idcode_iter_step(int *index)
{
return (*index < ARRAY_SIZE(id_types)) ? BKE_idtype_idcode_from_index((*index)++) : 0;
}
-/**
- * Wrapper around #IDTypeInfo foreach_cache that also handles embedded IDs.
- */
void BKE_idtype_id_foreach_cache(struct ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index c0efc246567..f43cf00a310 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -75,6 +75,7 @@
#include "BLT_translation.h"
+#include "BKE_bpath.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_icons.h"
@@ -252,6 +253,34 @@ static void image_foreach_cache(ID *id,
}
}
+static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Image *ima = (Image *)id;
+ const eBPathForeachFlag flag = bpath_data->flag;
+
+ if (BKE_image_has_packedfile(ima) && (flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
+ return;
+ }
+ /* Skip empty file paths, these are typically from generated images and
+ * don't make sense to add directories to until the image has been saved
+ * once to give it a meaningful value. */
+ /* TODO re-assess whether this behavior is desired in the new generic code context. */
+ if (!ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED) ||
+ ima->filepath[0] == '\0') {
+ return;
+ }
+
+ if (BKE_bpath_foreach_path_fixed_process(bpath_data, ima->filepath)) {
+ if (flag & BKE_BPATH_FOREACH_PATH_RELOAD_EDITED) {
+ if (!BKE_image_has_packedfile(ima) &&
+ /* Image may have been painted onto (and not saved, T44543). */
+ !BKE_image_is_dirty(ima)) {
+ BKE_image_signal(bpath_data->bmain, ima, NULL, IMA_SIGNAL_RELOAD);
+ }
+ }
+ }
+}
+
static void image_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Image *ima = (Image *)id;
@@ -369,6 +398,7 @@ IDTypeInfo IDType_ID_IM = {
.name_plural = "images",
.translation_context = BLT_I18NCONTEXT_ID_IMAGE,
.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = image_init_data,
.copy_data = image_copy_data,
@@ -376,6 +406,7 @@ IDTypeInfo IDType_ID_IM = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = image_foreach_cache,
+ .foreach_path = image_foreach_path,
.owner_get = NULL,
.blend_write = image_blend_write,
@@ -518,10 +549,6 @@ static void image_free_anims(Image *ima)
}
}
-/**
- * Simply free the image data from memory,
- * on display the image can load again (except for render buffers).
- */
void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
{
if (do_lock) {
@@ -548,7 +575,6 @@ void BKE_image_free_buffers(Image *ima)
BKE_image_free_buffers_ex(ima, false);
}
-/** Free (or release) any data used by this image (does not free the image itself). */
void BKE_image_free_data(Image *ima)
{
image_free_data(&ima->id);
@@ -675,9 +701,11 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
}
}
-/* NOTE: We could be clever and scale all imbuf's but since some are mipmaps its not so simple. */
bool BKE_image_scale(Image *image, int width, int height)
{
+ /* NOTE: We could be clever and scale all imbuf's
+ * but since some are mipmaps its not so simple. */
+
ImBuf *ibuf;
void *lock;
@@ -776,9 +804,6 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
return tile_number;
}
-/**
- * Return the tile_number for the closest UDIM tile.
- */
int BKE_image_find_nearest_tile(const Image *image, const float co[2])
{
const float co_floor[2] = {floorf(co[0]), floorf(co[1])};
@@ -877,17 +902,13 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
return ima;
}
-/* checks if image was already loaded, then returns same image */
-/* otherwise creates new. */
-/* does not load ibuf itself */
-/* pass on optional frame for #name images */
Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
{
Image *ima;
char str[FILE_MAX], strtest[FILE_MAX];
STRNCPY(str, filepath);
- BLI_path_abs(str, bmain->name);
+ BLI_path_abs(str, bmain->filepath);
/* first search an identical filepath */
for (ima = bmain->images.first; ima; ima = ima->id.next) {
@@ -1027,7 +1048,6 @@ static ImBuf *add_ibuf_size(unsigned int width,
return ibuf;
}
-/* adds new image block, creates ImBuf and initializes color */
Image *BKE_image_add_generated(Main *bmain,
unsigned int width,
unsigned int height,
@@ -1088,11 +1108,6 @@ Image *BKE_image_add_generated(Main *bmain,
return ima;
}
-/**
- * Create an image from ibuf. The refcount of ibuf is increased,
- * caller should take care to drop its reference by calling
- * #IMB_freeImBuf if needed.
- */
Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
{
/* on save, type is changed to FILE in editsima.c */
@@ -1144,7 +1159,6 @@ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath
return true;
}
-/* Pack image to memory. */
bool BKE_image_memorypack(Image *ima)
{
bool ok = true;
@@ -1377,7 +1391,6 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void
(except_frame != IMA_INDEX_ENTRY(ibuf->index));
}
-/* except_frame is weak, only works for seqs without offset... */
void BKE_image_free_anim_ibufs(Image *ima, int except_frame)
{
BLI_mutex_lock(ima->runtime.cache_mutex);
@@ -1639,8 +1652,6 @@ char BKE_imtype_valid_depths(const char imtype)
}
}
-/* string is from command line --render-format arg, keep in sync with
- * creator_args.c help info */
char BKE_imtype_from_arg(const char *imtype_arg)
{
if (STREQ(imtype_arg, "TGA")) {
@@ -2051,9 +2062,10 @@ static void stampdata(
time_t t;
if (scene->r.stamp & R_STAMP_FILENAME) {
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
SNPRINTF(stamp_data->file,
do_prefix ? "File %s" : "%s",
- G.relbase_valid ? BKE_main_blendfile_path_from_global() : "<untitled>");
+ (blendfile_path[0] != '\0') ? blendfile_path : "<untitled>");
}
else {
stamp_data->file[0] = '\0';
@@ -2744,8 +2756,6 @@ static const char *stamp_metadata_fields[] = {
NULL,
};
-/* Check whether the given metadata field name translates to a known field of
- * a stamp. */
bool BKE_stamp_is_known_field(const char *field_name)
{
int i = 0;
@@ -2907,8 +2917,6 @@ bool BKE_imbuf_alpha_test(ImBuf *ibuf)
return false;
}
-/* NOTE: imf->planes is ignored here, its assumed the image channels
- * are already set */
void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
{
char imtype = imf->imtype;
@@ -3085,8 +3093,6 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, const ImageFormatData *imf)
return ok;
}
-/* same as BKE_imbuf_write() but crappy workaround not to permanently modify
- * _some_, values in the imbuf */
int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, const bool save_copy)
{
ImBuf ibuf_back = *ibuf;
@@ -3185,7 +3191,6 @@ struct anim *openanim_noload(const char *name,
return anim;
}
-/* used by sequencer too */
struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
{
struct anim *anim;
@@ -3231,8 +3236,6 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
* -> comes from packedfile or filename or generated
*/
-/* forces existence of 1 Image for renderout or nodes, returns Image */
-/* name is only for default, when making new one */
Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
{
Image *ima;
@@ -3273,7 +3276,6 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima)
}
}
-/* Reset the image cache and views when the Viewer Nodes views don't match the scene views */
void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser)
{
bool do_reset;
@@ -3928,7 +3930,6 @@ bool BKE_image_fill_tile(struct Image *ima,
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesn't use the index! */
-/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
{
RenderLayer *rl;
@@ -3983,7 +3984,6 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesn't use the index! */
-/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
bool BKE_image_is_multilayer(Image *ima)
{
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
@@ -4233,13 +4233,16 @@ static int image_num_files(Image *ima)
return BLI_listbase_count(&ima->views);
}
-static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, const int view_id)
+static ImBuf *load_sequence_single(
+ Image *ima, ImageUser *iuser, int frame, const int view_id, bool *r_cache_ibuf)
{
struct ImBuf *ibuf;
char name[FILE_MAX];
int flag;
ImageUser iuser_t = {0};
+ *r_cache_ibuf = true;
+
ima->lastframe = frame;
if (iuser) {
@@ -4279,6 +4282,9 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
ima->type = IMA_TYPE_MULTILAYER;
IMB_freeImBuf(ibuf);
ibuf = NULL;
+ /* NULL ibuf in the cache means the image failed to load. However for multilayer we load
+ * pixels into RenderResult instead and intentionally leave ibuf NULL. */
+ *r_cache_ibuf = false;
}
}
else {
@@ -4299,17 +4305,21 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry,
const int totfiles = image_num_files(ima);
if (!is_multiview) {
- ibuf = load_sequence_single(ima, iuser, frame, 0);
- image_assign_ibuf(ima, ibuf, 0, entry);
+ bool put_in_cache;
+ ibuf = load_sequence_single(ima, iuser, frame, 0, &put_in_cache);
+ if (put_in_cache) {
+ image_assign_ibuf(ima, ibuf, 0, entry);
+ }
}
else {
const int totviews = BLI_listbase_count(&ima->views);
struct ImBuf **ibuf_arr;
ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs");
+ bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image View Put In Cache");
for (int i = 0; i < totfiles; i++) {
- ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i);
+ ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, cache_ibuf_arr + i);
}
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) {
@@ -4320,7 +4330,9 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry,
ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)];
for (int i = 0; i < totviews; i++) {
- image_assign_ibuf(ima, ibuf_arr[i], i, entry);
+ if (cache_ibuf_arr[i]) {
+ image_assign_ibuf(ima, ibuf_arr[i], i, entry);
+ }
}
/* "remove" the others (decrease their refcount) */
@@ -4332,6 +4344,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry,
/* cleanup */
MEM_freeN(ibuf_arr);
+ MEM_freeN(cache_ibuf_arr);
}
return ibuf;
@@ -4493,13 +4506,19 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
return ibuf;
}
-static ImBuf *load_image_single(
- Image *ima, ImageUser *iuser, int cfra, const int view_id, const bool has_packed)
+static ImBuf *load_image_single(Image *ima,
+ ImageUser *iuser,
+ int cfra,
+ const int view_id,
+ const bool has_packed,
+ bool *r_cache_ibuf)
{
char filepath[FILE_MAX];
struct ImBuf *ibuf = NULL;
int flag;
+ *r_cache_ibuf = true;
+
/* is there a PackedFile with this image ? */
if (has_packed) {
ImagePackedFile *imapf;
@@ -4550,6 +4569,9 @@ static ImBuf *load_image_single(
ima->type = IMA_TYPE_MULTILAYER;
IMB_freeImBuf(ibuf);
ibuf = NULL;
+ /* NULL ibuf in the cache means the image failed to load. However for multilayer we load
+ * pixels into RenderResult instead and intentionally leave ibuf NULL. */
+ *r_cache_ibuf = false;
}
}
else
@@ -4594,8 +4616,11 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
}
if (!is_multiview) {
- ibuf = load_image_single(ima, iuser, cfra, 0, has_packed);
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ bool put_in_cache;
+ ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &put_in_cache);
+ if (put_in_cache) {
+ image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ }
}
else {
struct ImBuf **ibuf_arr;
@@ -4603,9 +4628,10 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
BLI_assert(totviews > 0);
ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs");
+ bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image Views Put In Cache");
for (int i = 0; i < totfiles; i++) {
- ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed);
+ ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, cache_ibuf_arr + i);
}
/* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */
@@ -4619,7 +4645,9 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
ibuf = ibuf_arr[i];
for (i = 0; i < totviews; i++) {
- image_assign_ibuf(ima, ibuf_arr[i], i, 0);
+ if (cache_ibuf_arr[i]) {
+ image_assign_ibuf(ima, ibuf_arr[i], i, 0);
+ }
}
/* "remove" the others (decrease their refcount) */
@@ -4631,6 +4659,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
/* cleanup */
MEM_freeN(ibuf_arr);
+ MEM_freeN(cache_ibuf_arr);
}
return ibuf;
@@ -4986,9 +5015,10 @@ BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser)
return true;
}
-/* Checks optional ImageUser and verifies/creates ImBuf.
+/**
+ * Checks optional #ImageUser and verifies/creates #ImBuf.
*
- * not thread-safe, so callee should worry about thread locks
+ * \warning Not thread-safe, so callee should worry about thread locks.
*/
static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
@@ -5109,15 +5139,15 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
return ibuf;
}
-/* return image buffer for given image and user
- *
- * - will lock render result if image type is render result and lock is not NULL
- * - will return NULL if image type if render or composite result and lock is NULL
- *
- * references the result, BKE_image_release_ibuf should be used to de-reference
- */
ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
+ /* NOTE: same as #image_acquire_ibuf, but can be used to retrieve images being rendered in
+ * a thread safe way, always call both acquire and release. */
+
+ if (ima == NULL) {
+ return NULL;
+ }
+
ImBuf *ibuf;
BLI_mutex_lock(ima->runtime.cache_mutex);
@@ -5149,7 +5179,6 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
}
}
-/* checks whether there's an image buffer for given image and user */
bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
{
ImBuf *ibuf;
@@ -5657,19 +5686,16 @@ bool BKE_image_has_filepath(Image *ima)
return ima->filepath[0] != '\0';
}
-/* Checks the image buffer changes with time (not keyframed values). */
bool BKE_image_is_animated(Image *image)
{
return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE);
}
-/* Checks whether the image consists of multiple buffers. */
bool BKE_image_has_multiple_ibufs(Image *image)
{
return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED);
}
-/* Image modifications */
bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
{
bool is_dirty = false;
@@ -5745,8 +5771,12 @@ bool BKE_image_has_loaded_ibuf(Image *image)
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
- has_loaded_ibuf = true;
- break;
+ ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
+ if (ibuf != NULL) {
+ has_loaded_ibuf = true;
+ break;
+ }
+ IMB_moviecacheIter_step(iter);
}
IMB_moviecacheIter_free(iter);
}
@@ -5755,10 +5785,6 @@ bool BKE_image_has_loaded_ibuf(Image *image)
return has_loaded_ibuf;
}
-/**
- * References the result, #BKE_image_release_ibuf is to be called to de-reference.
- * Use lock=NULL when calling #BKE_image_release_ibuf().
- */
ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
{
ImBuf *ibuf = NULL;
@@ -5783,15 +5809,6 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
return ibuf;
}
-/**
- * References the result, #BKE_image_release_ibuf is to be called to de-reference.
- * Use lock=NULL when calling #BKE_image_release_ibuf().
- *
- * TODO(sergey): This is actually "get first item from the cache", which is
- * not so much predictable. But using first loaded image buffer
- * was also malicious logic and all the areas which uses this
- * function are to be re-considered.
- */
ImBuf *BKE_image_get_first_ibuf(Image *image)
{
ImBuf *ibuf = NULL;
diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.cc
index 330af1cc505..4440e4b101a 100644
--- a/source/blender/blenkernel/intern/image_gpu.c
+++ b/source/blender/blenkernel/intern/image_gpu.cc
@@ -47,7 +47,7 @@
#include "PIL_time.h"
/* Prototypes. */
-static void gpu_free_unused_buffers(void);
+static void gpu_free_unused_buffers();
static void image_free_gpu(Image *ima, const bool immediate);
static void image_free_gpu_limited_scale(Image *ima);
static void image_update_gputexture_ex(
@@ -55,13 +55,12 @@ static void image_update_gputexture_ex(
/* Internal structs. */
#define IMA_PARTIAL_REFRESH_TILE_SIZE 256
-typedef struct ImagePartialRefresh {
+struct ImagePartialRefresh {
struct ImagePartialRefresh *next, *prev;
int tile_x;
int tile_y;
-} ImagePartialRefresh;
+};
-/* Is the alpha of the `GPUTexture` for a given image/ibuf premultiplied. */
bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
{
if (image) {
@@ -71,7 +70,7 @@ bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
}
/* Generated images use pre multiplied float buffer, but straight alpha for byte buffers. */
if (image->type == IMA_TYPE_UV_TEST && ibuf) {
- return ibuf->rect_float != NULL;
+ return ibuf->rect_float != nullptr;
}
}
if (ibuf) {
@@ -85,8 +84,9 @@ bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
}
/* -------------------------------------------------------------------- */
-/** \name UDIM gpu texture
+/** \name UDIM GPU Texture
* \{ */
+
static bool is_over_resolution_limit(int w, int h, bool limit_gl_texture_size)
{
return (w > GPU_texture_size_with_limit(w, limit_gl_texture_size) ||
@@ -104,8 +104,8 @@ static GPUTexture *gpu_texture_create_tile_mapping(
const int resolution = (texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED) ? 1 : 0;
GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye][resolution];
- if (tilearray == NULL) {
- return 0;
+ if (tilearray == nullptr) {
+ return nullptr;
}
float array_w = GPU_texture_width(tilearray);
@@ -142,11 +142,11 @@ static GPUTexture *gpu_texture_create_tile_mapping(
return tex;
}
-typedef struct PackTile {
+struct PackTile {
FixedSizeBoxPack boxpack;
ImageTile *tile;
float pack_score;
-} PackTile;
+};
static int compare_packtile(const void *a, const void *b)
{
@@ -163,13 +163,13 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima,
const bool limit_gl_texture_size = texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED;
const int resolution = texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED ? 1 : 0;
int arraywidth = 0, arrayheight = 0;
- ListBase boxes = {NULL};
+ ListBase boxes = {nullptr};
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
ImageUser iuser;
BKE_imageuser_default(&iuser);
iuser.tile = tile->tile_number;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr);
if (ibuf) {
PackTile *packtile = (PackTile *)MEM_callocN(sizeof(PackTile), __func__);
@@ -190,7 +190,7 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima,
float w = packtile->boxpack.w, h = packtile->boxpack.h;
packtile->pack_score = max_ff(w, h) / min_ff(w, h) * w * h;
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, nullptr);
BLI_addtail(&boxes, packtile);
}
}
@@ -200,10 +200,10 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima,
BLI_listbase_sort(&boxes, compare_packtile);
int arraylayers = 0;
/* Keep adding layers until all tiles are packed. */
- while (boxes.first != NULL) {
- ListBase packed = {NULL};
+ while (boxes.first != nullptr) {
+ ListBase packed = {nullptr};
BLI_box_pack_2d_fixedarea(&boxes, arraywidth, arrayheight, &packed);
- BLI_assert(packed.first != NULL);
+ BLI_assert(packed.first != nullptr);
LISTBASE_FOREACH (PackTile *, packtile, &packed) {
ImageTile *tile = packtile->tile;
@@ -241,7 +241,7 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima,
ImageUser iuser;
BKE_imageuser_default(&iuser);
iuser.tile = tile->tile_number;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr);
if (ibuf) {
const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, ibuf);
@@ -254,7 +254,7 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima,
store_premultiplied);
}
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, nullptr);
}
if (GPU_mipmap_enabled()) {
@@ -305,7 +305,7 @@ static GPUTexture **get_image_gpu_texture_ptr(Image *ima,
if (in_range) {
return &(ima->gputexture[textarget][multiview_eye][resolution]);
}
- return NULL;
+ return nullptr;
}
static GPUTexture *image_gpu_texture_error_create(eGPUTextureTarget textarget)
@@ -342,8 +342,8 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
ImBuf *ibuf,
eGPUTextureTarget textarget)
{
- if (ima == NULL) {
- return NULL;
+ if (ima == nullptr) {
+ return nullptr;
}
/* Free any unused GPU textures, since we know we are in a thread with OpenGL
@@ -373,7 +373,7 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
/* Check if image has been updated and tagged to be updated (full or partial). */
ImageTile *tile = BKE_image_get_tile(ima, 0);
if (((ima->gpuflag & IMA_GPU_REFRESH) != 0) ||
- ((ibuf == NULL || tile == NULL) && ((ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) != 0))) {
+ ((ibuf == nullptr || tile == nullptr) && ((ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) != 0))) {
image_free_gpu(ima, true);
BLI_freelistN(&ima->gpu_refresh_areas);
ima->gpuflag &= ~(IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH);
@@ -382,7 +382,8 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
BLI_assert(ibuf);
BLI_assert(tile);
ImagePartialRefresh *refresh_area;
- while ((refresh_area = BLI_pophead(&ima->gpu_refresh_areas))) {
+ while ((
+ refresh_area = static_cast<ImagePartialRefresh *>(BLI_pophead(&ima->gpu_refresh_areas)))) {
const int tile_offset_x = refresh_area->tile_x * IMA_PARTIAL_REFRESH_TILE_SIZE;
const int tile_offset_y = refresh_area->tile_y * IMA_PARTIAL_REFRESH_TILE_SIZE;
const int tile_width = MIN2(IMA_PARTIAL_REFRESH_TILE_SIZE, ibuf->x - tile_offset_x);
@@ -404,7 +405,7 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
}
const bool limit_resolution = U.glreslimit != 0 &&
((iuser && (iuser->flag & IMA_SHOW_MAX_RESOLUTION) == 0) ||
- (iuser == NULL)) &&
+ (iuser == nullptr)) &&
((ima->gpuflag & IMA_GPU_REUSE_MAX_RESOLUTION) == 0);
const eImageTextureResolution texture_resolution = limit_resolution ?
IMA_TEXTURE_RESOLUTION_LIMITED :
@@ -416,16 +417,16 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
/* Check if we have a valid image. If not, we return a dummy
* texture with zero bind-code so we don't keep trying. */
- if (tile == NULL) {
+ if (tile == nullptr) {
*tex = image_gpu_texture_error_create(textarget);
return *tex;
}
/* check if we have a valid image buffer */
ImBuf *ibuf_intern = ibuf;
- if (ibuf_intern == NULL) {
- ibuf_intern = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ibuf_intern == NULL) {
+ if (ibuf_intern == nullptr) {
+ ibuf_intern = BKE_image_acquire_ibuf(ima, iuser, nullptr);
+ if (ibuf_intern == nullptr) {
*tex = image_gpu_texture_error_create(textarget);
return *tex;
}
@@ -477,8 +478,8 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
}
/* if `ibuf` was given, we don't own the `ibuf_intern` */
- if (ibuf == NULL) {
- BKE_image_release_ibuf(ima, ibuf_intern, NULL);
+ if (ibuf == nullptr) {
+ BKE_image_release_ibuf(ima, ibuf_intern, nullptr);
}
if (*tex) {
@@ -512,19 +513,19 @@ GPUTexture *BKE_image_get_gpu_tilemap(Image *image, ImageUser *iuser, ImBuf *ibu
* In that case we push them into a queue and free the buffers later.
* \{ */
-static LinkNode *gpu_texture_free_queue = NULL;
+static LinkNode *gpu_texture_free_queue = nullptr;
static ThreadMutex gpu_texture_queue_mutex = BLI_MUTEX_INITIALIZER;
-static void gpu_free_unused_buffers(void)
+static void gpu_free_unused_buffers()
{
- if (gpu_texture_free_queue == NULL) {
+ if (gpu_texture_free_queue == nullptr) {
return;
}
BLI_mutex_lock(&gpu_texture_queue_mutex);
- while (gpu_texture_free_queue != NULL) {
- GPUTexture *tex = BLI_linklist_pop(&gpu_texture_free_queue);
+ while (gpu_texture_free_queue != nullptr) {
+ GPUTexture *tex = static_cast<GPUTexture *>(BLI_linklist_pop(&gpu_texture_free_queue));
GPU_texture_free(tex);
}
@@ -549,7 +550,7 @@ static void image_free_gpu(Image *ima, const bool immediate)
for (int eye = 0; eye < 2; eye++) {
for (int i = 0; i < TEXTARGET_COUNT; i++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
- if (ima->gputexture[i][eye][resolution] != NULL) {
+ if (ima->gputexture[i][eye][resolution] != nullptr) {
if (immediate) {
GPU_texture_free(ima->gputexture[i][eye][resolution]);
}
@@ -559,7 +560,7 @@ static void image_free_gpu(Image *ima, const bool immediate)
BLI_mutex_unlock(&gpu_texture_queue_mutex);
}
- ima->gputexture[i][eye][resolution] = NULL;
+ ima->gputexture[i][eye][resolution] = nullptr;
}
}
}
@@ -573,9 +574,9 @@ static void image_free_gpu_limited_scale(Image *ima)
const eImageTextureResolution resolution = IMA_TEXTURE_RESOLUTION_LIMITED;
for (int eye = 0; eye < 2; eye++) {
for (int i = 0; i < TEXTARGET_COUNT; i++) {
- if (ima->gputexture[i][eye][resolution] != NULL) {
+ if (ima->gputexture[i][eye][resolution] != nullptr) {
GPU_texture_free(ima->gputexture[i][eye][resolution]);
- ima->gputexture[i][eye][resolution] = NULL;
+ ima->gputexture[i][eye][resolution] = nullptr;
}
}
}
@@ -597,7 +598,6 @@ void BKE_image_free_all_gputextures(Main *bmain)
}
}
-/* same as above but only free animated images */
void BKE_image_free_anim_gputextures(Main *bmain)
{
if (bmain) {
@@ -644,6 +644,7 @@ void BKE_image_free_old_gputextures(Main *bmain)
}
}
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -769,7 +770,7 @@ static void gpu_texture_update_from_ibuf(GPUTexture *tex,
{
const int resolution = texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED ? 1 : 0;
bool scaled;
- if (tile != NULL) {
+ if (tile != nullptr) {
ImageTile_RuntimeTextureSlot *tile_runtime = &tile->runtime.slots[resolution];
int *tilesize = tile_runtime->tilearray_size;
scaled = (ibuf->x != tilesize[0]) || (ibuf->y != tilesize[1]);
@@ -796,14 +797,14 @@ static void gpu_texture_update_from_ibuf(GPUTexture *tex,
int tex_offset = ibuf->channels * (y * ibuf->x + x);
const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, ibuf);
- if (rect_float == NULL) {
+ if (rect_float == nullptr) {
/* Byte pixels. */
if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(
ibuf->rect_colorspace);
rect = (uchar *)MEM_mallocN(sizeof(uchar[4]) * w * h, __func__);
- if (rect == NULL) {
+ if (rect == nullptr) {
return;
}
@@ -820,7 +821,7 @@ static void gpu_texture_update_from_ibuf(GPUTexture *tex,
/* Float pixels. */
if (ibuf->channels != 4 || scaled || !store_premultiplied) {
rect_float = (float *)MEM_mallocN(sizeof(float[4]) * w * h, __func__);
- if (rect_float == NULL) {
+ if (rect_float == nullptr) {
return;
}
@@ -834,7 +835,7 @@ static void gpu_texture_update_from_ibuf(GPUTexture *tex,
if (scaled) {
/* Slower update where we first have to scale the input pixels. */
- if (tile != NULL) {
+ if (tile != nullptr) {
ImageTile_RuntimeTextureSlot *tile_runtime = &tile->runtime.slots[resolution];
int *tileoffset = tile_runtime->tilearray_offset;
int *tilesize = tile_runtime->tilearray_size;
@@ -844,12 +845,12 @@ static void gpu_texture_update_from_ibuf(GPUTexture *tex,
}
else {
gpu_texture_update_scaled(
- tex, rect, rect_float, ibuf->x, ibuf->y, x, y, -1, NULL, NULL, w, h);
+ tex, rect, rect_float, ibuf->x, ibuf->y, x, y, -1, nullptr, nullptr, w, h);
}
}
else {
/* Fast update at same resolution. */
- if (tile != NULL) {
+ if (tile != nullptr) {
ImageTile_RuntimeTextureSlot *tile_runtime = &tile->runtime.slots[resolution];
int *tileoffset = tile_runtime->tilearray_offset;
int tilelayer = tile_runtime->tilearray_layer;
@@ -858,7 +859,7 @@ static void gpu_texture_update_from_ibuf(GPUTexture *tex,
}
else {
gpu_texture_update_unscaled(
- tex, rect, rect_float, x, y, -1, NULL, w, h, tex_stride, tex_offset);
+ tex, rect, rect_float, x, y, -1, nullptr, w, h, tex_stride, tex_offset);
}
}
@@ -886,39 +887,33 @@ static void image_update_gputexture_ex(
const int eye = 0;
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
GPUTexture *tex = ima->gputexture[TEXTARGET_2D][eye][resolution];
- eImageTextureResolution texture_resolution = resolution;
+ eImageTextureResolution texture_resolution = static_cast<eImageTextureResolution>(resolution);
/* Check if we need to update the main gputexture. */
- if (tex != NULL && tile == ima->tiles.first) {
- gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h, texture_resolution);
+ if (tex != nullptr && tile == ima->tiles.first) {
+ gpu_texture_update_from_ibuf(tex, ima, ibuf, nullptr, x, y, w, h, texture_resolution);
}
/* Check if we need to update the array gputexture. */
tex = ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution];
- if (tex != NULL) {
+ if (tex != nullptr) {
gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h, texture_resolution);
}
}
}
-/* Partial update of texture for texture painting. This is often much
- * quicker than fully updating the texture for high resolution images. */
void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr);
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
- if ((ibuf == NULL) || (w == 0) || (h == 0)) {
+ if ((ibuf == nullptr) || (w == 0) || (h == 0)) {
/* Full reload of texture. */
BKE_image_free_gputextures(ima);
}
image_update_gputexture_ex(ima, tile, ibuf, x, y, w, h);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, nullptr);
}
-/* Mark areas on the GPUTexture that needs to be updated. The areas are marked in chunks.
- * The next time the GPUTexture is used these tiles will be refreshes. This saves time
- * when writing to the same place multiple times This happens for during foreground
- * rendering. */
void BKE_image_update_gputexture_delayed(
struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h)
{
@@ -946,7 +941,7 @@ void BKE_image_update_gputexture_delayed(
const int num_tiles_y = (end_tile_y + 1) - (start_tile_y);
const int num_tiles = num_tiles_x * num_tiles_y;
const bool allocate_on_heap = BLI_BITMAP_SIZE(num_tiles) > 16;
- BLI_bitmap *requested_tiles = NULL;
+ BLI_bitmap *requested_tiles = nullptr;
if (allocate_on_heap) {
requested_tiles = BLI_BITMAP_NEW(num_tiles, __func__);
}
@@ -976,7 +971,8 @@ void BKE_image_update_gputexture_delayed(
for (int tile_y = start_tile_y; tile_y <= end_tile_y; tile_y++) {
for (int tile_x = start_tile_x; tile_x <= end_tile_x; tile_x++) {
if (!BLI_BITMAP_TEST_BOOL(requested_tiles, tile_index)) {
- ImagePartialRefresh *area = MEM_mallocN(sizeof(ImagePartialRefresh), __func__);
+ ImagePartialRefresh *area = static_cast<ImagePartialRefresh *>(
+ MEM_mallocN(sizeof(ImagePartialRefresh), __func__));
area->tile_x = tile_x;
area->tile_y = tile_y;
BLI_addtail(&ima->gpu_refresh_areas, area);
@@ -991,10 +987,6 @@ void BKE_image_update_gputexture_delayed(
}
}
-/* these two functions are called on entering and exiting texture paint mode,
- * temporary disabling/enabling mipmapping on all images for quick texture
- * updates with glTexSubImage2D. images that didn't change don't have to be
- * re-uploaded to OpenGL */
void BKE_image_paint_set_mipmap(Main *bmain, bool mipmap)
{
LISTBASE_FOREACH (Image *, ima, &bmain->images) {
@@ -1005,7 +997,7 @@ void BKE_image_paint_set_mipmap(Main *bmain, bool mipmap)
for (int eye = 0; eye < 2; eye++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
GPUTexture *tex = ima->gputexture[a][eye][resolution];
- if (tex != NULL) {
+ if (tex != nullptr) {
GPU_texture_mipmap_mode(tex, mipmap, true);
}
}
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 26a1240080f..d87331fd65c 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -185,6 +185,7 @@ IDTypeInfo IDType_ID_IP = {
.name_plural = "ipos",
.translation_context = "",
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING | IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = NULL,
@@ -192,6 +193,7 @@ IDTypeInfo IDType_ID_IP = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = NULL,
@@ -2093,17 +2095,6 @@ static bool seq_convert_callback(Sequence *seq, void *userdata)
/* *************************************************** */
/* External API - Only Called from do_versions() */
-/* Called from do_versions() in readfile.c to convert the old 'IPO/adrcode' system
- * to the new 'Animato/RNA' system.
- *
- * The basic method used here, is to loop over data-blocks which have IPO-data,
- * and add those IPO's to new AnimData blocks as Actions.
- * Action/NLA data only works well for Objects, so these only need to be checked for there.
- *
- * Data that has been converted should be freed immediately, which means that it is immediately
- * clear which data-blocks have yet to be converted, and also prevent freeing errors when we exit.
- */
-/* XXX currently done after all file reading... */
void do_versions_ipos_to_animato(Main *bmain)
{
ListBase drivers = {NULL, NULL};
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index c09fcf0715e..ff199794ab3 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -213,6 +213,7 @@ IDTypeInfo IDType_ID_KE = {
.name_plural = "shape_keys",
.translation_context = BLT_I18NCONTEXT_ID_SHAPEKEY,
.flags = IDTYPE_FLAGS_NO_LIBLINKING,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = shapekey_copy_data,
@@ -220,6 +221,7 @@ IDTypeInfo IDType_ID_KE = {
.make_local = NULL,
.foreach_id = shapekey_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
/* A bit weird, due to shapekeys not being strictly speaking embedded data... But they also
* share a lot with those (non linkable, only ever used by one owner ID, etc.). */
.owner_get = shapekey_owner_get,
@@ -244,7 +246,6 @@ typedef struct WeightsArrayCache {
float **defgroup_weights;
} WeightsArrayCache;
-/** Free (or release) any data used by this shapekey (does not free the key itself). */
void BKE_key_free_data(Key *key)
{
shapekey_free_data(&key->id);
@@ -314,11 +315,6 @@ Key *BKE_key_add(Main *bmain, ID *id) /* common function */
return key;
}
-/**
- * Sort shape keys after a change.
- * This assumes that at most one key was moved,
- * which is a valid assumption for the places it's currently being called.
- */
void BKE_key_sort(Key *key)
{
KeyBlock *kb;
@@ -392,7 +388,6 @@ void key_curve_position_weights(float t, float data[4], int type)
}
}
-/* first derivative */
void key_curve_tangent_weights(float t, float data[4], int type)
{
float t2, fc;
@@ -431,7 +426,6 @@ void key_curve_tangent_weights(float t, float data[4], int type)
}
}
-/* second derivative */
void key_curve_normal_weights(float t, float data[4], int type)
{
float fc;
@@ -1522,7 +1516,6 @@ static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
}
}
-/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t arr_size)
{
Key *key = BKE_key_from_object(ob);
@@ -1624,9 +1617,6 @@ float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0);
}
-/**
- * \param shape_index: The index to use or all (when -1).
- */
int BKE_keyblock_element_count_from_shape(const Key *key, const int shape_index)
{
int result = 0;
@@ -1644,9 +1634,6 @@ int BKE_keyblock_element_count(const Key *key)
return BKE_keyblock_element_count_from_shape(key, -1);
}
-/**
- * \param shape_index: The index to use or all (when -1).
- */
size_t BKE_keyblock_element_calc_size_from_shape(const Key *key, const int shape_index)
{
return (size_t)BKE_keyblock_element_count_from_shape(key, shape_index) * key->elemsize;
@@ -1664,9 +1651,6 @@ size_t BKE_keyblock_element_calc_size(const Key *key)
* use #BKE_keyblock_element_calc_size to allocate the size of the data needed.
* \{ */
-/**
- * \param shape_index: The index to use or all (when -1).
- */
void BKE_keyblock_data_get_from_shape(const Key *key, float (*arr)[3], const int shape_index)
{
uint8_t *elements = (uint8_t *)arr;
@@ -1685,9 +1669,6 @@ void BKE_keyblock_data_get(const Key *key, float (*arr)[3])
BKE_keyblock_data_get_from_shape(key, arr, -1);
}
-/**
- * Set the data to all key-blocks (or shape_index if != -1).
- */
void BKE_keyblock_data_set_with_mat4(Key *key,
const int shape_index,
const float (*coords)[3],
@@ -1715,10 +1696,6 @@ void BKE_keyblock_data_set_with_mat4(Key *key,
}
}
-/**
- * Set the data for all key-blocks (or shape_index if != -1),
- * transforming by \a mat.
- */
void BKE_keyblock_curve_data_set_with_mat4(
Key *key, const ListBase *nurb, const int shape_index, const void *data, const float mat[4][4])
{
@@ -1734,9 +1711,6 @@ void BKE_keyblock_curve_data_set_with_mat4(
}
}
-/**
- * Set the data for all key-blocks (or shape_index if != -1).
- */
void BKE_keyblock_data_set(Key *key, const int shape_index, const void *data)
{
const uint8_t *elements = data;
@@ -1868,14 +1842,6 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name)
return kb;
}
-/**
- * \note sorting is a problematic side effect in some cases,
- * better only do this explicitly by having its own function,
- *
- * \param key: The key datablock to add to.
- * \param name: Optional name for the new keyblock.
- * \param do_force: always use ctime even for relative keys.
- */
KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force)
{
KeyBlock *kb = BKE_keyblock_add(key, name);
@@ -1904,7 +1870,6 @@ KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force
return kb;
}
-/* Only the active key-block. */
KeyBlock *BKE_keyblock_from_object(Object *ob)
{
Key *key = BKE_key_from_object(ob);
@@ -1928,7 +1893,6 @@ KeyBlock *BKE_keyblock_from_object_reference(Object *ob)
return NULL;
}
-/* get the appropriate KeyBlock given an index */
KeyBlock *BKE_keyblock_from_key(Key *key, int index)
{
if (key) {
@@ -1946,15 +1910,11 @@ KeyBlock *BKE_keyblock_from_key(Key *key, int index)
return NULL;
}
-/* get the appropriate KeyBlock given a name to search for */
KeyBlock *BKE_keyblock_find_name(Key *key, const char name[])
{
return BLI_findstring(&key->block, name, offsetof(KeyBlock, name));
}
-/**
- * \brief copy shape-key attributes, but not key data.or name/uid
- */
void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
{
kb_dst->pos = kb_src->pos;
@@ -1966,9 +1926,6 @@ void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
kb_dst->slidermax = kb_src->slidermax;
}
-/* Get RNA-Path for 'value' setting of the given ShapeKey
- * NOTE: the user needs to free the returned string once they're finish with it
- */
char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb)
{
PointerRNA ptr;
@@ -1991,6 +1948,7 @@ char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb)
/* conversion functions */
/************************* Lattice ************************/
+
void BKE_keyblock_update_from_lattice(Lattice *lt, KeyBlock *kb)
{
BPoint *bp;
@@ -2191,6 +2149,7 @@ void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nu
}
/************************* Mesh ************************/
+
void BKE_keyblock_update_from_mesh(Mesh *me, KeyBlock *kb)
{
MVert *mvert;
@@ -2243,15 +2202,6 @@ void BKE_keyblock_convert_to_mesh(KeyBlock *kb, Mesh *me)
}
}
-/**
- * Computes normals (vertices, polygons and/or loops ones) of given mesh for given shape key.
- *
- * \param kb: the KeyBlock to use to compute normals.
- * \param mesh: the Mesh to apply key-block to.
- * \param r_vertnors: if non-NULL, an array of vectors, same length as number of vertices.
- * \param r_polynors: if non-NULL, an array of vectors, same length as number of polygons.
- * \param r_loopnors: if non-NULL, an array of vectors, same length as number of loops.
- */
void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
struct Mesh *mesh,
float (*r_vertnors)[3],
@@ -2316,6 +2266,7 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
}
/************************* raw coords ************************/
+
void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
{
const float(*co)[3] = vertCos;
@@ -2469,6 +2420,7 @@ float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
}
/************************* raw coord offsets ************************/
+
void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, const float (*ofs)[3])
{
int a;
@@ -2506,15 +2458,6 @@ void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, const float (*ofs
/* ==========================================================*/
-/**
- * Move shape key from org_index to new_index. Safe, clamps index to valid range,
- * updates reference keys, the object's active shape index,
- * the 'frame' value in case of absolute keys, etc.
- * Note indices are expected in real values (not 'fake' shapenr +1 ones).
- *
- * \param org_index: if < 0, current object's active shape will be used as skey to move.
- * \return true if something was done, else false.
- */
bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
{
Key *key = BKE_key_from_object(ob);
@@ -2593,9 +2536,6 @@ bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
return true;
}
-/**
- * Check if given key-block (as index) is used as basis by others in given key.
- */
bool BKE_keyblock_is_basis(Key *key, const int index)
{
KeyBlock *kb;
diff --git a/source/blender/blenkernel/intern/keyconfig.c b/source/blender/blenkernel/intern/keyconfig.c
index d25f475c140..84e11c1166e 100644
--- a/source/blender/blenkernel/intern/keyconfig.c
+++ b/source/blender/blenkernel/intern/keyconfig.c
@@ -121,7 +121,6 @@ void BKE_keyconfig_pref_type_free(void)
/** \name Key-Config Versioning
* \{ */
-/* Set select mouse, for versioning code. */
void BKE_keyconfig_pref_set_select_mouse(UserDef *userdef, int value, bool override)
{
wmKeyConfigPref *kpt = BKE_keyconfig_pref_ensure(userdef, WM_KEYCONFIG_STR_DEFAULT);
@@ -201,10 +200,6 @@ void BKE_keyconfig_keymap_filter_item(wmKeyMap *keymap,
}
}
-/**
- * Filter & optionally remove key-map items,
- * intended for versioning, but may be used in other situations too.
- */
void BKE_keyconfig_pref_filter_items(struct UserDef *userdef,
const struct wmKeyConfigFilterItemParams *params,
bool (*filter_fn)(wmKeyMapItem *kmi, void *user_data),
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index a2da59bca58..af0d91d29fc 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -197,6 +197,7 @@ IDTypeInfo IDType_ID_LT = {
.name_plural = "lattices",
.translation_context = BLT_I18NCONTEXT_ID_LATTICE,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = lattice_init_data,
.copy_data = lattice_copy_data,
@@ -204,6 +205,7 @@ IDTypeInfo IDType_ID_LT = {
.make_local = NULL,
.foreach_id = lattice_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = lattice_blend_write,
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 6aa8e78c4f6..1484d35f28a 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -77,7 +77,9 @@ static const short g_base_collection_flags = (BASE_VISIBLE_DEPSGRAPH | BASE_VISI
/* prototype */
static void object_bases_iterator_next(BLI_Iterator *iter, const int flag);
-/*********************** Layer Collections and bases *************************/
+/* -------------------------------------------------------------------- */
+/** \name Layer Collections and Bases
+ * \{ */
static LayerCollection *layer_collection_add(ListBase *lb_parent, Collection *collection)
{
@@ -113,12 +115,14 @@ static Base *object_base_new(Object *ob)
return base;
}
-/********************************* View Layer ********************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Layer
+ * \{ */
/* RenderLayer */
-/* Returns the default view layer to view in workspaces if there is
- * none linked to the workspace yet. */
ViewLayer *BKE_view_layer_default_view(const Scene *scene)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -131,7 +135,6 @@ ViewLayer *BKE_view_layer_default_view(const Scene *scene)
return scene->view_layers.first;
}
-/* Returns the default view layer to render if we need to render just one. */
ViewLayer *BKE_view_layer_default_render(const Scene *scene)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -144,7 +147,6 @@ ViewLayer *BKE_view_layer_default_render(const Scene *scene)
return scene->view_layers.first;
}
-/* Returns view layer with matching name, or NULL if not found. */
ViewLayer *BKE_view_layer_find(const Scene *scene, const char *layer_name)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -156,11 +158,6 @@ ViewLayer *BKE_view_layer_find(const Scene *scene, const char *layer_name)
return NULL;
}
-/**
- * This is a placeholder to know which areas of the code need to be addressed
- * for the Workspace changes. Never use this, you should typically get the
- * active layer from the context or window.
- */
ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene)
{
BLI_assert(scene->view_layers.first);
@@ -198,10 +195,6 @@ static void layer_collection_exclude_all(LayerCollection *layer_collection)
}
}
-/**
- * Add a new view layer
- * by default, a view layer has the master collection
- */
ViewLayer *BKE_view_layer_add(Scene *scene,
const char *name,
ViewLayer *view_layer_source,
@@ -261,9 +254,6 @@ void BKE_view_layer_free(ViewLayer *view_layer)
BKE_view_layer_free_ex(view_layer, true);
}
-/**
- * Free (or release) any data used by this ViewLayer.
- */
void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
{
view_layer->basact = NULL;
@@ -304,9 +294,6 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
MEM_freeN(view_layer);
}
-/**
- * Tag all the selected objects of a render-layer.
- */
void BKE_view_layer_selected_objects_tag(ViewLayer *view_layer, const int tag)
{
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
@@ -332,13 +319,6 @@ static bool find_scene_collection_in_scene_collections(ListBase *lb, const Layer
return false;
}
-/**
- * Fallback for when a Scene has no camera to use
- *
- * \param view_layer: in general you want to use the same ViewLayer that is used
- * for depsgraph. If rendering you pass the scene active layer, when viewing in the viewport
- * you want to get ViewLayer from context.
- */
Object *BKE_view_layer_camera_find(ViewLayer *view_layer)
{
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
@@ -350,9 +330,6 @@ Object *BKE_view_layer_camera_find(ViewLayer *view_layer)
return NULL;
}
-/**
- * Find the ViewLayer a LayerCollection belongs to
- */
ViewLayer *BKE_view_layer_find_from_collection(const Scene *scene, LayerCollection *lc)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -422,7 +399,12 @@ void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, Bas
}
}
-/**************************** Copy View Layer and Layer Collections ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy View Layer and Layer Collections
+ * \{ */
+
static void layer_aov_copy_data(ViewLayer *view_layer_dst,
const ViewLayer *view_layer_src,
ListBase *aovs_dst,
@@ -471,11 +453,6 @@ static void layer_collections_copy_data(ViewLayer *view_layer_dst,
}
}
-/**
- * Only copy internal data of ViewLayer from source to already allocated/initialized destination.
- *
- * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
- */
void BKE_view_layer_copy_data(Scene *scene_dst,
const Scene *UNUSED(scene_src),
ViewLayer *view_layer_dst,
@@ -620,26 +597,17 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc)
return false;
}
-/**
- * Get the collection for a given index
- */
LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index)
{
int i = 0;
return collection_from_index(&view_layer->layer_collections, index, &i);
}
-/**
- * Get the active collection
- */
LayerCollection *BKE_layer_collection_get_active(ViewLayer *view_layer)
{
return view_layer->active_collection;
}
-/*
- * Activate collection
- */
bool BKE_layer_collection_activate(ViewLayer *view_layer, LayerCollection *lc)
{
if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
@@ -650,9 +618,6 @@ bool BKE_layer_collection_activate(ViewLayer *view_layer, LayerCollection *lc)
return true;
}
-/**
- * Activate first parent collection
- */
LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, LayerCollection *lc)
{
CollectionParent *parent = lc->collection->parents.first;
@@ -690,10 +655,6 @@ static int collection_count(const ListBase *lb)
return i;
}
-/**
- * Get the total number of collections
- * (including all the nested collections)
- */
int BKE_layer_collection_count(const ViewLayer *view_layer)
{
return collection_count(&view_layer->layer_collections);
@@ -721,16 +682,16 @@ static int index_from_collection(ListBase *lb, const LayerCollection *lc, int *i
return -1;
}
-/**
- * Return -1 if not found
- */
int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection *lc)
{
int i = 0;
return index_from_collection(&view_layer->layer_collections, lc, &i);
}
-/*********************************** Syncing *********************************
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Syncing
*
* The layer collection tree mirrors the scene collection tree. Whenever that
* changes we need to synchronize them so that there is a corresponding layer
@@ -740,9 +701,9 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection
*
* The view layer also contains a list of bases for each object that exists
* in at least one layer collection. That list is also synchronized here, and
- * stores state like selection. */
-
-/* This API allows to temporarily forbid resync of LayerCollections.
+ * stores state like selection.
+ *
+ * This API allows to temporarily forbid resync of LayerCollections.
*
* This can greatly improve performances in cases where those functions get
* called a lot (e.g. during massive remappings of IDs).
@@ -751,19 +712,20 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection
* code must ensures it resync LayerCollections before any UI/Event loop
* handling can happen.
*
- * WARNING: This is not threadsafe at all, only use from main thread.
+ * \warning This is not threadsafe at all, only use from main thread.
*
- * NOTE: It is probably needed to use #BKE_main_collection_sync_remap instead
+ * \note It is probably needed to use #BKE_main_collection_sync_remap instead
* of just #BKE_main_collection_sync after disabling LayerCollection resync,
* unless it is absolutely certain that no ID remapping (or any other process
* that may invalidate the caches) will happen while it is disabled.
*
- * NOTE: This is a quick and safe band-aid around the long-known issue
+ * \note This is a quick and safe band-aid around the long-known issue
* regarding this resync process.
* Proper fix would be to make resync itself lazy, i.e. only happen
* when actually needed.
* See also T73411.
- */
+ * \{ */
+
static bool no_resync = false;
void BKE_layer_collection_resync_forbid(void)
@@ -1220,11 +1182,6 @@ static bool view_layer_objects_base_cache_validate(ViewLayer *UNUSED(view_layer)
}
#endif
-/**
- * Update view layer collection tree from collections used in the scene.
- * This is used when collections are removed or added, both while editing
- * and on file loaded in case linked data changed or went missing.
- */
void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
{
if (no_resync) {
@@ -1377,14 +1334,12 @@ void BKE_main_collection_sync_remap(const Main *bmain)
BKE_main_collection_sync(bmain);
}
-/* ---------------------------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Selection
+ * \{ */
-/**
- * Select all the objects of this layer collection
- *
- * It also select the objects that are in nested collections.
- * \note Recursive
- */
bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection *lc, bool deselect)
{
if (lc->collection->flag & COLLECTION_HIDE_SELECT) {
@@ -1461,9 +1416,12 @@ bool BKE_layer_collection_has_layer_collection(LayerCollection *lc_parent,
return false;
}
-/* ---------------------------------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Visibility
+ * \{ */
-/* Update after toggling visibility of an object base. */
void BKE_base_set_visible(Scene *scene, ViewLayer *view_layer, Base *base, bool extend)
{
if (!extend) {
@@ -1536,6 +1494,12 @@ bool BKE_object_is_visible_in_viewport(const View3D *v3d, const struct Object *o
return true;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Collection Isolation & Local View
+ * \{ */
+
static void layer_collection_flag_set_recursive(LayerCollection *lc, const int flag)
{
lc->flag |= flag;
@@ -1552,14 +1516,6 @@ static void layer_collection_flag_unset_recursive(LayerCollection *lc, const int
}
}
-/**
- * Isolate the collection - hide all other collections but this one.
- * Make sure to show all the direct parents and all children of the layer collection as well.
- * When extending we simply show the collections and its direct family.
- *
- * If the collection or any of its parents is disabled, make it enabled.
- * Don't change the children disable state though.
- */
void BKE_layer_collection_isolate_global(Scene *scene,
ViewLayer *view_layer,
LayerCollection *lc,
@@ -1668,9 +1624,6 @@ void BKE_layer_collection_local_sync(ViewLayer *view_layer, const View3D *v3d)
}
}
-/**
- * Sync the local collection for all the 3D Viewports.
- */
void BKE_layer_collection_local_sync_all(const Main *bmain)
{
if (no_resync) {
@@ -1694,11 +1647,6 @@ void BKE_layer_collection_local_sync_all(const Main *bmain)
}
}
-/**
- * Isolate the collection locally
- *
- * Same as BKE_layer_collection_isolate_local but for a viewport
- */
void BKE_layer_collection_isolate_local(ViewLayer *view_layer,
const View3D *v3d,
LayerCollection *lc,
@@ -1771,11 +1719,6 @@ static void layer_collection_bases_hide_recursive(ViewLayer *view_layer, LayerCo
}
}
-/**
- * Hide/show all the elements of a collection.
- * Don't change the collection children enable/disable state,
- * but it may change it for the collection itself.
- */
void BKE_layer_collection_set_visible(ViewLayer *view_layer,
LayerCollection *lc,
const bool visible,
@@ -1862,9 +1805,6 @@ static LayerCollection *find_layer_collection_by_scene_collection(LayerCollectio
return NULL;
}
-/**
- * Return the first matching LayerCollection in the ViewLayer for the Collection.
- */
LayerCollection *BKE_layer_collection_first_from_scene_collection(const ViewLayer *view_layer,
const Collection *collection)
{
@@ -1878,17 +1818,11 @@ LayerCollection *BKE_layer_collection_first_from_scene_collection(const ViewLaye
return NULL;
}
-/**
- * See if view layer has the scene collection linked directly, or indirectly (nested)
- */
bool BKE_view_layer_has_collection(const ViewLayer *view_layer, const Collection *collection)
{
return BKE_layer_collection_first_from_scene_collection(view_layer, collection) != NULL;
}
-/**
- * See if the object is in any of the scene layers of the scene
- */
bool BKE_scene_has_object(Scene *scene, Object *ob)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -1999,6 +1933,8 @@ static void objects_iterator_end(BLI_Iterator *iter)
object_bases_iterator_end(iter);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name BKE_view_layer_selected_objects_iterator
* See: #FOREACH_SELECTED_OBJECT_BEGIN
@@ -2188,11 +2124,10 @@ void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *UNUSED(iter))
/** \} */
-/* Evaluation. */
+/* -------------------------------------------------------------------- */
+/** \name Evaluation
+ * \{ */
-/* Applies object's restrict flags on top of flags coming from the collection
- * and stores those in base->flag. BASE_VISIBLE_DEPSGRAPH ignores viewport flags visibility
- * (i.e., restriction and local collection). */
void BKE_base_eval_flags(Base *base)
{
/* Apply collection flags. */
@@ -2251,6 +2186,12 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph,
layer_eval_view_layer(depsgraph, scene, view_layer);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend File I/O
+ * \{ */
+
static void write_layer_collections(BlendWriter *writer, ListBase *lb)
{
LISTBASE_FOREACH (LayerCollection *, lc, lb) {
@@ -2371,6 +2312,8 @@ void BKE_view_layer_blend_read_lib(BlendLibReader *reader, Library *lib, ViewLay
IDP_BlendReadLib(reader, view_layer->id_properties);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Shader AOV
* \{ */
@@ -2455,12 +2398,6 @@ static void bke_view_layer_verify_aov_cb(void *userdata,
}
}
-/* Update the naming and conflicts of the AOVs.
- *
- * Name must be unique between all AOVs.
- * Conflicts with render passes will show a conflict icon. Reason is that switching a render
- * engine or activating a render pass could lead to other conflicts that wouldn't be that clear
- * for the user. */
void BKE_view_layer_verify_aov(struct RenderEngine *engine,
struct Scene *scene,
struct ViewLayer *view_layer)
@@ -2478,7 +2415,6 @@ void BKE_view_layer_verify_aov(struct RenderEngine *engine,
BLI_ghash_free(name_count, MEM_freeN, NULL);
}
-/* Check if the given view layer has at least one valid AOV. */
bool BKE_view_layer_has_valid_aov(ViewLayer *view_layer)
{
LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
diff --git a/source/blender/blenkernel/intern/layer_utils.c b/source/blender/blenkernel/intern/layer_utils.c
index 48179e0c3bf..3760fe8a976 100644
--- a/source/blender/blenkernel/intern/layer_utils.c
+++ b/source/blender/blenkernel/intern/layer_utils.c
@@ -193,13 +193,6 @@ bool BKE_view_layer_filter_edit_mesh_has_edges(const Object *ob, void *UNUSED(us
return false;
}
-/**
- * Use this in rare cases we need to detect a pair of objects (active, selected).
- * This returns the other non-active selected object.
- *
- * Returns NULL with it finds multiple other selected objects
- * as behavior in this case would be random from the user perspective.
- */
Object *BKE_view_layer_non_active_selected_object(struct ViewLayer *view_layer,
const struct View3D *v3d)
{
@@ -221,4 +214,5 @@ Object *BKE_view_layer_non_active_selected_object(struct ViewLayer *view_layer,
FOREACH_SELECTED_OBJECT_END;
return ob_result;
}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index cd5b266eb75..692e27731c5 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -89,7 +89,6 @@
static CLG_LogRef LOG = {.identifier = "bke.lib_id"};
-/* Empty shell mostly, but needed for read code. */
IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
.id_code = ID_LINK_PLACEHOLDER,
.id_filter = 0,
@@ -99,6 +98,7 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
.name_plural = "link_placeholders",
.translation_context = BLT_I18NCONTEXT_ID_ID,
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = NULL,
@@ -106,6 +106,8 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = NULL,
+ .owner_get = NULL,
.blend_write = NULL,
.blend_read_data = NULL,
@@ -124,18 +126,56 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
/* ************* general ************************ */
/**
+ * Rewrites a relative path to be relative to the main file - unless the path is
+ * absolute, in which case it is not altered.
+ */
+static bool lib_id_library_local_paths_callback(BPathForeachPathData *bpath_data,
+ char *r_path_dst,
+ const char *path_src)
+{
+ const char **data = bpath_data->user_data;
+ /* be sure there is low chance of the path being too short */
+ char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
+ const char *base_new = data[0];
+ const char *base_old = data[1];
+
+ if (BLI_path_is_rel(base_old)) {
+ CLOG_ERROR(&LOG, "old base path '%s' is not absolute.", base_old);
+ return false;
+ }
+
+ /* Make referenced file absolute. This would be a side-effect of
+ * BLI_path_normalize, but we do it explicitly so we know if it changed. */
+ BLI_strncpy(filepath, path_src, FILE_MAX);
+ if (BLI_path_abs(filepath, base_old)) {
+ /* Path was relative and is now absolute. Remap.
+ * Important BLI_path_normalize runs before the path is made relative
+ * because it won't work for paths that start with "//../" */
+ BLI_path_normalize(base_new, filepath);
+ BLI_path_rel(filepath, base_new);
+ BLI_strncpy(r_path_dst, filepath, FILE_MAX);
+ return true;
+ }
+
+ /* Path was not relative to begin with. */
+ return false;
+}
+
+/**
* This has to be called from each make_local_* func, we could call from BKE_lib_id_make_local()
* but then the make local functions would not be self contained.
* Also note that the id _must_ have a library - campbell */
+/* TODO: This can probably be replaced by an ID-level version of #BKE_bpath_relative_rebase. */
static void lib_id_library_local_paths(Main *bmain, Library *lib, ID *id)
{
const char *bpath_user_data[2] = {BKE_main_blendfile_path(bmain), lib->filepath_abs};
- BKE_bpath_traverse_id(bmain,
- id,
- BKE_bpath_relocate_visitor,
- BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
- (void *)bpath_user_data);
+ BKE_bpath_foreach_path_id(
+ &(BPathForeachPathData){.bmain = bmain,
+ .callback_function = lib_id_library_local_paths_callback,
+ .flag = BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE,
+ .user_data = (void *)bpath_user_data},
+ id);
}
static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *cb_data)
@@ -149,12 +189,6 @@ static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *
return IDWALK_RET_NOP;
}
-/**
- * Pull an ID out of a library (make it local). Only call this for IDs that
- * don't have other library users.
- *
- * \param flags Same set of `LIB_ID_MAKELOCAL_` flags as passed to `BKE_lib_id_make_local`.
- */
void BKE_lib_id_clear_library_data(Main *bmain, ID *id, const int flags)
{
const bool id_in_mainlist = (id->tag & LIB_TAG_NO_MAIN) == 0 &&
@@ -179,8 +213,14 @@ void BKE_lib_id_clear_library_data(Main *bmain, ID *id, const int flags)
BKE_lib_libblock_session_uuid_renew(id);
}
- if ((flags & LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR) != 0 && id->asset_data != NULL) {
- BKE_asset_metadata_free(&id->asset_data);
+ if (ID_IS_ASSET(id)) {
+ if ((flags & LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR) != 0) {
+ BKE_asset_metadata_free(&id->asset_data);
+ }
+ else {
+ /* Assets should always have a fake user. Ensure this is the case after "Make Local". */
+ id_fake_user_set(id);
+ }
}
/* We need to tag this IDs and all of its users, conceptually new local ID and original linked
@@ -228,14 +268,6 @@ void id_lib_indirect_weak_link(ID *id)
}
}
-/**
- * Ensure we have a real user
- *
- * \note Now that we have flags, we could get rid of the 'fake_user' special case,
- * flags are enough to ensure we always have a real user.
- * However, #ID_REAL_USERS is used in several places outside of core lib.c,
- * so think we can wait later to make this change.
- */
void id_us_ensure_real(ID *id)
{
if (id) {
@@ -266,10 +298,6 @@ void id_us_clear_real(ID *id)
}
}
-/**
- * Same as \a id_us_plus, but does not handle lib indirect -> extern.
- * Only used by readfile.c so far, but simpler/safer to keep it here nonetheless.
- */
void id_us_plus_no_lib(ID *id)
{
if (id) {
@@ -294,7 +322,6 @@ void id_us_plus(ID *id)
}
}
-/* decrements the user count for *id. */
void id_us_min(ID *id)
{
if (id) {
@@ -410,10 +437,6 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
return IDWALK_RET_NOP;
}
-/**
- * Expand ID usages of given id as 'extern' (and no more indirect) linked data.
- * Used by ID copy/make_local functions.
- */
void BKE_lib_id_expand_local(Main *bmain, ID *id, const int flags)
{
BKE_library_foreach_ID_link(
@@ -431,9 +454,6 @@ static void lib_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id,
}
}
-/**
- * Generic 'make local' function, works for most of data-block types...
- */
void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
{
if (!ID_IS_LINKED(id)) {
@@ -503,15 +523,6 @@ void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
}
}
-/**
- * Calls the appropriate make_local method for the block, unless test is set.
- *
- * \note Always set #ID.newid pointer in case it gets duplicated.
- *
- * \param flags: Special flag used when making a whole library's content local,
- * it needs specific handling.
- * \return true is the ID has successfully been made local.
- */
bool BKE_lib_id_make_local(Main *bmain, ID *id, const int flags)
{
const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
@@ -586,27 +597,6 @@ bool BKE_id_copy_is_allowed(const ID *id)
#undef LIB_ID_TYPES_NOCOPY
}
-/**
- * Generic entry point for copying a data-block (new API).
- *
- * \note Copy is generally only affecting the given data-block
- * (no ID used by copied one will be affected, besides usercount).
- * There are exceptions though:
- * - Embedded IDs (root node trees and master collections) are always copied with their owner.
- * - If #LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated.
- * - If #LIB_ID_COPY_SHAPEKEY is defined, shapekeys will be duplicated.
- * - If #LIB_ID_CREATE_LOCAL is defined, root node trees will be deep-duplicated recursively.
- *
- * \note Usercount of new copy is always set to 1.
- *
- * \param bmain: Main database, may be NULL only if LIB_ID_CREATE_NO_MAIN is specified.
- * \param id: Source data-block.
- * \param r_newid: Pointer to new (copied) ID pointer, may be NULL. Used to allow copying into
- * already allocated memory.
- * \param flag: Set of copy options, see DNA_ID.h enum for details (leave to zero for default,
- * full copy).
- * \return NULL when copying that ID type is not supported, the new copy otherwise.
- */
ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
{
ID *newid = (r_newid != NULL) ? *r_newid : NULL;
@@ -669,19 +659,11 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
return newid;
}
-/**
- * Invokes the appropriate copy method for the block and returns the result in
- * newid, unless test. Returns true if the block can be copied.
- */
ID *BKE_id_copy(Main *bmain, const ID *id)
{
return BKE_id_copy_ex(bmain, id, NULL, LIB_ID_COPY_DEFAULT);
}
-/**
- * Invokes the appropriate copy method for the block and returns the result in
- * newid, unless test. Returns true if the block can be copied.
- */
ID *BKE_id_copy_for_duplicate(Main *bmain,
ID *id,
const eDupli_ID_Flags duplicate_flags,
@@ -762,31 +744,16 @@ static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id)
}
}
-/**
- * Does a mere memory swap over the whole IDs data (including type-specific memory).
- * \note Most internal ID data itself is not swapped (only IDProperties are).
- *
- * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to
- * itself.
- */
void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b)
{
id_swap(bmain, id_a, id_b, false);
}
-/**
- * Does a mere memory swap over the whole IDs data (including type-specific memory).
- * \note All internal ID data itself is also swapped.
- *
- * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to
- * itself.
- */
void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b)
{
id_swap(bmain, id_a, id_b, true);
}
-/** Does *not* set ID->newid pointer. */
bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
{
ID *newid = NULL;
@@ -851,7 +818,6 @@ static int libblock_management_us_min(LibraryIDLinkCallbackData *cb_data)
return IDWALK_RET_NOP;
}
-/** Add a 'NO_MAIN' data-block to given main (also sets usercounts of its IDs if needed). */
void BKE_libblock_management_main_add(Main *bmain, void *idv)
{
ID *id = idv;
@@ -885,7 +851,6 @@ void BKE_libblock_management_main_add(Main *bmain, void *idv)
BKE_lib_libblock_session_uuid_ensure(id);
}
-/** Remove a data-block from given main (set it to 'NO_MAIN' status). */
void BKE_libblock_management_main_remove(Main *bmain, void *idv)
{
ID *id = idv;
@@ -930,9 +895,6 @@ void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv)
id->tag |= LIB_TAG_NO_USER_REFCOUNT;
}
-/**
- * Clear or set given tags for all ids in listbase (runtime tags).
- */
void BKE_main_id_tag_listbase(ListBase *lb, const int tag, const bool value)
{
ID *id;
@@ -949,9 +911,6 @@ void BKE_main_id_tag_listbase(ListBase *lb, const int tag, const bool value)
}
}
-/**
- * Clear or set given tags for all ids of given type in bmain (runtime tags).
- */
void BKE_main_id_tag_idcode(struct Main *mainvar,
const short type,
const int tag,
@@ -962,9 +921,6 @@ void BKE_main_id_tag_idcode(struct Main *mainvar,
BKE_main_id_tag_listbase(lb, tag, value);
}
-/**
- * Clear or set given tags for all ids in bmain (runtime tags).
- */
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
{
ListBase *lbarray[INDEX_ID_MAX];
@@ -976,9 +932,6 @@ void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
}
}
-/**
- * Clear or set given flags for all ids in listbase (persistent flags).
- */
void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value)
{
ID *id;
@@ -995,9 +948,6 @@ void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value)
}
}
-/**
- * Clear or set given flags for all ids in bmain (persistent flags).
- */
void BKE_main_id_flag_all(Main *bmain, const int flag, const bool value)
{
ListBase *lbarray[INDEX_ID_MAX];
@@ -1063,9 +1013,6 @@ void BKE_main_lib_objects_recalc_all(Main *bmain)
*
* **************************** */
-/**
- * Get allocation size of a given data-block type and optionally allocation name.
- */
size_t BKE_libblock_get_alloc_info(short type, const char **name)
{
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(type);
@@ -1083,10 +1030,6 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
return id_type->struct_size;
}
-/**
- * Allocates and returns memory of the right size for the specified block type,
- * initialized to zero.
- */
void *BKE_libblock_alloc_notest(short type)
{
const char *name;
@@ -1098,12 +1041,6 @@ void *BKE_libblock_alloc_notest(short type)
return NULL;
}
-/**
- * Allocates and returns a block of the specified type, with the specified name
- * (adjusted as necessary to ensure uniqueness), and appended to the specified list.
- * The user count is set to 1, all other content (apart from name and links) being
- * initialized to zero.
- */
void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
{
BLI_assert((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
@@ -1166,10 +1103,6 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
return id;
}
-/**
- * Initialize an ID of given type, such that it has valid 'empty' data.
- * ID is assumed to be just calloc'ed.
- */
void BKE_libblock_init_empty(ID *id)
{
const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
@@ -1187,12 +1120,6 @@ void BKE_libblock_init_empty(ID *id)
/* ********** ID session-wise UUID management. ********** */
static uint global_session_uuid = 0;
-/**
- * Generate a session-wise uuid for the given \a id.
- *
- * \note "session-wise" here means while editing a given .blend file. Once a new .blend file is
- * loaded or created, undo history is cleared/reset, and so is the uuid counter.
- */
void BKE_lib_libblock_session_uuid_ensure(ID *id)
{
if (id->session_uuid == MAIN_ID_SESSION_UUID_UNSET) {
@@ -1206,25 +1133,12 @@ void BKE_lib_libblock_session_uuid_ensure(ID *id)
}
}
-/**
- * Re-generate a new session-wise uuid for the given \a id.
- *
- * \warning This has a few very specific use-cases, no other usage is expected currently:
- * - To handle UI-related data-blocks that are kept across new file reading, when we do keep
- * existing UI.
- * - For IDs that are made local without needing any copying.
- */
void BKE_lib_libblock_session_uuid_renew(ID *id)
{
id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
BKE_lib_libblock_session_uuid_ensure(id);
}
-/**
- * Generic helper to create a new empty data-block of given type in given \a bmain database.
- *
- * \param name: can be NULL, in which case we get default name for this ID type.
- */
void *BKE_id_new(Main *bmain, const short type, const char *name)
{
BLI_assert(bmain != NULL);
@@ -1239,11 +1153,6 @@ void *BKE_id_new(Main *bmain, const short type, const char *name)
return id;
}
-/**
- * Generic helper to create a new temporary empty data-block of given type,
- * *outside* of any Main database.
- *
- * \param name: can be NULL, in which case we get default name for this ID type. */
void *BKE_id_new_nomain(const short type, const char *name)
{
if (name == NULL) {
@@ -1357,7 +1266,6 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
*r_newid = new_id;
}
-/* used everywhere in blenkernel */
void *BKE_libblock_copy(Main *bmain, const ID *id)
{
ID *idn;
@@ -1368,6 +1276,7 @@ void *BKE_libblock_copy(Main *bmain, const ID *id)
}
/* ***************** ID ************************ */
+
ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *name)
{
ListBase *lb = which_libbase(bmain, type);
@@ -1389,14 +1298,6 @@ struct ID *BKE_libblock_find_session_uuid(Main *bmain,
return NULL;
}
-/**
- * Sort given \a id into given \a lb list, using case-insensitive comparison of the id names.
- *
- * \note All other IDs beside given one are assumed already properly sorted in the list.
- *
- * \param id_sorting_hint: Ignored if NULL. Otherwise, used to check if we can insert \a id
- * immediately before or after that pointer. It must always be into given \a lb list.
- */
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
{
#define ID_SORT_STEP_SIZE 512
@@ -1754,16 +1655,6 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
#undef MIN_NUMBER
#undef MAX_NUMBER
-/**
- * Ensures given ID has a unique name in given listbase.
- *
- * Only for local IDs (linked ones already have a unique ID in their library).
- *
- * \param do_linked_data: if true, also ensure a unique name in case the given \a id is linked
- * (otherwise, just ensure that it is properly sorted).
- *
- * \return true if a new name had to be created.
- */
bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname, const bool do_linked_data)
{
bool result = false;
@@ -1813,7 +1704,6 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname, const boo
return result;
}
-/* next to indirect usage in read/writefile also in editobject.c scene.c */
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
{
ID *id;
@@ -1936,30 +1826,20 @@ static void library_make_local_copying_check(ID *id,
BLI_gset_remove(loop_tags, id, NULL);
}
-/**
- * Make linked data-blocks local.
- *
- * \param bmain: Almost certainly global main.
- * \param lib: If not NULL, only make local data-blocks from this library.
- * \param untagged_only: If true, only make local data-blocks not tagged with
- * LIB_TAG_PRE_EXISTING.
- * \param set_fake: If true, set fake user on all localized data-blocks
- * (except group and objects ones).
- */
/* NOTE: Old (2.77) version was simply making (tagging) data-blocks as local,
* without actually making any check whether they were also indirectly used or not...
*
* Current version uses regular id_make_local callback, with advanced pre-processing step to
* detect all cases of IDs currently indirectly used, but which will be used by local data only
* once this function is finished. This allows to avoid any unneeded duplication of IDs, and
- * hence all time lost afterwards to remove orphaned linked data-blocks...
- */
+ * hence all time lost afterwards to remove orphaned linked data-blocks. */
void BKE_library_make_local(Main *bmain,
const Library *lib,
GHash *old_to_new_ids,
const bool untagged_only,
const bool set_fake)
{
+
ListBase *lbarray[INDEX_ID_MAX];
LinkNode *todo_ids = NULL;
@@ -2233,10 +2113,6 @@ void BKE_library_make_local(Main *bmain,
#endif
}
-/**
- * Use after setting the ID's name
- * When name exists: call 'new_id'
- */
void BLI_libblock_ensure_unique_name(Main *bmain, const char *name)
{
ListBase *lb;
@@ -2256,9 +2132,6 @@ void BLI_libblock_ensure_unique_name(Main *bmain, const char *name)
}
}
-/**
- * Sets the name of a block to name, suitably adjusted for uniqueness.
- */
void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
{
BLI_assert(!ID_IS_LINKED(id));
@@ -2268,16 +2141,6 @@ void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
}
}
-/**
- * Generate full name of the data-block (without ID code, but with library if any).
- *
- * \note Result is unique to a given ID type in a given Main database.
- *
- * \param name: An allocated string of minimal length #MAX_ID_FULL_NAME,
- * will be filled with generated string.
- * \param separator_char: Character to use for separating name and library name. Can be 0 to use
- * default (' ').
- */
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separator_char)
{
strcpy(name, id->name + 2);
@@ -2294,19 +2157,6 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa
}
}
-/**
- * Generate full name of the data-block (without ID code, but with library if any),
- * with a 2 to 3 character prefix prepended indicating whether it comes from a library,
- * is overriding, has a fake or no user, etc.
- *
- * \note Result is unique to a given ID type in a given Main database.
- *
- * \param name: An allocated string of minimal length #MAX_ID_FULL_NAME_UI,
- * will be filled with generated string.
- * \param separator_char: Character to use for separating name and library name. Can be 0 to use
- * default (' ').
- * \param r_prefix_len: The length of the prefix added.
- */
void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI],
const ID *id,
const bool add_lib_hint,
@@ -2328,11 +2178,6 @@ void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI],
}
}
-/**
- * Generate a concatenation of ID name (including two-chars type code) and its lib name, if any.
- *
- * \return A unique allocated string key for any ID in the whole Main database.
- */
char *BKE_id_to_unique_string_key(const struct ID *id)
{
if (!ID_IS_LINKED(id)) {
@@ -2356,10 +2201,6 @@ void BKE_id_tag_clear_atomic(ID *id, int tag)
atomic_fetch_and_and_int32(&id->tag, ~tag);
}
-/**
- * Check that given ID pointer actually is in G_MAIN.
- * Main intended use is for debug asserts in places we cannot easily get rid of G_Main...
- */
bool BKE_id_is_in_global_main(ID *id)
{
/* We do not want to fail when id is NULL here, even though this is a bit strange behavior...
@@ -2406,10 +2247,6 @@ static int id_order_compare(const void *a, const void *b)
return strcmp(id_a->name, id_b->name);
}
-/**
- * Returns ordered list of data-blocks for display in the UI.
- * Result is list of LinkData of IDs that must be freed.
- */
void BKE_id_ordered_list(ListBase *ordered_lb, const ListBase *lb)
{
BLI_listbase_clear(ordered_lb);
@@ -2429,9 +2266,6 @@ void BKE_id_ordered_list(ListBase *ordered_lb, const ListBase *lb)
}
}
-/**
- * Reorder ID in the list, before or after the "relative" ID.
- */
void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after)
{
int *id_order = id_order_get(id);
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index 502a1197616..1922a54addb 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -90,23 +90,6 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
BLI_assert_msg(0, "IDType Missing IDTypeInfo");
}
-/**
- * Complete ID freeing, extended version for corner cases.
- * Can override default (and safe!) freeing process, to gain some speed up.
- *
- * At that point, given id is assumed to not be used by any other data-block already
- * (might not be actually true, in case e.g. several inter-related IDs get freed together...).
- * However, they might still be using (referencing) other IDs, this code takes care of it if
- * #LIB_TAG_NO_USER_REFCOUNT is not defined.
- *
- * \param bmain: #Main database containing the freed #ID,
- * can be NULL in case it's a temp ID outside of any #Main.
- * \param idv: Pointer to ID to be freed.
- * \param flag: Set of \a LIB_ID_FREE_... flags controlling/overriding usual freeing process,
- * 0 to get default safe behavior.
- * \param use_flag_from_idtag: Still use freeing info flags from given #ID datablock,
- * even if some overriding ones are passed in \a flag parameter.
- */
void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
{
ID *id = idv;
@@ -191,24 +174,11 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
}
}
-/**
- * Complete ID freeing, should be usable in most cases (even for out-of-Main IDs).
- *
- * See #BKE_id_free_ex description for full details.
- *
- * \param bmain: Main database containing the freed ID,
- * can be NULL in case it's a temp ID outside of any Main.
- * \param idv: Pointer to ID to be freed.
- */
void BKE_id_free(Main *bmain, void *idv)
{
BKE_id_free_ex(bmain, idv, 0, true);
}
-/**
- * Not really a freeing function by itself,
- * it decrements usercount of given id, and only frees it if it reaches 0.
- */
void BKE_id_free_us(Main *bmain, void *idv) /* test users */
{
ID *id = idv;
@@ -378,9 +348,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
return num_datablocks_deleted;
}
-/**
- * Properly delete a single ID from given \a bmain database.
- */
void BKE_id_delete(Main *bmain, void *idv)
{
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
@@ -389,16 +356,6 @@ void BKE_id_delete(Main *bmain, void *idv)
id_delete(bmain, false);
}
-/**
- * Properly delete all IDs tagged with \a LIB_TAG_DOIT, in given \a bmain database.
- *
- * This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
- * (several times faster when deleting most of the IDs at once)...
- *
- * \warning Considered experimental for now, seems to be working OK but this is
- * risky code in a complicated area.
- * \return Number of deleted datablocks.
- */
size_t BKE_id_multi_tagged_delete(Main *bmain)
{
return id_delete(bmain, true);
@@ -408,12 +365,6 @@ size_t BKE_id_multi_tagged_delete(Main *bmain)
/** \name Python Data Handling
* \{ */
-/**
- * In most cases #BKE_id_free_ex handles this, when lower level functions are called directly
- * this function will need to be called too, if Python has access to the data.
- *
- * ID data-blocks such as #Material.nodetree are not stored in #Main.
- */
void BKE_libblock_free_data_py(ID *id)
{
#ifdef WITH_PYTHON
diff --git a/source/blender/blenkernel/intern/lib_id_eval.c b/source/blender/blenkernel/intern/lib_id_eval.c
index 140fe403ac3..a29d9270d72 100644
--- a/source/blender/blenkernel/intern/lib_id_eval.c
+++ b/source/blender/blenkernel/intern/lib_id_eval.c
@@ -29,11 +29,6 @@
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
-/**
- * Copy relatives parameters, from `id` to `id_cow`.
- * Use handle the #ID_RECALC_PARAMETERS tag.
- * \note Keep in sync with #ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW.
- */
void BKE_id_eval_properties_copy(ID *id_cow, ID *id)
{
const ID_Type id_type = GS(id->name);
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 66a550ec6b0..83ed0ee4c08 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -57,6 +57,7 @@
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
+#include "BLI_memarena.h"
#include "BLI_string.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
@@ -99,7 +100,6 @@ BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id)
return id->override_library;
}
-/** Initialize empty overriding of \a reference_id by \a local_id. */
IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id)
{
/* If reference_id is NULL, we are creating an override template for purely local data.
@@ -134,7 +134,6 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id)
return local_id->override_library;
}
-/** Shalow or deep copy of a whole override from \a src_id to \a dst_id. */
void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_full_copy)
{
BLI_assert(ID_IS_OVERRIDE_LIBRARY(src_id) || ID_IS_OVERRIDE_LIBRARY_TEMPLATE(src_id));
@@ -176,7 +175,6 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_f
dst_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK;
}
-/** Clear any overriding data from given \a override. */
void BKE_lib_override_library_clear(IDOverrideLibrary *override, const bool do_id_user)
{
BLI_assert(override != NULL);
@@ -196,7 +194,6 @@ void BKE_lib_override_library_clear(IDOverrideLibrary *override, const bool do_i
}
}
-/** Free given \a override. */
void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user)
{
BLI_assert(*override != NULL);
@@ -245,14 +242,11 @@ static ID *lib_override_library_create_from(Main *bmain,
return local_id;
}
-/**
- * Check if given ID has some override rules that actually indicate the user edited it.
- *
- * TODO: This could be simplified by storing a flag in #IDOverrideLibrary during the diffing
- * process?
- */
+/* TODO: This could be simplified by storing a flag in #IDOverrideLibrary
+ * during the diffing process? */
bool BKE_lib_override_library_is_user_edited(struct ID *id)
{
+
if (!ID_IS_OVERRIDE_LIBRARY(id)) {
return false;
}
@@ -280,7 +274,6 @@ bool BKE_lib_override_library_is_user_edited(struct ID *id)
return false;
}
-/** Create an overridden local copy of linked reference. */
ID *BKE_lib_override_library_create_from_id(Main *bmain,
ID *reference_id,
const bool do_tagged_remap)
@@ -322,25 +315,6 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
return local_id;
}
-/**
- * Create overridden local copies of all tagged data-blocks in given Main.
- *
- * \note Set `id->newid` of overridden libs with newly created overrides,
- * caller is responsible to clean those pointers before/after usage as needed.
- *
- * \note By default, it will only remap newly created local overriding data-blocks between
- * themselves, to avoid 'enforcing' those overrides into all other usages of the linked data in
- * main. You can add more local IDs to be remapped to use new overriding ones by setting their
- * LIB_TAG_DOIT tag.
- *
- * \param reference_library: the library from which the linked data being overridden come from
- * (i.e. the library of the linked reference ID).
- *
- * \param do_no_main: Create the new override data outside of Main database.
- * Used for resyncing of linked overrides.
- *
- * \return \a true on success, \a false otherwise.
- */
bool BKE_lib_override_library_create_from_tag(Main *bmain,
const Library *reference_library,
const bool do_no_main)
@@ -479,8 +453,59 @@ typedef struct LibOverrideGroupTagData {
bool is_override;
/* Whether we are creating new override, or resyncing existing one. */
bool is_resync;
+
+ /* Mapping linked objects to all their instantiating collections (as a linked list).
+ * Avoids calling #BKE_collection_object_find over and over, this function is very expansive. */
+ GHash *linked_object_to_instantiating_collections;
+ MemArena *mem_arena;
} LibOverrideGroupTagData;
+static void lib_override_group_tag_data_object_to_collection_init_collection_process(
+ LibOverrideGroupTagData *data, Collection *collection)
+{
+ LISTBASE_FOREACH (CollectionObject *, collection_object, &collection->gobject) {
+ Object *ob = collection_object->ob;
+ if (!ID_IS_LINKED(ob)) {
+ continue;
+ }
+
+ LinkNodePair **collections_linkedlist_p;
+ if (!BLI_ghash_ensure_p(
+ data->linked_object_to_instantiating_collections, ob, &collections_linkedlist_p)) {
+ *collections_linkedlist_p = BLI_memarena_calloc(data->mem_arena,
+ sizeof(**collections_linkedlist_p));
+ }
+ BLI_linklist_append_arena(*collections_linkedlist_p, collection, data->mem_arena);
+ }
+}
+
+/* Initialize complex data, `data` is expected to be already initialized with basic pointers and
+ * other simple data.
+ *
+ * NOTE: Currently creates a mapping from linked object to all of their instantiating collections
+ * (as returned by #BKE_collection_object_find). */
+static void lib_override_group_tag_data_object_to_collection_init(LibOverrideGroupTagData *data)
+{
+ data->mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ data->linked_object_to_instantiating_collections = BLI_ghash_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ if (data->scene != NULL) {
+ lib_override_group_tag_data_object_to_collection_init_collection_process(
+ data, data->scene->master_collection);
+ }
+ LISTBASE_FOREACH (Collection *, collection, &data->bmain->collections) {
+ lib_override_group_tag_data_object_to_collection_init_collection_process(data, collection);
+ }
+}
+
+static void lib_override_group_tag_data_clear(LibOverrideGroupTagData *data)
+{
+ BLI_ghash_free(data->linked_object_to_instantiating_collections, NULL, NULL);
+ BLI_memarena_free(data->mem_arena);
+ memset(data, 0, sizeof(*data));
+}
+
/* Tag all IDs in dependency relationships within an override hierarchy/group.
*
* Requires existing `Main.relations`.
@@ -599,7 +624,6 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat
static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
{
Main *bmain = data->bmain;
- Scene *scene = data->scene;
ID *id_root = data->id_root;
const bool is_resync = data->is_resync;
BLI_assert(!data->is_override);
@@ -637,18 +661,26 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
Collection *instantiating_collection_override_candidate = NULL;
/* Loop over all collections instantiating the object, if we already have a 'locale' one we
* have nothing to do, otherwise try to find a 'linked' one that we can override too. */
- while ((instantiating_collection = BKE_collection_object_find(
- bmain, scene, instantiating_collection, ob)) != NULL) {
- /* In (recursive) resync case, if a collection of a 'parent' lib instantiates the linked
- * object, it is also fine. */
- if (!ID_IS_LINKED(instantiating_collection) ||
- (is_resync && ID_IS_LINKED(id_root) &&
- instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) {
- break;
- }
- if (ID_IS_LINKED(instantiating_collection) &&
- (!is_resync || instantiating_collection->id.lib == id_root->lib)) {
- instantiating_collection_override_candidate = instantiating_collection;
+ LinkNodePair *instantiating_collection_linklist = BLI_ghash_lookup(
+ data->linked_object_to_instantiating_collections, ob);
+ if (instantiating_collection_linklist != NULL) {
+ for (LinkNode *instantiating_collection_linknode =
+ instantiating_collection_linklist->list;
+ instantiating_collection_linknode != NULL;
+ instantiating_collection_linknode = instantiating_collection_linknode->next) {
+ instantiating_collection = instantiating_collection_linknode->link;
+ /* In (recursive) resync case, if a collection of a 'parent' lib instantiates the
+ * linked object, it is also fine. */
+ if (!ID_IS_LINKED(instantiating_collection) ||
+ (is_resync && ID_IS_LINKED(id_root) &&
+ instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) {
+ break;
+ }
+ if (ID_IS_LINKED(instantiating_collection) &&
+ (!is_resync || instantiating_collection->id.lib == id_root->lib)) {
+ instantiating_collection_override_candidate = instantiating_collection;
+ }
+ instantiating_collection = NULL;
}
}
@@ -751,12 +783,14 @@ static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_roo
.missing_tag = LIB_TAG_MISSING,
.is_override = false,
.is_resync = false};
+ lib_override_group_tag_data_object_to_collection_init(&data);
lib_override_linked_group_tag(&data);
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
lib_override_hierarchy_dependencies_recursive_tag(&data);
BKE_main_relations_free(bmain);
+ lib_override_group_tag_data_clear(&data);
return BKE_lib_override_library_create_from_tag(bmain, id_root->lib, false);
}
@@ -890,24 +924,6 @@ static void lib_override_library_create_post_process(Main *bmain,
BLI_gset_free(all_objects_in_scene, NULL);
}
-/**
- * Advanced 'smart' function to create fully functional overrides.
- *
- * \note Currently it only does special things if given \a id_root is an object or collection, more
- * specific behaviors may be added in the future for other ID types.
- *
- * \note It will override all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at
- * its beginning, so caller code can add extra data-blocks to be overridden as well.
- *
- * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
- * which case \a scene's master collection children hierarchy is used instead).
- * \param id_root: The root ID to create an override from.
- * \param id_reference: Some reference ID used to do some post-processing after overrides have been
- * created, may be NULL. Typically, the Empty object instantiating the linked collection we
- * override, currently.
- * \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
- * \return true if override was successfully created.
- */
bool BKE_lib_override_library_create(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -942,9 +958,6 @@ bool BKE_lib_override_library_create(Main *bmain,
return success;
}
-/**
- * Create a library override template.
- */
bool BKE_lib_override_library_template_create(struct ID *id)
{
if (ID_IS_LINKED(id)) {
@@ -958,16 +971,6 @@ bool BKE_lib_override_library_template_create(struct ID *id)
return true;
}
-/**
- * Convert a given proxy object into a library override.
- *
- * \note This is a thin wrapper around \a BKE_lib_override_library_create, only extra work is to
- * actually convert the proxy itself into an override first.
- *
- * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
- * which case \a scene's master collection children hierarchy is used instead).
- * \return true if override was successfully created.
- */
bool BKE_lib_override_library_proxy_convert(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -1039,14 +1042,6 @@ static void lib_override_library_proxy_convert_do(Main *bmain,
}
}
-/**
- * Convert all proxy objects into library overrides.
- *
- * \note Only affects local proxies, linked ones are not affected.
- *
- * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
- * which case \a scene's master collection children hierarchy is used instead).
- */
void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
{
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
@@ -1086,15 +1081,6 @@ void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadRepor
}
}
-/**
- * Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked
- * data, from an existing override hierarchy.
- *
- * \param id_root: The root liboverride ID to resync from.
- * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
- * which case \a scene's master collection children hierarchy is used instead).
- * \return true if override was successfully resynced.
- */
bool BKE_lib_override_library_resync(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -1125,6 +1111,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
.missing_tag = LIB_TAG_MISSING,
.is_override = true,
.is_resync = true};
+ lib_override_group_tag_data_object_to_collection_init(&data);
lib_override_overrides_group_tag(&data);
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
@@ -1215,6 +1202,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
lib_override_hierarchy_dependencies_recursive_tag(&data);
BKE_main_relations_free(bmain);
+ lib_override_group_tag_data_clear(&data);
/* Make new override from linked data. */
/* Note that this call also remaps all pointers of tagged IDs from old override IDs to new
@@ -1607,6 +1595,14 @@ static void lib_override_library_main_resync_on_library_indirect_level(
/* Detect all linked data that would need to be overridden if we had to create an override from
* those used by current existing overrides. */
+ LibOverrideGroupTagData data = {.bmain = bmain,
+ .scene = scene,
+ .id_root = NULL,
+ .tag = LIB_TAG_DOIT,
+ .missing_tag = LIB_TAG_MISSING,
+ .is_override = false,
+ .is_resync = true};
+ lib_override_group_tag_data_object_to_collection_init(&data);
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
@@ -1617,19 +1613,14 @@ static void lib_override_library_main_resync_on_library_indirect_level(
continue;
}
- LibOverrideGroupTagData data = {.bmain = bmain,
- .scene = scene,
- .id_root = id->override_library->reference,
- .tag = LIB_TAG_DOIT,
- .missing_tag = LIB_TAG_MISSING,
- .is_override = false,
- .is_resync = true};
+ data.id_root = id->override_library->reference;
lib_override_linked_group_tag(&data);
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
lib_override_hierarchy_dependencies_recursive_tag(&data);
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
}
FOREACH_MAIN_ID_END;
+ lib_override_group_tag_data_clear(&data);
/* Now check existing overrides, those needing resync will be the one either already tagged as
* such, or the one using linked data that is now tagged as needing override. */
@@ -1801,23 +1792,6 @@ static int lib_override_libraries_index_define(Main *bmain)
return library_indirect_level_max;
}
-/**
- * Detect and handle required resync of overrides data, when relations between reference linked IDs
- * have changed.
- *
- * This is a fairly complex and costly operation, typically it should be called after
- * #BKE_lib_override_library_main_update, which would already detect and tag a lot of cases.
- *
- * This function will first detect the remaining cases requiring a resync (namely, either when an
- * existing linked ID that did not require to be overridden before now would be, or when new IDs
- * are added to the hierarchy).
- *
- * Then it will handle the resync of necessary IDs (through calls to
- * #BKE_lib_override_library_resync).
- *
- * \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
- * which case \a scene's master collection children hierarchy is used instead).
- */
void BKE_lib_override_library_main_resync(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -1866,14 +1840,6 @@ void BKE_lib_override_library_main_resync(Main *bmain,
}
}
-/**
- * Advanced 'smart' function to delete library overrides (including their existing override
- * hierarchy) and remap their usages to their linked reference IDs.
- *
- * \note All IDs tagged with `LIB_TAG_DOIT` will be deleted.
- *
- * \param id_root: The root liboverride ID to delete.
- */
void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
{
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
@@ -1887,9 +1853,11 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
.missing_tag = LIB_TAG_MISSING,
.is_override = true,
.is_resync = false};
+ lib_override_group_tag_data_object_to_collection_init(&data);
lib_override_overrides_group_tag(&data);
BKE_main_relations_free(bmain);
+ lib_override_group_tag_data_clear(&data);
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
@@ -1911,11 +1879,6 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
-/** Make given ID fully local.
- *
- * \note Only differs from lower-level `BKE_lib_override_library_free in infamous embedded ID
- * cases.
- */
void BKE_lib_override_library_make_local(ID *id)
{
if (!ID_IS_OVERRIDE_LIBRARY(id)) {
@@ -1972,9 +1935,6 @@ BLI_INLINE GHash *override_library_rna_path_mapping_ensure(IDOverrideLibrary *ov
return override_runtime->rna_path_to_override_properties;
}
-/**
- * Find override property from given RNA path, if it exists.
- */
IDOverrideLibraryProperty *BKE_lib_override_library_property_find(IDOverrideLibrary *override,
const char *rna_path)
{
@@ -1982,9 +1942,6 @@ IDOverrideLibraryProperty *BKE_lib_override_library_property_find(IDOverrideLibr
return BLI_ghash_lookup(override_runtime, rna_path);
}
-/**
- * Find override property from given RNA path, or create it if it does not exist.
- */
IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibrary *override,
const char *rna_path,
bool *r_created)
@@ -2010,13 +1967,6 @@ IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibra
return op;
}
-/**
- * Get the RNA-property matching the \a library_prop override property. Used for UI to query
- * additional data about the overridden property (e.g. UI name).
- *
- * \param idpoin: Pointer to the override ID.
- * \param library_prop: The library override property to find the matching RNA property for.
- */
bool BKE_lib_override_rna_property_find(PointerRNA *idpoin,
const IDOverrideLibraryProperty *library_prop,
PointerRNA *r_override_poin,
@@ -2053,9 +2003,6 @@ void lib_override_library_property_clear(IDOverrideLibraryProperty *op)
BLI_freelistN(&op->operations);
}
-/**
- * Remove and free given \a override_property from given ID \a override.
- */
void BKE_lib_override_library_property_delete(IDOverrideLibrary *override,
IDOverrideLibraryProperty *override_property)
{
@@ -2069,9 +2016,6 @@ void BKE_lib_override_library_property_delete(IDOverrideLibrary *override,
BLI_freelinkN(&override->properties, override_property);
}
-/**
- * Find override property operation from given sub-item(s), if it exists.
- */
IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_find(
IDOverrideLibraryProperty *override_property,
const char *subitem_refname,
@@ -2158,9 +2102,6 @@ IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_
return NULL;
}
-/**
- * Find override property operation from given sub-item(s), or create it if it does not exist.
- */
IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_get(
IDOverrideLibraryProperty *override_property,
const short operation,
@@ -2227,9 +2168,6 @@ void lib_override_library_property_operation_clear(IDOverrideLibraryPropertyOper
}
}
-/**
- * Remove and free given \a override_property_operation from given ID \a override_property.
- */
void BKE_lib_override_library_property_operation_delete(
IDOverrideLibraryProperty *override_property,
IDOverrideLibraryPropertyOperation *override_property_operation)
@@ -2238,9 +2176,6 @@ void BKE_lib_override_library_property_operation_delete(
BLI_freelinkN(&override_property->operations, override_property_operation);
}
-/**
- * Validate that required data for a given operation are available.
- */
bool BKE_lib_override_library_property_operation_operands_validate(
struct IDOverrideLibraryPropertyOperation *override_property_operation,
struct PointerRNA *ptr_dst,
@@ -2278,7 +2213,6 @@ bool BKE_lib_override_library_property_operation_operands_validate(
return true;
}
-/** Check against potential \a bmain. */
void BKE_lib_override_library_validate(Main *UNUSED(bmain), ID *id, ReportList *reports)
{
if (id->override_library == NULL) {
@@ -2312,7 +2246,6 @@ void BKE_lib_override_library_validate(Main *UNUSED(bmain), ID *id, ReportList *
}
}
-/** Check against potential \a bmain. */
void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports)
{
ID *id;
@@ -2325,16 +2258,6 @@ void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports)
FOREACH_MAIN_ID_END;
}
-/**
- * Check that status of local data-block is still valid against current reference one.
- *
- * It means that all overridable, but not overridden, properties' local values must be equal to
- * reference ones. Clears #LIB_TAG_OVERRIDE_OK if they do not.
- *
- * This is typically used to detect whether some property has been changed in local and a new
- * #IDOverrideProperty (of #IDOverridePropertyOperation) has to be added.
- *
- * \return true if status is OK, false otherwise. */
bool BKE_lib_override_library_status_check_local(Main *bmain, ID *local)
{
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(local));
@@ -2384,16 +2307,6 @@ bool BKE_lib_override_library_status_check_local(Main *bmain, ID *local)
return true;
}
-/**
- * Check that status of reference data-block is still valid against current local one.
- *
- * It means that all non-overridden properties' local values must be equal to reference ones.
- * Clears LIB_TAG_OVERRIDE_OK if they do not.
- *
- * This is typically used to detect whether some reference has changed and local
- * needs to be updated against it.
- *
- * \return true if status is OK, false otherwise. */
bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
{
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(local));
@@ -2450,20 +2363,6 @@ bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
return true;
}
-/**
- * Compare local and reference data-blocks and create new override operations as needed,
- * or reset to reference values if overriding is not allowed.
- *
- * \note Defining override operations is only mandatory before saving a `.blend` file on disk
- * (not for undo!).
- * Knowing that info at runtime is only useful for UI/UX feedback.
- *
- * \note This is by far the biggest operation (the more time-consuming) of the three so far,
- * since it has to go over all properties in depth (all overridable ones at least).
- * Generating differential values and applying overrides are much cheaper.
- *
- * \return true if any library operation was created.
- */
bool BKE_lib_override_library_operations_create(Main *bmain, ID *local)
{
BLI_assert(local->override_library != NULL);
@@ -2540,7 +2439,6 @@ static void lib_override_library_operations_create_cb(TaskPool *__restrict pool,
}
}
-/** Check all overrides from given \a bmain and create/update overriding operations as needed. */
bool BKE_lib_override_library_main_operations_create(Main *bmain, const bool force_auto)
{
ID *id;
@@ -2669,7 +2567,6 @@ static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root)
return was_op_deleted;
}
-/** Reset all overrides in given \a id_root, while preserving ID relations. */
void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
@@ -2728,7 +2625,6 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
}
}
-/** Reset all overrides in given \a id_root and its dependencies, while preserving ID relations. */
void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root)
{
BKE_main_relations_create(bmain, 0);
@@ -2749,7 +2645,6 @@ void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root)
FOREACH_MAIN_ID_END;
}
-/** Set or clear given tag in all operations in that override property data. */
void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property,
const short tag,
const bool do_set)
@@ -2773,7 +2668,6 @@ void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *o
}
}
-/** Set or clear given tag in all properties and operations in that override data. */
void BKE_lib_override_library_properties_tag(struct IDOverrideLibrary *override,
const short tag,
const bool do_set)
@@ -2785,7 +2679,6 @@ void BKE_lib_override_library_properties_tag(struct IDOverrideLibrary *override,
}
}
-/** Set or clear given tag in all properties and operations in that Main's ID override data. */
void BKE_lib_override_library_main_tag(struct Main *bmain, const short tag, const bool do_set)
{
ID *id;
@@ -2798,7 +2691,6 @@ void BKE_lib_override_library_main_tag(struct Main *bmain, const short tag, cons
FOREACH_MAIN_ID_END;
}
-/** Remove all tagged-as-unused properties and operations from that ID override data. */
void BKE_lib_override_library_id_unused_cleanup(struct ID *local)
{
if (ID_IS_OVERRIDE_LIBRARY_REAL(local)) {
@@ -2818,7 +2710,6 @@ void BKE_lib_override_library_id_unused_cleanup(struct ID *local)
}
}
-/** Remove all tagged-as-unused properties and operations from that Main's ID override data. */
void BKE_lib_override_library_main_unused_cleanup(struct Main *bmain)
{
ID *id;
@@ -2839,7 +2730,6 @@ static void lib_override_id_swap(Main *bmain, ID *id_local, ID *id_temp)
id_local->tag |= (id_temp->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC);
}
-/** Update given override from its reference (re-applying overridden properties). */
void BKE_lib_override_library_update(Main *bmain, ID *local)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(local)) {
@@ -2964,7 +2854,6 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
DEG_relations_tag_update(bmain);
}
-/** Update all overrides from given \a bmain. */
void BKE_lib_override_library_main_update(Main *bmain)
{
ID *id;
@@ -2985,7 +2874,6 @@ void BKE_lib_override_library_main_update(Main *bmain)
G_MAIN = orig_gmain;
}
-/** In case an ID is used by another liboverride ID, user may not be allowed to delete it. */
bool BKE_lib_override_library_id_is_user_deletable(struct Main *bmain, struct ID *id)
{
if (!(ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id))) {
@@ -3026,17 +2914,11 @@ bool BKE_lib_override_library_id_is_user_deletable(struct Main *bmain, struct ID
* exact same data as "desired" ones (kind of "baked" data-blocks).
*/
-/** Initialize an override storage. */
OverrideLibraryStorage *BKE_lib_override_library_operations_store_init(void)
{
return BKE_main_new();
}
-/**
- * Generate suitable 'write' data (this only affects differential override operations).
- *
- * Note that \a local ID is no more modified by this call,
- * all extra data are stored in its temp \a storage_id copy. */
ID *BKE_lib_override_library_operations_store_start(Main *bmain,
OverrideLibraryStorage *override_storage,
ID *local)
@@ -3101,10 +2983,6 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
return storage_id;
}
-/**
- * Restore given ID modified by #BKE_lib_override_library_operations_store_start, to its
- * original state.
- */
void BKE_lib_override_library_operations_store_end(
OverrideLibraryStorage *UNUSED(override_storage), ID *local)
{
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 74750a9b61a..4ad0186f9b5 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -76,8 +76,6 @@ typedef struct LibraryForeachIDData {
BLI_LINKSTACK_DECLARE(ids_todo, ID *);
} LibraryForeachIDData;
-/** 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)
{
return (data->status & IDWALK_STOP) != 0;
@@ -162,10 +160,6 @@ void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void
BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, cb_flag);
}
-/** 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. */
@@ -367,18 +361,12 @@ static bool library_foreach_ID_link(Main *bmain,
#undef CALLBACK_INVOKE
}
-/**
- * Loop over all of the ID's this data-block links to.
- */
void BKE_library_foreach_ID_link(
Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
{
library_foreach_ID_link(bmain, NULL, id, callback, user_data, flag, NULL);
}
-/**
- * re-usable function, use when replacing ID's
- */
void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
{
if (cb_flag & IDWALK_CB_USER) {
@@ -390,12 +378,6 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
}
}
-/**
- * Say whether given \a id_owner may use (in any way) a data-block of \a id_type_used.
- *
- * This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above,
- * quite useful to reduce useless iterations in some cases.
- */
bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
{
/* any type of ID can be used in custom props. */
@@ -567,16 +549,6 @@ static int foreach_libblock_id_users_callback(LibraryIDLinkCallbackData *cb_data
return IDWALK_RET_NOP;
}
-/**
- * Return the number of times given \a id_user uses/references \a id_used.
- *
- * \note This only checks for pointer references of an ID, shallow usages
- * (like e.g. by RNA paths, as done for FCurves) are not detected at all.
- *
- * \param id_user: the ID which is supposed to use (reference) \a id_used.
- * \param id_used: the ID which is supposed to be used (referenced) by \a id_user.
- * \return the number of direct usages/references of \a id_used by \a id_user.
- */
int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
{
IDUsersIter iter;
@@ -625,26 +597,16 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
return is_defined;
}
-/**
- * Check whether given ID is used locally (i.e. by another non-linked ID).
- */
bool BKE_library_ID_is_locally_used(Main *bmain, void *idv)
{
return library_ID_is_used(bmain, idv, false);
}
-/**
- * Check whether given ID is used indirectly (i.e. by another linked ID).
- */
bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
{
return library_ID_is_used(bmain, idv, true);
}
-/**
- * Combine #BKE_library_ID_is_locally_used() and #BKE_library_ID_is_indirectly_used()
- * in a single call.
- */
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
{
IDUsersIter iter;
@@ -759,21 +721,6 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
}
}
-/**
- * Tag all unused IDs (a.k.a 'orphaned').
- *
- * By default only tag IDs with `0` user count.
- * If `do_tag_recursive` is set, it will check dependencies to detect all IDs that are not actually
- * used in current file, including 'archipelagos` (i.e. set of IDs referencing each other in
- * loops, but without any 'external' valid usages.
- *
- * Valid usages here are defined as ref-counting usages, which are not towards embedded or
- * loop-back data.
- *
- * \param r_num_tagged: If non-NULL, must be a zero-initialized array of #INDEX_ID_MAX integers.
- * Number of tagged-as-unused IDs is then set for each type, and as total in
- * #INDEX_ID_NULL item.
- */
void BKE_lib_query_unused_ids_tag(Main *bmain,
const int tag,
const bool do_local_ids,
@@ -838,15 +785,6 @@ static int foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackD
return IDWALK_RET_NOP;
}
-/**
- * Detect orphaned linked data blocks (i.e. linked data not used (directly or indirectly)
- * in any way by any local data), including complex cases like 'linked archipelagoes', i.e.
- * linked data-blocks that use each other in loops,
- * which prevents their deletion by 'basic' usage checks.
- *
- * \param do_init_tag: if \a true, all linked data are checked, if \a false,
- * only linked data-blocks already tagged with #LIB_TAG_DOIT are checked.
- */
void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
{
ID *id;
@@ -876,14 +814,6 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
}
}
-/**
- * Untag linked data blocks used by other untagged linked data-blocks.
- * Used to detect data-blocks that we can forcefully make local
- * (instead of copying them to later get rid of original):
- * All data-blocks we want to make local are tagged by caller,
- * after this function has ran caller knows data-blocks still tagged can directly be made local,
- * since they are only used by other data-blocks that will also be made fully local.
- */
void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
{
ListBase *lb_array[INDEX_ID_MAX];
diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index 014c923f04f..3cea0de32ee 100644
--- a/source/blender/blenkernel/intern/lib_remap.c
+++ b/source/blender/blenkernel/intern/lib_remap.c
@@ -456,10 +456,6 @@ static void libblock_remap_data(
#endif
}
-/**
- * Replace all references in given Main to \a old_id by \a new_id
- * (if \a new_id is NULL, it unlinks \a old_id).
- */
void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
{
IDRemap id_remap_data;
@@ -565,13 +561,6 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short r
BKE_main_unlock(bmain);
}
-/**
- * Unlink given \a id from given \a bmain
- * (does not touch to indirect, i.e. library, usages of the ID).
- *
- * \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by
- * #LIB_TAG_DOIT flag (quite obviously, 'non-NULL' usages can never be unlinked by this function).
- */
void BKE_libblock_unlink(Main *bmain,
void *idv,
const bool do_flag_never_null,
@@ -587,16 +576,6 @@ void BKE_libblock_unlink(Main *bmain,
BKE_main_unlock(bmain);
}
-/**
- * Similar to libblock_remap, but only affects IDs used by given \a idv ID.
- *
- * \param old_idv: Unlike BKE_libblock_remap, can be NULL,
- * in which case all ID usages by given \a idv will be cleared.
- * \param us_min_never_null: If \a true and new_id is NULL,
- * 'NEVER_NULL' ID usages keep their old id, but this one still gets its user count decremented
- * (needed when given \a idv is going to be deleted right after being unlinked).
- */
-/* Should be able to replace all _relink() funcs (constraints, rigidbody, etc.) ? */
/* XXX Arg! Naming... :(
* _relink? avoids confusion with _remap, but is confusing with _unlink
* _remap_used_ids?
@@ -604,9 +583,13 @@ void BKE_libblock_unlink(Main *bmain,
* BKE_id_remap maybe?
* ... sigh
*/
+
void BKE_libblock_relink_ex(
Main *bmain, void *idv, void *old_idv, void *new_idv, const short remap_flags)
{
+
+ /* Should be able to replace all _relink() funcs (constraints, rigidbody, etc.) ? */
+
ID *id = idv;
ID *old_id = old_idv;
ID *new_id = new_idv;
@@ -710,15 +693,6 @@ static void libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
bmain, id, id_relink_to_newid_looper, POINTER_FROM_INT(remap_flag), 0);
}
-/**
- * Remaps ID usages of given ID to their `id->newid` pointer if not None, and proceeds recursively
- * in the dependency tree of IDs for all data-blocks tagged with `LIB_TAG_NEW`.
- *
- * NOTE: `LIB_TAG_NEW` is cleared
- *
- * 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(Main *bmain, ID *id, const int remap_flag)
{
if (ID_IS_LINKED(id)) {
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 1dba353d8ce..c97b003d241 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -36,6 +36,7 @@
#include "BLT_translation.h"
+#include "BKE_bpath.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
@@ -60,6 +61,22 @@ static void library_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, lib->parent, IDWALK_CB_NEVER_SELF);
}
+static void library_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Library *lib = (Library *)id;
+
+ /* FIXME: Find if we should respect #BKE_BPATH_FOREACH_PATH_SKIP_PACKED here, and if not, explain
+ * why. */
+ if (lib->packedfile !=
+ NULL /*&& (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0 */) {
+ return;
+ }
+
+ if (BKE_bpath_foreach_path_fixed_process(bpath_data, lib->filepath)) {
+ BKE_library_filepath_set(bpath_data->bmain, lib, lib->filepath);
+ }
+}
+
IDTypeInfo IDType_ID_LI = {
.id_code = ID_LI,
.id_filter = 0,
@@ -69,6 +86,7 @@ IDTypeInfo IDType_ID_LI = {
.name_plural = "libraries",
.translation_context = BLT_I18NCONTEXT_ID_LIBRARY,
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_LIBLINKING | IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = NULL,
@@ -76,6 +94,7 @@ IDTypeInfo IDType_ID_LI = {
.make_local = NULL,
.foreach_id = library_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = library_foreach_path,
.owner_get = NULL,
.blend_write = NULL,
@@ -108,7 +127,7 @@ void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
*/
/* Never make paths relative to parent lib - reading code (blenloader) always set *all*
* `lib->filepath` relative to current main, not to their parent for indirectly linked ones. */
- const char *basepath = BKE_main_blendfile_path(bmain);
- BLI_path_abs(lib->filepath_abs, basepath);
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
+ BLI_path_abs(lib->filepath_abs, blendfile_path);
}
}
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index 05e8d4fe978..e73cda7e24d 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -195,6 +195,7 @@ IDTypeInfo IDType_ID_LA = {
.name_plural = "lights",
.translation_context = BLT_I18NCONTEXT_ID_LIGHT,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = light_init_data,
.copy_data = light_copy_data,
@@ -202,6 +203,7 @@ IDTypeInfo IDType_ID_LA = {
.make_local = NULL,
.foreach_id = light_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = light_blend_write,
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index 57ad6695db4..035e41815e5 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -92,6 +92,7 @@ IDTypeInfo IDType_ID_LP = {
.name_plural = "lightprobes",
.translation_context = BLT_I18NCONTEXT_ID_LIGHTPROBE,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = lightprobe_init_data,
.copy_data = NULL,
@@ -99,6 +100,7 @@ IDTypeInfo IDType_ID_LP = {
.make_local = NULL,
.foreach_id = lightprobe_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = lightprobe_blend_write,
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 3c305d1fb3f..ac0dbcb715d 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -754,6 +754,7 @@ IDTypeInfo IDType_ID_LS = {
.name_plural = "linestyles",
.translation_context = BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = linestyle_init_data,
.copy_data = linestyle_copy_data,
@@ -761,6 +762,7 @@ IDTypeInfo IDType_ID_LS = {
.make_local = NULL,
.foreach_id = linestyle_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = linestyle_blend_write,
@@ -1910,10 +1912,6 @@ int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineSt
return 0;
}
-/**
- * Reinsert \a modifier in modifier list with an offset of \a direction.
- * \return if position of \a modifier has changed.
- */
bool BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle,
LineStyleModifier *modifier,
int direction)
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index a5de0bc99c8..64731be57ac 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -205,7 +205,6 @@ void BKE_main_free(Main *mainvar)
MEM_freeN(mainvar);
}
-/* Check whether given `bmain` is empty or contains some IDs. */
bool BKE_main_is_empty(struct Main *bmain)
{
ID *id_iter;
@@ -278,7 +277,6 @@ static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
return IDWALK_RET_NOP;
}
-/** Generate the mappings between used IDs and their users, and vice-versa. */
void BKE_main_relations_create(Main *bmain, const short flag)
{
if (bmain->relations != NULL) {
@@ -326,7 +324,6 @@ void BKE_main_relations_free(Main *bmain)
}
}
-/** Set or clear given `tag` in all relation entries of given `bmain`. */
void BKE_main_relations_tag_set(struct Main *bmain,
const eMainIDRelationsEntryTags tag,
const bool value)
@@ -350,12 +347,6 @@ void BKE_main_relations_tag_set(struct Main *bmain,
BLI_ghashIterator_free(gh_iter);
}
-/**
- * Create a GSet storing all IDs present in given \a bmain, by their pointers.
- *
- * \param gset: If not NULL, given GSet will be extended with IDs from given \a bmain,
- * instead of creating a new one.
- */
GSet *BKE_main_gset_create(Main *bmain, GSet *gset)
{
if (gset == NULL) {
@@ -404,12 +395,6 @@ static bool lib_weak_key_cmp(const void *a, const void *b)
STREQ(string_pair_a->id_name, string_pair_b->id_name));
}
-/**
- * Generate a mapping between 'library path' of an ID (as a pair (relative blend file path, id
- * name)), and a current local ID, if any.
- *
- * This uses the information stored in `ID.library_weak_reference`.
- */
GHash *BKE_main_library_weak_reference_create(Main *bmain)
{
GHash *library_weak_reference_mapping = BLI_ghash_new(
@@ -442,24 +427,11 @@ GHash *BKE_main_library_weak_reference_create(Main *bmain)
return library_weak_reference_mapping;
}
-/**
- * Destroy the data generated by #BKE_main_library_weak_reference_create.
- */
void BKE_main_library_weak_reference_destroy(GHash *library_weak_reference_mapping)
{
BLI_ghash_free(library_weak_reference_mapping, MEM_freeN, NULL);
}
-/**
- * Search for a local ID matching the given linked ID reference.
- *
- * \param library_weak_reference_mapping: the mapping data generated by
- * #BKE_main_library_weak_reference_create.
- * \param library_relative_path: the path of a blend file library (relative to current working
- * one).
- * \param library_id_name: the full ID name, including the leading two chars encoding the ID
- * type.
- */
ID *BKE_main_library_weak_reference_search_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name)
@@ -469,16 +441,6 @@ ID *BKE_main_library_weak_reference_search_item(GHash *library_weak_reference_ma
return (ID *)BLI_ghash_lookup(library_weak_reference_mapping, &key);
}
-/**
- * Add the given ID weak library reference to given local ID and the runtime mapping.
- *
- * \param library_weak_reference_mapping: the mapping data generated by
- * #BKE_main_library_weak_reference_create.
- * \param library_relative_path: the path of a blend file library (relative to current working
- * one).
- * \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
- * \param new_id: New local ID matching given weak reference.
- */
void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
@@ -507,21 +469,6 @@ void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapp
*id_p = new_id;
}
-/**
- * Update the status of the given ID weak library reference in current local IDs and the runtime
- * mapping.
- *
- * This effectively transfers the 'ownership' of the given weak reference from `old_id` to
- * `new_id`.
- *
- * \param library_weak_reference_mapping: the mapping data generated by
- * #BKE_main_library_weak_reference_create.
- * \param library_relative_path: the path of a blend file library (relative to current working
- * one).
- * \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
- * \param old_id: Existing local ID matching given weak reference.
- * \param new_id: New local ID matching given weak reference.
- */
void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
@@ -545,16 +492,6 @@ void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_m
*id_p = new_id;
}
-/**
- * Remove the given ID weak library reference from the given local ID and the runtime mapping.
- *
- * \param library_weak_reference_mapping: the mapping data generated by
- * #BKE_main_library_weak_reference_create.
- * \param library_relative_path: the path of a blend file library (relative to current working
- * one).
- * \param library_id_name: the full ID name, including the leading two chars encoding the ID type.
- * \param old_id: Existing local ID matching given weak reference.
- */
void BKE_main_library_weak_reference_remove_item(GHash *library_weak_reference_mapping,
const char *library_filepath,
const char *library_id_name,
@@ -572,13 +509,6 @@ void BKE_main_library_weak_reference_remove_item(GHash *library_weak_reference_m
MEM_SAFE_FREE(old_id->library_weak_reference);
}
-/**
- * Generates a raw .blend file thumbnail data from given image.
- *
- * \param bmain: If not NULL, also store generated data in this Main.
- * \param img: ImBuf image to generate thumbnail data from.
- * \return The generated .blend file raw thumbnail data.
- */
BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
{
BlendThumbnail *data = NULL;
@@ -603,13 +533,6 @@ BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
return data;
}
-/**
- * Generates an image from raw .blend file thumbnail \a data.
- *
- * \param bmain: Use this bmain->blen_thumb data if given \a data is NULL.
- * \param data: Raw .blend file thumbnail data.
- * \return An ImBuf from given data, or NULL if invalid.
- */
ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
{
ImBuf *img = NULL;
@@ -626,9 +549,6 @@ ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
return img;
}
-/**
- * Generates an empty (black) thumbnail for given Main.
- */
void BKE_main_thumbnail_create(struct Main *bmain)
{
MEM_SAFE_FREE(bmain->blen_thumb);
@@ -638,28 +558,16 @@ void BKE_main_thumbnail_create(struct Main *bmain)
bmain->blen_thumb->height = BLEN_THUMB_SIZE;
}
-/**
- * Return filepath of given \a main.
- */
const char *BKE_main_blendfile_path(const Main *bmain)
{
- return bmain->name;
+ return bmain->filepath;
}
-/**
- * Return filepath of global main #G_MAIN.
- *
- * \warning Usage is not recommended,
- * you should always try to get a valid Main pointer from context...
- */
const char *BKE_main_blendfile_path_from_global(void)
{
return BKE_main_blendfile_path(G_MAIN);
}
-/**
- * \return A pointer to the \a ListBase of given \a bmain for requested \a type ID type.
- */
ListBase *which_libbase(Main *bmain, short type)
{
switch ((ID_Type)type) {
@@ -747,18 +655,6 @@ ListBase *which_libbase(Main *bmain, short type)
return NULL;
}
-/**
- * Put the pointers to all the #ListBase structs in given `bmain` into the `*lb[INDEX_ID_MAX]`
- * array, and return the number of those for convenience.
- *
- * This is useful for generic traversal of all the blocks in a #Main (by traversing all the lists
- * in turn), without worrying about block types.
- *
- * \param lb: Array of lists #INDEX_ID_MAX in length.
- *
- * \note The order of each ID type #ListBase in the array is determined by the `INDEX_ID_<IDTYPE>`
- * enum definitions in `DNA_ID.h`. See also the #FOREACH_MAIN_ID_BEGIN macro in `BKE_main.h`
- */
int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
{
/* Libraries may be accessed from pretty much any other ID. */
diff --git a/source/blender/blenkernel/intern/main_idmap.c b/source/blender/blenkernel/intern/main_idmap.c
index c75365a788d..38523f22aad 100644
--- a/source/blender/blenkernel/intern/main_idmap.c
+++ b/source/blender/blenkernel/intern/main_idmap.c
@@ -88,18 +88,6 @@ static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id
return NULL;
}
-/**
- * Generate mapping from ID type/name to ID pointer for given \a bmain.
- *
- * \note When used during undo/redo, there is no guaranty that ID pointers from UI area
- * are not pointing to freed memory (when some IDs have been deleted). To avoid crashes
- * in those cases, one can provide the 'old' (aka current) Main database as reference.
- * #BKE_main_idmap_lookup_id will then check that given ID does exist in \a old_bmain
- * before trying to use it.
- *
- * \param create_valid_ids_set: If \a true, generate a reference to prevent freed memory accesses.
- * \param old_bmain: If not NULL, its IDs will be added the valid references set.
- */
struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
const bool create_valid_ids_set,
struct Main *old_bmain,
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 1d3ebaac303..6f498c5c9e7 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -255,6 +255,7 @@ IDTypeInfo IDType_ID_MSK = {
.name_plural = "masks",
.translation_context = BLT_I18NCONTEXT_ID_MASK,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = mask_copy_data,
@@ -262,6 +263,7 @@ IDTypeInfo IDType_ID_MSK = {
.make_local = NULL,
.foreach_id = mask_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = mask_blend_write,
@@ -371,7 +373,6 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name)
return masklay;
}
-/* NOTE: may still be hidden, caller needs to check. */
MaskLayer *BKE_mask_layer_active(Mask *mask)
{
return BLI_findlink(&mask->masklayers, mask->masklay_act);
@@ -787,12 +788,11 @@ BLI_INLINE void orthogonal_direction_get(const float vec[2], float result[2])
normalize_v2(result);
}
-/* TODO(sergey): This function will re-calculate loads of stuff again and again
- * when differentiating feather points. This might be easily cached
- * in the callee function for this case.
- */
void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2])
{
+ /* TODO(sergey): This function will re-calculate loads of stuff again and again
+ * when differentiating feather points. This might be easily cached
+ * in the callee function for this case. */
MaskSplinePoint *point_prev, *point_next;
@@ -1132,7 +1132,6 @@ MaskSpline *BKE_mask_spline_copy(const MaskSpline *spline)
return nspline;
}
-/* NOTE: Does NOT add to the list. */
MaskLayerShape *BKE_mask_layer_shape_alloc(MaskLayer *masklay, const int frame)
{
MaskLayerShape *masklay_shape;
@@ -1156,8 +1155,6 @@ void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape)
MEM_freeN(masklay_shape);
}
-/** \brief Free all animation keys for a mask layer
- */
void BKE_mask_layer_free_shapes(MaskLayer *masklay)
{
MaskLayerShape *masklay_shape;
@@ -1245,7 +1242,6 @@ void BKE_mask_coord_from_image(Image *image, ImageUser *iuser, float r_co[2], co
BKE_mask_coord_from_frame(r_co, co, frame_size);
}
-/* as above but divide */
void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame_size[2])
{
if (frame_size[0] == frame_size[1]) {
@@ -1428,8 +1424,6 @@ void BKE_mask_get_handle_point_adjacent(MaskSpline *spline,
*r_point_next = mask_spline_point_next(spline, points_array, point);
}
-/* calculates the tangent of a point by its previous and next
- * (ignoring handles - as if its a poly line) */
void BKE_mask_calc_tangent_polyline(MaskSpline *spline, MaskSplinePoint *point, float t[2])
{
float tvec_a[2], tvec_b[2];
@@ -1513,11 +1507,6 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline,
}
}
-/**
- * \brief Resets auto handles even for non-auto bezier points
- *
- * Useful for giving sane defaults.
- */
void BKE_mask_calc_handle_point_auto(MaskSpline *spline,
MaskSplinePoint *point,
const bool do_recalc_length)
@@ -1640,7 +1629,6 @@ static void mask_layer_shape_to_mask_point(BezTriple *bezt,
bezt->radius = fp[7];
}
-/* these functions match. copy is swapped */
void BKE_mask_layer_shape_from_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape)
{
int tot = BKE_mask_layer_shape_totvert(masklay);
@@ -1696,7 +1684,6 @@ BLI_INLINE void interp_v2_v2v2_flfl(
target[1] = s * a[1] + t * b[1];
}
-/* linear interpolation only */
void BKE_mask_layer_shape_to_mask_interp(MaskLayer *masklay,
MaskLayerShape *masklay_shape_a,
MaskLayerShape *masklay_shape_b,
@@ -1757,9 +1744,6 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int fr
return NULL;
}
-/**
- * When returning 2 - the frame isn't found but before/after frames are.
- */
int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay,
const float frame,
MaskLayerShape **r_masklay_shape_a,
@@ -1922,7 +1906,6 @@ static void interp_weights_uv_v2_apply(const float uv[2],
r_pt[1] += dvec[0] * uv[1];
}
-/* When a new points added - resize all shape-key array. */
void BKE_mask_layer_shape_changed_add(MaskLayer *masklay,
int index,
bool do_init,
@@ -2017,7 +2000,6 @@ void BKE_mask_layer_shape_changed_add(MaskLayer *masklay,
}
}
-/* move array to account for removed point */
void BKE_mask_layer_shape_changed_remove(MaskLayer *masklay, int index, int count)
{
MaskLayerShape *masklay_shape;
@@ -2079,13 +2061,11 @@ static void mask_clipboard_free_ex(bool final_free)
}
}
-/* Free the clipboard. */
void BKE_mask_clipboard_free(void)
{
mask_clipboard_free_ex(true);
}
-/* Copy selected visible splines from the given layer to clipboard. */
void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer)
{
MaskSpline *spline;
@@ -2120,13 +2100,11 @@ void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer)
}
}
-/* Check clipboard is empty. */
bool BKE_mask_clipboard_is_empty(void)
{
return BLI_listbase_is_empty(&mask_clipboard.splines);
}
-/* Paste the contents of clipboard to given mask layer */
void BKE_mask_clipboard_paste_to_layer(Main *bmain, MaskLayer *mask_layer)
{
MaskSpline *spline;
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 4584d9e527e..69fc7554eed 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -720,10 +720,6 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double
return feather;
}
-/**
- * values align with #BKE_mask_spline_differentiate_with_resolution
- * when \a resol arguments match.
- */
float (*BKE_mask_spline_feather_differentiated_points_with_resolution(
MaskSpline *spline,
const unsigned int resol,
@@ -788,7 +784,6 @@ float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *r_tot_feather_po
return feather;
}
-/* *** mask point functions which involve evaluation *** */
float *BKE_mask_point_segment_feather_diff(MaskSpline *spline,
MaskSplinePoint *point,
int width,
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 0c40a1b5078..b0876957620 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -1474,9 +1474,6 @@ static void maskrasterize_buffer_cb(void *__restrict userdata,
}
}
-/**
- * \brief Rasterize a buffer from a single mask (threaded execution).
- */
void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle,
const unsigned int width,
const unsigned int height,
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 1fac83c5665..d6035887790 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -261,6 +261,7 @@ IDTypeInfo IDType_ID_MA = {
.name_plural = "materials",
.translation_context = BLT_I18NCONTEXT_ID_MATERIAL,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = material_init_data,
.copy_data = material_copy_data,
@@ -268,6 +269,7 @@ IDTypeInfo IDType_ID_MA = {
.make_local = NULL,
.foreach_id = material_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = material_blend_write,
@@ -387,7 +389,6 @@ short *BKE_object_material_len_p(Object *ob)
return NULL;
}
-/* same as above but for ID's */
Material ***BKE_id_material_array_p(ID *id)
{
/* ensure we don't try get materials from non-obdata */
@@ -726,13 +727,6 @@ static ID *get_evaluated_object_data_with_materials(Object *ob)
return data;
}
-/**
- * On evaluated objects the number of materials on an object and its data might go out of sync.
- * This is because during evaluation materials can be added/removed on the object data.
- *
- * For rendering or exporting we generally use the materials on the object data. However, some
- * material indices might be overwritten by the object.
- */
Material *BKE_object_material_get_eval(Object *ob, short act)
{
BLI_assert(DEG_is_evaluated_object(ob));
@@ -806,10 +800,6 @@ void BKE_id_material_eval_assign(ID *id, int slot, Material *material)
(*materials_ptr)[slot_index] = material;
}
-/**
- * Add an empty material slot if the id has no material slots. This material slot allows the
- * material to be overwritten by object-linked materials.
- */
void BKE_id_material_eval_ensure_default_slot(ID *id)
{
short *len_ptr = BKE_id_material_len_p(id);
@@ -1099,12 +1089,6 @@ void BKE_object_material_remap(Object *ob, const unsigned int *remap)
}
}
-/**
- * Calculate a material remapping from \a ob_src to \a ob_dst.
- *
- * \param remap_src_to_dst: An array the size of `ob_src->totcol`
- * where index values are filled in which map to \a ob_dst materials.
- */
void BKE_object_material_remap_calc(Object *ob_dst, Object *ob_src, short *remap_src_to_dst)
{
if (ob_src->totcol == 0) {
@@ -1153,9 +1137,6 @@ void BKE_object_material_remap_calc(Object *ob_dst, Object *ob_src, short *remap
BLI_ghash_free(gh_mat_map, NULL, NULL);
}
-/**
- * Copy materials from evaluated geometry to the original geometry of an object.
- */
void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, ID *data_eval)
{
ID *data_orig = ob_orig->data;
@@ -1190,7 +1171,6 @@ void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, ID *data_e
BKE_object_materials_test(bmain, ob_orig, data_orig);
}
-/* XXX: this calls many more update calls per object then are needed, could be optimized. */
void BKE_object_material_array_assign(Main *bmain,
struct Object *ob,
struct Material ***matar,
@@ -1553,7 +1533,6 @@ bNode *BKE_texpaint_slot_material_find_node(Material *ma, short texpaint_slot)
return find_data.r_node;
}
-/* r_col = current value, col = new value, (fac == 0) is no change */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
{
float tmp, facm = 1.0f - fac;
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 48d31361eac..ac6b0a04def 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -189,6 +189,7 @@ IDTypeInfo IDType_ID_MB = {
.name_plural = "metaballs",
.translation_context = BLT_I18NCONTEXT_ID_METABALL,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = metaball_init_data,
.copy_data = metaball_copy_data,
@@ -196,6 +197,7 @@ IDTypeInfo IDType_ID_MB = {
.make_local = NULL,
.foreach_id = metaball_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = metaball_blend_write,
@@ -219,8 +221,6 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name)
return mb;
}
-/* most simple meta-element adding function
- * don't do context manipulation here (rna uses) */
MetaElem *BKE_mball_element_add(MetaBall *mb, const int type)
{
MetaElem *ml = MEM_callocN(sizeof(MetaElem), "metaelem");
@@ -267,13 +267,6 @@ MetaElem *BKE_mball_element_add(MetaBall *mb, const int type)
return ml;
}
-/**
- * Compute bounding box of all #MetaElem / #MetaBall
- *
- * Bounding box is computed from polygonized surface. \a ob is
- * basic meta-balls (with name `Meta` for example). All other meta-ball objects
- * (with names `Meta.001`, `Meta.002`, etc) are included in this bounding-box.
- */
void BKE_mball_texspace_calc(Object *ob)
{
DispList *dl;
@@ -317,7 +310,6 @@ void BKE_mball_texspace_calc(Object *ob)
bb->flag &= ~BOUNDBOX_DIRTY;
}
-/** Return or compute bbox for given metaball object. */
BoundBox *BKE_mball_boundbox_get(Object *ob)
{
BLI_assert(ob->type == OB_MBALL);
@@ -370,38 +362,29 @@ float *BKE_mball_make_orco(Object *ob, ListBase *dispbase)
return orcodata;
}
-/**
- * \brief Test, if \a ob is a basis meta-ball.
- *
- * It test last character of Object ID name. If last character
- * is digit it return 0, else it return 1.
- *
- *
- * Meta-Ball Basis Notes from Blender-2.5x
- * =======================================
- *
- * This is a can of worms.
- *
- * This really needs a rewrite/refactor its totally broken in anything other than basic cases
- * Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the
- * depsgraph on rename and linking into scenes or removal of basis meta-ball.
- * So take care when changing this code.
- *
- * Main idiot thing here is that the system returns #BKE_mball_basis_find()
- * objects which fail a #BKE_mball_is_basis() test.
- *
- * Not only that but the depsgraph and their areas depend on this behavior,
- * so making small fixes here isn't worth it.
- * - Campbell
- */
bool BKE_mball_is_basis(Object *ob)
{
- /* just a quick test */
+ /* Meta-Ball Basis Notes from Blender-2.5x
+ * =======================================
+ *
+ * NOTE(@campbellbarton): This is a can of worms.
+ *
+ * This really needs a rewrite/refactor its totally broken in anything other than basic cases
+ * Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the
+ * depsgraph on rename and linking into scenes or removal of basis meta-ball.
+ * So take care when changing this code.
+ *
+ * Main idiot thing here is that the system returns #BKE_mball_basis_find()
+ * objects which fail a #BKE_mball_is_basis() test.
+ *
+ * Not only that but the depsgraph and their areas depend on this behavior,
+ * so making small fixes here isn't worth it. */
+
+ /* Just a quick test. */
const int len = strlen(ob->id.name);
return (!isdigit(ob->id.name[len - 1]));
}
-/* return nonzero if ob1 is a basis mball for ob */
bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
{
int basis1nr, basis2nr;
@@ -454,13 +437,6 @@ bool BKE_mball_is_any_unselected(const MetaBall *mb)
return false;
}
-/**
- * \brief copy some properties from object to other meta-ball object with same base name
- *
- * When some properties (wire-size, threshold, update flags) of meta-ball are changed, then this
- * properties are copied to all meta-balls in same "group" (meta-balls with same base name:
- * `MBall`, `MBall.001`, `MBall.002`, etc). The most important is to copy properties to the base
- * meta-ball, because this meta-ball influence polygonization of meta-balls. */
void BKE_mball_properties_copy(Scene *scene, Object *active_object)
{
Scene *sce_iter = scene;
@@ -499,14 +475,6 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
}
}
-/** \brief This function finds the basis MetaBall.
- *
- * Basis meta-ball doesn't include any number at the end of
- * its name. All meta-balls with same base of name can be
- * blended. meta-balls with different basic name can't be blended.
- *
- * \warning #BKE_mball_is_basis() can fail on returned object, see function docs for details.
- */
Object *BKE_mball_basis_find(Scene *scene, Object *object)
{
Object *bob = object;
@@ -571,7 +539,6 @@ bool BKE_mball_minmax_ex(
return changed;
}
-/* basic vertex data functions */
bool BKE_mball_minmax(const MetaBall *mb, float min[3], float max[3])
{
INIT_MINMAX(min, max);
@@ -646,7 +613,6 @@ void BKE_mball_translate(MetaBall *mb, const float offset[3])
}
}
-/* *** select funcs *** */
int BKE_mball_select_count(const MetaBall *mb)
{
int sel = 0;
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index a2590171abd..eebe6efad78 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -55,6 +55,8 @@
/* experimental (faster) normal calculation */
// #define USE_ACCUM_NORMAL
+#define MBALL_ARRAY_LEN_INIT 4096
+
/* Data types */
typedef struct corner { /* corner of a cube */
@@ -448,7 +450,7 @@ static void make_face(PROCESS *process, int i1, int i2, int i3, int i4)
#endif
if (UNLIKELY(process->totindex == process->curindex)) {
- process->totindex += 4096;
+ process->totindex = process->totindex ? (process->totindex * 2) : MBALL_ARRAY_LEN_INIT;
process->indices = MEM_reallocN(process->indices, sizeof(int[4]) * process->totindex);
}
@@ -946,8 +948,8 @@ static int getedge(EDGELIST *table[], int i1, int j1, int k1, int i2, int j2, in
*/
static void addtovertices(PROCESS *process, const float v[3], const float no[3])
{
- if (process->curvertex == process->totvertex) {
- process->totvertex += 4096;
+ if (UNLIKELY(process->curvertex == process->totvertex)) {
+ process->totvertex = process->totvertex ? process->totvertex * 2 : MBALL_ARRAY_LEN_INIT;
process->co = MEM_reallocN(process->co, process->totvertex * sizeof(float[3]));
process->no = MEM_reallocN(process->no, process->totvertex * sizeof(float[3]));
}
@@ -1447,6 +1449,16 @@ void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBa
/* add resulting surface to displist */
if (process.curindex) {
+
+ /* Avoid over-allocation since this is stored in the displist. */
+ if (process.curindex != process.totindex) {
+ process.indices = MEM_reallocN(process.indices, sizeof(int[4]) * process.curindex);
+ }
+ if (process.curvertex != process.totvertex) {
+ process.co = MEM_reallocN(process.co, process.curvertex * sizeof(float[3]));
+ process.no = MEM_reallocN(process.no, process.curvertex * sizeof(float[3]));
+ }
+
dl = MEM_callocN(sizeof(DispList), "mballdisp");
BLI_addtail(dispbase, dl);
dl->type = DL_INDEX4;
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 73e0c2cfa74..05aa9111fa3 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -48,6 +48,7 @@
#include "BLT_translation.h"
#include "BKE_anim_data.h"
+#include "BKE_bpath.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
@@ -183,6 +184,14 @@ static void mesh_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
+static void mesh_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Mesh *me = (Mesh *)id;
+ if (me->ldata.external) {
+ BKE_bpath_foreach_path_fixed_process(bpath_data, me->ldata.external->filename);
+ }
+}
+
static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Mesh *mesh = (Mesh *)id;
@@ -355,28 +364,33 @@ static void mesh_read_expand(BlendExpander *expander, ID *id)
}
IDTypeInfo IDType_ID_ME = {
- 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,
+ /* 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,
+ /* asset_type_info */ nullptr,
+
+ /* init_data */ mesh_init_data,
+ /* copy_data */ mesh_copy_data,
+ /* free_data */ mesh_free_data,
+ /* make_local */ nullptr,
+ /* foreach_id */ mesh_foreach_id,
+ /* foreach_cache */ nullptr,
+ /* foreach_path */ mesh_foreach_path,
+ /* owner_get */ nullptr,
+
+ /* 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 */ nullptr,
+
+ /* lib_override_apply_post */ nullptr,
};
enum {
@@ -438,13 +452,15 @@ static int customdata_compare(
const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic;
for (int i = 0; i < c1->totlayer; i++) {
- if (CD_TYPE_AS_MASK(c1->layers[i].type) & cd_mask_all_attr) {
+ l1 = &c1->layers[i];
+ if (CD_TYPE_AS_MASK(l1->type) & cd_mask_all_attr && l1->anonymous_id != nullptr) {
layer_count1++;
}
}
for (int i = 0; i < c2->totlayer; i++) {
- if (CD_TYPE_AS_MASK(c2->layers[i].type) & cd_mask_all_attr) {
+ l2 = &c2->layers[i];
+ if (CD_TYPE_AS_MASK(l1->type) & cd_mask_all_attr && l2->anonymous_id != nullptr) {
layer_count2++;
}
}
@@ -460,7 +476,8 @@ static int customdata_compare(
l1 = c1->layers + i1;
for (int i2 = 0; i2 < c2->totlayer; i2++) {
l2 = c2->layers + i2;
- if (l1->type != l2->type || !STREQ(l1->name, l2->name)) {
+ if (l1->type != l2->type || !STREQ(l1->name, l2->name) || l1->anonymous_id != nullptr ||
+ l2->anonymous_id != nullptr) {
continue;
}
/* At this point `l1` and `l2` have the same name and type, so they should be compared. */
@@ -673,12 +690,6 @@ static int customdata_compare(
return 0;
}
-/**
- * Used for unit testing; compares two meshes, checking only
- * differences we care about. should be usable with leaf's
- * testing framework I get RNA work done, will use hackish
- * testing code for now.
- */
const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
{
int c;
@@ -879,10 +890,6 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me)
return CustomData_has_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
}
-/**
- * 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(nullptr, me)` should be used.
- */
void BKE_mesh_free_data_for_undo(Mesh *me)
{
mesh_free_data(&me->id);
@@ -997,10 +1004,6 @@ Mesh *BKE_mesh_new_nomain(
return mesh;
}
-/**
- * Copy user editable settings that we want to preserve
- * when a new mesh is based on an existing mesh.
- */
void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src)
{
/* Copy general settings. */
@@ -1023,12 +1026,6 @@ void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src)
me_dst->vertex_group_active_index = me_src->vertex_group_active_index;
}
-/**
- * A version of #BKE_mesh_copy_parameters that is intended for evaluated output
- * (the modifier stack for example).
- *
- * \warning User counts are not handled for ID's.
- */
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
{
/* User counts aren't handled, don't copy into a mesh from #G_MAIN. */
@@ -1249,7 +1246,7 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_size[3])
}
}
-void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, float **r_size)
+void BKE_mesh_texspace_get_reference(Mesh *me, char **r_texflag, float **r_loc, float **r_size)
{
BKE_mesh_texspace_ensure(me);
@@ -1267,7 +1264,7 @@ void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc,
void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob)
{
float *texloc, *texsize;
- short *texflag;
+ char *texflag;
if (BKE_object_obdata_texspace_get(ob, &texflag, &texloc, &texsize)) {
me->texflag = *texflag;
@@ -1315,10 +1312,18 @@ void BKE_mesh_orco_verts_transform(Mesh *me, float (*orco)[3], int totvert, int
}
}
-/**
- * Rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0.
- * this is necessary to make the if #MFace.v4 check for quads work.
- */
+void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh)
+{
+ if (CustomData_has_layer(&mesh->vdata, CD_ORCO)) {
+ return;
+ }
+
+ /* Orcos are stored in normalized 0..1 range by convention. */
+ float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob);
+ BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false);
+ CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_ASSIGN, orcodata, mesh->totvert);
+}
+
int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex, int nr)
{
/* first test if the face is legal */
@@ -1522,10 +1527,6 @@ void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth)
}
}
-/**
- * Find the index of the loop in 'poly' which references vertex,
- * returns -1 if not found
- */
int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, uint vert)
{
for (int j = 0; j < poly->totloop; j++, loopstart++) {
@@ -1537,11 +1538,6 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, uint ver
return -1;
}
-/**
- * Fill \a r_adj with the loop indices in \a poly adjacent to the
- * vertex. Returns the index of the loop matching vertex, or -1 if the
- * vertex is not in \a poly
- */
int poly_get_adj_loops_from_vert(const MPoly *poly, const MLoop *mloop, uint vert, uint r_adj[2])
{
int corner = poly_find_loop_from_vert(poly, &mloop[poly->loopstart], vert);
@@ -1555,10 +1551,6 @@ int poly_get_adj_loops_from_vert(const MPoly *poly, const MLoop *mloop, uint ver
return corner;
}
-/**
- * Return the index of the edge vert that is not equal to \a v. If
- * neither edge vertex is equal to \a v, returns -1.
- */
int BKE_mesh_edge_other_vert(const MEdge *e, int v)
{
if (e->v1 == v) {
@@ -1571,9 +1563,6 @@ int BKE_mesh_edge_other_vert(const MEdge *e, int v)
return -1;
}
-/**
- * Sets each output array element to the edge index if it is a real edge, or -1.
- */
void BKE_mesh_looptri_get_real_edges(const Mesh *mesh, const MLoopTri *looptri, int r_edges[3])
{
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
@@ -1586,7 +1575,6 @@ void BKE_mesh_looptri_get_real_edges(const Mesh *mesh, const MLoopTri *looptri,
}
}
-/* basic vertex data functions */
bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3])
{
int i = me->totvert;
@@ -1768,9 +1756,6 @@ void BKE_mesh_mselect_validate(Mesh *me)
me->mselect = mselect_dst;
}
-/**
- * Return the index within me->mselect, or -1
- */
int BKE_mesh_mselect_find(Mesh *me, int index, int type)
{
BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
@@ -1784,9 +1769,6 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
return -1;
}
-/**
- * Return The index of the active element.
- */
int BKE_mesh_mselect_active_get(Mesh *me, int type)
{
BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
@@ -1887,13 +1869,6 @@ void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3])
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
}
-/**
- * Compute 'split' (aka loop, or per face corner's) normals.
- *
- * \param r_lnors_spacearr: Allows to get computed loop normal space array.
- * That data, among other things, contains 'smooth fan' info, useful e.g.
- * to split geometry along sharp edges...
- */
void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)
{
float(*r_loopnors)[3];
@@ -2169,12 +2144,6 @@ static void split_faces_split_new_edges(Mesh *mesh,
}
}
-/* Split faces based on the edge angle and loop normals.
- * Matches behavior of face splitting in render engines.
- *
- * NOTE: Will leave CD_NORMAL loop data layer which is
- * used by render engines to set shading up.
- */
void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
{
const int num_polys = mesh->totpoly;
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index 3086f117707..771d79a0445 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -807,16 +807,6 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
#endif // WITH_GMP
-/**
- * Do a mesh boolean operation directly on meshes (without going back and forth to BMesh).
- * \param meshes: An array of Mesh pointers.
- * \param obmats: An array of pointers to the obmat matrices that transform local
- * coordinates to global ones. It is allowed for the pointers to be null, meaning the
- * transformation is the identity.
- * \param material_remaps: An array of pointers to arrays of maps from material slot numbers in the
- * corresponding mesh to the material slot in the first mesh. It is OK for material_remaps or any
- * of its constituent arrays to be empty.
- */
Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
Span<const float4x4 *> obmats,
const float4x4 &target_transform,
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index 1769be54211..e8054884f26 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -1277,11 +1277,6 @@ static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
}
}
-/**
- * \param use_virtual_modifiers: When enabled calculate virtual-modifiers before applying `md_eval`
- * support this since virtual-modifiers are not modifiers from a user perspective,
- * allowing shape keys to be included with the modifier being applied, see: T91923.
- */
Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob_eval,
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc
index 91fd022a316..5cc1b4e4860 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.cc
+++ b/source/blender/blenkernel/intern/mesh_evaluate.cc
@@ -191,7 +191,6 @@ void BKE_mesh_calc_poly_center(const MPoly *mpoly,
}
}
-/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */
float BKE_mesh_calc_poly_area(const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray)
{
if (mpoly->totloop == 3) {
@@ -249,23 +248,6 @@ float BKE_mesh_calc_poly_uv_area(const MPoly *mpoly, const MLoopUV *uv_array)
return area;
}
-/**
- * Calculate the volume and volume-weighted centroid of the volume
- * formed by the polygon and the origin.
- * Results will be negative if the origin is "outside" the polygon
- * (+ve normal side), but the polygon may be non-planar with no effect.
- *
- * Method from:
- * - http://forums.cgsociety.org/archive/index.php?t-756235.html
- * - http://www.globalspec.com/reference/52702/203279/4-8-the-centroid-of-a-tetrahedron
- *
- * \note
- * - Volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid
- * (so division can be done once at the end).
- * - Results will have bias if polygon is non-planar.
- * - The resulting volume will only be correct if the mesh is manifold and has consistent
- * face winding (non-contiguous face normals or holes in the mesh surface).
- */
static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MPoly *mpoly,
const MLoop *loopstart,
const MVert *mvarray,
@@ -445,10 +427,6 @@ bool BKE_mesh_center_median(const Mesh *me, float r_cent[3])
return (me->totvert != 0);
}
-/**
- * Calculate the center from polygons,
- * use when we want to ignore vertex locations that don't have connected faces.
- */
bool BKE_mesh_center_median_from_polys(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
@@ -514,10 +492,6 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
return (me->totpoly != 0);
}
-/**
- * \note Mesh must be manifold with consistent face-winding,
- * see #mesh_calc_poly_volume_centroid for details.
- */
bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
@@ -602,12 +576,6 @@ static bool mesh_calc_center_centroid_ex(const MVert *mverts,
return true;
}
-/**
- * Calculate the volume and center.
- *
- * \param r_volume: Volume (unsigned).
- * \param r_center: Center of mass.
- */
void BKE_mesh_calc_volume(const MVert *mverts,
const int mverts_num,
const MLoopTri *looptri,
@@ -800,19 +768,6 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
BKE_mesh_update_customdata_pointers(mesh, true);
}
-/**
- * The same as #BKE_mesh_convert_mfaces_to_mpolys
- * but oriented to be used in #do_versions from `readfile.c`
- * the difference is how active/render/clone/stencil indices are handled here.
- *
- * normally they're being set from `pdata` which totally makes sense for meshes which are already
- * converted to #BMesh structures, but when loading older files indices shall be updated in other
- * way around, so newly added `pdata` and `ldata` would have this indices set
- * based on `fdata` layer.
- *
- * this is normally only needed when reading older files,
- * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used.
- */
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
{
BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id,
@@ -957,12 +912,9 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
#undef ME_FGON
}
+
/** \} */
-/**
- * Flip a single MLoop's #MDisps structure,
- * low level function to be called from face-flipping code which re-arranged the mdisps themselves.
- */
void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
{
if (UNLIKELY(!md->totdisp || !md->disps)) {
@@ -999,14 +951,6 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
}
}
-/**
- * Flip (invert winding of) the given \a mpoly, i.e. reverse order of its loops
- * (keeping the same vertex as 'start point').
- *
- * \param mpoly: the polygon to flip.
- * \param mloop: the full loops array.
- * \param ldata: the loops custom data.
- */
void BKE_mesh_polygon_flip_ex(MPoly *mpoly,
MLoop *mloop,
CustomData *ldata,
@@ -1056,11 +1000,6 @@ void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata)
BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, nullptr, mdisp, true);
}
-/**
- * Flip (invert winding of) all polygons (used to inverse their normals).
- *
- * \note Invalidates tessellation, caller must handle that.
- */
void BKE_mesh_polygons_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata, int totpoly)
{
MDisps *mdisp = (MDisps *)CustomData_get_layer(ldata, CD_MDISPS);
@@ -1076,8 +1015,6 @@ void BKE_mesh_polygons_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata, int t
/** \name Mesh Flag Flushing
* \{ */
-/* update the hide flag for edges and faces from the corresponding
- * flag in verts */
void BKE_mesh_flush_hidden_from_verts_ex(const MVert *mvert,
const MLoop *mloop,
MEdge *medge,
@@ -1149,9 +1086,6 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
me->mvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly);
}
-/**
- * simple poly -> vert/edge selection.
- */
void BKE_mesh_flush_select_from_polys_ex(MVert *mvert,
const int totvert,
const MLoop *mloop,
@@ -1248,23 +1182,13 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
BKE_mesh_flush_select_from_verts_ex(
me->mvert, me->totvert, me->mloop, me->medge, me->totedge, me->mpoly, me->totpoly);
}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Mesh Spatial Calculation
* \{ */
-/**
- * This function takes the difference between 2 vertex-coord-arrays
- * (\a vert_cos_src, \a vert_cos_dst),
- * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
- *
- * \param vert_cos_src: reference deform source.
- * \param vert_cos_dst: reference deform destination.
- *
- * \param vert_cos_org: reference for the output location.
- * \param vert_cos_new: resulting coords.
- */
void BKE_mesh_calc_relative_deform(const MPoly *mpoly,
const int totpoly,
const MLoop *mloop,
@@ -1318,4 +1242,5 @@ void BKE_mesh_calc_relative_deform(const MPoly *mpoly,
MEM_freeN(vert_accum);
}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c
index 7a776b0ecb7..3b6afc1f47a 100644
--- a/source/blender/blenkernel/intern/mesh_iterators.c
+++ b/source/blender/blenkernel/intern/mesh_iterators.c
@@ -34,7 +34,6 @@
#include "MEM_guardedalloc.h"
-/* Copied from cdDM_foreachMappedVert */
void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
void (*func)(void *userData,
int index,
@@ -95,11 +94,6 @@ void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
}
}
-/**
- * Copied from #cdDM_foreachMappedEdge.
- * \param tot_edges: Number of original edges. Used to avoid calling the callback with invalid
- * edge indices.
- */
void BKE_mesh_foreach_mapped_edge(
Mesh *mesh,
const int tot_edges,
@@ -151,7 +145,6 @@ void BKE_mesh_foreach_mapped_edge(
}
}
-/* Copied from cdDM_foreachMappedLoop */
void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
void (*func)(void *userData,
int vertex_index,
@@ -232,7 +225,6 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
}
}
-/* Copied from cdDM_foreachMappedFaceCenter */
void BKE_mesh_foreach_mapped_face_center(
Mesh *mesh,
void (*func)(void *userData, int index, const float cent[3], const float no[3]),
@@ -309,7 +301,6 @@ void BKE_mesh_foreach_mapped_face_center(
}
}
-/* Copied from cdDM_foreachMappedFaceCenter */
void BKE_mesh_foreach_mapped_subdiv_face_center(
Mesh *mesh,
void (*func)(void *userData, int index, const float cent[3], const float no[3]),
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index d28bb9c0744..415cce95d38 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -42,9 +42,6 @@
* \{ */
/* ngon version wip, based on BM_uv_vert_map_create */
-/* this replaces the non bmesh function (in trunk) which takes MTFace's,
- * if we ever need it back we could but for now this replaces it because its unused. */
-
UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
const MLoop *mloop,
const MLoopUV *mloopuv,
@@ -250,11 +247,6 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
*r_mem = indices;
}
-/**
- * Generates a map where the key is the vertex and the value
- * is a list of polys that use that vertex as a corner.
- * The lists are allocated from one memory pool.
- */
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const MPoly *mpoly,
@@ -266,11 +258,6 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
}
-/**
- * Generates a map where the key is the vertex and the value
- * is a list of loops that use that vertex as a corner.
- * The lists are allocated from one memory pool.
- */
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const MPoly *mpoly,
@@ -282,11 +269,6 @@ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
}
-/**
- * Generates a map where the key is the edge and the value
- * is a list of looptris that use that edge.
- * The lists are allocated from one memory pool.
- */
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
int **r_mem,
const MVert *UNUSED(mvert),
@@ -331,11 +313,6 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
*r_mem = indices;
}
-/**
- * Generates a map where the key is the vertex and the value
- * is a list of edges that use that vertex as an endpoint.
- * The lists are allocated from one memory pool.
- */
void BKE_mesh_vert_edge_map_create(
MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
{
@@ -375,10 +352,6 @@ void BKE_mesh_vert_edge_map_create(
*r_mem = indices;
}
-/**
- * A version of #BKE_mesh_vert_edge_map_create that references connected vertices directly
- * (not their edges).
- */
void BKE_mesh_vert_edge_vert_map_create(
MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
{
@@ -418,11 +391,6 @@ void BKE_mesh_vert_edge_vert_map_create(
*r_mem = indices;
}
-/**
- * Generates a map where the key is the edge and the value is a list of loops that use that edge.
- * Loops indices of a same poly are contiguous and in winding order.
- * The lists are allocated from one memory pool.
- */
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const MEdge *UNUSED(medge),
@@ -476,11 +444,6 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
*r_mem = indices;
}
-/**
- * Generates a map where the key is the edge and the value
- * is a list of polygons that use that edge.
- * The lists are allocated from one memory pool.
- */
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const MEdge *UNUSED(medge),
@@ -529,20 +492,6 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
*r_mem = indices;
}
-/**
- * This function creates a map so the source-data (vert/edge/loop/poly)
- * can loop over the destination data (using the destination arrays origindex).
- *
- * This has the advantage that it can operate on any data-types.
- *
- * \param totsource: The total number of elements that \a final_origindex points to.
- * \param totfinal: The size of \a final_origindex
- * \param final_origindex: The size of the final array.
- *
- * \note `totsource` could be `totpoly`,
- * `totfinal` could be `tottessface` and `final_origindex` its ORIGINDEX custom-data.
- * This would allow an MPoly to loop over its tessfaces.
- */
void BKE_mesh_origindex_map_create(MeshElemMap **r_map,
int **r_mem,
const int totsource,
@@ -584,10 +533,6 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map,
*r_mem = indices;
}
-/**
- * A version of #BKE_mesh_origindex_map_create that takes a looptri array.
- * Making a poly -> looptri map.
- */
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
int **r_mem,
const MPoly *mpoly,
@@ -630,7 +575,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
typedef bool (*MeshRemap_CheckIslandBoundary)(const struct MPoly *mpoly,
const struct MLoop *mloop,
const struct MEdge *medge,
- const int nbr_egde_users,
+ const int nbr_edge_users,
const struct MPoly *mpoly_array,
const struct MeshElemMap *edge_poly_map,
void *user_data);
@@ -833,14 +778,14 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
const MLoop *UNUSED(ml),
const MEdge *me,
- const int nbr_egde_users,
+ const int nbr_edge_users,
const MPoly *mpoly_array,
const MeshElemMap *edge_poly_map,
void *UNUSED(user_data))
{
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
* or edge is not used by exactly two polygons. */
- if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (nbr_egde_users == 2)) {
+ if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (nbr_edge_users == 2)) {
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
&mpoly_array[edge_poly_map->indices[1]] :
@@ -850,14 +795,6 @@ static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
return true;
}
-/**
- * Calculate smooth groups from sharp edges.
- *
- * \param r_totgroup: The total number of groups, 1 or more.
- * \return Polygon aligned array of group index values (bitflags if use_bitflags is true),
- * starting at 1 (0 being used as 'invalid' flag).
- * Note it's callers's responsibility to MEM_freeN returned array.
- */
int *BKE_mesh_calc_smoothgroups(const MEdge *medge,
const int totedge,
const MPoly *mpoly,
@@ -1012,7 +949,7 @@ typedef struct MeshCheckIslandBoundaryUv {
static bool mesh_check_island_boundary_uv(const MPoly *UNUSED(mp),
const MLoop *ml,
const MEdge *me,
- const int UNUSED(nbr_egde_users),
+ const int UNUSED(nbr_edge_users),
const MPoly *UNUSED(mpoly_array),
const MeshElemMap *UNUSED(edge_poly_map),
void *user_data)
@@ -1202,10 +1139,6 @@ static bool mesh_calc_islands_loop_poly_uv(MVert *UNUSED(verts),
return true;
}
-/**
- * Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams),
- * not some UV layers coordinates.
- */
bool BKE_mesh_calc_islands_loop_poly_edgeseam(MVert *verts,
const int totvert,
MEdge *edges,
@@ -1220,19 +1153,6 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(MVert *verts,
verts, totvert, edges, totedge, polys, totpoly, loops, totloop, NULL, r_island_store);
}
-/**
- * Calculate UV islands.
- *
- * \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries.
- * This has the advantages of simplicity, and being valid/common to all UV maps.
- * However, it means actual UV islands without matching UV seams will not be handled correctly...
- * If a valid UV layer is passed as \a luvs parameter,
- * UV coordinates are also used to detect islands boundaries.
- *
- * \note All this could be optimized...
- * Not sure it would be worth the more complex code, though,
- * those loops are supposed to be really quick to do...
- */
bool BKE_mesh_calc_islands_loop_poly_uvmap(MVert *verts,
const int totvert,
MEdge *edges,
diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c
index d3d835378ca..0115a70a52a 100644
--- a/source/blender/blenkernel/intern/mesh_merge.c
+++ b/source/blender/blenkernel/intern/mesh_merge.c
@@ -204,38 +204,6 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2)
return true;
}
-/**
- * Merge Verts
- *
- * This frees the given mesh and returns a new mesh.
- *
- * \param vtargetmap: The table that maps vertices to target vertices. a value of -1
- * indicates a vertex is a target, and is to be kept.
- * This array is aligned with 'mesh->totvert'
- * \warning \a vtargetmap must **not** contain any chained mapping (v1 -> v2 -> v3 etc.),
- * this is not supported and will likely generate corrupted geometry.
- *
- * \param tot_vtargetmap: The number of non '-1' values in vtargetmap. (not the size)
- *
- * \param merge_mode: enum with two modes.
- * - #MESH_MERGE_VERTS_DUMP_IF_MAPPED
- * When called by the Mirror Modifier,
- * In this mode it skips any faces that have all vertices merged (to avoid creating pairs
- * of faces sharing the same set of vertices)
- * - #MESH_MERGE_VERTS_DUMP_IF_EQUAL
- * When called by the Array Modifier,
- * In this mode, faces where all vertices are merged are double-checked,
- * to see whether all target vertices actually make up a poly already.
- * Indeed it could be that all of a poly's vertices are merged,
- * but merged to vertices that do not make up a single poly,
- * in which case the original poly should not be dumped.
- * Actually this later behavior could apply to the Mirror Modifier as well,
- * but the additional checks are costly and not necessary in the case of mirror,
- * because each vertex is only merged to its own mirror.
- *
- * \note #BKE_mesh_tessface_calc_ex has to run on the returned DM
- * if you want to access tessfaces.
- */
Mesh *BKE_mesh_merge_verts(Mesh *mesh,
const int *vtargetmap,
const int tot_vtargetmap,
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index 6df13e71e72..2d4308945fc 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -130,14 +130,11 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
BM_mesh_free(bm);
}
-/**
- * \warning This should _not_ be used to modify original meshes since
- * it doesn't handle shape-keys, use #BKE_mesh_mirror_apply_mirror_on_axis instead.
- */
Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
Object *ob,
const Mesh *mesh,
- const int axis)
+ const int axis,
+ const bool use_correct_order_on_merge)
{
const float tolerance_sq = mmd->tolerance * mmd->tolerance;
const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0;
@@ -266,23 +263,46 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
* Always merge from the copied into the original vertices so it's possible to
* generate a 1:1 mapping by scanning vertices from the beginning of the array
* as is done in #BKE_editmesh_vert_coords_when_deformed. Without this,
- * the coordinates returned will sometimes point to the copied vertex locations, see: T91444.
+ * the coordinates returned will sometimes point to the copied vertex locations, see:
+ * T91444.
+ *
+ * However, such a change also affects non-versionable things like some modifiers binding, so
+ * we cannot enforce that behavior on existing modifiers, in which case we keep using the
+ * old, incorrect behavior of merging the source vertex into its copy.
*/
- if (UNLIKELY(len_squared_v3v3(mv_prev->co, mv->co) < tolerance_sq)) {
- *vtmap_b = i;
- tot_vtargetmap++;
+ if (use_correct_order_on_merge) {
+ if (UNLIKELY(len_squared_v3v3(mv_prev->co, mv->co) < tolerance_sq)) {
+ *vtmap_b = i;
+ tot_vtargetmap++;
+
+ /* average location */
+ mid_v3_v3v3(mv->co, mv_prev->co, mv->co);
+ copy_v3_v3(mv_prev->co, mv->co);
+ }
+ else {
+ *vtmap_b = -1;
+ }
- /* average location */
- mid_v3_v3v3(mv->co, mv_prev->co, mv->co);
- copy_v3_v3(mv_prev->co, mv->co);
+ /* Fill here to avoid 2x loops. */
+ *vtmap_a = -1;
}
else {
+ if (UNLIKELY(len_squared_v3v3(mv_prev->co, mv->co) < tolerance_sq)) {
+ *vtmap_a = maxVerts + i;
+ tot_vtargetmap++;
+
+ /* average location */
+ mid_v3_v3v3(mv->co, mv_prev->co, mv->co);
+ copy_v3_v3(mv_prev->co, mv->co);
+ }
+ else {
+ *vtmap_a = -1;
+ }
+
+ /* Fill here to avoid 2x loops. */
*vtmap_b = -1;
}
- /* Fill here to avoid 2x loops. */
- *vtmap_a = -1;
-
vtmap_a++;
vtmap_b++;
}
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index 9a761c6fa11..da5b4ccc764 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -316,9 +316,6 @@ void BKE_mesh_ensure_normals(Mesh *mesh)
BLI_assert((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) == 0);
}
-/**
- * Called after calculating all modifiers.
- */
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
{
switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
@@ -378,10 +375,6 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
}
}
-/**
- * NOTE: this does not update the #CD_NORMAL layer,
- * but does update the normals in the #CD_MVERT layer.
- */
void BKE_mesh_calc_normals(Mesh *mesh)
{
#ifdef DEBUG_TIME
@@ -479,13 +472,6 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
lnors_spacearr->data_type = data_type;
}
-/**
- * Utility for multi-threaded calculation that ensures
- * `lnors_spacearr_tls` doesn't share memory with `lnors_spacearr`
- * that would cause it not to be thread safe.
- *
- * \note This works as long as threads never operate on the same loops at once.
- */
void BKE_lnor_spacearr_tls_init(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpaceArray *lnors_spacearr_tls)
{
@@ -493,10 +479,6 @@ void BKE_lnor_spacearr_tls_init(MLoopNorSpaceArray *lnors_spacearr,
lnors_spacearr_tls->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
-/**
- * Utility for multi-threaded calculation
- * that merges `lnors_spacearr_tls` into `lnors_spacearr`.
- */
void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpaceArray *lnors_spacearr_tls)
{
@@ -537,11 +519,6 @@ MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
/* This threshold is a bit touchy (usual float precision issue), this value seems OK. */
#define LNOR_SPACE_TRIGO_THRESHOLD (1.0f - 1e-4f)
-/* Should only be called once.
- * Beware, this modifies ref_vec and other_vec in place!
- * In case no valid space can be generated, ref_alpha and ref_beta are set to zero
- * (which means 'use auto lnors').
- */
void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
const float lnor[3],
float vec_ref[3],
@@ -614,14 +591,6 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
}
}
-/**
- * Add a new given loop to given lnor_space.
- * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct
- * (in case of BMLOOP_PTR), or nullptr (in case of LOOP_INDEX), loop index is then stored in
- * pointer. If \a is_single is set, the BMLoop or loop index is directly stored in \a
- * lnor_space->loops pointer (since there is only one loop in this fan), else it is added to the
- * linked list of loops in the fan.
- */
void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpace *lnor_space,
const int ml_index,
@@ -901,12 +870,6 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
}
}
-/**
- * Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
- *
- * Used when defining an empty custom loop normals data layer,
- * to keep same shading as with auto-smooth!
- */
void BKE_edges_sharp_from_angle_set(const struct MVert *mverts,
const int UNUSED(numVerts),
struct MEdge *medges,
@@ -1568,11 +1531,6 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
#endif
}
-/**
- * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
- * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
- * (splitting edges).
- */
void BKE_mesh_normals_loop_split(const MVert *mverts,
const int UNUSED(numVerts),
MEdge *medges,
@@ -2057,36 +2015,16 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
}
}
-/**
- * Higher level functions hiding most of the code needed around call to
- * #BKE_mesh_normals_loop_custom_set().
- *
- * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there
- * with automatically computed vectors.
- */
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3])
{
mesh_set_custom_normals(mesh, r_custom_loopnors, false);
}
-/**
- * Higher level functions hiding most of the code needed around call to
- * #BKE_mesh_normals_loop_custom_from_vertices_set().
- *
- * \param r_custom_vertnors: is not const, since code will replace zero_v3 normals there
- * with automatically computed vectors.
- */
void BKE_mesh_set_custom_normals_from_vertices(Mesh *mesh, float (*r_custom_vertnors)[3])
{
mesh_set_custom_normals(mesh, r_custom_vertnors, true);
}
-/**
- * Computes average per-vertex normals from given custom loop normals.
- *
- * \param clnors: The computed custom loop normals.
- * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals.
- */
void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const MLoop *mloops,
const int numLoops,
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index 53a31cbbc7a..5b5378bd829 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -50,7 +50,7 @@
static CLG_LogRef LOG = {"bke.mesh"};
/* -------------------------------------------------------------------- */
-/** \name Some generic helpers.
+/** \name Some Generic Helpers
* \{ */
static bool mesh_remap_bvhtree_query_nearest(BVHTreeFromMesh *treedata,
@@ -117,22 +117,12 @@ static bool mesh_remap_bvhtree_query_raycast(BVHTreeFromMesh *treedata,
/** \} */
-/**
- * \name Auto-match.
+/* -------------------------------------------------------------------- */
+/** \name Auto-match.
*
* Find transform of a mesh to get best match with another.
* \{ */
-/**
- * Compute a value of the difference between both given meshes.
- * The smaller the result, the better the match.
- *
- * We return the inverse of the average of the inversed
- * shortest distance from each dst vertex to src ones.
- * In other words, beyond a certain (relatively small) distance, all differences have more or less
- * the same weight in final result, which allows to reduce influence of a few high differences,
- * in favor of a global good matching.
- */
float BKE_mesh_remap_calc_difference_from_mesh(const SpaceTransform *space_transform,
const MVert *verts_dst,
const int numverts_dst,
@@ -268,9 +258,6 @@ static void mesh_calc_eigen_matrix(const MVert *verts,
copy_v3_v3(r_mat[3], center);
}
-/**
- * Set r_space_transform so that best bbox of dst matches best bbox of src.
- */
void BKE_mesh_remap_find_best_match_from_mesh(const MVert *verts_dst,
const int numverts_dst,
Mesh *me_src,
@@ -328,7 +315,7 @@ void BKE_mesh_remap_find_best_match_from_mesh(const MVert *verts_dst,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Mesh to mesh mapping
+/** \name Mesh to Mesh Mapping
* \{ */
void BKE_mesh_remap_calc_source_cddata_masks_from_map_modes(const int UNUSED(vert_mode),
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index 7b1d5140421..45c84ed0862 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -74,28 +74,17 @@ static void mesh_runtime_free_mutexes(Mesh *mesh)
}
}
-/**
- * \brief Initialize the runtime of the given mesh.
- *
- * Function expects that the runtime is already cleared.
- */
void BKE_mesh_runtime_init_data(Mesh *mesh)
{
mesh_runtime_init_mutexes(mesh);
}
-/**
- * \brief Free all data (and mutexes) inside the runtime of the given mesh.
- */
void BKE_mesh_runtime_free_data(Mesh *mesh)
{
BKE_mesh_runtime_clear_cache(mesh);
mesh_runtime_free_mutexes(mesh);
}
-/* Clear all pointers which we don't want to be shared on copying the datablock.
- * However, keep all the flags which defines what the mesh is (for example, that
- * it's deformed only, or that its custom data layers are out of date.) */
void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
{
Mesh_Runtime *runtime = &mesh->runtime;
@@ -111,11 +100,6 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
mesh_runtime_init_mutexes(mesh);
}
-/**
- * \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)
{
if (mesh->runtime.mesh_eval != NULL) {
@@ -128,7 +112,6 @@ void BKE_mesh_runtime_clear_cache(Mesh *mesh)
BKE_mesh_runtime_clear_edit_data(mesh);
}
-/* This is a ported copy of DM_ensure_looptri_data(dm) */
/**
* Ensure the array is large enough
*
@@ -137,6 +120,7 @@ void BKE_mesh_runtime_clear_cache(Mesh *mesh)
*/
static void mesh_ensure_looptri_data(Mesh *mesh)
{
+ /* This is a ported copy of `DM_ensure_looptri_data(dm)`. */
const uint totpoly = mesh->totpoly;
const int looptris_len = poly_to_tri_count(totpoly, mesh->totloop);
@@ -162,7 +146,6 @@ static void mesh_ensure_looptri_data(Mesh *mesh)
}
}
-/* This is a ported copy of CDDM_recalc_looptri(dm). */
void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
{
mesh_ensure_looptri_data(mesh);
@@ -182,9 +165,9 @@ void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
mesh->runtime.looptris.array_wip = NULL;
}
-/* This is a ported copy of dm_getNumLoopTri(dm). */
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
{
+ /* This is a ported copy of `dm_getNumLoopTri(dm)`. */
const int looptri_len = poly_to_tri_count(mesh->totpoly, mesh->totloop);
BLI_assert(ELEM(mesh->runtime.looptris.len, 0, looptri_len));
return looptri_len;
@@ -196,11 +179,6 @@ static void mesh_runtime_looptri_recalc_isolated(void *userdata)
BKE_mesh_runtime_looptri_recalc(mesh);
}
-/**
- * \note This function only fills a cache, and therefore the mesh argument can
- * be considered logically const. Concurrent access is protected by a mutex.
- * \note This is a ported copy of dm_getLoopTriArray(dm).
- */
const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
{
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
@@ -222,7 +200,6 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
return looptri;
}
-/* This is a copy of DM_verttri_from_looptri(). */
void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
const MLoop *mloop,
const MLoopTri *looptri,
@@ -314,10 +291,10 @@ void BKE_mesh_batch_cache_free(Mesh *me)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Mesh runtime debug helpers.
+/** \name Mesh Runtime Debug Helpers
* \{ */
-/* evaluated mesh info printing function,
- * to help track down differences output */
+
+/* Evaluated mesh info printing function, to help track down differences output. */
#ifndef NDEBUG
# include "BLI_dynstr.h"
@@ -412,7 +389,6 @@ void BKE_mesh_runtime_debug_print(Mesh *me_eval)
MEM_freeN(str);
}
-/* XXX Should go in customdata file? */
void BKE_mesh_runtime_debug_print_cdlayers(CustomData *data)
{
int i;
diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c
index e5e971fd574..c7a1b22dad1 100644
--- a/source/blender/blenkernel/intern/mesh_tangent.c
+++ b/source/blender/blenkernel/intern/mesh_tangent.c
@@ -115,12 +115,6 @@ static void set_tspace(const SMikkTSpaceContext *pContext,
p_res[3] = face_sign;
}
-/**
- * Compute simplified tangent space normals, i.e.
- * tangent vector + sign of bi-tangent one, which combined with
- * split normals can be used to recreate the full tangent space.
- * NOTE: * The mesh should be made of only tris and quads!
- */
void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts,
const int UNUSED(numVerts),
const MLoop *mloops,
@@ -172,12 +166,6 @@ void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts,
}
}
-/**
- * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boiling code.
- * \note
- * - There must be a valid loop's CD_NORMALS available.
- * - The mesh should be made of only tris and quads!
- */
void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
const char *uvmap,
float (*r_looptangents)[4],
@@ -485,12 +473,6 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
}
}
-/**
- * Here we get some useful information such as active uv layer name and
- * search if it is already in tangent_names.
- * Also, we calculate tangent_mask that works as a descriptor of tangents state.
- * If tangent_mask has changed, then recalculate tangents.
- */
void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
@@ -564,9 +546,6 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
}
}
-/**
- * See: #BKE_editmesh_loop_tangent_calc (matching logic).
- */
void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert,
const MPoly *mpoly,
const uint mpoly_len,
diff --git a/source/blender/blenkernel/intern/mesh_tessellate.c b/source/blender/blenkernel/intern/mesh_tessellate.c
index 213f2929d63..241aefc418c 100644
--- a/source/blender/blenkernel/intern/mesh_tessellate.c
+++ b/source/blender/blenkernel/intern/mesh_tessellate.c
@@ -154,17 +154,6 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
}
}
-/**
- * Recreate #MFace Tessellation.
- *
- * \param do_face_nor_copy: Controls whether the normals from the poly
- * are copied to the tessellated faces.
- *
- * \return number of tessellation faces.
- *
- * \note This doesn't use multi-threading like #BKE_mesh_recalc_looptri since
- * it's not used in many places and #MFace should be phased out.
- */
int BKE_mesh_tessface_calc_ex(CustomData *fdata,
CustomData *ldata,
CustomData *pdata,
@@ -712,9 +701,6 @@ static void mesh_recalc_looptri__multi_threaded(const MLoop *mloop,
&settings);
}
-/**
- * Calculate tessellation into #MLoopTri which exist only for this purpose.
- */
void BKE_mesh_recalc_looptri(const MLoop *mloop,
const MPoly *mpoly,
const MVert *mvert,
@@ -730,14 +716,6 @@ void BKE_mesh_recalc_looptri(const MLoop *mloop,
}
}
-/**
- * A version of #BKE_mesh_recalc_looptri which takes pre-calculated polygon normals
- * (used to avoid having to calculate the face normal for NGON tessellation).
- *
- * \note Only use this function if normals have already been calculated, there is no need
- * to calculate normals just to use this function as it will cause the normals for triangles
- * to be calculated which aren't needed for tessellation.
- */
void BKE_mesh_recalc_looptri_with_normals(const MLoop *mloop,
const MPoly *mpoly,
const MVert *mvert,
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 08668d55cf4..ba86c0fd449 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -193,6 +193,7 @@ static int search_polyloop_cmp(const void *v1, const void *v2)
/* Else, sort on loopstart. */
return sp1->loopstart > sp2->loopstart ? 1 : sp1->loopstart < sp2->loopstart ? -1 : 0;
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -213,21 +214,6 @@ static int search_polyloop_cmp(const void *v1, const void *v2)
} \
} while (0)
-/**
- * Validate the mesh, \a do_fixes requires \a mesh to be non-null.
- *
- * \return false if no changes needed to be made.
- *
- * Vertex Normals
- * ==============
- *
- * While zeroed normals are checked, these checks aren't comprehensive.
- * Technically, to detect errors here a normal recalculation and comparison is necessary.
- * However this function is mainly to prevent severe errors in geometry
- * (invalid data that will crash Blender, or cause some features to behave incorrectly),
- * not to detect subtle differences in the resulting normals which could be caused
- * by importers that load normals (for example).
- */
/* NOLINTNEXTLINE: readability-function-size */
bool BKE_mesh_validate_arrays(Mesh *mesh,
MVert *mverts,
@@ -997,9 +983,6 @@ static bool mesh_validate_customdata(CustomData *data,
return is_valid;
}
-/**
- * \returns is_valid.
- */
bool BKE_mesh_validate_all_customdata(CustomData *vdata,
const uint totvert,
CustomData *edata,
@@ -1061,11 +1044,6 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata,
return is_valid;
}
-/**
- * Validates and corrects a Mesh.
- *
- * \returns true if a change is made.
- */
bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_mask)
{
bool is_valid = true;
@@ -1112,13 +1090,6 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_
return false;
}
-/**
- * Checks if a Mesh is valid without any modification. This is always verbose.
- *
- * \see #DM_is_valid to call on derived meshes
- *
- * \returns is_valid.
- */
bool BKE_mesh_is_valid(Mesh *me)
{
const bool do_verbose = true;
@@ -1162,10 +1133,6 @@ bool BKE_mesh_is_valid(Mesh *me)
return is_valid;
}
-/**
- * Check all material indices of polygons are valid, invalid ones are set to 0.
- * \returns is_valid.
- */
bool BKE_mesh_validate_material_indices(Mesh *me)
{
/* Cast to unsigned to catch negative indices too. */
@@ -1196,9 +1163,9 @@ bool BKE_mesh_validate_material_indices(Mesh *me)
/** \name Mesh Stripping (removing invalid data)
* \{ */
-/* We need to keep this for edge creation (for now?), and some old readfile code... */
void BKE_mesh_strip_loose_faces(Mesh *me)
{
+ /* NOTE: We need to keep this for edge creation (for now?), and some old `readfile.c` code. */
MFace *f;
int a, b;
@@ -1217,13 +1184,6 @@ void BKE_mesh_strip_loose_faces(Mesh *me)
}
}
-/**
- * Works on both loops and polys!
- *
- * \note It won't try to guess which loops of an invalid poly to remove!
- * this is the work of the caller, to mark those loops...
- * See e.g. #BKE_mesh_validate_arrays().
- */
void BKE_mesh_strip_loose_polysloops(Mesh *me)
{
MPoly *p;
@@ -1329,6 +1289,7 @@ void BKE_mesh_strip_loose_edges(Mesh *me)
MEM_freeN(new_idx);
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1512,10 +1473,6 @@ static void mesh_calc_edges_mdata(MVert *UNUSED(allvert),
*r_totedge = totedge_final;
}
-/**
- * If the mesh is from a very old blender version,
- * convert mface->edcode to edge drawflags
- */
void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
{
MEdge *medge;
@@ -1565,12 +1522,6 @@ void BKE_mesh_calc_edges_loose(Mesh *mesh)
}
}
-/**
- * Calculate/create edges from tessface data
- *
- * \param mesh: The mesh to add edges into
- */
-
void BKE_mesh_calc_edges_tessface(Mesh *mesh)
{
const int numFaces = mesh->totface;
diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc
index 574ab785445..c8fae3cf880 100644
--- a/source/blender/blenkernel/intern/mesh_validate.cc
+++ b/source/blender/blenkernel/intern/mesh_validate.cc
@@ -220,9 +220,6 @@ static void clear_hash_tables(MutableSpan<EdgeMap> edge_maps)
} // namespace blender::bke::calc_edges
-/**
- * Calculate edges from polygons.
- */
void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select_new_edges)
{
using namespace blender;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 6f6cf12f023..e1d201d7806 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -133,9 +133,6 @@ const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type)
return NULL;
}
-/**
- * Get the idname of the modifier type's panel, which was defined in the #panelRegister callback.
- */
void BKE_modifier_type_panel_id(ModifierType type, char *r_idname)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
@@ -213,9 +210,6 @@ void BKE_modifier_free(ModifierData *md)
BKE_modifier_free_ex(md, 0);
}
-/**
- * Use instead of `BLI_remlink` when the object's active modifier should change.
- */
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
{
BLI_assert(BLI_findindex(&ob->modifiers, md) != -1);
@@ -328,9 +322,6 @@ void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *userData
}
}
-/* callback's can use this
- * to avoid copying every member.
- */
void BKE_modifier_copydata_generic(const ModifierData *md_src,
ModifierData *md_dst,
const int UNUSED(flag))
@@ -457,13 +448,6 @@ void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *_for
CLOG_ERROR(&LOG, "Object: \"%s\", Modifier: \"%s\", %s", ob->id.name + 2, md->name, md->error);
}
-/* used for buttons, to find out if the 'draw deformed in editmode' option is
- * there
- *
- * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
- * then is NULL)
- * also used for some mesh tools to give warnings
- */
int BKE_modifiers_get_cage_index(const Scene *scene,
Object *ob,
int *r_lastPossibleCageIndex,
@@ -547,12 +531,6 @@ bool BKE_modifiers_is_particle_enabled(Object *ob)
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
-/**
- * Check whether is enabled.
- *
- * \param scene: Current scene, may be NULL,
- * in which case isDisabled callback of the modifier is never called.
- */
bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int required_mode)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
@@ -575,12 +553,6 @@ bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int re
return true;
}
-/**
- * Check whether given modifier is not local (i.e. from linked data) when the object is a library
- * override.
- *
- * \param md: May be NULL, in which case we consider it as a non-local modifier case.
- */
bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md)
{
return (ID_IS_OVERRIDE_LIBRARY(ob) &&
@@ -674,8 +646,6 @@ ModifierData *BKE_modifier_get_last_preview(const struct Scene *scene,
return tmp_md;
}
-/* This is to include things that are not modifiers in the evaluation of the modifier stack, for
- * example parenting to an armature. */
ModifierData *BKE_modifiers_get_virtual_modifierlist(const Object *ob,
VirtualModifierData *virtualModifierData)
{
@@ -719,9 +689,6 @@ ModifierData *BKE_modifiers_get_virtual_modifierlist(const Object *ob,
return md;
}
-/* Takes an object and returns its first selected armature, else just its armature
- * This should work for multiple armatures per object
- */
Object *BKE_modifiers_is_deformed_by_armature(Object *ob)
{
if (ob->type == OB_GPENCIL) {
@@ -790,9 +757,6 @@ Object *BKE_modifiers_is_deformed_by_meshdeform(Object *ob)
return NULL;
}
-/* Takes an object and returns its first selected lattice, else just its lattice
- * This should work for multiple lattices per object
- */
Object *BKE_modifiers_is_deformed_by_lattice(Object *ob)
{
VirtualModifierData virtualModifierData;
@@ -816,9 +780,6 @@ Object *BKE_modifiers_is_deformed_by_lattice(Object *ob)
return NULL;
}
-/* Takes an object and returns its first selected curve, else just its curve
- * This should work for multiple curves per object
- */
Object *BKE_modifiers_is_deformed_by_curve(Object *ob)
{
VirtualModifierData virtualModifierData;
@@ -946,7 +907,6 @@ void BKE_modifier_free_temporary_data(ModifierData *md)
}
}
-/* ensure modifier correctness when changing ob->data */
void BKE_modifiers_test_object(Object *ob)
{
ModifierData *md;
@@ -967,45 +927,29 @@ void BKE_modifiers_test_object(Object *ob)
}
}
-/* where should this go?, it doesn't fit well anywhere :S - campbell */
-
-/* elubie: changed this to default to the same dir as the render output
- * to prevent saving to C:\ on Windows */
-
-/* campbell: logic behind this...
- *
- * - if the ID is from a library, return library path
- * - else if the file has been saved return the blend file path.
- * - else if the file isn't saved and the ID isn't from a library, return the temp dir.
- */
const char *BKE_modifier_path_relbase(Main *bmain, Object *ob)
{
- if (G.relbase_valid || ID_IS_LINKED(ob)) {
+ /* - If the ID is from a library, return library path.
+ * - Else if the file has been saved return the blend file path.
+ * - Else if the file isn't saved and the ID isn't from a library, return the temp dir.
+ */
+ if ((bmain->filepath[0] != '\0') || ID_IS_LINKED(ob)) {
return ID_BLEND_PATH(bmain, &ob->id);
}
- /* last resort, better than using "" which resolves to the current
- * working directory */
+ /* Last resort, better than using "" which resolves to the current working directory. */
return BKE_tempdir_session();
}
const char *BKE_modifier_path_relbase_from_global(Object *ob)
{
- if (G.relbase_valid || ID_IS_LINKED(ob)) {
- return ID_BLEND_PATH_FROM_GLOBAL(&ob->id);
- }
-
- /* last resort, better than using "" which resolves to the current
- * working directory */
- return BKE_tempdir_session();
+ return BKE_modifier_path_relbase(G_MAIN, ob);
}
-/* initializes the path with either */
void BKE_modifier_path_init(char *path, int path_maxlen, const char *name)
{
- /* elubie: changed this to default to the same dir as the render output
- * to prevent saving to C:\ on Windows */
- BLI_join_dirfile(path, path_maxlen, G.relbase_valid ? "//" : BKE_tempdir_session(), name);
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ BLI_join_dirfile(path, path_maxlen, blendfile_path[0] ? "//" : BKE_tempdir_session(), name);
}
/**
@@ -1086,15 +1030,6 @@ void BKE_modifier_deform_vertsEM(ModifierData *md,
/* end modifier callback wrappers */
-/**
- * Get evaluated mesh for other evaluated object, which is used as an operand for the modifier,
- * e.g. second operand for boolean modifier.
- * Note that modifiers in stack always get fully evaluated COW ID pointers,
- * never original ones. Makes things simpler.
- *
- * \param get_cage_mesh: Return evaluated mesh with only deforming modifiers applied
- * (i.e. mesh topology remains the same as original one, a.k.a. 'cage' mesh).
- */
Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval,
const bool get_cage_mesh)
{
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 34fb9f71bd9..fc2e7d0a6a3 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -60,6 +60,7 @@
#include "BLT_translation.h"
#include "BKE_anim_data.h"
+#include "BKE_bpath.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
@@ -165,6 +166,12 @@ static void movie_clip_foreach_cache(ID *id,
function_callback(id, &key, (void **)&movie_clip->tracking.camera.intrinsics, 0, user_data);
}
+static void movie_clip_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ MovieClip *movie_clip = (MovieClip *)id;
+ BKE_bpath_foreach_path_fixed_process(bpath_data, movie_clip->filepath);
+}
+
static void write_movieTracks(BlendWriter *writer, ListBase *tracks)
{
MovieTrackingTrack *track;
@@ -347,6 +354,7 @@ IDTypeInfo IDType_ID_MC = {
.name_plural = "movieclips",
.translation_context = BLT_I18NCONTEXT_ID_MOVIECLIP,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = movie_clip_init_data,
.copy_data = movie_clip_copy_data,
@@ -354,6 +362,7 @@ IDTypeInfo IDType_ID_MC = {
.make_local = NULL,
.foreach_id = movie_clip_foreach_id,
.foreach_cache = movie_clip_foreach_cache,
+ .foreach_path = movie_clip_foreach_path,
.owner_get = NULL,
.blend_write = movieclip_blend_write,
@@ -535,10 +544,6 @@ static void movieclip_convert_multilayer_add_pass(void *UNUSED(layer),
#endif /* WITH_OPENEXR */
-/* Will try to make image buffer usable when originating from the multi-layer
- * source.
- * Internally finds a first combined pass and uses that as a buffer. Not ideal,
- * but is better than a complete empty buffer. */
void BKE_movieclip_convert_multilayer_ibuf(struct ImBuf *ibuf)
{
if (ibuf == NULL) {
@@ -979,10 +984,6 @@ static void detect_clip_source(Main *bmain, MovieClip *clip)
}
}
-/* checks if image was already loaded, then returns same image
- * otherwise creates new.
- * does not load ibuf itself
- * pass on optional frame for #name images */
MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
{
MovieClip *clip;
@@ -1612,7 +1613,6 @@ void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
*aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
}
-/* get segments of cached frames. useful for debugging cache policies */
void BKE_movieclip_get_cache_segments(MovieClip *clip,
MovieClipUser *user,
int *r_totseg,
@@ -1848,9 +1848,6 @@ static void movieclip_build_proxy_ibuf(
IMB_freeImBuf(scaleibuf);
}
-/* NOTE: currently used by proxy job for movies, threading happens within single frame
- * (meaning scaling shall be threaded)
- */
void BKE_movieclip_build_proxy_frame(MovieClip *clip,
int clip_flag,
struct MovieDistortion *distortion,
@@ -1892,9 +1889,6 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip,
}
}
-/* NOTE: currently used by proxy job for sequences, threading happens within sequence
- * (different threads handles different frames, no threading within frame is needed)
- */
void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip,
ImBuf *ibuf,
struct MovieDistortion *distortion,
@@ -2150,4 +2144,5 @@ void BKE_movieclip_free_gputexture(struct MovieClip *clip)
MEM_freeN(tex);
}
}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index dc418545e23..fbad7d98630 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -330,9 +330,6 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *
return NULL;
}
-/* used for applying scale on mdisps layer and syncing subdivide levels when joining objects
- * use_first - return first multires modifier if all multires'es are disabled
- */
MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, bool use_first)
{
ModifierData *md;
@@ -519,7 +516,6 @@ static int get_levels_from_disps(Object *ob)
return totlvl;
}
-/* reset the multires levels to match the number of mdisps */
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
{
Mesh *me = ob->data;
@@ -712,7 +708,6 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
multires_set_tot_level(ob, mmd, lvl);
}
-/* (direction = 1) for delete higher, (direction = 0) for lower (not implemented yet) */
void multiresModifier_del_levels(MultiresModifierData *mmd,
Scene *scene,
Object *ob,
@@ -1295,7 +1290,6 @@ DerivedMesh *multires_make_derived_from_derived(
return result;
}
-/* Adapted from sculptmode.c */
void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v)
{
int x, y, x2, y2;
@@ -1349,8 +1343,6 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
add_v3_v3v3(out, d2[0], d2[1]);
}
-/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
- * such that 'ob_dst' has the same total number of levels as 'ob_src'. */
void multiresModifier_sync_levels_ex(Object *ob_dst,
MultiresModifierData *mmd_src,
MultiresModifierData *mmd_dst)
@@ -1469,7 +1461,6 @@ void multiresModifier_prepare_join(struct Depsgraph *depsgraph,
multires_apply_smat(depsgraph, scene, ob, mat);
}
-/* update multires data after topology changing */
void multires_topology_changed(Mesh *me)
{
MDisps *mdisp = NULL, *cur = NULL;
@@ -1504,11 +1495,6 @@ void multires_topology_changed(Mesh *me)
}
}
-/* Makes sure data from an external file is fully read.
- *
- * Since the multires data files only contain displacement vectors without knowledge about
- * subdivision level some extra work is needed. Namely make is to all displacement grids have
- * proper level and number of displacement vectors set. */
void multires_ensure_external_read(struct Mesh *mesh, int top_level)
{
if (!CustomData_external_test(&mesh->ldata, CD_MDISPS)) {
@@ -1544,7 +1530,6 @@ void multiresModifier_ensure_external_read(struct Mesh *mesh, const MultiresModi
/***************** Multires interpolation stuff *****************/
-/* Find per-corner coordinate with given per-face UV coord */
int mdisp_rot_face_to_crn(struct MVert *UNUSED(mvert),
struct MPoly *mpoly,
struct MLoop *UNUSED(mloop),
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index bd52d70b223..e0bb3cf792c 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -69,10 +69,6 @@ bool multiresModifier_reshapeFromVertcos(struct Depsgraph *depsgraph,
return true;
}
-/* Returns truth on success, false otherwise.
- *
- * This function might fail in cases like source and destination not having
- * matched amount of vertices. */
bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph,
struct MultiresModifierData *mmd,
struct Object *dst,
diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h
index 36ecf1a6395..db419418998 100644
--- a/source/blender/blenkernel/intern/multires_reshape.h
+++ b/source/blender/blenkernel/intern/multires_reshape.h
@@ -143,15 +143,19 @@ typedef struct ReshapeConstGridElement {
* Construct/destruct reshape context.
*/
-/* Create subdivision surface descriptor which is configured for surface evaluation at a given
- * multires modifier. */
+/**
+ * Create subdivision surface descriptor which is configured for surface evaluation at a given
+ * multi-res modifier.
+ */
struct Subdiv *multires_reshape_create_subdiv(struct Depsgraph *depsgraph,
struct Object *object,
const struct MultiresModifierData *mmd);
-/* NOTE: Initialized base mesh to object's mesh, the Subdiv is created from the deformed
- * mesh prior to the multires modifier if depsgraph is not NULL. If the depsgraph is NULL
- * then Subdiv is created from base mesh (without any deformation applied). */
+/**
+ * \note Initialized base mesh to object's mesh, the Subdivision is created from the deformed
+ * mesh prior to the multi-res modifier if depsgraph is not NULL. If the depsgraph is NULL
+ * then Subdivision is created from base mesh (without any deformation applied).
+ */
bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context,
struct Depsgraph *depsgraph,
struct Object *object,
@@ -185,29 +189,41 @@ void multires_reshape_context_free(MultiresReshapeContext *reshape_context);
* Helper accessors.
*/
-/* For the given grid index get index of face it was created for. */
+/**
+ * For the given grid index get index of face it was created for.
+ */
int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context,
int grid_index);
-/* For the given grid index get corner of a face it was created for. */
+/**
+ * For the given grid index get corner of a face it was created for.
+ */
int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index);
bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index);
-/* For the given grid index get index of corresponding ptex face. */
+/**
+ * For the given grid index get index of corresponding PTEX face.
+ */
int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context,
int grid_index);
-/* Convert normalized coordinate within a grid to a normalized coordinate within a ptex face. */
+/**
+ * Convert normalized coordinate within a grid to a normalized coordinate within a PTEX face.
+ */
PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *reshape_context,
const GridCoord *grid_coord);
-/* Convert a normalized coordinate within a ptex face to a normalized coordinate within a grid. */
+/**
+ * Convert a normalized coordinate within a PTEX face to a normalized coordinate within a grid.
+ */
GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context,
const PTexCoord *ptex_coord);
-/* Calculate tangent matrix which converts displacement to a object vector.
- * Is calculated for the given surface derivatives at a given base face corner. */
+/**
+ * Calculate tangent matrix which converts displacement to a object vector.
+ * Is calculated for the given surface derivatives at a given base face corner.
+ */
void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *reshape_context,
const int face_index,
const int corner,
@@ -215,14 +231,18 @@ void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *re
const float dPdv[3],
float r_tangent_matrix[3][3]);
-/* Get grid elements which are to be reshaped at a given or ptex coordinate.
- * The data is coming from final custom mdata layers. */
+/**
+ * Get grid elements which are to be reshaped at a given or PTEX coordinate.
+ * The data is coming from final custom mdata layers.
+ */
ReshapeGridElement multires_reshape_grid_element_for_grid_coord(
const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord);
ReshapeGridElement multires_reshape_grid_element_for_ptex_coord(
const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord);
-/* Get original grid element for the given coordinate. */
+/**
+ * Get original grid element for the given coordinate.
+ */
ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord);
@@ -230,8 +250,10 @@ ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
* Sample limit surface of the base mesh.
*/
-/* Evaluate limit surface created from base mesh.
- * This is the limit surface which defines tangent space for MDisps. */
+/**
+ * Evaluate limit surface created from base mesh.
+ * This is the limit surface which defines tangent space for MDisps.
+ */
void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context,
const GridCoord *grid_coord,
float r_P[3],
@@ -241,17 +263,23 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha
* Custom data preparation.
*/
-/* Make sure custom data is allocated for the given level. */
+/**
+ * Make sure custom data is allocated for the given level.
+ */
void multires_reshape_ensure_grids(struct Mesh *mesh, const int level);
/* --------------------------------------------------------------------
* Functions specific to reshaping from a set of vertices in a object position.
*/
-/* Returns truth if all coordinates were assigned.
+/**
+ * Set displacement grids values at a reshape level to a object coordinates of the given source.
+ *
+ * \returns truth if all coordinates were assigned.
*
* False will be returned if the number of vertex coordinates did not match required number of
- * vertices at a reshape level. */
+ * vertices at a reshape level.
+ */
bool multires_reshape_assign_final_coords_from_vertcos(
const MultiresReshapeContext *reshape_context,
const float (*vert_coords)[3],
@@ -261,13 +289,15 @@ bool multires_reshape_assign_final_coords_from_vertcos(
* Functions specific to reshaping from CCG.
*/
-/* Store final object-space coordinates in the displacement grids.
+/**
+ * Store final object-space coordinates in the displacement grids.
* The reason why displacement grids are used for storage is based on memory
* footprint optimization.
*
- * NOTE: Displacement grids to be at least at a reshape level.
+ * \note Displacement grids to be at least at a reshape level.
*
- * Return truth if all coordinates have been updated. */
+ * \return truth if all coordinates have been updated.
+ */
bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context,
struct SubdivCCG *subdiv_ccg);
@@ -275,11 +305,15 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
* Functions specific to reshaping from MDISPS.
*/
-/* Reads and writes to the current mesh CD_MDISPS. */
+/**
+ * Reads and writes to the current mesh #CD_MDISPS.
+ */
void multires_reshape_assign_final_coords_from_mdisps(
const MultiresReshapeContext *reshape_context);
-/* Reads from original CD_MIDTSPS, writes to the current mesh CD_MDISPS. */
+/**
+ * Reads from original #CD_MIDTSPS, writes to the current mesh #CD_MDISPS.
+ */
void multires_reshape_assign_final_elements_from_orig_mdisps(
const MultiresReshapeContext *reshape_context);
@@ -287,15 +321,18 @@ void multires_reshape_assign_final_elements_from_orig_mdisps(
* Displacement smooth.
*/
-/* Operates on a displacement grids (CD_MDISPS) which contains object space coordinates stored for
+/**
+ * Operates on a displacement grids (CD_MDISPS) which contains object space coordinates stored for
* the reshape level.
*
* The result is grids which are defining mesh with a smooth surface and details starting from
- * reshape level up to top level added back from original displacement grids. */
+ * reshape level up to top level added back from original displacement grids.
+ */
void multires_reshape_smooth_object_grids_with_details(
const MultiresReshapeContext *reshape_context);
-/* Operates on a displacement grids (CD_MDISPS) which contains object space-coordinates stored for
+/**
+ * Operates on a displacement grids (CD_MDISPS) which contains object space-coordinates stored for
* the reshape level.
*
* Makes it so surface on top level looks smooth. Details are not preserved
@@ -307,8 +344,10 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_
* Displacement, space conversion.
*/
-/* Store original grid data, so then it's possible to calculate delta from it and add
- * high-frequency content on top of reshaped grids. */
+/**
+ * Store original grid data, so then it's possible to calculate delta from it and add
+ * high-frequency content on top of reshaped grids.
+ */
void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context);
void multires_reshape_object_grids_to_tangent_displacement(
@@ -318,21 +357,29 @@ void multires_reshape_object_grids_to_tangent_displacement(
* Apply base.
*/
-/* Update mesh coordinates to the final positions of displacement in object space.
+/**
+ * Update mesh coordinates to the final positions of displacement in object space.
* This is effectively desired position of base mesh vertices after canceling out displacement.
*
- * NOTE: Expects that mesh's CD_MDISPS has been set to object space positions. */
+ * \note Expects that mesh's CD_MDISPS has been set to object space positions.
+ */
void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context);
-/* Perform better fitting of the base mesh so its subdivided version brings vertices to their
- * desired locations. */
+/**
+ * Perform better fitting of the base mesh so its subdivided version brings vertices to their
+ * desired locations.
+ */
void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context);
-/* Refine subdivision surface to the new positions of the base mesh. */
+/**
+ * Refine subdivision surface to the new positions of the base mesh.
+ */
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context);
-/* Refine subdivision surface to the new positions of the deformed mesh (base mesh with all
- * modifiers leading the multires applied).
+/**
+ * Refine subdivision surface to the new positions of the deformed mesh (base mesh with all
+ * modifiers leading the multi-res applied).
*
- * NOTE: Will re-evaluate all leading modifiers, so it's not cheap. */
+ * \note Will re-evaluate all leading modifiers, so it's not cheap.
+ */
void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context);
diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c
index 79a2b9eb002..b7572204182 100644
--- a/source/blender/blenkernel/intern/multires_reshape_util.c
+++ b/source/blender/blenkernel/intern/multires_reshape_util.c
@@ -47,8 +47,6 @@
/** \name Construct/destruct reshape context
* \{ */
-/* Create subdivision surface descriptor which is configured for surface evaluation at a given
- * multires modifier. */
Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
/*const*/ Object *object,
const MultiresModifierData *mmd)
@@ -332,7 +330,6 @@ void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
/** \name Helper accessors
* \{ */
-/* For the given grid index get index of face it was created for. */
int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context,
int grid_index)
{
@@ -345,7 +342,6 @@ int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_co
return reshape_context->grid_to_face_index[grid_index];
}
-/* For the given grid index get corner of a face it was created for. */
int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index)
{
BLI_assert(grid_index >= 0);
@@ -364,7 +360,6 @@ bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context
return (base_poly->totloop == 4);
}
-/* For the given grid index get index of corresponding ptex face. */
int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context,
int grid_index)
{
@@ -374,7 +369,6 @@ int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_co
return reshape_context->face_ptex_offset[face_index] + (is_quad ? 0 : corner);
}
-/* Convert normalized coordinate within a grid to a normalized coordinate within a ptex face. */
PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *reshape_context,
const GridCoord *grid_coord)
{
@@ -402,7 +396,6 @@ PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *resh
return ptex_coord;
}
-/* Convert a normalized coordinate within a ptex face to a normalized coordinate within a grid. */
GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context,
const PTexCoord *ptex_coord)
{
diff --git a/source/blender/blenkernel/intern/multires_reshape_vertcos.c b/source/blender/blenkernel/intern/multires_reshape_vertcos.c
index 04df5698cf9..ed2df1ba8c5 100644
--- a/source/blender/blenkernel/intern/multires_reshape_vertcos.c
+++ b/source/blender/blenkernel/intern/multires_reshape_vertcos.c
@@ -182,7 +182,6 @@ static void multires_reshape_vertcos_foreach_vertex_every_edge(
multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
}
-/* Set displacement grids values at a reshape level to a object coordinates of the given source. */
bool multires_reshape_assign_final_coords_from_vertcos(
const MultiresReshapeContext *reshape_context,
const float (*vert_coords)[3],
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 124db07298d..84484a63291 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -61,14 +61,20 @@
static CLG_LogRef LOG = {"bke.nla"};
+/**
+ * Find the active track and strip.
+ *
+ * The active strip may or may not be on the active track.
+ */
+static void nla_tweakmode_find_active(const ListBase /* NlaTrack */ *nla_tracks,
+ NlaTrack **r_track_of_active_strip,
+ NlaStrip **r_active_strip);
+
/* *************************************************** */
/* Data Management */
/* Freeing ------------------------------------------- */
-/* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
- * and the strip itself.
- */
void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
{
NlaStrip *cs, *csn;
@@ -108,9 +114,6 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
}
}
-/* Remove the given NLA track from the set of NLA tracks, free the track's data,
- * and the track itself.
- */
void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user)
{
NlaStrip *strip, *stripn;
@@ -135,9 +138,6 @@ void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user)
}
}
-/* Free the elements of type NLA Tracks provided in the given list, but do not free
- * the list itself since that is not free-standing
- */
void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user)
{
NlaTrack *nlt, *nltn;
@@ -159,13 +159,6 @@ void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user)
/* Copying ------------------------------------------- */
-/**
- * Copy NLA strip
- *
- * \param use_same_action: When true, the existing action is used (instead of being duplicated)
- * \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
- * flags in BKE_lib_id.h
- */
NlaStrip *BKE_nlastrip_copy(Main *bmain,
NlaStrip *strip,
const bool use_same_action,
@@ -215,11 +208,6 @@ NlaStrip *BKE_nlastrip_copy(Main *bmain,
return strip_d;
}
-/**
- * Copy a single NLA Track.
- * \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
- * flags in BKE_lib_id.h
- */
NlaTrack *BKE_nlatrack_copy(Main *bmain,
NlaTrack *nlt,
const bool use_same_actions,
@@ -249,11 +237,6 @@ NlaTrack *BKE_nlatrack_copy(Main *bmain,
return nlt_d;
}
-/**
- * Copy all NLA data.
- * \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
- * flags in BKE_lib_id.h
- */
void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, const ListBase *src, const int flag)
{
NlaTrack *nlt, *nlt_d;
@@ -309,6 +292,14 @@ static void update_active_track(AnimData *adt_dest, const AnimData *adt_source)
track_dest = track_dest->next;
}
+
+ /* If the above assumption failed to hold, do a more thorough search for the active strip. */
+ if (adt_source->actstrip != NULL && adt_dest->actstrip == NULL) {
+ nla_tweakmode_find_active(&adt_source->nla_tracks, &track_dest, &adt_dest->actstrip);
+ }
+
+ BLI_assert_msg((adt_source->actstrip == NULL) == (adt_dest->actstrip == NULL),
+ "Active strip did not copy correctly");
}
void BKE_nla_tracks_copy_from_adt(Main *bmain,
@@ -325,9 +316,6 @@ void BKE_nla_tracks_copy_from_adt(Main *bmain,
/* Adding ------------------------------------------- */
-/* Add a NLA Track to the given AnimData
- * - prev: NLA-Track to add the new one after
- */
NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev, const bool is_liboverride)
{
NlaTrack *nlt;
@@ -371,7 +359,6 @@ NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev, const bool is_liboverr
return nlt;
}
-/* Create a NLA Strip referencing the given Action */
NlaStrip *BKE_nlastrip_new(bAction *act)
{
NlaStrip *strip;
@@ -390,6 +377,16 @@ NlaStrip *BKE_nlastrip_new(bAction *act)
*/
strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_SYNC_LENGTH;
+ /* Disable sync for actions with a manual frame range, since it only syncs to range anyway. */
+ if (act->flag & ACT_FRAME_RANGE) {
+ strip->flag &= ~NLASTRIP_FLAG_SYNC_LENGTH;
+ }
+
+ /* Enable cyclic time for known cyclic actions. */
+ if (BKE_action_is_cyclic(act)) {
+ strip->flag |= NLASTRIP_FLAG_USR_TIME_CYCLIC;
+ }
+
/* assign the action reference */
strip->act = act;
id_us_plus(&act->id);
@@ -397,7 +394,7 @@ NlaStrip *BKE_nlastrip_new(bAction *act)
/* determine initial range
* - strip length cannot be 0... ever...
*/
- calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+ BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend);
strip->start = strip->actstart;
strip->end = (IS_EQF(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f) :
@@ -411,8 +408,6 @@ NlaStrip *BKE_nlastrip_new(bAction *act)
return strip;
}
-/* Add new NLA-strip to the top of the NLA stack - i.e.
- * into the last track if space, or a new one otherwise. */
NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_liboverride)
{
NlaStrip *strip;
@@ -445,7 +440,6 @@ NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_libo
return strip;
}
-/* Add a NLA Strip referencing the given speaker's sound */
NlaStrip *BKE_nla_add_soundstrip(Main *bmain, Scene *scene, Speaker *speaker)
{
NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
@@ -482,10 +476,6 @@ NlaStrip *BKE_nla_add_soundstrip(Main *bmain, Scene *scene, Speaker *speaker)
return strip;
}
-/**
- * Callback used by lib_query to walk over all ID usages (mimics `foreach_id` callback of
- * `IDTypeInfo` structure).
- */
void BKE_nla_strip_foreach_id(NlaStrip *strip, LibraryForeachIDData *data)
{
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, strip->act, IDWALK_CB_USER);
@@ -601,12 +591,6 @@ static float nlastrip_get_frame_transition(NlaStrip *strip, float cframe, short
return (cframe - strip->start) / length;
}
-/* non clipped mapping for strip-time <-> global time
- * mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
- *
- * only secure for 'internal' (i.e. within AnimSys evaluation) operations,
- * but should not be directly relied on for stuff which interacts with editors
- */
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode)
{
switch (strip->type) {
@@ -621,12 +605,6 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode)
}
}
-/* Non clipped mapping for strip-time <-> global time
- * mode = eNlaTime_ConvertModes -> NLATIME_CONVERT_*
- *
- * Public API method - perform this mapping using the given AnimData block
- * and perform any necessary sanity checks on the value
- */
float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
{
NlaStrip *strip;
@@ -675,7 +653,6 @@ float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
/* List of Strips ------------------------------------ */
/* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
-/* Check if there is any space in the given list to add the given strip */
bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
{
NlaStrip *strip;
@@ -710,9 +687,6 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
return true;
}
-/* Rearrange the strips in the track so that they are always in order
- * (usually only needed after a strip has been moved)
- */
void BKE_nlastrips_sort_strips(ListBase *strips)
{
ListBase tmp = {NULL, NULL};
@@ -756,9 +730,6 @@ void BKE_nlastrips_sort_strips(ListBase *strips)
strips->last = tmp.last;
}
-/* Add the given NLA-Strip to the given list of strips, assuming that it
- * isn't currently a member of another list
- */
bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
{
NlaStrip *ns;
@@ -794,10 +765,6 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
/* Meta-Strips ------------------------------------ */
-/* Convert 'islands' (i.e. continuous string of) selected strips to be
- * contained within 'Meta-Strips' which act as strips which contain strips.
- * temp: are the meta-strips to be created 'temporary' ones used for transforms?
- */
void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp)
{
NlaStrip *mstrip = NULL;
@@ -851,7 +818,6 @@ void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp)
}
}
-/* Split a meta-strip into a set of normal strips */
void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
{
NlaStrip *cs, *csn;
@@ -874,10 +840,6 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
BKE_nlastrip_free(strips, strip, true);
}
-/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
- * sel: only consider selected meta-strips, otherwise all meta-strips are removed
- * onlyTemp: only remove the 'temporary' meta-strips used for transforms
- */
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
{
NlaStrip *strip, *stripn;
@@ -903,9 +865,6 @@ void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
}
}
-/* Add the given NLA-Strip to the given Meta-Strip, assuming that the
- * strip isn't attached to any list of strips
- */
bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
{
/* sanity checks */
@@ -954,9 +913,6 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
return BKE_nlastrips_add_strip(&mstrip->strips, strip);
}
-/* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively),
- * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
- */
void BKE_nlameta_flush_transforms(NlaStrip *mstrip)
{
NlaStrip *strip;
@@ -1039,7 +995,6 @@ void BKE_nlameta_flush_transforms(NlaStrip *mstrip)
/* NLA-Tracks ---------------------------------------- */
-/* Find the active NLA-track for the given stack */
NlaTrack *BKE_nlatrack_find_active(ListBase *tracks)
{
NlaTrack *nlt;
@@ -1060,11 +1015,6 @@ NlaTrack *BKE_nlatrack_find_active(ListBase *tracks)
return NULL;
}
-/* Get the NLA Track that the active action/action strip comes from,
- * since this info is not stored in AnimData. It also isn't as simple
- * as just using the active track, since multiple tracks may have been
- * entered at the same time.
- */
NlaTrack *BKE_nlatrack_find_tweaked(AnimData *adt)
{
NlaTrack *nlt;
@@ -1096,9 +1046,6 @@ NlaTrack *BKE_nlatrack_find_tweaked(AnimData *adt)
return NULL;
}
-/* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
- * that has this status in its AnimData block.
- */
void BKE_nlatrack_solo_toggle(AnimData *adt, NlaTrack *nlt)
{
NlaTrack *nt;
@@ -1133,9 +1080,6 @@ void BKE_nlatrack_solo_toggle(AnimData *adt, NlaTrack *nlt)
}
}
-/* Make the given NLA-track the active one for the given stack. If no track is provided,
- * this function can be used to simply deactivate all the NLA tracks in the given stack too.
- */
void BKE_nlatrack_set_active(ListBase *tracks, NlaTrack *nlt_a)
{
NlaTrack *nlt;
@@ -1156,7 +1100,6 @@ void BKE_nlatrack_set_active(ListBase *tracks, NlaTrack *nlt_a)
}
}
-/* Check if there is any space in the given track to add a strip of the given length */
bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end)
{
/* sanity checks
@@ -1177,9 +1120,6 @@ bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end)
return BKE_nlastrips_has_space(&nlt->strips, start, end);
}
-/* Rearrange the strips in the track so that they are always in order
- * (usually only needed after a strip has been moved)
- */
void BKE_nlatrack_sort_strips(NlaTrack *nlt)
{
/* sanity checks */
@@ -1191,9 +1131,6 @@ void BKE_nlatrack_sort_strips(NlaTrack *nlt)
BKE_nlastrips_sort_strips(&nlt->strips);
}
-/* Add the given NLA-Strip to the given NLA-Track, assuming that it
- * isn't currently attached to another one
- */
bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_liboverride)
{
/* sanity checks */
@@ -1211,9 +1148,6 @@ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_libove
return BKE_nlastrips_add_strip(&nlt->strips, strip);
}
-/* Get the extents of the given NLA-Track including gaps between strips,
- * returning whether this succeeded or not
- */
bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
{
NlaStrip *strip;
@@ -1243,12 +1177,6 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
return true;
}
-/**
- * Check whether given NLA track is not local (i.e. from linked data) when the object is a library
- * override.
- *
- * \param nlt: May be NULL, in which case we consider it as a non-local track case.
- */
bool BKE_nlatrack_is_nonlocal_in_liboverride(const ID *id, const NlaTrack *nlt)
{
return (ID_IS_OVERRIDE_LIBRARY(id) &&
@@ -1257,7 +1185,6 @@ bool BKE_nlatrack_is_nonlocal_in_liboverride(const ID *id, const NlaTrack *nlt)
/* NLA Strips -------------------------------------- */
-/* Find the active NLA-strip within the given track */
NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
{
NlaStrip *strip;
@@ -1278,7 +1205,6 @@ NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
return NULL;
}
-/* Make the given NLA-Strip the active one within the given block */
void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip)
{
NlaTrack *nlt;
@@ -1302,7 +1228,6 @@ void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip)
}
}
-/* Does the given NLA-strip fall within the given bounds (times)? */
bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
{
const float stripLen = (strip) ? strip->end - strip->start : 0.0f;
@@ -1430,10 +1355,6 @@ static void nlastrip_fix_resize_overlaps(NlaStrip *strip)
}
}
-/**
- * Recalculate the start and end frames for the strip to match the bounds of its action such that
- * the overall NLA animation result is unchanged.
- */
void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip)
{
float prev_actstart;
@@ -1444,16 +1365,13 @@ void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip)
prev_actstart = strip->actstart;
- calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+ BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend);
/* Set start such that key's do not visually move, to preserve the overall animation result. */
strip->start += (strip->actstart - prev_actstart) * strip->scale;
BKE_nlastrip_recalculate_bounds(strip);
}
-/* Recalculate the start and end frames for the current strip, after changing
- * the extents of the action or the mapping (repeats or scale factor) info
- */
void BKE_nlastrip_recalculate_bounds(NlaStrip *strip)
{
float actlen, mapping;
@@ -1518,7 +1436,6 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip)
/* Animated Strips ------------------------------------------- */
-/* Check if the given NLA-Track has any strips with own F-Curves */
bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt)
{
NlaStrip *strip;
@@ -1539,7 +1456,6 @@ bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt)
return false;
}
-/* Check if given NLA-Tracks have any strips with own F-Curves */
bool BKE_nlatracks_have_animated_strips(ListBase *tracks)
{
NlaTrack *nlt;
@@ -1560,7 +1476,6 @@ bool BKE_nlatracks_have_animated_strips(ListBase *tracks)
return false;
}
-/* Validate the NLA-Strips 'control' F-Curves based on the flags set. */
void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
{
FCurve *fcu;
@@ -1624,9 +1539,6 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
}
}
-/* Check if the given RNA pointer + property combo should be handled by
- * NLA strip curves or not.
- */
bool BKE_nlastrip_has_curves_for_property(const PointerRNA *ptr, const PropertyRNA *prop)
{
/* sanity checks */
@@ -1666,11 +1578,6 @@ static bool nla_editbone_name_check(void *arg, const char *name)
return BLI_ghash_haskey((GHash *)arg, (const void *)name);
}
-/* Find (and set) a unique name for a strip from the whole AnimData block
- * Uses a similar method to the BLI method, but is implemented differently
- * as we need to ensure that the name is unique over several lists of tracks,
- * not just a single track.
- */
void BKE_nlastrip_validate_name(AnimData *adt, NlaStrip *strip)
{
GHash *gh;
@@ -1844,7 +1751,6 @@ static void BKE_nlastrip_validate_autoblends(NlaTrack *nlt, NlaStrip *nls)
}
}
-/* Ensure that auto-blending and other settings are set correctly */
void BKE_nla_validate_state(AnimData *adt)
{
NlaStrip *strip, *fstrip = NULL;
@@ -1901,12 +1807,6 @@ void BKE_nla_validate_state(AnimData *adt)
/* name of stashed tracks - the translation stuff is included here to save extra work */
#define STASH_TRACK_NAME DATA_("[Action Stash]")
-/* Check if an action is "stashed" in the NLA already
- *
- * The criteria for this are:
- * 1) The action in question lives in a "stash" track
- * 2) We only check first-level strips. That is, we will not check inside meta strips.
- */
bool BKE_nla_action_is_stashed(AnimData *adt, bAction *act)
{
NlaTrack *nlt;
@@ -1925,9 +1825,6 @@ bool BKE_nla_action_is_stashed(AnimData *adt, bAction *act)
return false;
}
-/* "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing)
- * to retain it in the file for future uses
- */
bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride)
{
NlaTrack *prev_track = NULL;
@@ -1996,12 +1893,6 @@ bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride)
/* Core Tools ------------------------------------------- */
-/* For the given AnimData block, add the active action to the NLA
- * stack (i.e. 'push-down' action). The UI should only allow this
- * for normal editing only (i.e. not in editmode for some strip's action),
- * so no checks for this are performed.
- */
-/* TODO: maybe we should have checks for this too... */
void BKE_nla_action_pushdown(AnimData *adt, const bool is_liboverride)
{
NlaStrip *strip;
@@ -2076,29 +1967,17 @@ void BKE_nla_action_pushdown(AnimData *adt, const bool is_liboverride)
BKE_nlastrip_set_active(adt, strip);
}
-/* Find the active strip + track combo, and set them up as the tweaking track,
- * and return if successful or not.
- */
-bool BKE_nla_tweakmode_enter(AnimData *adt)
+static void nla_tweakmode_find_active(const ListBase /* NlaTrack */ *nla_tracks,
+ NlaTrack **r_track_of_active_strip,
+ NlaStrip **r_active_strip)
{
NlaTrack *nlt, *activeTrack = NULL;
NlaStrip *strip, *activeStrip = NULL;
- /* verify that data is valid */
- if (ELEM(NULL, adt, adt->nla_tracks.first)) {
- return false;
- }
-
- /* If block is already in tweak-mode, just leave, but we should report
- * that this block is in tweak-mode (as our returncode). */
- if (adt->flag & ADT_NLA_EDIT_ON) {
- return true;
- }
-
/* go over the tracks, finding the active one, and its active strip
* - if we cannot find both, then there's nothing to do
*/
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ for (nlt = nla_tracks->first; nlt; nlt = nlt->next) {
/* check if active */
if (nlt->flag & NLATRACK_ACTIVE) {
/* store reference to this active track */
@@ -2117,7 +1996,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
*/
if (activeTrack == NULL) {
/* try last selected track for active strip */
- for (nlt = adt->nla_tracks.last; nlt; nlt = nlt->prev) {
+ for (nlt = nla_tracks->last; nlt; nlt = nlt->prev) {
if (nlt->flag & NLATRACK_SELECTED) {
/* assume this is the active track */
activeTrack = nlt;
@@ -2139,6 +2018,28 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
}
+ *r_track_of_active_strip = activeTrack;
+ *r_active_strip = activeStrip;
+}
+
+bool BKE_nla_tweakmode_enter(AnimData *adt)
+{
+ NlaTrack *nlt, *activeTrack = NULL;
+ NlaStrip *strip, *activeStrip = NULL;
+
+ /* verify that data is valid */
+ if (ELEM(NULL, adt, adt->nla_tracks.first)) {
+ return false;
+ }
+
+ /* If block is already in tweak-mode, just leave, but we should report
+ * that this block is in tweak-mode (as our returncode). */
+ if (adt->flag & ADT_NLA_EDIT_ON) {
+ return true;
+ }
+
+ nla_tweakmode_find_active(&adt->nla_tracks, &activeTrack, &activeStrip);
+
if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) {
if (G.debug & G_DEBUG) {
printf("NLA tweak-mode enter - neither active requirement found\n");
@@ -2191,7 +2092,6 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
return true;
}
-/* Exit tweak-mode for this AnimData block. */
void BKE_nla_tweakmode_exit(AnimData *adt)
{
NlaStrip *strip;
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index e02ea3f7e37..be458ed036e 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -47,22 +47,23 @@
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
+#include "BLI_color.hh"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
-#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_set.hh"
#include "BLI_stack.hh"
#include "BLI_string.h"
#include "BLI_string_utils.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_vector_set.hh"
-
#include "BLT_translation.h"
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
+#include "BKE_bpath.h"
#include "BKE_colortools.h"
#include "BKE_cryptomatte.h"
#include "BKE_global.h"
@@ -74,8 +75,6 @@
#include "BKE_main.h"
#include "BKE_node.h"
-#include "BLI_ghash.h"
-#include "BLI_threads.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -103,6 +102,7 @@ using blender::MutableSpan;
using blender::Set;
using blender::Span;
using blender::Stack;
+using blender::StringRef;
using blender::Vector;
using blender::VectorSet;
using blender::nodes::FieldInferencingInterface;
@@ -416,6 +416,29 @@ static void node_foreach_cache(ID *id,
}
}
+static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
+
+ switch (ntree->type) {
+ case NTREE_SHADER: {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type == SH_NODE_SCRIPT) {
+ NodeShaderScript *nss = reinterpret_cast<NodeShaderScript *>(node->storage);
+ BKE_bpath_foreach_path_fixed_process(bpath_data, nss->filepath);
+ }
+ else if (node->type == SH_NODE_TEX_IES) {
+ NodeShaderTexIES *ies = reinterpret_cast<NodeShaderTexIES *>(node->storage);
+ BKE_bpath_foreach_path_fixed_process(bpath_data, ies->filepath);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
static ID *node_owner_get(Main *bmain, ID *id)
{
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
@@ -520,7 +543,6 @@ static void write_node_socket_interface(BlendWriter *writer, bNodeSocket *sock)
write_node_socket_default_value(writer, sock);
}
-/* this is only direct data, tree itself should have been written */
void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
{
BKE_id_blend_write(writer, &ntree->id);
@@ -682,7 +704,6 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
sock->declaration = nullptr;
}
-/* ntree itself has been read! */
void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
{
/* NOTE: writing and reading goes in sync, for speed. */
@@ -1047,6 +1068,7 @@ IDTypeInfo IDType_ID_NT = {
/* name_plural */ "node_groups",
/* translation_context */ BLT_I18NCONTEXT_ID_NODETREE,
/* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ /* asset_type_info */ nullptr,
/* init_data */ ntree_init_data,
/* copy_data */ ntree_copy_data,
@@ -1054,6 +1076,7 @@ IDTypeInfo IDType_ID_NT = {
/* make_local */ nullptr,
/* foreach_id */ node_foreach_id,
/* foreach_cache */ node_foreach_cache,
+ /* foreach_path */ node_foreach_path,
/* owner_get */ node_owner_get,
/* blend_write */ ntree_blend_write,
@@ -1272,14 +1295,6 @@ static void update_typeinfo(Main *bmain,
FOREACH_NODETREE_END;
}
-/**
- * Try to initialize all type-info in a node tree.
- *
- * \note In general undefined type-info is a perfectly valid case,
- * the type may just be registered later.
- * In that case the update_typeinfo function will set type-info on registration
- * and do necessary updates.
- */
void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
{
ntree->init |= NTREE_TYPE_INIT;
@@ -1351,7 +1366,7 @@ bool ntreeIsRegistered(bNodeTree *ntree)
return (ntree->typeinfo != &NodeTreeTypeUndefined);
}
-GHashIterator *ntreeTypeGetIterator(void)
+GHashIterator *ntreeTypeGetIterator()
{
return BLI_ghashIterator_new(nodetreetypes_hash);
}
@@ -1429,14 +1444,14 @@ void nodeUnregisterType(bNodeType *nt)
BLI_ghash_remove(nodetypes_hash, nt->idname, nullptr, node_free_type);
}
-bool nodeTypeUndefined(bNode *node)
+bool nodeTypeUndefined(const bNode *node)
{
return (node->typeinfo == &NodeTypeUndefined) ||
((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id &&
ID_IS_LINKED(node->id) && (node->id->tag & LIB_TAG_MISSING));
}
-GHashIterator *nodeTypeGetIterator(void)
+GHashIterator *nodeTypeGetIterator()
{
return BLI_ghashIterator_new(nodetypes_hash);
}
@@ -1484,7 +1499,7 @@ bool nodeSocketIsRegistered(bNodeSocket *sock)
return (sock->typeinfo != &NodeSocketTypeUndefined);
}
-GHashIterator *nodeSocketTypeGetIterator(void)
+GHashIterator *nodeSocketTypeGetIterator()
{
return BLI_ghashIterator_new(nodesockettypes_hash);
}
@@ -1508,6 +1523,33 @@ struct bNodeSocket *nodeFindSocket(const bNode *node,
return nullptr;
}
+namespace blender::bke {
+
+bNodeSocket *node_find_enabled_socket(bNode &node,
+ const eNodeSocketInOut in_out,
+ const StringRef name)
+{
+ ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs;
+ LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
+ if (!(socket->flag & SOCK_UNAVAIL) && socket->name == name) {
+ return socket;
+ }
+ }
+ return nullptr;
+}
+
+bNodeSocket *node_find_enabled_input_socket(bNode &node, StringRef name)
+{
+ return node_find_enabled_socket(node, SOCK_IN, name);
+}
+
+bNodeSocket *node_find_enabled_output_socket(bNode &node, StringRef name)
+{
+ return node_find_enabled_socket(node, SOCK_OUT, name);
+}
+
+} // namespace blender::bke
+
/* find unique socket identifier */
static bool unique_identifier_check(void *arg, const char *identifier)
{
@@ -2035,13 +2077,11 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
node->update |= NODE_UPDATE;
}
-/* finds a node based on its name */
bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
{
return (bNode *)BLI_findstring(&ntree->nodes, name, offsetof(bNode, name));
}
-/* Finds a node based on given socket and returns true on success. */
bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
{
*r_node = nullptr;
@@ -2065,9 +2105,6 @@ bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_so
return false;
}
-/**
- * \note Recursive
- */
bNode *nodeFindRootParent(bNode *node)
{
if (node->parent) {
@@ -2076,10 +2113,6 @@ bNode *nodeFindRootParent(bNode *node)
return node->type == NODE_FRAME ? node : nullptr;
}
-/**
- * \returns true if \a child has \a parent as a parent/grandparent/...
- * \note Recursive
- */
bool nodeIsChildOf(const bNode *parent, const bNode *child)
{
if (parent == child) {
@@ -2091,13 +2124,6 @@ bool nodeIsChildOf(const bNode *parent, const bNode *child)
return false;
}
-/**
- * Iterate over a chain of nodes, starting with \a node_start, executing
- * \a callback for each node (which can return false to end iterator).
- *
- * \param reversed: for backwards iteration
- * \note Recursive
- */
void nodeChainIter(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *, const bool),
@@ -2152,17 +2178,6 @@ static void iter_backwards_ex(const bNodeTree *ntree,
}
}
-/**
- * Iterate over a chain of nodes, starting with \a node_start, executing
- * \a callback for each node (which can return false to end iterator).
- *
- * Faster than nodeChainIter. Iter only once per node.
- * Can be called recursively (using another nodeChainIterBackwards) by
- * setting the recursion_lvl accordingly.
- *
- * \note Needs updated socket links (ntreeUpdateTree).
- * \note Recursive
- */
void nodeChainIterBackwards(const bNodeTree *ntree,
const bNode *node_start,
bool (*callback)(bNode *, bNode *, void *),
@@ -2185,12 +2200,6 @@ void nodeChainIterBackwards(const bNodeTree *ntree,
iter_backwards_ex(ntree, node_start, callback, userdata, recursion_mask);
}
-/**
- * Iterate over all parents of \a node, executing \a callback for each parent
- * (which can return false to end iterator)
- *
- * \note Recursive
- */
void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata)
{
if (node->parent) {
@@ -2203,7 +2212,6 @@ void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userd
/* ************** Add stuff ********** */
-/* Find the first available, non-duplicate name for a given node */
void nodeUniqueName(bNodeTree *ntree, bNode *node)
{
BLI_uniquename(
@@ -2266,9 +2274,6 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src,
sock_dst->cache = nullptr;
}
-/* keep socket listorder identical, for copying links */
-/* ntree is the target tree */
-/* unique_name needs to be true. It's only disabled for speed when doing GPUnodetrees. */
bNode *BKE_node_copy_ex(bNodeTree *ntree,
const bNode *node_src,
const int flag,
@@ -2412,7 +2417,6 @@ static int node_count_links(const bNodeTree *ntree, const bNodeSocket *socket)
return count;
}
-/* also used via rna api, so we check for proper input output direction */
bNodeLink *nodeAddLink(
bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
{
@@ -2831,8 +2835,8 @@ bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
/* XXX this should be removed eventually ...
* Currently BKE functions are modeled closely on previous code,
* using BKE_node_preview_init_tree to set up previews for a whole node tree in advance.
- * This should be left more to the individual node tree implementations.
- */
+ * This should be left more to the individual node tree implementations. */
+
bool BKE_node_preview_used(const bNode *node)
{
/* XXX check for closed nodes? */
@@ -3065,9 +3069,6 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo
}
}
-/* hack warning! this function is only used for shader previews, and
- * since it gets called multiple times per pixel for Ztransp we only
- * add the color once. Preview gets cleared before it starts render though */
void BKE_node_preview_set_pixel(
bNodePreview *preview, const float col[4], int x, int y, bool do_manage)
{
@@ -3091,7 +3092,6 @@ void BKE_node_preview_set_pixel(
/* ************** Free stuff ********** */
-/* goes over entire tree */
void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
@@ -3281,8 +3281,6 @@ static void free_localized_node_groups(bNodeTree *ntree)
}
}
-/* Free (or release) any data used by this nodetree. Does not free the
- * nodetree itself and does no ID user counting. */
void ntreeFreeTree(bNodeTree *ntree)
{
ntree_free_data(&ntree->id);
@@ -3386,12 +3384,6 @@ void ntreeSetOutput(bNodeTree *ntree)
* might be different for editor or for "real" use... */
}
-/**
- * Get address of potential node-tree pointer of given ID.
- *
- * \warning Using this function directly is potentially dangerous, if you don't know or are not
- * sure, please use `ntreeFromID()` instead.
- */
bNodeTree **BKE_ntree_ptr_from_id(ID *id)
{
switch (GS(id->name)) {
@@ -3414,7 +3406,6 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id)
}
}
-/* Returns the private NodeTree object of the datablock, if it has one. */
bNodeTree *ntreeFromID(ID *id)
{
bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
@@ -3453,48 +3444,43 @@ void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable)
}
}
-/* returns localized tree for execution in threads */
bNodeTree *ntreeLocalize(bNodeTree *ntree)
{
- if (ntree) {
- /* Make full copy outside of Main database.
- * NOTE: previews are not copied here.
- */
- bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex(
- nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA));
-
- ltree->id.tag |= LIB_TAG_LOCALIZED;
+ if (ntree == nullptr) {
+ return nullptr;
+ }
- LISTBASE_FOREACH (bNode *, node, &ltree->nodes) {
- if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
- node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
- }
- }
+ /* Make full copy outside of Main database.
+ * NOTE: previews are not copied here. */
+ bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex(
+ nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA));
- /* ensures only a single output node is enabled */
- ntreeSetOutput(ntree);
+ ltree->id.tag |= LIB_TAG_LOCALIZED;
- bNode *node_src = (bNode *)ntree->nodes.first;
- bNode *node_local = (bNode *)ltree->nodes.first;
- while (node_src != nullptr) {
- node_local->original = node_src;
- node_src = node_src->next;
- node_local = node_local->next;
+ LISTBASE_FOREACH (bNode *, node, &ltree->nodes) {
+ if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
+ node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
}
+ }
- if (ntree->typeinfo->localize) {
- ntree->typeinfo->localize(ltree, ntree);
- }
+ /* ensures only a single output node is enabled */
+ ntreeSetOutput(ntree);
- return ltree;
+ bNode *node_src = (bNode *)ntree->nodes.first;
+ bNode *node_local = (bNode *)ltree->nodes.first;
+ while (node_src != nullptr) {
+ node_local->original = node_src;
+ node_src = node_src->next;
+ node_local = node_local->next;
}
- return nullptr;
+ if (ntree->typeinfo->localize) {
+ ntree->typeinfo->localize(ltree, ntree);
+ }
+
+ return ltree;
}
-/* sync local composite with real tree */
-/* local tree is supposed to be running, be careful moving previews! */
-/* is called by jobs manager, outside threads, so it doesn't happen during draw */
void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
{
if (localtree && ntree) {
@@ -3504,8 +3490,6 @@ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
}
}
-/* merge local tree results back, and free local tree */
-/* we have to assume the editor already changed completely */
void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
{
if (ntree && localtree) {
@@ -3873,7 +3857,6 @@ static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key,
return nullptr;
}
-/* two active flags, ID nodes have special flag for buttons display */
bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
{
if (ntree) {
@@ -3916,7 +3899,6 @@ bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
return ok;
}
-/* two active flags, ID nodes have special flag for buttons display */
void nodeClearActiveID(bNodeTree *ntree, short idtype)
{
if (ntree == nullptr) {
@@ -3959,7 +3941,6 @@ void nodeClearActive(bNodeTree *ntree)
}
}
-/* two active flags, ID nodes have special flag for buttons display */
void nodeSetActive(bNodeTree *ntree, bNode *node)
{
/* make sure only one node is active, and only one per ID type */
@@ -4028,10 +4009,6 @@ static void update_socket_declarations(ListBase *sockets,
}
}
-/**
- * Update `socket->declaration` for all sockets in the node. This assumes that the node declaration
- * and sockets are up to date already.
- */
void nodeSocketDeclarationsUpdate(bNode *node)
{
BLI_assert(node->declaration != nullptr);
@@ -4039,10 +4016,6 @@ void nodeSocketDeclarationsUpdate(bNode *node)
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) {
@@ -4064,10 +4037,6 @@ bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node)
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)) {
@@ -4115,7 +4084,7 @@ void BKE_node_clipboard_init(const struct bNodeTree *ntree)
node_clipboard.type = ntree->type;
}
-void BKE_node_clipboard_clear(void)
+void BKE_node_clipboard_clear()
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node_clipboard.links) {
nodeRemLink(nullptr, link);
@@ -4132,8 +4101,7 @@ void BKE_node_clipboard_clear(void)
#endif
}
-/* return false when one or more ID's are lost */
-bool BKE_node_clipboard_validate(void)
+bool BKE_node_clipboard_validate()
{
bool ok = true;
@@ -4211,22 +4179,22 @@ void BKE_node_clipboard_add_link(bNodeLink *link)
BLI_addtail(&node_clipboard.links, link);
}
-const ListBase *BKE_node_clipboard_get_nodes(void)
+const ListBase *BKE_node_clipboard_get_nodes()
{
return &node_clipboard.nodes;
}
-const ListBase *BKE_node_clipboard_get_links(void)
+const ListBase *BKE_node_clipboard_get_links()
{
return &node_clipboard.links;
}
-int BKE_node_clipboard_get_type(void)
+int BKE_node_clipboard_get_type()
{
return node_clipboard.type;
}
-void BKE_node_clipboard_free(void)
+void BKE_node_clipboard_free()
{
BKE_node_clipboard_validate();
BKE_node_clipboard_clear();
@@ -4234,7 +4202,6 @@ void BKE_node_clipboard_free(void)
/* Node Instance Hash */
-/* magic number for initial hash key */
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE = {5381};
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE = {0};
@@ -4520,7 +4487,8 @@ static void ntree_validate_links(bNodeTree *ntree)
link->flag &= ~NODE_LINK_VALID;
}
else if (ntree->typeinfo->validate_link) {
- if (!ntree->typeinfo->validate_link(ntree, link)) {
+ if (!ntree->typeinfo->validate_link((eNodeSocketDatatype)link->fromsock->type,
+ (eNodeSocketDatatype)link->tosock->type)) {
link->flag &= ~NODE_LINK_VALID;
}
}
@@ -4809,7 +4777,9 @@ static void propagate_data_requirements_from_right_to_left(
/* The output is required to be a single value when it is connected to any input that does
* not support fields. */
for (const InputSocketRef *target_socket : output_socket->directly_linked_sockets()) {
- state.requires_single |= field_state_by_socket_id[target_socket->id()].requires_single;
+ if (target_socket->is_available()) {
+ state.requires_single |= field_state_by_socket_id[target_socket->id()].requires_single;
+ }
}
if (state.requires_single) {
@@ -5059,9 +5029,6 @@ static bool update_field_inferencing(bNodeTree &btree)
} // namespace blender::bke::node_field_inferencing
-/**
- * \param tree_update_flag: #eNodeTreeUpdate enum.
- */
void ntreeUpdateAllUsers(Main *main, ID *id, const int tree_update_flag)
{
if (id == nullptr) {
@@ -5244,7 +5211,7 @@ void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node)
/* ************* node type access ********** */
-void nodeLabel(bNodeTree *ntree, bNode *node, char *label, int maxlen)
+void nodeLabel(const bNodeTree *ntree, const bNode *node, char *label, int maxlen)
{
label[0] = '\0';
@@ -5266,7 +5233,6 @@ void nodeLabel(bNodeTree *ntree, bNode *node, char *label, int maxlen)
}
}
-/* Get node socket label if it is set */
const char *nodeSocketLabel(const bNodeSocket *sock)
{
return (sock->label[0] != '\0') ? sock->label : sock->name;
@@ -5448,10 +5414,6 @@ void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size)
}
}
-/**
- * \warning Nodes defining a storage type _must_ allocate this for new nodes.
- * Otherwise nodes will reload as undefined (T46619).
- */
void node_type_storage(bNodeType *ntype,
const char *storagename,
void (*freefunc)(struct bNode *node),
@@ -5469,13 +5431,6 @@ void node_type_storage(bNodeType *ntype,
ntype->freefunc = freefunc;
}
-void node_type_label(
- struct bNodeType *ntype,
- void (*labelfunc)(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen))
-{
- ntype->labelfunc = labelfunc;
-}
-
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
{
@@ -5827,6 +5782,7 @@ static void registerGeometryNodes()
register_node_type_geo_attribute_compare();
register_node_type_geo_attribute_convert();
register_node_type_geo_attribute_curve_map();
+ register_node_type_geo_attribute_domain_size();
register_node_type_geo_attribute_fill();
register_node_type_geo_attribute_map_range();
register_node_type_geo_attribute_math();
@@ -5845,7 +5801,6 @@ static void registerGeometryNodes()
register_node_type_geo_curve_fillet();
register_node_type_geo_curve_handle_type_selection();
register_node_type_geo_curve_length();
- register_node_type_geo_curve_parameter();
register_node_type_geo_curve_primitive_bezier_segment();
register_node_type_geo_curve_primitive_circle();
register_node_type_geo_curve_primitive_line();
@@ -5857,6 +5812,7 @@ static void registerGeometryNodes()
register_node_type_geo_curve_reverse();
register_node_type_geo_curve_sample();
register_node_type_geo_curve_set_handles();
+ register_node_type_geo_curve_spline_parameter();
register_node_type_geo_curve_spline_type();
register_node_type_geo_curve_subdivide();
register_node_type_geo_curve_to_mesh();
@@ -5864,7 +5820,9 @@ static void registerGeometryNodes()
register_node_type_geo_curve_trim();
register_node_type_geo_delete_geometry();
register_node_type_geo_distribute_points_on_faces();
+ register_node_type_geo_dual_mesh();
register_node_type_geo_edge_split();
+ register_node_type_geo_geometry_to_instance();
register_node_type_geo_image_texture();
register_node_type_geo_input_curve_handles();
register_node_type_geo_input_curve_tilt();
@@ -5872,9 +5830,16 @@ static void registerGeometryNodes()
register_node_type_geo_input_index();
register_node_type_geo_input_material_index();
register_node_type_geo_input_material();
+ register_node_type_geo_input_mesh_edge_neighbors();
+ register_node_type_geo_input_mesh_edge_vertices();
+ register_node_type_geo_input_mesh_face_area();
+ register_node_type_geo_input_mesh_face_neighbors();
+ register_node_type_geo_input_mesh_island();
+ register_node_type_geo_input_mesh_vertex_neighbors();
register_node_type_geo_input_normal();
register_node_type_geo_input_position();
register_node_type_geo_input_radius();
+ register_node_type_geo_input_scene_time();
register_node_type_geo_input_shade_smooth();
register_node_type_geo_input_spline_cyclic();
register_node_type_geo_input_spline_length();
@@ -5943,7 +5908,7 @@ static void registerFunctionNodes()
register_node_type_fn_align_euler_to_vector();
register_node_type_fn_boolean_math();
- register_node_type_fn_float_compare();
+ register_node_type_fn_compare();
register_node_type_fn_float_to_int();
register_node_type_fn_input_bool();
register_node_type_fn_input_color();
@@ -5959,7 +5924,7 @@ static void registerFunctionNodes()
register_node_type_fn_value_to_string();
}
-void BKE_node_system_init(void)
+void BKE_node_system_init()
{
nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh");
nodetypes_hash = BLI_ghash_str_new("nodetypes_hash gh");
@@ -5986,7 +5951,7 @@ void BKE_node_system_init(void)
registerFunctionNodes();
}
-void BKE_node_system_exit(void)
+void BKE_node_system_exit()
{
if (nodetypes_hash) {
NODE_TYPES_BEGIN (nt) {
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index d650003afe2..7fec91ed65a 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -83,6 +83,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_asset.h"
+#include "BKE_bpath.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
@@ -548,6 +549,67 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
+static void object_foreach_path_pointcache(ListBase *ptcache_list,
+ BPathForeachPathData *bpath_data)
+{
+ for (PointCache *cache = (PointCache *)ptcache_list->first; cache != nullptr;
+ cache = cache->next) {
+ if (cache->flag & PTCACHE_DISK_CACHE) {
+ BKE_bpath_foreach_path_fixed_process(bpath_data, cache->path);
+ }
+ }
+}
+
+static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Object *ob = reinterpret_cast<Object *>(id);
+
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
+ /* TODO: Move that to #ModifierTypeInfo. */
+ switch (md->type) {
+ case eModifierType_Fluidsim: {
+ FluidsimModifierData *fluidmd = reinterpret_cast<FluidsimModifierData *>(md);
+ if (fluidmd->fss) {
+ BKE_bpath_foreach_path_fixed_process(bpath_data, fluidmd->fss->surfdataPath);
+ }
+ break;
+ }
+ case eModifierType_Fluid: {
+ FluidModifierData *fmd = reinterpret_cast<FluidModifierData *>(md);
+ if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
+ BKE_bpath_foreach_path_fixed_process(bpath_data, fmd->domain->cache_directory);
+ }
+ break;
+ }
+ case eModifierType_Cloth: {
+ ClothModifierData *clmd = reinterpret_cast<ClothModifierData *>(md);
+ object_foreach_path_pointcache(&clmd->ptcaches, bpath_data);
+ break;
+ }
+ case eModifierType_Ocean: {
+ OceanModifierData *omd = reinterpret_cast<OceanModifierData *>(md);
+ BKE_bpath_foreach_path_fixed_process(bpath_data, omd->cachepath);
+ break;
+ }
+ case eModifierType_MeshCache: {
+ MeshCacheModifierData *mcmd = reinterpret_cast<MeshCacheModifierData *>(md);
+ BKE_bpath_foreach_path_fixed_process(bpath_data, mcmd->filepath);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (ob->soft != nullptr) {
+ object_foreach_path_pointcache(&ob->soft->shared->ptcaches, bpath_data);
+ }
+
+ LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
+ object_foreach_path_pointcache(&psys->ptcaches, bpath_data);
+ }
+}
+
static void write_fmaps(BlendWriter *writer, ListBase *fbase)
{
LISTBASE_FOREACH (bFaceMap *, fmap, fbase) {
@@ -1258,6 +1320,7 @@ IDTypeInfo IDType_ID_OB = {
/* name_plural */ "objects",
/* translation_context */ BLT_I18NCONTEXT_ID_OBJECT,
/* flags */ 0,
+ /* asset_type_info */ &AssetType_OB,
/* init_data */ object_init_data,
/* copy_data */ object_copy_data,
@@ -1265,6 +1328,7 @@ IDTypeInfo IDType_ID_OB = {
/* make_local */ object_make_local,
/* foreach_id */ object_foreach_id,
/* foreach_cache */ nullptr,
+ /* foreach_path */ object_foreach_path,
/* owner_get */ nullptr,
/* blend_write */ object_blend_write,
@@ -1275,8 +1339,6 @@ IDTypeInfo IDType_ID_OB = {
/* blend_read_undo_preserve */ nullptr,
/* lib_override_apply_post */ object_lib_override_apply_post,
-
- /* asset_type_info */ &AssetType_OB,
};
void BKE_object_workob_clear(Object *workob)
@@ -1394,12 +1456,6 @@ void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData
}
}
-/**
- * Set the object's active modifier.
- *
- * \param md: If nullptr, only clear the active modifier, otherwise
- * it must be in the #Object.modifiers list.
- */
void BKE_object_modifier_set_active(Object *ob, ModifierData *md)
{
LISTBASE_FOREACH (ModifierData *, md_iter, &ob->modifiers) {
@@ -1434,9 +1490,6 @@ ModifierData *BKE_object_active_modifier(const Object *ob)
return nullptr;
}
-/**
- * \return True if the object's type supports regular modifiers (not grease pencil modifiers).
- */
bool BKE_object_supports_modifiers(const Object *ob)
{
return (
@@ -1514,17 +1567,6 @@ static ParticleSystem *object_copy_modifier_particle_system_ensure(Main *bmain,
return psys_dst;
}
-/**
- * Copy a single modifier.
- *
- * \note **Do not** use this function to copy a whole modifier stack (see note below too). Use
- * `BKE_object_modifier_stack_copy` instead.
- *
- * \note Complex modifiers relaying on other data (like e.g. dynamic paint or fluid using particle
- * systems) are not always 100% 'correctly' copied here, since we have to use heuristics to decide
- * which particle system to use or add in `ob_dst`, and it's placement in the stack, etc. If used
- * more than once, this function should preferably be called in stack order.
- */
bool BKE_object_copy_modifier(
Main *bmain, Scene *scene, Object *ob_dst, const Object *ob_src, ModifierData *md_src)
{
@@ -1624,12 +1666,6 @@ bool BKE_object_copy_modifier(
return true;
}
-/**
- * Copy a single GPencil modifier.
- *
- * \note **Do not** use this function to copy a whole modifier stack. Use
- * `BKE_object_modifier_stack_copy` instead.
- */
bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData *gmd_src)
{
BLI_assert(ob_dst->type == OB_GPENCIL);
@@ -1647,15 +1683,6 @@ bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData
return true;
}
-/**
- * Copy the whole stack of modifiers from one object into another.
- *
- * \warning **Does not** clear modifier stack and related data (particle systems, soft-body,
- * etc.) in `ob_dst`, if needed calling code must do it.
- *
- * \param do_copy_all: If true, even modifiers that should not support copying (like Hook one)
- * will be duplicated.
- */
bool BKE_object_modifier_stack_copy(Object *ob_dst,
const Object *ob_src,
const bool do_copy_all,
@@ -1804,9 +1831,6 @@ static void object_update_from_subsurf_ccg(Object *object)
subdiv_ccg->dirty.hidden = false;
}
-/**
- * Assign #Object.data after modifier stack evaluation.
- */
void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_owned)
{
BLI_assert(object_eval->id.tag & LIB_TAG_COPIED_ON_WRITE);
@@ -1836,9 +1860,6 @@ void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_own
object_eval->runtime.geometry_set_eval = nullptr;
}
-/**
- * Free data derived from mesh, called when mesh changes or is freed.
- */
void BKE_object_free_derived_caches(Object *ob)
{
MEM_SAFE_FREE(ob->runtime.bb);
@@ -1933,9 +1954,6 @@ void BKE_object_free_caches(Object *object)
}
}
-/**
- * Actual check for internal data, not context or flags.
- */
bool BKE_object_is_in_editmode(const Object *ob)
{
if (ob->data == nullptr) {
@@ -2085,9 +2103,6 @@ bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode)
return ((ob->mode == object_mode) || (ob->mode & object_mode) != 0);
}
-/**
- * Return which parts of the object are visible, as evaluated by depsgraph
- */
int BKE_object_visibility(const Object *ob, const int dag_eval_mode)
{
if ((ob->base_flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
@@ -2255,9 +2270,6 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
}
}
-/**
- * Return -1 on failure.
- */
int BKE_object_obdata_to_type(const ID *id)
{
/* Keep in sync with #OB_DATA_SUPPORT_ID macro. */
@@ -2293,9 +2305,6 @@ int BKE_object_obdata_to_type(const ID *id)
}
}
-/**
- * More general add: creates minimum required data, but without vertices etc.
- */
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
{
if (!name) {
@@ -2325,14 +2334,6 @@ static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, c
return ob;
}
-/**
- * General add: to scene, with layer from area and default name
- *
- * Object is added to the active #Collection.
- * If there is no linked collection to the active #ViewLayer we create a new one.
- *
- * \note Creates minimum required data, but without vertices etc.
- */
Object *BKE_object_add(Main *bmain, ViewLayer *view_layer, int type, const char *name)
{
Object *ob = object_add_common(bmain, view_layer, type, name);
@@ -2346,11 +2347,6 @@ Object *BKE_object_add(Main *bmain, ViewLayer *view_layer, int type, const char
return ob;
}
-/**
- * Add a new object, using another one as a reference
- *
- * \param ob_src: object to use to determine the collections of the new object.
- */
Object *BKE_object_add_from(
Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name, Object *ob_src)
{
@@ -2363,15 +2359,6 @@ Object *BKE_object_add_from(
return ob;
}
-/**
- * Add a new object, but assign the given data-block as the `ob->data`
- * for the newly created 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)
{
@@ -2623,9 +2610,6 @@ Object *BKE_object_pose_armature_get_visible(Object *ob, ViewLayer *view_layer,
return nullptr;
}
-/**
- * Access pose array with special check to get pose object when in weight paint mode.
- */
Object **BKE_object_pose_array_get_ex(ViewLayer *view_layer,
View3D *v3d,
uint *r_objects_len,
@@ -2720,17 +2704,6 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
copy_v3_v3(ob_tar->scale, ob_src->scale);
}
-/**
- * Perform deep-copy of object and its 'children' data-blocks (obdata, materials, actions, etc.).
- *
- * \param dupflag: Controls which sub-data are also duplicated
- * (see #eDupli_ID_Flags in DNA_userdef_types.h).
- *
- * \note This function does not do any remapping to new IDs, caller must do it
- * (\a #BKE_libblock_relink_to_newid()).
- * \note Caller MUST free \a newid pointers itself (#BKE_main_id_newptr_and_tag_clear()) and call
- * updates of DEG too (#DAG_relations_tag_update()).
- */
Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplicate_options)
{
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
@@ -2900,17 +2873,11 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica
return obn;
}
-/**
- * Returns true if the Object is from an external blend file (libdata).
- */
bool BKE_object_is_libdata(const Object *ob)
{
return (ob && ID_IS_LINKED(ob));
}
-/**
- * Returns true if the Object data is from an external blend file (libdata).
- */
bool BKE_object_obdata_is_libdata(const Object *ob)
{
/* Linked objects with local obdata are forbidden! */
@@ -2974,12 +2941,6 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
}
}
-/**
- * Proxy rule:
- * - lib_object->proxy_from == the one we borrow from, set temporally while object_update.
- * - local_object->proxy == pointer to library object, saved in files and read.
- * - local_object->proxy_group == pointer to collection dupli-object, saved in files and read.
- */
void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
{
/* paranoia checks */
@@ -3079,10 +3040,6 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
ob->dt = target->dt;
}
-/**
- * Use with newly created objects to set their size
- * (used to apply scene-scale).
- */
void BKE_object_obdata_size_init(struct Object *ob, const float size)
{
/* apply radius as a scale to types that support it */
@@ -3721,12 +3678,6 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o
object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
}
-/**
- * Calculate object transformation matrix without recalculating dependencies and
- * constraints -- assume dependencies are already solved by depsgraph.
- * No changes to object and its parent would be done.
- * Used for bundles orientation in 3d space relative to parented blender camera.
- */
void BKE_object_where_is_calc_mat4(Object *ob, float r_obmat[4][4])
{
if (ob->parent) {
@@ -3750,14 +3701,6 @@ void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
}
-/**
- * For calculation of the inverse parent transform, only used for editor.
- *
- * It assumes the object parent is already in the depsgraph.
- * Otherwise, after changing ob->parent you need to call:
- * - #DEG_relations_tag_update(bmain);
- * - #BKE_scene_graph_update_tagged(depsgraph, bmain);
- */
void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *workob)
{
BKE_object_workob_clear(workob);
@@ -3789,16 +3732,6 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o
BKE_object_where_is_calc(depsgraph, scene, workob);
}
-/**
- * Applies the global transformation \a mat to the \a ob using a relative parent space if
- * supplied.
- *
- * \param mat: the global transformation mat that the object should be set object to.
- * \param parent: the parent space in which this object will be set relative to
- * (should probably always be parent_eval).
- * \param use_compat: true to ensure that rotations are set using the
- * min difference between the old and new orientation.
- */
void BKE_object_apply_mat4_ex(Object *ob,
const float mat[4][4],
Object *parent,
@@ -3842,9 +3775,6 @@ void BKE_object_apply_mat4_ex(Object *ob,
/* BKE_object_mat3_to_rot handles delta rotations */
}
-/**
- * XXX: should be removed after COW operators port to use BKE_object_apply_mat4_ex directly.
- */
void BKE_object_apply_mat4(Object *ob,
const float mat[4][4],
const bool use_compat,
@@ -3859,7 +3789,7 @@ void BKE_object_apply_mat4(Object *ob,
/** \name Object Bounding Box API
* \{ */
-BoundBox *BKE_boundbox_alloc_unit(void)
+BoundBox *BKE_boundbox_alloc_unit()
{
const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
@@ -3948,9 +3878,6 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
return bb;
}
-/**
- * Use this to temporally disable/enable bound-box.
- */
void BKE_object_boundbox_flag(Object *ob, int flag, const bool set)
{
BoundBox *bb = BKE_object_boundbox_get(ob);
@@ -3984,6 +3911,37 @@ void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval)
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
}
+bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
+{
+ blender::float3 min, max;
+ INIT_MINMAX(min, max);
+
+ if (ob->runtime.geometry_set_eval) {
+ ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max);
+ }
+ else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) {
+ if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) {
+ return false;
+ }
+ }
+ else if (ob->runtime.curve_cache) {
+ BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
+ }
+ else {
+ return false;
+ }
+
+ if (ob->runtime.bb == nullptr) {
+ ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__);
+ }
+
+ BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
+
+ ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
+
+ return true;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -4009,14 +3967,6 @@ void BKE_object_dimensions_get(Object *ob, float r_vec[3])
}
}
-/**
- * The original scale and object matrix can be passed in so any difference
- * of the objects matrix and the final matrix can be accounted for,
- * typically this caused by parenting, constraints or delta-scale.
- *
- * Re-using these values from the object causes a feedback loop
- * when multiple values are modified at once in some situations. see: T69536.
- */
void BKE_object_dimensions_set_ex(Object *ob,
const float value[3],
int axis_mask,
@@ -4341,6 +4291,12 @@ void BKE_scene_foreach_display_point(Depsgraph *depsgraph,
DEG_OBJECT_ITER_END;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Transform Channels (Backup/Restore)
+ * \{ */
+
/**
* See struct members from #Object in DNA_object_types.h
*/
@@ -4401,17 +4357,11 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
copy_m4_m4(ob->imat, obtfm->imat);
}
-bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
-{
- /* test if 'ob' is a parent somewhere in par's parents */
- if (par == nullptr) {
- return false;
- }
- if (ob == par) {
- return true;
- }
- return BKE_object_parent_loop_check(par->parent, ob);
-}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Evaluation/Update API
+ * \{ */
static void object_handle_update_proxy(Depsgraph *depsgraph,
Scene *scene,
@@ -4435,19 +4385,6 @@ static void object_handle_update_proxy(Depsgraph *depsgraph,
}
}
-/**
- * Proxy rule:
- * - lib_object->proxy_from == the one we borrow from, only set temporal and cleared here.
- * - local_object->proxy == pointer to library object, saved in files and read.
- *
- * Function below is polluted with proxy exceptions, cleanup will follow!
- *
- * The main object update call, for object matrix, constraints, keys and displist (modifiers)
- * requires flags to be set!
- *
- * Ideally we shouldn't have to pass the rigid body world,
- * but need bigger restructuring to avoid id.
- */
void BKE_object_handle_update_ex(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -4502,13 +4439,6 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update);
}
-/**
- * \warning "scene" here may not be the scene object actually resides in.
- * When dealing with background-sets, "scene" is actually the active scene.
- * e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
- * rigid bodies depend on their world so use #BKE_object_handle_update_ex()
- * to also pass along the current rigid body world.
- */
void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr, true);
@@ -4521,7 +4451,7 @@ void BKE_object_sculpt_data_create(Object *ob)
ob->sculpt->mode_type = (eObjectMode)ob->mode;
}
-bool BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, float **r_size)
+bool BKE_object_obdata_texspace_get(Object *ob, char **r_texflag, float **r_loc, float **r_size)
{
if (ob->data == nullptr) {
@@ -4566,17 +4496,17 @@ bool BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc
return true;
}
-/** Get evaluated mesh for given object. */
Mesh *BKE_object_get_evaluated_mesh(const Object *object)
{
/* First attempt to retrieve the evaluated mesh from the evaluated geometry set. Most
* object types either store it there or add a reference to it if it's owned elsewhere. */
GeometrySet *geometry_set_eval = object->runtime.geometry_set_eval;
if (geometry_set_eval) {
- /* Some areas expect to be able to modify the evaluated mesh. Theoretically this should be
- * avoided, or at least protected with a lock, so a const mesh could be returned from this
- * function. */
- Mesh *mesh = geometry_set_eval->get_mesh_for_write();
+ /* Some areas expect to be able to modify the evaluated mesh in limited ways. Theoretically
+ * this should be avoided, or at least protected with a lock, so a const mesh could be returned
+ * from this function. We use a const_cast instead of #get_mesh_for_write, because that might
+ * result in a copy of the mesh when it is shared. */
+ Mesh *mesh = const_cast<Mesh *>(geometry_set_eval->get_mesh_for_read());
if (mesh) {
return mesh;
}
@@ -4593,13 +4523,6 @@ Mesh *BKE_object_get_evaluated_mesh(const Object *object)
return nullptr;
}
-/**
- * Get mesh which is not affected by modifiers:
- * - For original objects it will be same as `object->data`, and it is a mesh
- * which is in the corresponding #Main.
- * - For copied-on-write objects it will give pointer to a copied-on-write
- * mesh which corresponds to original object's mesh.
- */
Mesh *BKE_object_get_pre_modified_mesh(const Object *object)
{
if (object->type == OB_MESH && object->runtime.data_orig != nullptr) {
@@ -4615,12 +4538,6 @@ Mesh *BKE_object_get_pre_modified_mesh(const Object *object)
return (Mesh *)object->data;
}
-/**
- * Get a mesh which corresponds to the very original mesh from #Main.
- * - For original objects it will be object->data.
- * - For evaluated objects it will be same mesh as corresponding original
- * object uses as data.
- */
Mesh *BKE_object_get_original_mesh(const Object *object)
{
Mesh *result = nullptr;
@@ -4669,6 +4586,12 @@ Lattice *BKE_object_get_evaluated_lattice(const Object *object)
return lt_eval;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Point Cache
+ * \{ */
+
static int pc_cmp(const void *a, const void *b)
{
const LinkData *ad = (const LinkData *)a, *bd = (const LinkData *)b;
@@ -4733,6 +4656,8 @@ void BKE_object_delete_ptcache(Object *ob, int index)
BLI_freelinkN(&ob->pc_ids, link);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Object Data Shape Key Insert
* \{ */
@@ -4971,6 +4896,22 @@ bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Object Query API
+ * \{ */
+
+bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
+{
+ /* test if 'ob' is a parent somewhere in par's parents */
+ if (par == nullptr) {
+ return false;
+ }
+ if (ob == par) {
+ return true;
+ }
+ return BKE_object_parent_loop_check(par->parent, ob);
+}
+
bool BKE_object_flag_test_recursive(const Object *ob, short flag)
{
if (ob->flag & flag) {
@@ -4993,10 +4934,6 @@ bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_chi
return false;
}
-/**
- * Most important if this is modified it should _always_ return true, in certain
- * cases false positives are hard to avoid (shape keys for example).
- */
int BKE_object_is_modified(Scene *scene, Object *ob)
{
/* Always test on original object since evaluated object may no longer
@@ -5030,21 +4967,6 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
return flag;
}
-/**
- * Check of objects moves in time.
- *
- * \note This function is currently optimized for usage in combination
- * with modifier deformation checks (#eModifierTypeType_OnlyDeform),
- * so modifiers can quickly check if their target objects moves
- * (causing deformation motion blur) or not.
- *
- * This makes it possible to give some degree of false-positives here,
- * but it's currently an acceptable tradeoff between complexity and check
- * speed. In combination with checks of modifier stack and real life usage
- * percentage of false-positives shouldn't be that high.
- *
- * \note This function does not consider physics systems.
- */
bool BKE_object_moves_in_time(const Object *object, bool recurse_parent)
{
/* If object has any sort of animation data assume it is moving. */
@@ -5140,11 +5062,6 @@ static bool modifiers_has_animation_check(const Object *ob)
return false;
}
-/**
- * Test if object is affected by deforming modifiers (for motion blur). again
- * most important is to avoid false positives, this is to skip computations
- * and we can still if there was actual deformation afterwards.
- */
int BKE_object_is_deform_modified(Scene *scene, Object *ob)
{
/* Always test on original object since evaluated object may no longer
@@ -5194,7 +5111,6 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
return flag;
}
-/** Return the number of scenes using (instantiating) that object in their collections. */
int BKE_object_scenes_users_get(Main *bmain, Object *ob)
{
int num_scenes = 0;
@@ -5234,14 +5150,31 @@ MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
return clip;
}
+bool BKE_object_supports_material_slots(struct Object *ob)
+{
+ return ELEM(ob->type,
+ OB_MESH,
+ OB_CURVE,
+ OB_SURF,
+ OB_FONT,
+ OB_MBALL,
+ OB_HAIR,
+ OB_POINTCLOUD,
+ OB_VOLUME,
+ OB_GPENCIL);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Runtime
+ * \{ */
+
void BKE_object_runtime_reset(Object *object)
{
memset(&object->runtime, 0, sizeof(object->runtime));
}
-/**
- * Reset all pointers which we don't want to be shared when copying the object.
- */
void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
{
Object_Runtime *runtime = &object->runtime;
@@ -5254,12 +5187,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
runtime->geometry_set_eval = nullptr;
}
-/**
- * The function frees memory used by the runtime data, but not the runtime field itself.
- *
- * All runtime data is cleared to ensure it's not used again,
- * in keeping with other `_free_data(..)` functions.
- */
void BKE_object_runtime_free_data(Object *object)
{
/* Currently this is all that's needed. */
@@ -5268,6 +5195,12 @@ void BKE_object_runtime_free_data(Object *object)
BKE_object_runtime_reset(object);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Relationships
+ * \{ */
+
/**
* Find an associated armature object.
*/
@@ -5301,13 +5234,6 @@ static void obrel_list_add(LinkNode **links, Object *ob)
ob->id.tag |= LIB_TAG_DOIT;
}
-/**
- * Iterates over all objects of the given scene layer.
- * Depending on the #eObjectSet flag:
- * collect either #OB_SET_ALL, #OB_SET_VISIBLE or #OB_SET_SELECTED objects.
- * If #OB_SET_VISIBLE or#OB_SET_SELECTED are collected,
- * then also add related objects according to the given \a includeFilter.
- */
LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer,
eObjectSet objectSet,
eObRelationTypes includeFilter)
@@ -5385,9 +5311,6 @@ LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer,
return links;
}
-/**
- * return all groups this object is a part of, caller must free.
- */
struct LinkNode *BKE_object_groups(Main *bmain, Scene *scene, Object *ob)
{
LinkNode *collection_linknode = nullptr;
@@ -5408,15 +5331,12 @@ void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *ob)
}
}
-/**
- * Return a KDTree_3d from the deformed object (in world-space).
- *
- * \note Only mesh objects currently support deforming, others are TODO.
- *
- * \param ob:
- * \param r_tot:
- * \return The kdtree or nullptr if it can't be created.
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object KD-Tree
+ * \{ */
+
KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
{
KDTree_3d *tree = nullptr;
@@ -5534,6 +5454,12 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
return tree;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Modifier Utilities
+ * \{ */
+
bool BKE_object_modifier_use_time(Scene *scene,
Object *ob,
ModifierData *md,
@@ -5679,10 +5605,6 @@ static void object_cacheIgnoreClear(Object *ob, int state)
BLI_freelistN(&pidlist);
}
-/**
- * \note this function should eventually be replaced by depsgraph functionality.
- * Avoid calling this in new code unless there is a very good reason for it!
- */
bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -5786,9 +5708,6 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
return false;
}
-/**
- * Updates select_id of all objects in the given \a bmain.
- */
void BKE_object_update_select_id(struct Main *bmain)
{
Object *ob = (Object *)bmain->objects.first;
@@ -5799,6 +5718,12 @@ void BKE_object_update_select_id(struct Main *bmain)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Conversion
+ * \{ */
+
Mesh *BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
{
BKE_object_to_mesh_clear(object);
@@ -5866,16 +5791,4 @@ void BKE_object_replace_data_on_shallow_copy(Object *ob, ID *new_data)
ob->id.py_instance = nullptr;
}
-bool BKE_object_supports_material_slots(struct Object *ob)
-{
- return ELEM(ob->type,
- OB_MESH,
- OB_CURVE,
- OB_SURF,
- OB_FONT,
- OB_MBALL,
- OB_HAIR,
- OB_POINTCLOUD,
- OB_VOLUME,
- OB_GPENCIL);
-}
+/** \} */
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 511f5d4ae66..fb4f4a14265 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -63,13 +63,6 @@ static Lattice *object_defgroup_lattice_get(ID *id)
return (lt->editlatt) ? lt->editlatt->latt : lt;
}
-/**
- * Update users of vgroups from this object, according to given map.
- *
- * Use it when you remove or reorder vgroups in the object.
- *
- * \param map: an array mapping old indices to new indices.
- */
void BKE_object_defgroup_remap_update_users(Object *ob, const int *map)
{
ModifierData *md;
@@ -106,15 +99,13 @@ void BKE_object_defgroup_remap_update_users(Object *ob, const int *map)
}
}
}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Group creation
* \{ */
-/**
- * Add a vgroup of given name to object. *Does not* handle MDeformVert data at all!
- */
bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
{
bDeformGroup *defgroup;
@@ -129,17 +120,11 @@ bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
return defgroup;
}
-/**
- * Add a vgroup of default name to object. *Does not* handle MDeformVert data at all!
- */
bDeformGroup *BKE_object_defgroup_add(Object *ob)
{
return BKE_object_defgroup_add_name(ob, DATA_("Group"));
}
-/**
- * Create MDeformVert data for given ID. Work in Object mode only.
- */
MDeformVert *BKE_object_defgroup_data_create(ID *id)
{
if (GS(id->name) == ID_ME) {
@@ -156,18 +141,13 @@ MDeformVert *BKE_object_defgroup_data_create(ID *id)
return NULL;
}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Group clearing
* \{ */
-/**
- * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes.
- *
- * \param use_selection: Only operate on selection.
- * \return True if any vertex was removed, false otherwise.
- */
bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
{
MDeformVert *dv;
@@ -239,12 +219,6 @@ bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_sele
return changed;
}
-/**
- * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes.
- *
- * \param use_selection: Only operate on selection.
- * \return True if any vertex was removed, false otherwise.
- */
bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
{
bDeformGroup *dg;
@@ -260,6 +234,7 @@ bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
return changed;
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -406,9 +381,6 @@ static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
object_defgroup_remove_common(ob, dg, def_nr);
}
-/**
- * Remove given vgroup from object. Work in Object and Edit modes.
- */
void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
{
if (ob->type == OB_GPENCIL) {
@@ -426,10 +398,6 @@ void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
}
}
-/**
- * Remove all vgroups from object. Work in Object and Edit modes.
- * When only_unlocked=true, locked vertex groups are not removed.
- */
void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
{
ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
@@ -469,19 +437,11 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
}
}
-/**
- * Remove all vgroups from object. Work in Object and Edit modes.
- */
void BKE_object_defgroup_remove_all(struct Object *ob)
{
BKE_object_defgroup_remove_all_ex(ob, false);
}
-/**
- * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
- * Returns null if no remapping is required.
- * The returned array has to be freed.
- */
int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
{
const ListBase *src_defbase = BKE_object_defgroup_list(ob_src);
@@ -549,11 +509,6 @@ void BKE_object_defgroup_index_map_apply(MDeformVert *dvert,
}
}
-/**
- * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
- *
- * \return True if the id type supports weights.
- */
bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
{
if (id) {
@@ -579,14 +534,11 @@ bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_t
*dvert_tot = 0;
return false;
}
+
/** \} */
/* --- functions for getting vgroup aligned maps --- */
-/**
- * gets the status of "flag" for each bDeformGroup
- * in the object data's vertex group list and returns an array containing them
- */
bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
{
bool is_locked = false;
@@ -675,8 +627,6 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
return defgroup_validmap;
}
-/* Returns total selected vgroups,
- * wpi.defbase_sel is assumed malloc'd, all values are set */
bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
{
bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
@@ -708,11 +658,6 @@ bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_fl
return dg_selection;
}
-/**
- * Checks if the lock relative mode is applicable.
- *
- * \return true if an unlocked deform group is active.
- */
bool BKE_object_defgroup_check_lock_relative(const bool *lock_flags,
const bool *validmap,
int index)
@@ -720,11 +665,6 @@ bool BKE_object_defgroup_check_lock_relative(const bool *lock_flags,
return validmap && validmap[index] && !(lock_flags && lock_flags[index]);
}
-/**
- * Additional check for whether the lock relative mode is applicable in multi-paint mode.
- *
- * \return true if none of the selected groups are locked.
- */
bool BKE_object_defgroup_check_lock_relative_multi(int defbase_tot,
const bool *lock_flags,
const bool *selected,
@@ -747,11 +687,6 @@ bool BKE_object_defgroup_check_lock_relative_multi(int defbase_tot,
return true;
}
-/**
- * Takes a pair of boolean masks of all locked and all deform groups, and computes
- * a pair of masks for locked deform and unlocked deform groups. Output buffers may
- * reuse the input ones.
- */
void BKE_object_defgroup_split_locked_validmap(
int defbase_tot, const bool *locked, const bool *deform, bool *r_locked, bool *r_unlocked)
{
@@ -774,11 +709,6 @@ void BKE_object_defgroup_split_locked_validmap(
}
}
-/**
- * Marks mirror vgroups in output and counts them.
- * Output and counter assumed to be already initialized.
- * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
- */
void BKE_object_defgroup_mirror_selection(struct Object *ob,
int defbase_tot,
const bool *dg_selection,
@@ -808,9 +738,6 @@ void BKE_object_defgroup_mirror_selection(struct Object *ob,
}
}
-/**
- * Return the subset type of the Vertex Group Selection
- */
bool *BKE_object_defgroup_subset_from_select_type(Object *ob,
eVGroupSelect subset_type,
int *r_defgroup_tot,
@@ -873,9 +800,6 @@ bool *BKE_object_defgroup_subset_from_select_type(Object *ob,
return defgroup_validmap;
}
-/**
- * store indices from the defgroup_validmap (faster lookups in some cases)
- */
void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap,
const int defgroup_tot,
int *r_defgroup_subset_map)
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index 442755be15d..9f998b746a2 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -147,7 +147,7 @@ static void init_context(DupliContext *r_ctx,
/**
* Create sub-context for recursive duplis.
*/
-static void copy_dupli_context(
+static bool copy_dupli_context(
DupliContext *r_ctx, const DupliContext *ctx, Object *ob, const float mat[4][4], int index)
{
*r_ctx = *ctx;
@@ -168,9 +168,11 @@ static void copy_dupli_context(
if (r_ctx->level == MAX_DUPLI_RECUR - 1) {
std::cerr << "Warning: Maximum instance recursion level reached.\n";
+ return false;
}
r_ctx->gen = get_dupli_generator(r_ctx);
+ return true;
}
/**
@@ -258,7 +260,9 @@ static void make_recursive_duplis(const DupliContext *ctx,
/* Simple preventing of too deep nested collections with #MAX_DUPLI_RECUR. */
if (ctx->level < MAX_DUPLI_RECUR) {
DupliContext rctx;
- copy_dupli_context(&rctx, ctx, ob, space_mat, index);
+ if (!copy_dupli_context(&rctx, ctx, ob, space_mat, index)) {
+ return;
+ }
if (rctx.gen) {
ctx->instance_stack->append(ob);
rctx.gen->make_duplis(&rctx);
@@ -301,13 +305,13 @@ static void make_child_duplis(const DupliContext *ctx,
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (ctx->collection, ob, mode) {
if ((ob != ctx->obedit) && is_child(ob, parent)) {
DupliContext pctx;
- copy_dupli_context(&pctx, ctx, ctx->object, nullptr, _base_id);
-
- /* Meta-balls have a different dupli handling. */
- if (ob->type != OB_MBALL) {
- ob->flag |= OB_DONE; /* Doesn't render. */
+ if (copy_dupli_context(&pctx, ctx, ctx->object, nullptr, _base_id)) {
+ /* Meta-balls have a different dupli handling. */
+ if (ob->type != OB_MBALL) {
+ ob->flag |= OB_DONE; /* Doesn't render. */
+ }
+ make_child_duplis_cb(&pctx, userdata, ob);
}
- make_child_duplis_cb(&pctx, userdata, ob);
}
}
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
@@ -324,14 +328,14 @@ static void make_child_duplis(const DupliContext *ctx,
DEG_OBJECT_ITER_BEGIN (ctx->depsgraph, ob, deg_objects_visibility_flags) {
if ((ob != ctx->obedit) && is_child(ob, parent)) {
DupliContext pctx;
- copy_dupli_context(&pctx, ctx, ctx->object, nullptr, persistent_dupli_id);
+ if (copy_dupli_context(&pctx, ctx, ctx->object, nullptr, persistent_dupli_id)) {
+ /* Meta-balls have a different dupli-handling. */
+ if (ob->type != OB_MBALL) {
+ ob->flag |= OB_DONE; /* Doesn't render. */
+ }
- /* Meta-balls have a different dupli-handling. */
- if (ob->type != OB_MBALL) {
- ob->flag |= OB_DONE; /* Doesn't render. */
+ make_child_duplis_cb(&pctx, userdata, ob);
}
-
- make_child_duplis_cb(&pctx, userdata, ob);
}
persistent_dupli_id++;
}
@@ -893,7 +897,9 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx,
* between the instances component below and the other components above. */
DupliContext new_instances_ctx;
if (creates_duplis_for_components) {
- copy_dupli_context(&new_instances_ctx, ctx, ctx->object, nullptr, component_index);
+ if (!copy_dupli_context(&new_instances_ctx, ctx, ctx->object, nullptr, component_index)) {
+ return;
+ }
instances_ctx = &new_instances_ctx;
}
@@ -928,7 +934,9 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx,
mul_m4_m4_pre(collection_matrix, parent_transform);
DupliContext sub_ctx;
- copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id);
+ if (!copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id)) {
+ break;
+ }
eEvaluationMode mode = DEG_get_mode(instances_ctx->depsgraph);
int object_id = 0;
@@ -951,8 +959,9 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx,
mul_m4_m4m4(new_transform, parent_transform, instance_offset_matrices[i].values);
DupliContext sub_ctx;
- copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id);
- make_duplis_geometry_set_impl(&sub_ctx, reference.geometry_set(), new_transform, true);
+ if (copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id)) {
+ make_duplis_geometry_set_impl(&sub_ctx, reference.geometry_set(), new_transform, true);
+ }
break;
}
case InstanceReference::Type::None: {
@@ -1499,7 +1508,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
else {
/* First key. */
state.time = ctime;
- if (psys_get_particle_state(&sim, a, &state, 0) == 0) {
+ if (psys_get_particle_state(&sim, a, &state, false) == 0) {
continue;
}
@@ -1609,8 +1618,9 @@ static void make_duplis_particles(const DupliContext *ctx)
LISTBASE_FOREACH_INDEX (ParticleSystem *, psys, &ctx->object->particlesystem, psysid) {
/* Particles create one more level for persistent `psys` index. */
DupliContext pctx;
- copy_dupli_context(&pctx, ctx, ctx->object, nullptr, psysid);
- make_duplis_particle_system(&pctx, psys);
+ if (copy_dupli_context(&pctx, ctx, ctx->object, nullptr, psysid)) {
+ make_duplis_particle_system(&pctx, psys);
+ }
}
}
@@ -1678,9 +1688,6 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
/** \name Dupli-Container Implementation
* \{ */
-/**
- * \return a #ListBase of #DupliObject.
- */
ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
{
ListBase *duplilist = (ListBase *)MEM_callocN(sizeof(ListBase), "duplilist");
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 7e15ac5de5d..4c0d0303c1f 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -67,14 +67,6 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-/**
- * Restore the object->data to a non-modifier evaluated state.
- *
- * Some changes done directly in evaluated object require them to be reset
- * before being re-evaluated.
- * For example, we need to call this before #BKE_mesh_new_from_object(),
- * in case we removed/added modifiers in the evaluated object.
- */
void BKE_object_eval_reset(Object *ob_eval)
{
BKE_object_free_derived_caches(ob_eval);
@@ -88,10 +80,10 @@ void BKE_object_eval_local_transform(Depsgraph *depsgraph, Object *ob)
BKE_object_to_mat4(ob, ob->obmat);
}
-/* Evaluate parent */
-/* NOTE: based on solve_parenting(), but with the cruft stripped out */
void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob)
{
+ /* NOTE: based on `solve_parenting()`, but with the cruft stripped out. */
+
Object *par = ob->parent;
float totmat[4][4];
@@ -282,7 +274,12 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
/** Bounding box from evaluated geometry. */
static void object_sync_boundbox_to_original(Object *object_orig, Object *object_eval)
{
- BoundBox *bb = BKE_object_boundbox_get(object_eval);
+ BoundBox *bb = object_eval->runtime.bb;
+ if (!bb || (bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_object_boundbox_calc_from_evaluated_geometry(object_eval);
+ }
+
+ bb = BKE_object_boundbox_get(object_eval);
if (bb != NULL) {
if (object_orig->runtime.bb == NULL) {
object_orig->runtime.bb = MEM_mallocN(sizeof(*object_orig->runtime.bb), __func__);
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index e9683d3b52c..97326c24a61 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -270,7 +270,6 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
BLI_rw_mutex_unlock(&oc->oceanmutex);
}
-/* use catmullrom interpolation rather than linear */
void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
{
int i0, i1, i2, i3, j0, j1, j2, j3;
@@ -378,8 +377,6 @@ void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x
BKE_ocean_eval_uv_catrom(oc, ocr, x / oc->_Lx, z / oc->_Lz);
}
-/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being
- * just a way to get the raw data out to save in some image format. */
void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
{
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
@@ -650,9 +647,6 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskd
fftw_execute(o->_N_z_plan);
}
-/**
- * Return true if the ocean is valid and can be used.
- */
bool BKE_ocean_is_valid(const struct Ocean *o)
{
return o->_k != NULL;
@@ -777,9 +771,6 @@ bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution)
return true;
}
-/**
- * Return true if the ocean data is valid and can be used.
- */
bool BKE_ocean_init_from_modifier(struct Ocean *ocean,
struct OceanModifierData const *omd,
const int resolution)
@@ -818,9 +809,6 @@ bool BKE_ocean_init_from_modifier(struct Ocean *ocean,
omd->seed);
}
-/**
- * Return true if the ocean data is valid and can be used.
- */
bool BKE_ocean_init(struct Ocean *o,
int M,
int N,
diff --git a/source/blender/blenkernel/intern/ocean_spectrum.c b/source/blender/blenkernel/intern/ocean_spectrum.c
index c5504b22b43..43e0f399213 100644
--- a/source/blender/blenkernel/intern/ocean_spectrum.c
+++ b/source/blender/blenkernel/intern/ocean_spectrum.c
@@ -128,11 +128,6 @@ static float jonswap(const Ocean *oc, const float k2)
return val;
}
-/**
- * Pierson-Moskowitz model, 1964, assumes waves reach equilibrium with wind.
- * Model is intended for large area 'fully developed' sea, where winds have been steadily blowing
- * for days over an area that includes hundreds of wavelengths on a side.
- */
float BLI_ocean_spectrum_piersonmoskowitz(const Ocean *oc, const float kx, const float kz)
{
const float k2 = kx * kx + kz * kz;
@@ -159,10 +154,6 @@ float BLI_ocean_spectrum_piersonmoskowitz(const Ocean *oc, const float kx, const
return val;
}
-/**
- * TMA extends the JONSWAP spectrum.
- * This spectral model is best suited to shallow water.
- */
float BLI_ocean_spectrum_texelmarsenarsloe(const Ocean *oc, const float kx, const float kz)
{
const float k2 = kx * kx + kz * kz;
@@ -195,14 +186,6 @@ float BLI_ocean_spectrum_texelmarsenarsloe(const Ocean *oc, const float kx, cons
return val;
}
-/**
- * Hasselmann et al, 1973. This model extends the Pierson-Moskowitz model with a peak sharpening
- * function This enhancement is an artificial construct to address the problem that the wave
- * spectrum is never fully developed.
- *
- * The fetch parameter represents the distance from a lee shore,
- * called the fetch, or the distance over which the wind blows with constant velocity.
- */
float BLI_ocean_spectrum_jonswap(const Ocean *oc, const float kx, const float kz)
{
const float k2 = kx * kx + kz * kz;
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index f0f8343420d..8989450e41b 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -242,7 +242,6 @@ PackedFile *BKE_packedfile_new(ReportList *reports, const char *filename, const
return pf;
}
-/* no libraries for now */
void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
{
Image *ima;
@@ -373,14 +372,6 @@ int BKE_packedfile_write_to_file(ReportList *reports,
return ret_value;
}
-/**
- * This function compares a packed file to a 'real' file.
- * It returns an integer indicating if:
- *
- * - PF_EQUAL: the packed file and original file are identical
- * - PF_DIFFERENT: the packed file and original file differ
- * - PF_NOFILE: the original file doesn't exist
- */
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
const char *filename,
PackedFile *pf)
@@ -434,16 +425,6 @@ enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
return ret_val;
}
-/**
- * #BKE_packedfile_unpack_to_file() looks at the existing files (abs_name, local_name)
- * and a packed file.
- *
- * It returns a char *to the existing file name / new file name or NULL when
- * there was an error or when the user decides to cancel the operation.
- *
- * \warning 'abs_name' may be relative still! (use a "//" prefix)
- * be sure to run #BLI_path_abs on it first.
- */
char *BKE_packedfile_unpack_to_file(ReportList *reports,
const char *ref_file_name,
const char *abs_name,
@@ -804,7 +785,6 @@ void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileSt
}
}
-/* ID should be not NULL, return 1 if there's a packed file */
bool BKE_packedfile_id_check(const ID *id)
{
switch (GS(id->name)) {
@@ -834,7 +814,6 @@ bool BKE_packedfile_id_check(const ID *id)
return false;
}
-/* ID should be not NULL */
void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF_FileStatus how)
{
switch (GS(id->name)) {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index d6030941c6d..72210eea71d 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -143,6 +143,7 @@ IDTypeInfo IDType_ID_PAL = {
.name_plural = "palettes",
.translation_context = BLT_I18NCONTEXT_ID_PALETTE,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = palette_init_data,
.copy_data = palette_copy_data,
@@ -150,6 +151,7 @@ IDTypeInfo IDType_ID_PAL = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = palette_blend_write,
@@ -208,6 +210,7 @@ IDTypeInfo IDType_ID_PC = {
.name_plural = "paint_curves",
.translation_context = BLT_I18NCONTEXT_ID_PAINTCURVE,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = paint_curve_copy_data,
@@ -215,6 +218,7 @@ IDTypeInfo IDType_ID_PC = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = paint_curve_blend_write,
@@ -723,7 +727,6 @@ void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, const int add_inde
pc->add_index = (add_index || pc->tot_points == 1) ? (add_index + 1) : 0;
}
-/** Remove color from palette. Must be certain color is inside the palette! */
void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
{
if (BLI_listbase_count_at_most(&palette->colors, palette->active_color) ==
@@ -962,7 +965,6 @@ bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name, co
return done;
}
-/* are we in vertex paint or weight paint face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
return ((ob != NULL) && (ob->type == OB_MESH) && (ob->data != NULL) &&
@@ -970,7 +972,6 @@ bool BKE_paint_select_face_test(Object *ob)
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)));
}
-/* are we in weight paint vertex select mode? */
bool BKE_paint_select_vert_test(Object *ob)
{
return ((ob != NULL) && (ob->type == OB_MESH) && (ob->data != NULL) &&
@@ -978,10 +979,6 @@ bool BKE_paint_select_vert_test(Object *ob)
(ob->mode & OB_MODE_WEIGHT_PAINT || ob->mode & OB_MODE_VERTEX_PAINT));
}
-/**
- * used to check if selection is possible
- * (when we don't care if its face or vert)
- */
bool BKE_paint_select_elem_test(Object *ob)
{
return (BKE_paint_select_vert_test(ob) || BKE_paint_select_face_test(ob));
@@ -1024,9 +1021,6 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode)
}
}
-/**
- * Call when entering each respective paint mode.
- */
bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
{
Paint *paint = NULL;
@@ -1147,10 +1141,6 @@ void BKE_paint_free(Paint *paint)
MEM_SAFE_FREE(paint->tool_slots);
}
-/* called when copying scene settings, so even if 'src' and 'tar' are the same
- * still do a id_us_plus(), rather than if we were copying between 2 existing
- * scenes where a matching value should decrease the existing user count as
- * with paint_brush_set() */
void BKE_paint_copy(Paint *src, Paint *tar, const int flag)
{
tar->brush = src->brush;
@@ -1230,8 +1220,6 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p)
}
}
-/* returns non-zero if any of the face's vertices
- * are hidden, zero otherwise */
bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop)
{
return ((mvert[mloop[lt->tri[0]].v].flag & ME_HIDE) ||
@@ -1239,9 +1227,6 @@ bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *m
(mvert[mloop[lt->tri[2]].v].flag & ME_HIDE));
}
-/* returns non-zero if any of the corners of the grid
- * face whose inner corner is at (x, y) are hidden,
- * zero otherwise */
bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y)
{
/* skip face if any of its corners are hidden */
@@ -1251,7 +1236,6 @@ bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int
BLI_BITMAP_TEST(grid_hidden, (y + 1) * gridsize + x));
}
-/* Return true if all vertices in the face are visible, false otherwise */
bool paint_is_bmesh_face_hidden(BMFace *f)
{
BMLoop *l_iter;
@@ -1520,8 +1504,6 @@ void BKE_sculptsession_free(Object *ob)
}
}
-/* Sculpt mode handles multires differently from regular meshes, but only if
- * it's the last modifier on the stack and it is not on the first level */
MultiresModifierData *BKE_sculpt_multires_active(Scene *scene, Object *ob)
{
Mesh *me = (Mesh *)ob->data;
@@ -1811,7 +1793,6 @@ void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES);
}
-/** \warning Expects a fully evaluated depsgraph. */
void BKE_sculpt_update_object_for_edit(
Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors)
{
@@ -1941,10 +1922,6 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
return deformed;
}
-/**
- * Ensures that a Face Set data-layers exists. If it does not, it creates one respecting the
- * visibility stored in the vertices of the mesh. If it does, it copies the visibility from the
- * mesh to the Face Sets. */
void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh)
{
const int face_sets_default_visible_id = 1;
@@ -2046,12 +2023,6 @@ void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *su
BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg);
}
-/**
- * Ensures we do have expected mesh data in original mesh for the sculpt mode.
- *
- * \note IDs are expected to be original ones here, and calling code should ensure it updates its
- * depsgraph properly after calling this function if it needs up-to-date evaluated data.
- */
void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
{
Mesh *mesh = BKE_mesh_from_object(object);
@@ -2223,8 +2194,6 @@ void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
subdiv_ccg->grid_hidden);
}
-/* Test if PBVH can be used directly for drawing, which is faster than
- * drawing the mesh and all updates that come with it. */
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D *v3d)
{
SculptSession *ss = ob->sculpt;
diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c
index 0ea0173f8a3..bdb7b483997 100644
--- a/source/blender/blenkernel/intern/paint_toolslots.c
+++ b/source/blender/blenkernel/intern/paint_toolslots.c
@@ -140,10 +140,6 @@ void BKE_paint_toolslots_brush_update(Paint *paint)
BKE_paint_toolslots_brush_update_ex(paint, paint->brush);
}
-/**
- * Run this to ensure brush types are set for each slot on entering modes
- * (for new scenes for example).
- */
void BKE_paint_toolslots_brush_validate(Main *bmain, Paint *paint)
{
/* Clear slots with invalid slots or mode (unlikely but possible). */
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index b158633294e..674f264feb7 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -500,6 +500,7 @@ IDTypeInfo IDType_ID_PA = {
.name_plural = "particles",
.translation_context = BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
.flags = 0,
+ .asset_type_info = NULL,
.init_data = particle_settings_init,
.copy_data = particle_settings_copy_data,
@@ -507,6 +508,7 @@ IDTypeInfo IDType_ID_PA = {
.make_local = NULL,
.foreach_id = particle_settings_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = particle_settings_blend_write,
@@ -554,7 +556,6 @@ static void get_cpa_texture(Mesh *mesh,
int event,
float cfra);
-/* few helpers for countall etc. */
int count_particles(ParticleSystem *psys)
{
ParticleSettings *part = psys->part;
@@ -644,7 +645,7 @@ static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *buf
/************************************************/
/* Getting stuff */
/************************************************/
-/* get object's active particle system safely */
+
ParticleSystem *psys_get_current(Object *ob)
{
ParticleSystem *psys;
@@ -912,9 +913,11 @@ int psys_uses_gravity(ParticleSimulationData *sim)
return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part &&
sim->psys->part->effector_weights->global_gravity != 0.0f;
}
+
/************************************************/
/* Freeing stuff */
/************************************************/
+
static void fluid_free_settings(SPHFluidSettings *fluid)
{
if (fluid) {
@@ -1054,7 +1057,6 @@ void psys_free_pdd(ParticleSystem *psys)
psys->pdd->partsize = 0;
}
}
-/* free everything */
void psys_free(Object *ob, ParticleSystem *psys)
{
if (psys) {
@@ -1202,6 +1204,7 @@ void psys_copy_particles(ParticleSystem *psys_dst, ParticleSystem *psys_src)
/************************************************/
/* Interpolation */
/************************************************/
+
static float interpolate_particle_value(
float v1, float v2, float v3, float v4, const float w[4], int four)
{
@@ -1669,7 +1672,7 @@ static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCach
/************************************************/
/* Particles on a dm */
/************************************************/
-/* interpolate a location on a face based on face coordinates */
+
void psys_interpolate_face(MVert *mvert,
MFace *mface,
MTFace *tface,
@@ -1901,18 +1904,6 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4
}
}
-/**
- * Find the final derived mesh tessface for a particle, from its original tessface index.
- * This is slow and can be optimized but only for many lookups.
- *
- * \param mesh_final: Final mesh, it may not have the same topology as original mesh.
- * \param mesh_original: Original mesh, use for accessing #MPoly to #MFace mapping.
- * \param findex_orig: The input tessface index.
- * \param fw: Face weights (position of the particle inside the \a findex_orig tessface).
- * \param poly_nodes: May be NULL, otherwise an array of linked list,
- * one for each final \a mesh_final polygon, containing all its tessfaces indices.
- * \return The \a mesh_final tessface index.
- */
int psys_particle_dm_face_lookup(Mesh *mesh_final,
Mesh *mesh_original,
int findex_orig,
@@ -2094,7 +2085,6 @@ static int psys_map_index_on_dm(Mesh *mesh,
return 1;
}
-/* interprets particle data to get a point on a mesh in object space */
void psys_particle_on_dm(Mesh *mesh_final,
int from,
int index,
@@ -2216,9 +2206,11 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys)
}
return NULL;
}
+
/************************************************/
/* Particles on a shape */
/************************************************/
+
/* ready for future use */
static void psys_particle_on_shape(int UNUSED(distr),
int UNUSED(index),
@@ -2247,6 +2239,7 @@ static void psys_particle_on_shape(int UNUSED(distr),
copy_v3_v3(orco, zerovec);
}
}
+
/************************************************/
/* Particles on emitter */
/************************************************/
@@ -2321,6 +2314,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd,
psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco);
}
}
+
/************************************************/
/* Path Cache */
/************************************************/
@@ -3273,11 +3267,6 @@ static void cache_key_incremental_rotation(ParticleCacheKey *key0,
}
}
-/**
- * Calculates paths ready for drawing/rendering
- * - Useful for making use of opengl vertex arrays for super fast strand drawing.
- * - Makes child strands possible and creates them too into the cache.
- * - Cached path data is also used to determine cut position for the editmode tool. */
void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
{
PARTICLE_PSMD;
@@ -3760,9 +3749,11 @@ void psys_cache_edit_paths(Depsgraph *depsgraph,
}
}
}
+
/************************************************/
/* Particle Key handling */
/************************************************/
+
void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
{
if (time) {
@@ -3922,6 +3913,7 @@ void psys_mat_hair_to_global(
/************************************************/
/* ParticleSettings handling */
/************************************************/
+
static ModifierData *object_add_or_copy_particle_system(
Main *bmain, Scene *scene, Object *ob, const char *name, const ParticleSystem *psys_orig)
{
@@ -4458,9 +4450,11 @@ void psys_get_texture(
CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp);
CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
}
+
/************************************************/
/* Particle State */
/************************************************/
+
float psys_get_timestep(ParticleSimulationData *sim)
{
return 0.04f * sim->psys->part->timetweak;
@@ -4586,7 +4580,6 @@ static void get_child_modifier_parameters(ParticleSettings *part,
ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_twist);
}
}
-/* gets hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(ParticleSimulationData *sim,
int p,
ParticleKey *state,
@@ -4855,8 +4848,10 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
}
}
}
-/* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
-int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always)
+bool psys_get_particle_state(ParticleSimulationData *sim,
+ int p,
+ ParticleKey *state,
+ const bool always)
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
@@ -4871,12 +4866,12 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
if (p >= totpart) {
if (!psys->totchild) {
- return 0;
+ return false;
}
if (part->childtype == PART_CHILD_FACES) {
if (!(psys->flag & PSYS_KEYED)) {
- return 0;
+ return false;
}
cpa = psys->child + p - totpart;
@@ -4886,7 +4881,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
if (!always) {
if ((state->time < 0.0f && !(part->flag & PART_UNBORN)) ||
(state->time > 1.0f && !(part->flag & PART_DIED))) {
- return 0;
+ return false;
}
}
@@ -4894,7 +4889,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
(part->lifetime * psys_frand(psys, p + 24));
psys_get_particle_on_path(sim, p, state, 1);
- return 1;
+ return true;
}
cpa = sim->psys->child + p - totpart;
@@ -4908,7 +4903,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
if (!always) {
if ((cfra < pa->time && (part->flag & PART_UNBORN) == 0) ||
(cfra >= pa->dietime && (part->flag & PART_DIED) == 0)) {
- return 0;
+ return false;
}
}
@@ -4918,7 +4913,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
if (sim->psys->flag & PSYS_KEYED) {
state->time = -cfra;
psys_get_particle_on_path(sim, p, state, 1);
- return 1;
+ return true;
}
if (cpa) {
@@ -5018,7 +5013,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
}
- return 1;
+ return true;
}
void psys_get_dupli_texture(ParticleSystem *psys,
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 863476c6638..fd4f89e3f6d 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -997,12 +997,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
BKE_mesh_tessface_ensure(mesh);
/* we need orco for consistent distributions */
- if (!CustomData_has_layer(&mesh->vdata, CD_ORCO)) {
- /* Orcos are stored in normalized 0..1 range by convention. */
- float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob);
- BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false);
- CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_ASSIGN, orcodata, mesh->totvert);
- }
+ BKE_mesh_orco_ensure(ob, mesh);
if (from == PART_FROM_VERT) {
MVert *mv = mesh->mvert;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 8986847a034..e489f9e2bac 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -452,7 +452,6 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic
}
}
-/* threaded child particle distribution and path caching */
void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData *sim)
{
memset(ctx, 0, sizeof(ParticleThreadContext));
@@ -591,7 +590,6 @@ static void init_particle_texture(ParticleSimulationData *sim, ParticleData *pa,
}
}
-/* set particle parameters that don't change during particle's life */
void init_particle(ParticleSimulationData *sim, ParticleData *pa)
{
ParticleSettings *part = sim->psys->part;
@@ -1066,7 +1064,6 @@ static void evaluate_emitter_anim(struct Depsgraph *depsgraph,
BKE_object_where_is_calc_time(depsgraph, scene, ob, cfra);
}
-/* sets particle to the emitter surface with initial velocity & rotation */
void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra)
{
ParticleSystem *psys = sim->psys;
@@ -1157,9 +1154,11 @@ static void reset_all_particles(ParticleSimulationData *sim, float dtime, float
reset_particle(sim, pa, dtime, cfra);
}
}
+
/************************************************/
/* Particle targets */
/************************************************/
+
ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt)
{
ParticleSystem *psys = NULL;
@@ -1180,10 +1179,11 @@ ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt)
return psys;
}
+
/************************************************/
/* Keyed particles */
/************************************************/
-/* Counts valid keyed targets */
+
void psys_count_keyed_targets(ParticleSimulationData *sim)
{
ParticleSystem *psys = sim->psys, *kpsys;
@@ -1288,6 +1288,7 @@ static void set_keyed_keys(ParticleSimulationData *sim)
/************************************************/
/* Point Cache */
/************************************************/
+
void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
{
PointCache *cache = psys->pointcache;
@@ -1325,6 +1326,7 @@ static void bvhtree_balance_isolated(void *userdata)
/************************************************/
/* Effectors */
/************************************************/
+
static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
{
if (psys) {
@@ -2181,7 +2183,6 @@ void psys_sph_finalize(SPHData *sphdata)
}
}
-/* Sample the density field at a point in space. */
void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
{
ParticleSystem **psys = sphdata->psys;
@@ -2234,6 +2235,7 @@ static void sph_integrate(ParticleSimulationData *sim,
/************************************************/
/* Basic physics */
/************************************************/
+
typedef struct EfData {
ParticleTexture ptex;
ParticleSimulationData *sim;
@@ -2787,7 +2789,6 @@ static int collision_sphere_to_verts(ParticleCollision *col,
return hit != NULL;
}
-/* Callback for BVHTree near test */
void BKE_psys_collision_neartest_cb(void *userdata,
int index,
const BVHTreeRay *ray,
@@ -3179,10 +3180,14 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa
}
}
}
+
/************************************************/
/* Hair */
/************************************************/
-/* check if path cache or children need updating and do it if needed */
+
+/**
+ * Check if path cache or children need updating and do it if needed.
+ */
static void psys_update_path_cache(ParticleSimulationData *sim,
float cfra,
const bool use_render_params)
@@ -4627,7 +4632,6 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
}
}
-/* system type has changed so set sensible defaults and clear non applicable flags */
void psys_changed_type(Object *ob, ParticleSystem *psys)
{
ParticleSettings *part = psys->part;
@@ -4765,8 +4769,6 @@ static void particle_settings_free_local(ParticleSettings *particle_settings)
MEM_freeN(particle_settings);
}
-/* main particle update call, checks that things are ok on the large scale and
- * then advances in to actual particle calculations depending on particle type */
void particle_system_update(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 2318a05e635..2f22f94d142 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -78,7 +78,6 @@ void BB_reset(BB *bb)
bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
}
-/* Expand the bounding box to include a new coordinate */
void BB_expand(BB *bb, const float co[3])
{
for (int i = 0; i < 3; i++) {
@@ -87,7 +86,6 @@ void BB_expand(BB *bb, const float co[3])
}
}
-/* Expand the bounding box to include another bounding box */
void BB_expand_with_bb(BB *bb, BB *bb2)
{
for (int i = 0; i < 3; i++) {
@@ -96,7 +94,6 @@ void BB_expand_with_bb(BB *bb, BB *bb2)
}
}
-/* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
int BB_widest_axis(const BB *bb)
{
float dim[3];
@@ -351,7 +348,6 @@ static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int
node->orig_vb = node->vb;
}
-/* Returns the number of visible quads in the nodes' grids. */
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
const int *grid_indices,
int totgrid,
@@ -555,12 +551,6 @@ static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
build_sub(pbvh, 0, cb, prim_bbc, 0, totprim);
}
-/**
- * Do a full rebuild with on Mesh data structure.
- *
- * \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH
- * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
- */
void BKE_pbvh_build_mesh(PBVH *pbvh,
const Mesh *mesh,
const MPoly *mpoly,
@@ -621,7 +611,6 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
MEM_freeN(pbvh->vert_bitmap);
}
-/* Do a full rebuild with on Grids data structure */
void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
@@ -1954,11 +1943,6 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
*r_orco_coords = node->bm_orco;
}
-/**
- * \note doing a full search on all vertices here seems expensive,
- * however this is important to avoid having to recalculate bound-box & sync the buffers to the
- * GPU (which is far more expensive!) See: T47232.
- */
bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node)
{
BLI_assert(pbvh->type == PBVH_FACES);
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 679a8b378b9..6f57448b0ab 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1875,7 +1875,6 @@ static void pbvh_bmesh_create_nodes_fast_recursive(
/***************************** Public API *****************************/
-/* Build a PBVH from a BMesh */
void BKE_pbvh_build_bmesh(PBVH *pbvh,
BMesh *bm,
bool smooth_shading,
@@ -1953,7 +1952,6 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
MEM_freeN(nodeinfo);
}
-/* Collapse short edges, subdivide long edges */
bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
@@ -2031,10 +2029,6 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
return modified;
}
-/* In order to perform operations on the original node coordinates
- * (currently just raycast), store the node's triangles and vertices.
- *
- * Skips triangles that are hidden. */
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
{
/* Skip if original coords/triangles are already saved */
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 79b25c027ba..12c2d7aac78 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -180,9 +180,18 @@ struct PBVH {
/* pbvh.c */
void BB_reset(BB *bb);
+/**
+ * Expand the bounding box to include a new coordinate.
+ */
void BB_expand(BB *bb, const float co[3]);
+/**
+ * Expand the bounding box to include another bounding box.
+ */
void BB_expand_with_bb(BB *bb, BB *bb2);
void BBC_update_centroid(BBC *bbc);
+/**
+ * Return 0, 1, or 2 to indicate the widest axis of the bounding box.
+ */
int BB_widest_axis(const BB *bb);
void pbvh_grow_nodes(PBVH *bvh, int totnode);
bool ray_face_intersection_quad(const float ray_start[3],
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 57225872c7e..df76f003498 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -266,7 +266,8 @@ static void ptcache_softbody_error(const ID *UNUSED(owner_id),
/* ignored for now */
}
-/* Particle functions */
+/* Particle functions. */
+
void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
{
PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
@@ -873,6 +874,7 @@ static void ptcache_rigidbody_error(const struct ID *UNUSED(owner_id),
}
/* Creating ID's */
+
void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
{
memset(pid, 0, sizeof(PTCacheID));
@@ -1008,9 +1010,6 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->file_type = PTCACHE_FILE_PTCACHE;
}
-/* The fluid modifier does not actually use this anymore, but some parts of Blender expect that it
- * still has a point cache currently. For example, the fluid modifier uses
- * #DEG_add_collision_relations, which internally creates relations with the point cache. */
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *fmd)
{
FluidDomainSettings *fds = fmd->domain;
@@ -1104,10 +1103,6 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->file_type = PTCACHE_FILE_PTCACHE;
}
-/**
- * \param ob: Optional, may be NULL.
- * \param scene: Optional may be NULL.
- */
PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
{
PTCacheID result = {0};
@@ -1327,10 +1322,11 @@ static int ptcache_frame_from_filename(const char *filename, const char *ext)
static int ptcache_path(PTCacheID *pid, char *filename)
{
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
Library *lib = (pid->owner_id) ? pid->owner_id->lib : NULL;
const char *blendfilename = (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH) == 0) ?
lib->filepath_abs :
- BKE_main_blendfile_path_from_global();
+ blendfile_path;
size_t i;
if (pid->cache->flag & PTCACHE_EXTERNAL) {
@@ -1342,7 +1338,7 @@ static int ptcache_path(PTCacheID *pid, char *filename)
return BLI_path_slash_ensure(filename); /* new strlen() */
}
- if (G.relbase_valid || lib) {
+ if ((blendfile_path[0] != '\0') || lib) {
char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
BLI_split_file_part(blendfilename, file, sizeof(file));
@@ -1427,8 +1423,11 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p
filename[0] = '\0';
newname = filename;
- if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
- return 0; /* save blend file before using disk pointcache */
+ if ((pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ if (blendfile_path[0] == '\0') {
+ return 0; /* save blend file before using disk pointcache */
+ }
}
/* start with temp dir */
@@ -1474,8 +1473,11 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
return NULL;
}
#endif
- if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
- return NULL; /* save blend file before using disk pointcache */
+ if ((pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ if (blendfile_path[0] == '\0') {
+ return NULL; /* save blend file before using disk pointcache */
+ }
}
ptcache_filename(pid, filename, cfra, 1, 1);
@@ -1713,7 +1715,8 @@ static int ptcache_file_header_begin_write(PTCacheFile *pf)
return 1;
}
-/* Data pointer handling */
+/* Data pointer handling. */
+
int BKE_ptcache_data_size(int data_type)
{
return ptcache_data_size[data_type];
@@ -1734,7 +1737,6 @@ static void ptcache_file_pointers_init(PTCacheFile *pf)
pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1 << BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL;
}
-/* Check to see if point number "index" is in pm, uses binary search for index data. */
int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
{
if (pm->totpoint > 0 && pm->data[BPHYS_DATA_INDEX]) {
@@ -2288,7 +2290,6 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
return 1;
}
/* reads cache from disk or memory */
-/* possible to get old or interpolated result */
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
{
int cfrai = (int)floor(cfra), cfra1 = 0, cfra2 = 0;
@@ -2549,7 +2550,6 @@ static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
return 0;
}
-/* writes cache to disk or memory */
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
{
PointCache *cache = pid->cache;
@@ -2600,7 +2600,8 @@ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
* mode - PTCACHE_CLEAR_ALL,
*/
-/* Clears & resets */
+/* Clears & resets. */
+
void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
{
unsigned int len; /* store the length of the string */
@@ -2632,8 +2633,6 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
}
#endif
- // if (!G.relbase_valid) return; /* Save blend file before using pointcache. */
-
/* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
switch (mode) {
case PTCACHE_CLEAR_ALL:
@@ -3014,50 +3013,6 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
return reset;
}
-/* Use this when quitting blender, with unsaved files */
-void BKE_ptcache_remove(void)
-{
- char path[MAX_PTCACHE_PATH];
- char path_full[MAX_PTCACHE_PATH];
- int rmdir = 1;
-
- ptcache_path(NULL, path);
-
- if (BLI_exists(path)) {
- /* The pointcache dir exists? - remove all pointcache */
-
- DIR *dir;
- struct dirent *de;
-
- dir = opendir(path);
- if (dir == NULL) {
- return;
- }
-
- while ((de = readdir(dir)) != NULL) {
- if (FILENAME_IS_CURRPAR(de->d_name)) {
- /* do nothing */
- }
- else if (strstr(de->d_name, PTCACHE_EXT)) { /* Do we have the right extension? */
- BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
- BLI_delete(path_full, false, false);
- }
- else {
- rmdir = 0; /* unknown file, don't remove the dir */
- }
- }
-
- closedir(dir);
- }
- else {
- rmdir = 0; /* Path doesn't exist. */
- }
-
- if (rmdir) {
- BLI_delete(path, true, false);
- }
-}
-
/* Point Cache handling */
PointCache *BKE_ptcache_add(ListBase *ptcaches)
@@ -3150,7 +3105,6 @@ static PointCache *ptcache_copy(PointCache *cache, const bool copy_data)
return ncache;
}
-/* returns first point cache */
PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new,
const ListBase *ptcaches_old,
const int flag)
@@ -3170,6 +3124,7 @@ PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new,
* every user action changing stuff, and then it runs a complete bake??? (ton) */
/* Baking */
+
void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
PTCacheBaker baker;
@@ -3202,7 +3157,6 @@ static void ptcache_dt_to_str(char *str, double dtime)
}
}
-/* if bake is not given run simulations to current frame */
void BKE_ptcache_bake(PTCacheBaker *baker)
{
Scene *scene = baker->scene;
@@ -3439,7 +3393,9 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
/* TODO: call redraw all windows somehow */
}
+
/* Helpers */
+
void BKE_ptcache_disk_to_mem(PTCacheID *pid)
{
PointCache *cache = pid->cache;
@@ -3495,8 +3451,9 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
{
PointCache *cache = pid->cache;
int last_exact = cache->last_exact;
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
- if (!G.relbase_valid) {
+ if (blendfile_path[0] == '\0') {
cache->flag &= ~PTCACHE_DISK_CACHE;
if (G.debug & G_DEBUG) {
printf("File must be saved before using disk cache!\n");
diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc
index 15c5a809118..82dde79cff6 100644
--- a/source/blender/blenkernel/intern/pointcloud.cc
+++ b/source/blender/blenkernel/intern/pointcloud.cc
@@ -79,7 +79,7 @@ static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_s
{
PointCloud *pointcloud_dst = (PointCloud *)id_dst;
const PointCloud *pointcloud_src = (const PointCloud *)id_src;
- pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_dst->mat));
+ pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat));
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&pointcloud_src->pdata,
@@ -175,6 +175,7 @@ IDTypeInfo IDType_ID_PT = {
/* name_plural */ "pointclouds",
/* translation_context */ BLT_I18NCONTEXT_ID_POINTCLOUD,
/* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ /* asset_type_info */ nullptr,
/* init_data */ pointcloud_init_data,
/* copy_data */ pointcloud_copy_data,
@@ -182,6 +183,7 @@ IDTypeInfo IDType_ID_PT = {
/* make_local */ nullptr,
/* foreach_id */ pointcloud_foreach_id,
/* foreach_cache */ nullptr,
+ /* foreach_path */ nullptr,
/* owner_get */ nullptr,
/* blend_write */ pointcloud_blend_write,
@@ -417,6 +419,7 @@ void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene
}
/* Draw Cache */
+
void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode) = nullptr;
void (*BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud) = nullptr;
diff --git a/source/blender/blenkernel/intern/preferences.c b/source/blender/blenkernel/intern/preferences.c
index 41046563f98..4bb2231bbb1 100644
--- a/source/blender/blenkernel/intern/preferences.c
+++ b/source/blender/blenkernel/intern/preferences.c
@@ -62,10 +62,6 @@ bUserAssetLibrary *BKE_preferences_asset_library_add(UserDef *userdef,
return library;
}
-/**
- * Unlink and free a library preference member.
- * \note Free's \a library itself.
- */
void BKE_preferences_asset_library_remove(UserDef *userdef, bUserAssetLibrary *library)
{
BLI_freelinkN(&userdef->asset_libraries, library);
@@ -84,13 +80,9 @@ void BKE_preferences_asset_library_name_set(UserDef *userdef,
sizeof(library->name));
}
-/* Set the library path, ensuring it is pointing to a directory.
- * Single blend files can only act as "Current File" library; libraries on disk
- * should always be directories. If the path does not exist, that's fine; it can
- * created as directory if necessary later. */
void BKE_preferences_asset_library_path_set(bUserAssetLibrary *library, const char *path)
{
- BLI_strncpy_utf8(library->path, path, sizeof(library->path));
+ BLI_strncpy(library->path, path, sizeof(library->path));
if (BLI_is_file(library->path)) {
BLI_path_parent_dir(library->path);
}
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 90e7ca3f11a..bc11861f2c8 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -76,11 +76,6 @@ void BKE_reports_init(ReportList *reports, int flag)
reports->flag = flag;
}
-/**
- * Only frees the list \a reports.
- * To make displayed reports disappear, either remove window-manager reports
- * (wmWindowManager.reports, or CTX_wm_reports()), or use #WM_report_banners_cancel().
- */
void BKE_reports_clear(ReportList *reports)
{
Report *report, *report_next;
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 4482285c271..75e9bc2fbee 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -103,7 +103,6 @@ static void RB_constraint_delete(void *UNUSED(con))
#endif
-/* Free rigidbody world */
void BKE_rigidbody_free_world(Scene *scene)
{
bool is_orig = (scene->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
@@ -160,7 +159,6 @@ void BKE_rigidbody_free_world(Scene *scene)
MEM_freeN(rbw);
}
-/* Free RigidBody settings and sim instances */
void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
{
bool is_orig = (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
@@ -208,7 +206,6 @@ void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
ob->rigidbody_object = NULL;
}
-/* Free RigidBody constraint and sim instance */
void BKE_rigidbody_free_constraint(Object *ob)
{
RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
@@ -637,8 +634,6 @@ static void rigidbody_validate_sim_shape(RigidBodyWorld *rbw, Object *ob, bool r
/* --------------------- */
-/* helper function to calculate volume of rigidbody object */
-/* TODO: allow a parameter to specify method used to calculate this? */
void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
{
RigidBodyOb *rbo = ob->rigidbody_object;
@@ -1133,12 +1128,6 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
/* --------------------- */
-/**
- * Create physics sim world given RigidBody world settings
- *
- * \note this does NOT update object references that the scene uses,
- * in case those aren't ready yet!
- */
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
{
/* sanity checks */
@@ -1161,7 +1150,6 @@ void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool re
/* ************************************** */
/* Setup Utilities - Create Settings Blocks */
-/* Set up RigidBody world */
RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
{
/* try to get whatever RigidBody world that might be representing this already */
@@ -1246,7 +1234,6 @@ void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func,
}
}
-/* Add rigid body settings to the specified object */
RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
{
RigidBodyOb *rbo;
@@ -1309,7 +1296,6 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
return rbo;
}
-/* Add rigid body constraint to the specified object */
RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
{
RigidBodyCon *rbc;
@@ -1429,11 +1415,6 @@ void BKE_rigidbody_main_collection_object_add(Main *bmain, Collection *collectio
/* ************************************** */
/* Utilities API */
-/**
- * Get RigidBody world for the given scene, creating one if needed
- *
- * \param scene: Scene to find active Rigid Body world for.
- */
RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
{
/* sanity check */
@@ -2058,7 +2039,6 @@ bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0 && ctime > rbw->shared->pointcache->startframe);
}
-/* Sync rigid body and object transformations */
void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
{
if (!BKE_rigidbody_is_affected_by_simulation(ob)) {
@@ -2089,7 +2069,6 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
}
}
-/* Used when canceling transforms - return rigidbody and object to initial states */
void BKE_rigidbody_aftertrans_update(
Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
{
@@ -2168,8 +2147,6 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
/* ------------------ */
-/* Rebuild rigid body world */
-/* NOTE: this needs to be called before frame update to work correctly */
void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
@@ -2209,7 +2186,6 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime
}
}
-/* Run RigidBody simulation for the specified physics world */
void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
@@ -2307,6 +2283,7 @@ void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
{
}
+
void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
{
if (r_vol) {
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a0bd3abbc1a..916a2786a98 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -71,6 +71,7 @@
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
+#include "BKE_bpath.h"
#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_colortools.h"
@@ -891,6 +892,45 @@ static void scene_foreach_cache(ID *id,
user_data);
}
+static bool seq_foreach_path_callback(Sequence *seq, void *user_data)
+{
+ if (SEQ_HAS_PATH(seq)) {
+ StripElem *se = seq->strip->stripdata;
+ BPathForeachPathData *bpath_data = (BPathForeachPathData *)user_data;
+
+ if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
+ BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dir, se->name);
+ }
+ else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
+ /* NOTE: An option not to loop over all strips could be useful? */
+ unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
+ unsigned int i;
+
+ if (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE) {
+ /* only operate on one path */
+ len = MIN2(1u, len);
+ }
+
+ for (i = 0; i < len; i++, se++) {
+ BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dir, se->name);
+ }
+ }
+ else {
+ /* simple case */
+ BKE_bpath_foreach_path_fixed_process(bpath_data, seq->strip->dir);
+ }
+ }
+ return true;
+}
+
+static void scene_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Scene *scene = (Scene *)id;
+ if (scene->ed != NULL) {
+ SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data);
+ }
+}
+
static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Scene *sce = (Scene *)id;
@@ -1600,6 +1640,7 @@ IDTypeInfo IDType_ID_SCE = {
.name_plural = "scenes",
.translation_context = BLT_I18NCONTEXT_ID_SCENE,
.flags = 0,
+ .asset_type_info = NULL,
.init_data = scene_init_data,
.copy_data = scene_copy_data,
@@ -1609,6 +1650,7 @@ IDTypeInfo IDType_ID_SCE = {
.make_local = NULL,
.foreach_id = scene_foreach_id,
.foreach_cache = scene_foreach_cache,
+ .foreach_path = scene_foreach_path,
.owner_get = NULL,
.blend_write = scene_blend_write,
@@ -1659,7 +1701,6 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
-/* flag -- copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more). */
ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
{
if (toolsettings == NULL) {
@@ -1986,9 +2027,6 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
return sce;
}
-/**
- * Check if there is any instance of the object in the scene
- */
bool BKE_scene_object_find(Scene *scene, Object *ob)
{
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
@@ -2011,12 +2049,6 @@ Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name)
return NULL;
}
-/**
- * Sets the active scene, mainly used when running in background mode
- * (`--scene` command line argument).
- * This is also called to set the scene directly, bypassing windowing code.
- * Otherwise #WM_window_set_active_scene is used when changing scenes by the user.
- */
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
Object *ob;
@@ -2041,7 +2073,6 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
* (render code calls own animation updates). */
}
-/* called from creator_args.c */
Scene *BKE_scene_set_name(Main *bmain, const char *name)
{
Scene *sce = (Scene *)BKE_libblock_find_name(bmain, ID_SCE, name);
@@ -2055,8 +2086,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
return NULL;
}
-/* Used by meta-balls, return *all* objects (including duplis)
- * existing in the scene (including scene's sets). */
int BKE_scene_base_iter_next(
Depsgraph *depsgraph, SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob)
{
@@ -2281,8 +2310,6 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame)
return NULL;
}
-/* return the current marker for this frame,
- * we can have more than 1 marker per frame, this just returns the first :/ */
const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
{
const TimeMarker *marker, *best_marker = NULL;
@@ -2326,7 +2353,6 @@ void BKE_scene_remove_rigidbody_object(struct Main *bmain,
}
}
-/* checks for cycle, returns 1 if it's all OK */
bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
{
Scene *sce_iter;
@@ -2349,16 +2375,11 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
return true;
}
-/* Return fractional frame number taking into account subframes and time
- * remapping. This the time value used by animation, modifiers and physics
- * evaluation. */
float BKE_scene_ctime_get(const Scene *scene)
{
return BKE_scene_frame_to_ctime(scene, scene->r.cfra);
}
-/* Convert integer frame number to fractional frame number taking into account
- * subframes and time remapping. */
float BKE_scene_frame_to_ctime(const Scene *scene, const int frame)
{
float ctime = frame;
@@ -2368,13 +2389,11 @@ float BKE_scene_frame_to_ctime(const Scene *scene, const int frame)
return ctime;
}
-/* Get current fractional frame based on frame and subframe. */
float BKE_scene_frame_get(const Scene *scene)
{
return scene->r.cfra + scene->r.subframe;
}
-/* Set current frame and subframe based on a fractional frame. */
void BKE_scene_frame_set(Scene *scene, float frame)
{
double intpart;
@@ -2411,12 +2430,6 @@ TransformOrientationSlot *BKE_scene_orientation_slot_get_from_flag(Scene *scene,
return BKE_scene_orientation_slot_get(scene, slot_index);
}
-/**
- * Activate a transform orientation in a 3D view based on an enum value.
- *
- * \param orientation: If this is #V3D_ORIENT_CUSTOM or greater, the custom transform orientation
- * with index \a orientation - #V3D_ORIENT_CUSTOM gets activated.
- */
void BKE_scene_orientation_slot_set_index(TransformOrientationSlot *orient_slot, int orientation)
{
const bool is_custom = orientation >= V3D_ORIENT_CUSTOM;
@@ -2623,7 +2636,6 @@ void BKE_scene_graph_evaluated_ensure(Depsgraph *depsgraph, Main *bmain)
scene_graph_update_tagged(depsgraph, bmain, true);
}
-/* applies changes right away, does all sets too */
void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, const bool clear_recalc)
{
Scene *scene = DEG_get_input_scene(depsgraph);
@@ -2699,12 +2711,6 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
BKE_scene_graph_update_for_newframe_ex(depsgraph, true);
}
-/**
- * Ensures given scene/view_layer pair has a valid, up-to-date depsgraph.
- *
- * \warning Sets matching depsgraph as active,
- * so should only be called from the active editing context (usually, from operators).
- */
void BKE_scene_view_layer_graph_evaluated_ensure(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
@@ -2712,7 +2718,6 @@ void BKE_scene_view_layer_graph_evaluated_ensure(Main *bmain, Scene *scene, View
BKE_scene_graph_update_tagged(depsgraph, bmain);
}
-/* return default view */
SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name)
{
SceneRenderView *srv;
@@ -2782,12 +2787,6 @@ int get_render_child_particle_number(const RenderData *r, int num, bool for_rend
return num;
}
-/**
- * Helper function for the SETLOOPER and SETLOOPER_VIEW_LAYER macros
- *
- * It iterates over the bases of the active layer and then the bases
- * of the active layer of the background (set) scenes recursively.
- */
Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
{
if (base && base->next) {
@@ -2852,7 +2851,6 @@ typedef enum eCyclesFeatureSet {
CYCLES_FEATURES_EXPERIMENTAL = 1,
} eCyclesFeatureSet;
-/* We cannot use const as RNA_id_pointer_create is not using a const ID. */
bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
{
BLI_assert(BKE_scene_uses_cycles(scene));
@@ -2878,16 +2876,6 @@ void BKE_scene_base_flag_to_objects(ViewLayer *view_layer)
}
}
-/**
- * Synchronize object base flags
- *
- * This is usually handled by the depsgraph.
- * However, in rare occasions we need to use the latest object flags
- * before depsgraph is fully updated.
- *
- * It should (ideally) only run for copy-on-written objects since this is
- * runtime data generated per-viewlayer.
- */
void BKE_scene_object_base_flag_sync_from_base(Base *base)
{
Object *ob = base->object;
@@ -2960,10 +2948,6 @@ int BKE_render_preview_pixel_size(const RenderData *r)
return r->preview_pixel_size;
}
-/**
- * Apply the needed correction factor to value, based on unit_type
- * (only length-related are affected currently) and unit->scale_length.
- */
double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, double value)
{
if (unit->system == USER_UNIT_NONE) {
@@ -3038,7 +3022,6 @@ bool BKE_scene_multiview_is_stereo3d(const RenderData *rd)
((srv[1]->viewflag & SCE_VIEW_DISABLE) == 0));
}
-/* return whether to render this SceneRenderView */
bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
{
if (srv == NULL) {
@@ -3065,7 +3048,6 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene
return false;
}
-/* return true if viewname is the first or if the name is NULL or not found */
bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname)
{
SceneRenderView *srv;
@@ -3087,7 +3069,6 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *
return true;
}
-/* return true if viewname is the last or if the name is NULL or not found */
bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname)
{
SceneRenderView *srv;
@@ -3171,12 +3152,6 @@ void BKE_scene_multiview_filepath_get(SceneRenderView *srv, const char *filepath
BLI_path_suffix(r_filepath, FILE_MAX, srv->suffix, "");
}
-/**
- * When multiview is not used the filepath is as usual (e.g., `Image.jpg`).
- * When multiview is on, even if only one view is enabled the view is incorporated
- * into the file name (e.g., `Image_L.jpg`). That allows for the user to re-render
- * individual views.
- */
void BKE_scene_multiview_view_filepath_get(const RenderData *rd,
const char *filepath,
const char *viewname,
@@ -3564,10 +3539,6 @@ TransformOrientation *BKE_scene_transform_orientation_find(const Scene *scene, c
return BLI_findlink(&scene->transform_spaces, index);
}
-/**
- * \return the index that \a orientation has within \a scene's transform-orientation list
- * or -1 if not found.
- */
int BKE_scene_transform_orientation_get_index(const Scene *scene,
const TransformOrientation *orientation)
{
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 6352e08ec4b..cd8493ee559 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -45,6 +45,7 @@
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
+#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BLI_mempool.h"
@@ -97,10 +98,6 @@ 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);
@@ -258,7 +255,6 @@ static void screen_blend_write(BlendWriter *writer, ID *id, const void *id_addre
BKE_screen_area_map_blend_write(writer, AREAMAP_FROM_SCREEN(screen));
}
-/* Cannot use IDTypeInfo callback yet, because of the return value. */
bool BKE_screen_blend_read_data(BlendDataReader *reader, bScreen *screen)
{
bool success = true;
@@ -304,6 +300,7 @@ IDTypeInfo IDType_ID_SCR = {
.name_plural = "screens",
.translation_context = BLT_I18NCONTEXT_ID_SCREEN,
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_ONLY_APPEND | IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = NULL,
.copy_data = NULL,
@@ -311,6 +308,7 @@ IDTypeInfo IDType_ID_SCR = {
.make_local = NULL,
.foreach_id = screen_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = screen_blend_write,
@@ -502,39 +500,35 @@ ARegion *BKE_area_region_copy(const SpaceType *st, const ARegion *region)
return newar;
}
-/* from lb2 to lb1, lb1 is supposed to be freed */
-static void region_copylist(SpaceType *st, ListBase *lb1, ListBase *lb2)
+/* from lb_src to lb_dst, lb_dst is supposed to be freed */
+static void region_copylist(SpaceType *st, ListBase *lb_dst, ListBase *lb_src)
{
/* to be sure */
- BLI_listbase_clear(lb1);
+ BLI_listbase_clear(lb_dst);
- LISTBASE_FOREACH (ARegion *, region, lb2) {
+ LISTBASE_FOREACH (ARegion *, region, lb_src) {
ARegion *region_new = BKE_area_region_copy(st, region);
- BLI_addtail(lb1, region_new);
+ BLI_addtail(lb_dst, region_new);
}
}
-/* lb1 should be empty */
-void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2)
+void BKE_spacedata_copylist(ListBase *lb_dst, ListBase *lb_src)
{
- BLI_listbase_clear(lb1); /* to be sure */
+ BLI_listbase_clear(lb_dst); /* to be sure */
- LISTBASE_FOREACH (SpaceLink *, sl, lb2) {
+ LISTBASE_FOREACH (SpaceLink *, sl, lb_src) {
SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
if (st && st->duplicate) {
SpaceLink *slnew = st->duplicate(sl);
- BLI_addtail(lb1, slnew);
+ BLI_addtail(lb_dst, slnew);
region_copylist(st, &slnew->regionbase, &sl->regionbase);
}
}
}
-/* facility to set locks for drawing to survive (render) threads accessing drawing data */
-/* lock can become bitflag too */
-/* should be replaced in future by better local data handling for threads */
void BKE_spacedata_draw_locks(bool set)
{
LISTBASE_FOREACH (SpaceType *, st, &spacetypes) {
@@ -549,10 +543,6 @@ void BKE_spacedata_draw_locks(bool set)
}
}
-/**
- * Version of #BKE_area_find_region_type that also works if \a slink
- * is not the active space of \a area.
- */
ARegion *BKE_spacedata_find_region_type(const SpaceLink *slink,
const ScrArea *area,
int region_type)
@@ -586,7 +576,6 @@ void BKE_spacedata_callback_id_remap_set(void (*func)(ScrArea *area, SpaceLink *
spacedata_id_remap_cb = func;
}
-/* UNUSED!!! */
void BKE_spacedata_id_unref(struct ScrArea *area, struct SpaceLink *sl, struct ID *id)
{
if (spacedata_id_remap_cb) {
@@ -650,7 +639,6 @@ void BKE_area_region_panels_free(ListBase *panels)
BLI_listbase_clear(panels);
}
-/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *region)
{
if (st) {
@@ -684,13 +672,17 @@ void BKE_area_region_free(SpaceType *st, ARegion *region)
region_free_gizmomap_callback(region->gizmo_map);
}
+ if (region->runtime.block_name_map != NULL) {
+ BLI_ghash_free(region->runtime.block_name_map, NULL, NULL);
+ region->runtime.block_name_map = NULL;
+ }
+
BLI_freelistN(&region->ui_lists);
BLI_freelistN(&region->ui_previews);
BLI_freelistN(&region->panels_category);
BLI_freelistN(&region->panels_category_active);
}
-/* not area itself */
void BKE_screen_area_free(ScrArea *area)
{
SpaceType *st = BKE_spacetype_from_id(area->spacetype);
@@ -718,7 +710,6 @@ void BKE_screen_area_map_free(ScrAreaMap *area_map)
BLI_freelistN(&area_map->areabase);
}
-/** Free (or release) any data used by this screen (does not free the screen itself). */
void BKE_screen_free_data(bScreen *screen)
{
screen_free_data(&screen->id);
@@ -881,12 +872,6 @@ void BKE_screen_remove_unused_scrverts(bScreen *screen)
/* ***************** Utilities ********************** */
-/**
- * Find a region of type \a region_type in the currently active space of \a area.
- *
- * \note This does _not_ work if the region to look up is not in the active
- * space. Use #BKE_spacedata_find_region_type if that may be the case.
- */
ARegion *BKE_area_find_region_type(const ScrArea *area, int region_type)
{
if (area) {
@@ -931,9 +916,6 @@ ARegion *BKE_area_find_region_xy(ScrArea *area, const int regiontype, int x, int
return NULL;
}
-/**
- * \note This is only for screen level regions (typically menus/popups).
- */
ARegion *BKE_screen_find_region_xy(bScreen *screen, const int regiontype, int x, int y)
{
LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
@@ -946,10 +928,6 @@ ARegion *BKE_screen_find_region_xy(bScreen *screen, const int regiontype, int x,
return NULL;
}
-/**
- * \note Ideally we can get the area from the context,
- * there are a few places however where this isn't practical.
- */
ScrArea *BKE_screen_find_area_from_space(struct bScreen *screen, SpaceLink *sl)
{
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
@@ -961,10 +939,6 @@ ScrArea *BKE_screen_find_area_from_space(struct bScreen *screen, SpaceLink *sl)
return NULL;
}
-/**
- * \note Using this function is generally a last resort, you really want to be
- * using the context when you can - campbell
- */
ScrArea *BKE_screen_find_big_area(bScreen *screen, const int spacetype, const short min)
{
ScrArea *big = NULL;
@@ -1054,14 +1028,11 @@ ARegion *BKE_screen_find_main_region_at_xy(bScreen *screen,
return BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, x, y);
}
-/* magic zoom calculation, no idea what
- * it signifies, if you find out, tell me! -zr
- */
+/* Magic zoom calculation, no idea what it signifies, if you find out, tell me! -zr
+ *
+ * Simple, its magic dude! Well, to be honest,
+ * this gives a natural feeling zooming with multiple keypad presses (ton). */
-/* simple, its magic dude!
- * well, to be honest, this gives a natural feeling zooming
- * with multiple keypad presses (ton)
- */
float BKE_screen_view3d_zoom_to_fac(float camzoom)
{
return powf(((float)M_SQRT2 + camzoom / 50.0f), 2.0f) / 4.0f;
@@ -1476,7 +1447,6 @@ static void direct_link_region(BlendDataReader *reader, ARegion *region, int spa
}
/* for the saved 2.50 files without regiondata */
-/* and as patch for 2.48 and older */
void BKE_screen_view3d_do_versions_250(View3D *v3d, ListBase *regions)
{
LISTBASE_FOREACH (ARegion *, region, regions) {
@@ -1783,9 +1753,6 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
BLO_read_data_address(reader, &area->v4);
}
-/**
- * \return false on error.
- */
bool BKE_screen_area_map_blend_read_data(BlendDataReader *reader, ScrAreaMap *area_map)
{
BLO_read_list(reader, &area_map->vertbase);
diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c
index 12017907038..a0d67a78d0f 100644
--- a/source/blender/blenkernel/intern/shader_fx.c
+++ b/source/blender/blenkernel/intern/shader_fx.c
@@ -57,7 +57,6 @@ static ShaderFxTypeInfo *shader_fx_types[NUM_SHADER_FX_TYPES] = {NULL};
/* *************************************************** */
/* Methods - Evaluation Loops, etc. */
-/* check if exist grease pencil effects */
bool BKE_shaderfx_has_gpencil(const Object *ob)
{
const ShaderFxData *fx;
@@ -136,7 +135,6 @@ void BKE_shaderfx_free(ShaderFxData *fx)
BKE_shaderfx_free_ex(fx, 0);
}
-/* check unique name */
bool BKE_shaderfx_unique_name(ListBase *shaders, ShaderFxData *fx)
{
if (shaders && fx) {
@@ -164,24 +162,12 @@ const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type)
return NULL;
}
-/**
- * Check whether given shaderfx is not local (i.e. from linked data) when the object is a library
- * override.
- *
- * \param shaderfx: May be NULL, in which case we consider it as a non-local shaderfx case.
- */
bool BKE_shaderfx_is_nonlocal_in_liboverride(const Object *ob, const ShaderFxData *shaderfx)
{
return (ID_IS_OVERRIDE_LIBRARY(ob) &&
((shaderfx == NULL) || (shaderfx->flag & eShaderFxFlag_OverrideLibrary_Local) == 0));
}
-/**
- * Get an effect's panel type, which was defined in the #panelRegister callback.
- *
- * \note ShaderFx panel types are assumed to be named with the struct name field concatenated to
- * the defined prefix.
- */
void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname)
{
const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type);
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index dd863f1ce06..7618323f488 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <time.h>
+#include "DNA_gpencil_modifier_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -101,7 +102,6 @@ typedef struct ShrinkwrapCalcCBData {
SpaceTransform *local2aux;
} ShrinkwrapCalcCBData;
-/* Checks if the modifier needs target normals with these settings. */
bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
{
return (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) ||
@@ -109,7 +109,6 @@ bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
shrinkMode == MOD_SHRINKWRAP_ABOVE_SURFACE);
}
-/* Initializes the mesh data structure from the given mesh and settings. */
bool BKE_shrinkwrap_init_tree(
ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
{
@@ -160,13 +159,11 @@ bool BKE_shrinkwrap_init_tree(
return true;
}
-/* Frees the tree data if necessary. */
void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
{
free_bvhtree_from_mesh(&data->treeData);
}
-/* Free boundary data for target project */
void BKE_shrinkwrap_discard_boundary_data(struct Mesh *mesh)
{
struct ShrinkwrapBoundaryData *data = mesh->runtime.shrinkwrap_data;
@@ -434,14 +431,6 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
0, calc->numVerts, &data, shrinkwrap_calc_nearest_vertex_cb_ex, &settings);
}
-/*
- * This function raycast a single vertex and updates the hit if the "hit" is considered valid.
- * Returns true if "hit" was updated.
- * Opts control whether an hit is valid or not
- * Supported options are:
- * - MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored)
- * - MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored)
- */
bool BKE_shrinkwrap_project_normal(char options,
const float vert[3],
const float dir[3],
@@ -1089,9 +1078,6 @@ static void mesh_looptri_target_project(void *userdata,
}
}
-/*
- * Maps the point to the nearest surface, either by simple nearest, or by target normal projection.
- */
void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree,
BVHTreeNearest *nearest,
float co[3],
@@ -1196,13 +1182,6 @@ static void shrinkwrap_calc_nearest_surface_point_cb_ex(void *__restrict userdat
}
}
-/**
- * Compute a smooth normal of the target (if applicable) at the hit location.
- *
- * \param tree: information about the mesh
- * \param transform: transform from the hit coordinate space to the object space; may be null
- * \param r_no: output in hit coordinate space; may be shared with inputs
- */
void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
const struct SpaceTransform *transform,
int looptri_idx,
@@ -1318,13 +1297,6 @@ static void shrinkwrap_snap_with_side(float r_point_co[3],
}
}
-/**
- * Apply the shrink to surface modes to the given original coordinates and nearest point.
- *
- * \param tree: mesh data for smooth normals
- * \param transform: transform from the hit coordinate space to the object space; may be null
- * \param r_point_co: may be the same memory location as point_co, hit_co, or hit_no.
- */
void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree,
const struct SpaceTransform *transform,
int mode,
@@ -1404,7 +1376,6 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
0, calc->numVerts, &data, shrinkwrap_calc_nearest_surface_point_cb_ex, &settings);
}
-/* Main shrinkwrap function */
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
const ModifierEvalContext *ctx,
struct Scene *scene,
@@ -1513,6 +1484,55 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
}
}
+void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd,
+ Object *ob,
+ MDeformVert *dvert,
+ const int defgrp_index,
+ float (*vertexCos)[3],
+ int numVerts)
+{
+
+ ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
+ /* Convert gpencil struct to use the same struct and function used with meshes. */
+ ShrinkwrapModifierData smd;
+ smd.target = mmd->target;
+ smd.auxTarget = mmd->aux_target;
+ smd.keepDist = mmd->keep_dist;
+ smd.shrinkType = mmd->shrink_type;
+ smd.shrinkOpts = mmd->shrink_opts;
+ smd.shrinkMode = mmd->shrink_mode;
+ smd.projLimit = mmd->proj_limit;
+ smd.projAxis = mmd->proj_axis;
+
+ /* Configure Shrinkwrap calc data. */
+ calc.smd = &smd;
+ calc.ob = ob;
+ calc.numVerts = numVerts;
+ calc.vertexCos = vertexCos;
+ calc.dvert = dvert;
+ calc.vgroup = defgrp_index;
+ calc.invert_vgroup = (mmd->flag & GP_SHRINKWRAP_INVERT_VGROUP) != 0;
+
+ BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, mmd->target);
+ calc.keepDist = mmd->keep_dist;
+ calc.tree = mmd->cache_data;
+
+ switch (mmd->shrink_type) {
+ case MOD_SHRINKWRAP_NEAREST_SURFACE:
+ case MOD_SHRINKWRAP_TARGET_PROJECT:
+ TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), gpdeform_surface);
+ break;
+
+ case MOD_SHRINKWRAP_PROJECT:
+ TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), gpdeform_project);
+ break;
+
+ case MOD_SHRINKWRAP_NEAREST_VERTEX:
+ TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), gpdeform_vertex);
+ break;
+ }
+}
+
void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
Object *ob_source,
Object *ob_target)
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 98e7405bde6..b0f9de5963a 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -154,6 +154,7 @@ IDTypeInfo IDType_ID_SIM = {
/* name_plural */ "simulations",
/* translation_context */ BLT_I18NCONTEXT_ID_SIMULATION,
/* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ /* asset_type_info */ nullptr,
/* init_data */ simulation_init_data,
/* copy_data */ simulation_copy_data,
@@ -161,6 +162,7 @@ IDTypeInfo IDType_ID_SIM = {
/* make_local */ nullptr,
/* foreach_id */ simulation_foreach_id,
/* foreach_cache */ nullptr,
+ /* foreach_path */ nullptr,
/* owner_get */ nullptr,
/* blend_write */ simulation_blend_write,
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index a008edd038a..b811c17a3bc 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -3112,7 +3112,6 @@ static void sb_new_scratch(SoftBody *sb)
/* ************ Object level, exported functions *************** */
-/* allocates and initializes general main data */
SoftBody *sbNew(void)
{
SoftBody *sb;
@@ -3162,7 +3161,6 @@ SoftBody *sbNew(void)
return sb;
}
-/* frees all */
void sbFree(Object *ob)
{
SoftBody *sb = ob->soft;
@@ -3193,7 +3191,6 @@ void sbFreeSimulation(SoftBody *sb)
free_softbody_intern(sb);
}
-/* makes totally fresh start situation */
void sbObjectToSoftbody(Object *ob)
{
// ob->softflag |= OB_SB_REDO;
@@ -3213,7 +3210,6 @@ static bool object_has_edges(const Object *ob)
return false;
}
-/* SB global visible functions */
void sbSetInterruptCallBack(int (*f)(void))
{
SB_localInterruptCallBack = f;
@@ -3244,20 +3240,6 @@ static void softbody_update_positions(Object *ob,
}
}
-/* void SB_estimate_transform */
-/* input Object *ob out (says any object that can do SB like mesh, lattice, curve )
- * output float lloc[3], float lrot[3][3], float lscale[3][3]
- * that is:
- * a precise position vector denoting the motion of the center of mass
- * give a rotation/scale matrix using averaging method, that's why estimate and not calculate
- * see: this is kind of reverse engineering: having to states of a point cloud and recover what
- * happened our advantage here we know the identity of the vertex there are others methods giving
- * other results. lloc, lrot, lscale are allowed to be NULL, just in case you don't need it.
- * should be pretty useful for pythoneers :)
- * not! velocity .. 2nd order stuff
- * vcloud_estimate_transform_v3 see
- */
-
void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3])
{
BodyPoint *bp;
@@ -3523,7 +3505,6 @@ static void sbStoreLastFrame(struct Depsgraph *depsgraph, Object *object, float
object_orig->soft->last_frame = framenr;
}
-/* simulates one step. framenr is in frames */
void sbObjectStep(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index f523c5e02bd..b27231e6a17 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -54,6 +54,7 @@
# include <AUD_Special.h>
#endif
+#include "BKE_bpath.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
@@ -133,6 +134,17 @@ static void sound_foreach_cache(ID *id,
function_callback(id, &key, &sound->waveform, 0, user_data);
}
+static void sound_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ bSound *sound = (bSound *)id;
+ if (sound->packedfile != NULL && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
+ return;
+ }
+
+ /* FIXME: This does not check for empty path... */
+ BKE_bpath_foreach_path_fixed_process(bpath_data, sound->filepath);
+}
+
static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bSound *sound = (bSound *)id;
@@ -205,6 +217,7 @@ IDTypeInfo IDType_ID_SO = {
.name_plural = "sounds",
.translation_context = BLT_I18NCONTEXT_ID_SOUND,
.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
/* A fuzzy case, think NULLified content is OK here... */
.init_data = NULL,
@@ -213,6 +226,7 @@ IDTypeInfo IDType_ID_SO = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = sound_foreach_cache,
+ .foreach_path = sound_foreach_path,
.owner_get = NULL,
.blend_write = sound_blend_write,
@@ -257,14 +271,11 @@ BLI_INLINE void sound_verify_evaluated_id(const ID *id)
bSound *BKE_sound_new_file(Main *bmain, const char *filepath)
{
bSound *sound;
- const char *path;
+ const char *blendfile_path = BKE_main_blendfile_path(bmain);
char str[FILE_MAX];
BLI_strncpy(str, filepath, sizeof(str));
-
- path = BKE_main_blendfile_path(bmain);
-
- BLI_path_abs(str, path);
+ BLI_path_abs(str, blendfile_path);
sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath), 0);
BLI_strncpy(sound->filepath, filepath, FILE_MAX);
@@ -1235,15 +1246,14 @@ bool BKE_sound_stream_info_get(struct Main *main,
int stream,
SoundStreamInfo *sound_info)
{
- const char *path;
+ const char *blendfile_path = BKE_main_blendfile_path(main);
char str[FILE_MAX];
AUD_Sound *sound;
AUD_StreamInfo *stream_infos;
int stream_count;
BLI_strncpy(str, filepath, sizeof(str));
- path = BKE_main_blendfile_path(main);
- BLI_path_abs(str, path);
+ BLI_path_abs(str, blendfile_path);
sound = AUD_Sound_file(str);
if (!sound) {
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 230ff9d6da0..b7199dc1e20 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -99,6 +99,7 @@ IDTypeInfo IDType_ID_SPK = {
.name_plural = "speakers",
.translation_context = BLT_I18NCONTEXT_ID_SPEAKER,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = speaker_init_data,
.copy_data = NULL,
@@ -106,6 +107,7 @@ IDTypeInfo IDType_ID_SPK = {
.make_local = NULL,
.foreach_id = speaker_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = speaker_blend_write,
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 52bbd2bec57..4ff392a5ddb 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -62,9 +62,6 @@ static SplinePtr create_spline(const Spline::Type type)
return {};
}
-/**
- * Return a new spline with the same data, settings, and attributes.
- */
SplinePtr Spline::copy() const
{
SplinePtr dst = this->copy_without_attributes();
@@ -72,9 +69,6 @@ SplinePtr Spline::copy() const
return dst;
}
-/**
- * Return a new spline with the same type and settings like "cyclic", but without any data.
- */
SplinePtr Spline::copy_only_settings() const
{
SplinePtr dst = create_spline(type_);
@@ -83,9 +77,6 @@ SplinePtr Spline::copy_only_settings() const
return dst;
}
-/**
- * The same as #copy, but skips copying dynamic attributes to the new spline.
- */
SplinePtr Spline::copy_without_attributes() const
{
SplinePtr dst = this->copy_only_settings();
@@ -185,12 +176,6 @@ static void accumulate_lengths(Span<float3> positions,
}
}
-/**
- * Return non-owning access to the cache of accumulated lengths along the spline. Each item is the
- * length of the subsequent segment, i.e. the first value is the length of the first segment rather
- * than 0. This calculation is rather trivial, and only depends on the evaluated positions.
- * However, the results are used often, and it is necessarily single threaded, so it is cached.
- */
Span<float> Spline::evaluated_lengths() const
{
if (!length_cache_dirty_) {
@@ -252,9 +237,6 @@ static void calculate_tangents(Span<float3> positions,
}
}
-/**
- * Return non-owning access to the direction of the curve at each evaluated point.
- */
Span<float3> Spline::evaluated_tangents() const
{
if (!tangent_cache_dirty_) {
@@ -375,10 +357,6 @@ static void calculate_normals_minimum(Span<float3> tangents,
}
}
-/**
- * Return non-owning access to the direction vectors perpendicular to the tangents at every
- * evaluated point. The method used to generate the normal vectors depends on Spline.normal_mode.
- */
Span<float3> Spline::evaluated_normals() const
{
if (!normal_cache_dirty_) {
@@ -428,9 +406,6 @@ Spline::LookupResult Spline::lookup_evaluated_factor(const float factor) const
return this->lookup_evaluated_length(this->length() * factor);
}
-/**
- * \note This does not support extrapolation currently.
- */
Spline::LookupResult Spline::lookup_evaluated_length(const float length) const
{
BLI_assert(length >= 0.0f && length <= this->length());
@@ -447,11 +422,6 @@ Spline::LookupResult Spline::lookup_evaluated_length(const float length) const
return LookupResult{index, next_index, factor};
}
-/**
- * Return an array of evenly spaced samples along the length of the spline. The samples are indices
- * and factors to the next index encoded in floats. The logic for converting from the float values
- * to interpolation data is in #lookup_data_from_index_factor.
- */
Array<float> Spline::sample_uniform_index_factors(const int samples_size) const
{
const Span<float> lengths = this->evaluated_lengths();
@@ -532,11 +502,6 @@ GVArray Spline::interpolate_to_evaluated(GSpan data) const
return this->interpolate_to_evaluated(GVArray::ForSpan(data));
}
-/**
- * Sample any input data with a value for each evaluated point (already interpolated to evaluated
- * points) to arbitrary parameters in between the evaluated points. The interpolation is quite
- * simple, but this handles the cyclic and end point special cases.
- */
void Spline::sample_with_index_factors(const GVArray &src,
Span<float> index_factors,
GMutableSpan dst) const
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index 0cadab998f5..9ce285cebb8 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -70,9 +70,6 @@ void BezierSpline::set_resolution(const int value)
this->mark_cache_invalid();
}
-/**
- * \warning Call #reallocate on the spline's attributes after adding all points.
- */
void BezierSpline::add_point(const float3 position,
const HandleType handle_type_left,
const float3 handle_position_left,
@@ -203,10 +200,6 @@ static float3 next_position(Span<float3> positions, const bool cyclic, const int
return positions[i + 1];
}
-/**
- * Recalculate all #Auto and #Vector handles with positions automatically
- * derived from the neighboring control points.
- */
void BezierSpline::ensure_auto_handles() const
{
if (!auto_handles_dirty_) {
@@ -315,10 +308,6 @@ static void set_handle_position(const float3 &position,
}
}
-/**
- * Set positions for the right handle of the control point, ensuring that
- * aligned handles stay aligned. Has no effect for auto and vector type handles.
- */
void BezierSpline::set_handle_position_right(const int index, const blender::float3 &value)
{
set_handle_position(positions_[index],
@@ -329,10 +318,6 @@ void BezierSpline::set_handle_position_right(const int index, const blender::flo
handle_positions_left_[index]);
}
-/**
- * Set positions for the left handle of the control point, ensuring that
- * aligned handles stay aligned. Has no effect for auto and vector type handles.
- */
void BezierSpline::set_handle_position_left(const int index, const blender::float3 &value)
{
set_handle_position(positions_[index],
@@ -349,9 +334,6 @@ bool BezierSpline::point_is_sharp(const int index) const
ELEM(handle_types_right_[index], HandleType::Vector, HandleType::Free);
}
-/**
- * \warning This functional assumes that the spline has more than one point.
- */
bool BezierSpline::segment_is_vector(const int index) const
{
/* Two control points are necessary to form a segment, that should be checked by the caller. */
@@ -387,12 +369,6 @@ int BezierSpline::evaluated_points_size() const
return this->control_point_offsets().last();
}
-/**
- * If the spline is not cyclic, the direction for the first and last points is just the
- * direction formed by the corresponding handles and control points. In the unlikely situation
- * that the handles define a zero direction, fallback to using the direction defined by the
- * first and last evaluated segments already calculated in #Spline::evaluated_tangents().
- */
void BezierSpline::correct_end_tangents() const
{
if (is_cyclic_) {
@@ -409,25 +385,6 @@ void BezierSpline::correct_end_tangents() const
}
}
-/**
- * De Casteljau Bezier subdivision.
- * \param index: The index of the segment's start control point.
- * \param next_index: The index of the control point at the end of the segment. Could be 0,
- * if the spline is cyclic.
- * \param parameter: The factor along the segment, between 0 and 1. Note that this is used
- * directly by the calculation, it doesn't correspond to a portion of the evaluated length.
- *
- * <pre>
- * handle_prev handle_next
- * x----------------x
- * / \
- * / x---O---x \
- * / result \
- * / \
- * O O
- * point_prev point_next
- * </pre>
- */
BezierSpline::InsertResult BezierSpline::calculate_segment_insertion(const int index,
const int next_index,
const float parameter)
@@ -493,15 +450,6 @@ void BezierSpline::evaluate_segment(const int index,
}
}
-/**
- * Returns access to a cache of offsets into the evaluated point array for each control point.
- * While most control point edges generate the number of edges specified by the resolution, vector
- * segments only generate one edge.
- *
- * \note The length of the result is one greater than the number of points, so that the last item
- * is the total number of evaluated points. This is useful to avoid recalculating the size of the
- * last segment everywhere.
- */
Span<int> BezierSpline::control_point_offsets() const
{
if (!offset_cache_dirty_) {
@@ -568,12 +516,6 @@ static void calculate_mappings_linear_resolution(Span<int> offsets,
}
}
-/**
- * Returns non-owning access to an array of values containing the information necessary to
- * interpolate values from the original control points to evaluated points. The control point
- * index is the integer part of each value, and the factor used for interpolating to the next
- * control point is the remaining factional part.
- */
Span<float> BezierSpline::evaluated_mappings() const
{
if (!mapping_cache_dirty_) {
@@ -659,11 +601,6 @@ Span<float3> BezierSpline::evaluated_positions() const
return positions;
}
-/**
- * Convert the data encoded in #evaulated_mappings into its parts-- the information necessary
- * to interpolate data from control points to evaluated points between them. The next control
- * point index result will not overflow the size of the control point vectors.
- */
BezierSpline::InterpolationData BezierSpline::interpolation_data_from_index_factor(
const float index_factor) const
{
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index 7fa332a0330..69afb82baa8 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -81,9 +81,6 @@ void NURBSpline::set_order(const uint8_t value)
this->mark_cache_invalid();
}
-/**
- * \warning Call #reallocate on the spline's attributes after adding all points.
- */
void NURBSpline::add_point(const float3 position,
const float radius,
const float tilt,
diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc
index d495c977285..4af68b5f270 100644
--- a/source/blender/blenkernel/intern/spline_poly.cc
+++ b/source/blender/blenkernel/intern/spline_poly.cc
@@ -45,9 +45,6 @@ int PolySpline::size() const
return size;
}
-/**
- * \warning Call #reallocate on the spline's attributes after adding all points.
- */
void PolySpline::add_point(const float3 position, const float radius, const float tilt)
{
positions_.append(position);
@@ -115,12 +112,6 @@ Span<float3> PolySpline::evaluated_positions() const
return this->positions();
}
-/**
- * Poly spline interpolation from control points to evaluated points is a special case, since
- * the result data is the same as the input data. This function returns a GVArray that points to
- * the original data. Therefore the lifetime of the returned virtual array must not be longer than
- * the source data.
- */
GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const
{
BLI_assert(src.size() == this->size());
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 29f726ece71..b7690e69aa1 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -1402,7 +1402,6 @@ void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3])
lights[3].vec[2] = -0.542269f;
}
-/* API */
void BKE_studiolight_init(void)
{
/* Add default studio light */
@@ -1532,7 +1531,6 @@ void BKE_studiolight_preview(uint *icon_buffer, StudioLight *sl, int icon_id_typ
}
}
-/* Ensure state of Studiolights */
void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
{
if ((sl->flag & flag) == flag) {
@@ -1570,8 +1568,9 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
}
/*
- * Python API Functions
+ * Python API Functions.
*/
+
void BKE_studiolight_remove(StudioLight *sl)
{
if (sl->flag & STUDIOLIGHT_USER_DEFINED) {
@@ -1608,7 +1607,6 @@ StudioLight *BKE_studiolight_create(const char *path,
return sl;
}
-/* Only useful for workbench while editing the userprefs. */
StudioLight *BKE_studiolight_studio_edit_get(void)
{
static StudioLight sl = {0};
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 6796b1ac397..2669da98488 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -717,7 +717,6 @@ static void minmax_v3_v3v3(const float vec[3], float min[3], float max[3])
}
}
-/* UNUSED, keep since this functionality may be useful in the future. */
static void UNUSED_FUNCTION(ccgDM_getMinMax)(DerivedMesh *dm, float r_min[3], float r_max[3])
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -912,8 +911,6 @@ static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float r_no[3])
normal_short_to_float_v3(r_no, mvert.no);
}
-/* Translate GridHidden into the ME_HIDE flag for MVerts. Assumes
- * vertices are in the order output by ccgDM_copyFinalVertArray. */
void subsurf_copy_grid_hidden(DerivedMesh *dm,
const MPoly *mpoly,
MVert *mvert,
@@ -955,8 +952,6 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm,
}
}
-/* Translate GridPaintMask into vertex paint masks. Assumes vertices
- * are in the order output by ccgDM_copyFinalVertArray. */
void subsurf_copy_grid_paint_mask(DerivedMesh *dm,
const MPoly *mpoly,
float *paint_mask,
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 7ac9e20d1a7..4406647bd2c 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -49,6 +49,7 @@
#include "DNA_text_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_bpath.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -169,6 +170,15 @@ static void text_free_data(ID *id)
#endif
}
+static void text_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Text *text = (Text *)id;
+
+ if (text->filepath != NULL) {
+ BKE_bpath_foreach_path_allocated_process(bpath_data, &text->filepath);
+ }
+}
+
static void text_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Text *text = (Text *)id;
@@ -242,6 +252,7 @@ IDTypeInfo IDType_ID_TXT = {
.name_plural = "texts",
.translation_context = BLT_I18NCONTEXT_ID_TEXT,
.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = text_init_data,
.copy_data = text_copy_data,
@@ -249,6 +260,7 @@ IDTypeInfo IDType_ID_TXT = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = text_foreach_path,
.owner_get = NULL,
.blend_write = text_blend_write,
@@ -267,9 +279,6 @@ IDTypeInfo IDType_ID_TXT = {
/** \name Text Add, Free, Validation
* \{ */
-/**
- * \note caller must handle `compiled` member.
- */
void BKE_text_free_lines(Text *text)
{
for (TextLine *tmp = text->lines.first, *tmp_next; tmp; tmp = tmp_next) {
@@ -299,8 +308,6 @@ Text *BKE_text_add(Main *bmain, const char *name)
return ta;
}
-/* this function replaces extended ascii characters */
-/* to a valid utf-8 sequences */
int txt_extended_ascii_as_utf8(char **str)
{
ptrdiff_t bad_char, i = 0;
@@ -463,14 +470,6 @@ bool BKE_text_reload(Text *text)
return true;
}
-/**
- * Load a text file.
- *
- * \param is_internal: If \a true, this text data-block only exists in memory,
- * not as a file on disk.
- *
- * \note text data-blocks have no real user but have 'fake user' enabled by default
- */
Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal)
{
unsigned char *buffer;
@@ -523,11 +522,6 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
return ta;
}
-/**
- * Load a text file.
- *
- * \note Text data-blocks have no user by default, only the 'real user' flag.
- */
Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
{
return BKE_text_load_ex(bmain, file, relpath, false);
@@ -547,11 +541,6 @@ void BKE_text_write(Text *text, const char *str) /* called directly from rna */
txt_make_dirty(text);
}
-/* returns 0 if file on disk is the same or Text is in memory only
- * returns 1 if file has been modified on disk since last local edit
- * returns 2 if file on disk has been deleted
- * -1 is returned if an error occurs */
-
int BKE_text_file_modified_check(Text *text)
{
BLI_stat_t st;
@@ -1131,7 +1120,6 @@ void txt_move_toline(Text *text, unsigned int line, const bool sel)
txt_move_to(text, line, 0, sel);
}
-/* Moves to a certain byte in a line, not a certain utf8-character! */
void txt_move_to(Text *text, unsigned int line, unsigned int ch, const bool sel)
{
TextLine **linep;
@@ -1291,11 +1279,6 @@ void txt_sel_all(Text *text)
text->selc = text->sell->len;
}
-/**
- * Reverse of #txt_pop_sel
- * Clears the selection and ensures the cursor is located
- * at the selection (where the cursor is visually while editing).
- */
void txt_sel_clear(Text *text)
{
if (text->sell) {
@@ -1382,9 +1365,6 @@ void txt_sel_set(Text *text, int startl, int startc, int endl, int endc)
* - Are not null terminated.
* \{ */
-/**
- * Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it.
- */
char *txt_to_buf_for_undo(Text *text, int *r_buf_len)
{
int buf_len = 0;
@@ -1402,9 +1382,6 @@ char *txt_to_buf_for_undo(Text *text, int *r_buf_len)
return buf;
}
-/**
- * Decode a buffer from #txt_to_buf_for_undo.
- */
void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len)
{
const char *buf_end = buf + buf_len;
@@ -2401,10 +2378,11 @@ int text_check_bracket(const char ch)
return 0;
}
-/* TODO: have a function for operators -
- * http://docs.python.org/py3k/reference/lexical_analysis.html#operators */
bool text_check_delim(const char ch)
{
+ /* TODO: have a function for operators:
+ * http://docs.python.org/py3k/reference/lexical_analysis.html#operators */
+
int a;
char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,@";
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index a8c8eaa6a1c..ee9247e6e60 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -211,6 +211,7 @@ IDTypeInfo IDType_ID_TE = {
.name_plural = "textures",
.translation_context = BLT_I18NCONTEXT_ID_TEXTURE,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = texture_init_data,
.copy_data = texture_copy_data,
@@ -218,6 +219,7 @@ IDTypeInfo IDType_ID_TE = {
.make_local = NULL,
.foreach_id = texture_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = texture_blend_write,
@@ -230,7 +232,6 @@ IDTypeInfo IDType_ID_TE = {
.lib_override_apply_post = NULL,
};
-/* Utils for all IDs using those texture slots. */
void BKE_texture_mtex_foreach_id(LibraryForeachIDData *data, MTex *mtex)
{
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, mtex->object, IDWALK_CB_NOP);
@@ -412,7 +413,6 @@ MTex *BKE_texture_mtex_add(void)
return mtex;
}
-/* slot -1 for first free ID */
MTex *BKE_texture_mtex_add_id(ID *id, int slot)
{
MTex **mtex_ar;
@@ -670,9 +670,6 @@ void BKE_texture_pointdensity_free(PointDensity *pd)
}
/* ------------------------------------------------------------------------- */
-/**
- * \returns true if this texture can use its #Texture.ima (even if its NULL)
- */
bool BKE_texture_is_image_user(const struct Tex *tex)
{
switch (tex->type) {
@@ -684,7 +681,6 @@ bool BKE_texture_is_image_user(const struct Tex *tex)
return false;
}
-/* ------------------------------------------------------------------------- */
bool BKE_texture_dependsOnTime(const struct Tex *texture)
{
if (texture->ima && BKE_image_is_animated(texture->ima)) {
@@ -758,7 +754,6 @@ static void texture_nodes_fetch_images_for_pool(Tex *texture,
}
}
-/* Make sure all images used by texture are loaded into pool. */
void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool)
{
if (texture->nodetree != NULL) {
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 3cdb8e927a6..3878d3b1c98 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -160,11 +160,6 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
dopesheet->tot_channel = 0;
}
-/* Free tracking structure, only frees structure contents
- * (if structure is allocated in heap, it shall be handled outside).
- *
- * All the pointers inside structure becomes invalid after this call.
- */
void BKE_tracking_free(MovieTracking *tracking)
{
tracking_tracks_free(&tracking->tracks);
@@ -276,7 +271,6 @@ static void tracking_objects_copy(ListBase *objects_dst,
}
}
-/* Copy tracking structure content. */
void BKE_tracking_copy(MovieTracking *tracking_dst,
const MovieTracking *tracking_src,
const int flag)
@@ -321,9 +315,6 @@ void BKE_tracking_copy(MovieTracking *tracking_dst,
BLI_ghash_free(tracks_mapping, NULL, NULL);
}
-/* Initialize motion tracking settings to default values,
- * used when new movie clip datablock is created.
- */
void BKE_tracking_settings_init(MovieTracking *tracking)
{
tracking->camera.sensor_width = 35.0f;
@@ -361,7 +352,6 @@ void BKE_tracking_settings_init(MovieTracking *tracking)
BKE_tracking_object_add(tracking, "Camera");
}
-/* Get list base of active object's tracks. */
ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
{
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
@@ -373,7 +363,6 @@ ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
return &tracking->tracks;
}
-/* Get list base of active object's plane tracks. */
ListBase *BKE_tracking_get_active_plane_tracks(MovieTracking *tracking)
{
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
@@ -385,7 +374,6 @@ ListBase *BKE_tracking_get_active_plane_tracks(MovieTracking *tracking)
return &tracking->plane_tracks;
}
-/* Get reconstruction data of active object. */
MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking)
{
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
@@ -393,9 +381,6 @@ MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTrackin
return BKE_tracking_object_get_reconstruction(tracking, object);
}
-/* Get transformation matrix for a given object which is used
- * for parenting motion tracker reconstruction to 3D world.
- */
void BKE_tracking_get_camera_object_matrix(Object *camera_object, float mat[4][4])
{
BLI_assert(camera_object != NULL);
@@ -412,11 +397,6 @@ void BKE_tracking_get_camera_object_matrix(Object *camera_object, float mat[4][4
BKE_object_where_is_calc_mat4(camera_object, mat);
}
-/* Get projection matrix for camera specified by given tracking object
- * and frame number.
- *
- * NOTE: frame number should be in clip space, not scene space
- */
void BKE_tracking_get_projection_matrix(MovieTracking *tracking,
MovieTrackingObject *object,
int framenr,
@@ -472,7 +452,6 @@ void BKE_tracking_get_projection_matrix(MovieTracking *tracking,
/*********************** clipboard *************************/
-/* Free clipboard by freeing memory used by all tracks in it. */
void BKE_tracking_clipboard_free(void)
{
MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
@@ -489,7 +468,6 @@ void BKE_tracking_clipboard_free(void)
BLI_listbase_clear(&tracking_clipboard.tracks);
}
-/* Copy selected tracks from specified object to the clipboard. */
void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
{
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
@@ -510,17 +488,11 @@ void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingOb
}
}
-/* Check whether there are any tracks in the clipboard. */
bool BKE_tracking_clipboard_has_tracks(void)
{
return (BLI_listbase_is_empty(&tracking_clipboard.tracks) == false);
}
-/* Paste tracks from clipboard to specified object.
- *
- * Names of new tracks in object are guaranteed to
- * be unique here.
- */
void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
{
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
@@ -541,10 +513,6 @@ void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingO
/*********************** Tracks *************************/
-/* Add new empty track to the given list of tracks.
- *
- * It is required that caller will append at least one marker to avoid degenerate tracks.
- */
MovieTrackingTrack *BKE_tracking_track_add_empty(MovieTracking *tracking, ListBase *tracks_list)
{
const MovieTrackingSettings *settings = &tracking->settings;
@@ -569,14 +537,6 @@ MovieTrackingTrack *BKE_tracking_track_add_empty(MovieTracking *tracking, ListBa
return track;
}
-/* Add new track to a specified tracks base.
- *
- * Coordinates are expected to be in normalized 0..1 space,
- * frame number is expected to be in clip space.
- *
- * Width and height are clip's dimension used to scale track's
- * pattern and search regions.
- */
MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking,
ListBase *tracksbase,
float x,
@@ -618,7 +578,6 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking,
return track;
}
-/* Duplicate the specified track, result will no belong to any list. */
MovieTrackingTrack *BKE_tracking_track_duplicate(MovieTrackingTrack *track)
{
MovieTrackingTrack *new_track;
@@ -639,10 +598,6 @@ MovieTrackingTrack *BKE_tracking_track_duplicate(MovieTrackingTrack *track)
return new_track;
}
-/* Ensure specified track has got unique name,
- * if it's not name of specified track will be changed
- * keeping names of all other tracks unchanged.
- */
void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
{
BLI_uniquename(tracksbase,
@@ -653,11 +608,6 @@ void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *tr
sizeof(track->name));
}
-/* Free specified track, only frees contents of a structure
- * (if track is allocated in heap, it shall be handled outside).
- *
- * All the pointers inside track becomes invalid after this call.
- */
void BKE_tracking_track_free(MovieTrackingTrack *track)
{
if (track->markers) {
@@ -665,8 +615,6 @@ void BKE_tracking_track_free(MovieTrackingTrack *track)
}
}
-/* Get frame numbers of the very first and last markers.
- * There is no check on whether the marker is enabled or not. */
void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track,
int *r_first_frame,
int *r_last_frame)
@@ -677,9 +625,6 @@ void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track,
*r_last_frame = track->markers[last_marker_index].framenr;
}
-/* Find the minimum starting frame and maximum ending frame within given set of
- * tracks.
- */
void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ MovieTrackingTrack **tracks,
const int num_tracks,
int *r_first_frame,
@@ -745,11 +690,6 @@ MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(MovieTracking
return source_tracks;
}
-/* Set flag for all specified track's areas.
- *
- * area - which part of marker should be selected. see TRACK_AREA_* constants.
- * flag - flag to be set for areas.
- */
void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag)
{
if (area == TRACK_AREA_NONE) {
@@ -767,11 +707,6 @@ void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag)
}
}
-/* Clear flag from all specified track's areas.
- *
- * area - which part of marker should be selected. see TRACK_AREA_* constants.
- * flag - flag to be cleared for areas.
- */
void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag)
{
if (area == TRACK_AREA_NONE) {
@@ -789,19 +724,11 @@ void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag
}
}
-/* Check whether track has got marker at specified frame.
- *
- * NOTE: frame number should be in clip space, not scene space.
- */
bool BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr)
{
return BKE_tracking_marker_get_exact(track, framenr) != NULL;
}
-/* Check whether track has got enabled marker at specified frame.
- *
- * NOTE: frame number should be in clip space, not scene space.
- */
bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr)
{
MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
@@ -809,18 +736,6 @@ bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, i
return marker && (marker->flag & MARKER_DISABLED) == 0;
}
-/* Clear track's path:
- *
- * - If action is TRACK_CLEAR_REMAINED path from ref_frame+1 up to
- * end will be clear.
- *
- * - If action is TRACK_CLEAR_UPTO path from the beginning up to
- * ref_frame-1 will be clear.
- *
- * - If action is TRACK_CLEAR_ALL only marker at frame ref_frame will remain.
- *
- * NOTE: frame number should be in clip space, not scene space
- */
void BKE_tracking_track_path_clear(MovieTrackingTrack *track, int ref_frame, int action)
{
int a;
@@ -1281,7 +1196,6 @@ static void track_mask_gpencil_layer_rasterize(int frame_width,
}
}
-/* Region is in pixel space, relative to marker's center. */
float *tracking_track_get_mask_for_region(int frame_width,
int frame_height,
const float region_min[2],
@@ -1336,7 +1250,6 @@ float BKE_tracking_track_get_weight_for_marker(MovieClip *clip,
return weight;
}
-/* area - which part of marker should be selected. see TRACK_AREA_* constants */
void BKE_tracking_track_select(ListBase *tracksbase,
MovieTrackingTrack *track,
int area,
@@ -1510,16 +1423,6 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
}
}
-/**
- * Get marker closest to the given frame number.
- *
- * If there is maker with exact frame number it returned.
- * Otherwise, marker with highest frame number but lower than the requested
- * frame is returned if such marker exists. Otherwise, the marker with lowest
- * frame number greater than the requested frame number is returned.
- *
- * This function has complexity of `O(log number_of_markers)`.
- */
MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr)
{
const int num_markers = track->markersnr;
@@ -1705,7 +1608,6 @@ void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track,
/*********************** Plane Track *************************/
-/* Creates new plane track out of selected point tracks */
MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking,
ListBase *plane_tracks_base,
ListBase *tracks,
@@ -1789,11 +1691,6 @@ void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base,
sizeof(plane_track->name));
}
-/* Free specified plane track, only frees contents of a structure
- * (if track is allocated in heap, it shall be handled outside).
- *
- * All the pointers inside track becomes invalid after this call.
- */
void BKE_tracking_plane_track_free(MovieTrackingPlaneTrack *plane_track)
{
if (plane_track->markers) {
@@ -1988,9 +1885,6 @@ void BKE_tracking_plane_marker_delete(MovieTrackingPlaneTrack *plane_track, int
* would be nice to de-duplicate them somehow..
*/
-/* Get a plane marker at given frame,
- * If there's no such marker, closest one from the left side will be returned.
- */
MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack *plane_track,
int framenr)
{
@@ -2039,9 +1933,6 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack
return NULL;
}
-/* Get a plane marker at exact given frame, if there's no marker at the frame,
- * NULL will be returned.
- */
MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(MovieTrackingPlaneTrack *plane_track,
int framenr)
{
@@ -2054,7 +1945,6 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(MovieTrackingPlane
return plane_marker;
}
-/* Ensure there's a marker for the given frame. */
MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTrack *plane_track,
int framenr)
{
@@ -2326,7 +2216,6 @@ static void reconstructed_camera_scale_set(MovieTrackingObject *object, float ma
}
}
-/* converts principal offset from center to offset of blender's camera */
void BKE_tracking_camera_shift_get(
MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
{
@@ -2899,10 +2788,6 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf,
return searchibuf;
}
-/* zap channels from the imbuf that are disabled by the user. this can lead to
- * better tracks sometimes. however, instead of simply zeroing the channels
- * out, do a partial grayscale conversion so the display is better.
- */
void BKE_tracking_disable_channels(
ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale)
{
@@ -3417,9 +3302,6 @@ static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
MEM_freeN(per_frame_counter);
}
-/* Tag dopesheet for update, actual update will happen later
- * when it'll be actually needed.
- */
void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking)
{
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@ -3427,7 +3309,6 @@ void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking)
dopesheet->ok = false;
}
-/* Do dopesheet update, if update is not needed nothing will happen. */
void BKE_tracking_dopesheet_update(MovieTracking *tracking)
{
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@ -3451,7 +3332,6 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
dopesheet->ok = true;
}
-/* NOTE: Returns NULL if the track comes from camera object, */
MovieTrackingObject *BKE_tracking_find_object_for_track(const MovieTracking *tracking,
const MovieTrackingTrack *track)
{
@@ -3479,7 +3359,6 @@ ListBase *BKE_tracking_find_tracks_list_for_track(MovieTracking *tracking,
return &tracking->tracks;
}
-/* NOTE: Returns NULL if the track comes from camera object, */
MovieTrackingObject *BKE_tracking_find_object_for_plane_track(
const MovieTracking *tracking, const MovieTrackingPlaneTrack *plane_track)
{
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index e2a29d7858d..c83e595c611 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -775,7 +775,7 @@ void BKE_autotrack_context_sync(AutoTrackContext *context)
}
/* TODO(sergey): Find a way to avoid this, somehow making all needed logic in
- * BKE_autotrack_context_sync(). */
+ * #BKE_autotrack_context_sync(). */
void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *user)
{
user->framenr = context->synchronized_scene_frame;
diff --git a/source/blender/blenkernel/intern/tracking_detect.c b/source/blender/blenkernel/intern/tracking_detect.c
index 08719161e1a..be680ef8a8b 100644
--- a/source/blender/blenkernel/intern/tracking_detect.c
+++ b/source/blender/blenkernel/intern/tracking_detect.c
@@ -148,7 +148,6 @@ static void run_configured_detector(MovieTracking *tracking,
}
}
-/* Detect features using FAST detector */
void BKE_tracking_detect_fast(MovieTracking *tracking,
ListBase *tracksbase,
ImBuf *ibuf,
@@ -170,7 +169,6 @@ void BKE_tracking_detect_fast(MovieTracking *tracking,
tracking, tracksbase, ibuf, framenr, layer, place_outside_layer, &options);
}
-/* Detect features using Harris detector */
void BKE_tracking_detect_harris(MovieTracking *tracking,
ListBase *tracksbase,
ImBuf *ibuf,
diff --git a/source/blender/blenkernel/intern/tracking_plane_tracker.c b/source/blender/blenkernel/intern/tracking_plane_tracker.c
index b787cd366c5..d4a5bb2aa9d 100644
--- a/source/blender/blenkernel/intern/tracking_plane_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_plane_tracker.c
@@ -167,7 +167,6 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
}
}
-/* NOTE: frame number should be in clip space, not scene space */
void BKE_tracking_track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track,
int start_frame)
{
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index 179def0a6f2..ad3f226fa92 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -180,7 +180,6 @@ static ImBuf *tracking_context_get_reference_ibuf(MovieClip *clip,
return ibuf;
}
-/* Fill in libmv tracker options structure with settings need to be used to perform track. */
void tracking_configure_tracker(const MovieTrackingTrack *track,
float *mask,
const bool is_backwards,
@@ -311,11 +310,6 @@ static bool refine_marker_reference_frame_get(MovieTrackingTrack *track,
return (reference->flag & MARKER_DISABLED) == 0;
}
-/* Refine marker's position using previously known keyframe.
- * Direction of searching for a keyframe depends on backwards flag,
- * which means if backwards is false, previous keyframe will be as
- * reference.
- */
void BKE_tracking_refine_marker(MovieClip *clip,
MovieTrackingTrack *track,
MovieTrackingMarker *marker,
diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c
index d89d36f85ea..47a955c9d93 100644
--- a/source/blender/blenkernel/intern/tracking_solver.c
+++ b/source/blender/blenkernel/intern/tracking_solver.c
@@ -325,7 +325,6 @@ static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking,
return tot;
}
-/* Perform early check on whether everything is fine to start reconstruction. */
bool BKE_tracking_reconstruction_check(MovieTracking *tracking,
MovieTrackingObject *object,
char *error_msg,
@@ -354,11 +353,6 @@ bool BKE_tracking_reconstruction_check(MovieTracking *tracking,
return true;
}
-/* Create context for camera/object motion reconstruction.
- * Copies all data needed for reconstruction from movie
- * clip datablock, so editing this clip is safe during
- * reconstruction job is in progress.
- */
MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip,
MovieTrackingObject *object,
int keyframe1,
@@ -446,7 +440,6 @@ const char *BKE_tracking_reconstruction_error_message_get(const MovieReconstruct
return context->error_message;
}
-/* Free memory used by a reconstruction process. */
void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context)
{
if (context->reconstruction) {
@@ -486,15 +479,6 @@ static void reconstructionOptionsFromContext(libmv_ReconstructionOptions *recons
reconstruction_options->refine_intrinsics = context->refine_flags;
}
-/* Solve camera/object motion and reconstruct 3D markers position
- * from a prepared reconstruction context.
- *
- * stop is not actually used at this moment, so reconstruction
- * job could not be stopped.
- *
- * do_update, progress and stat_message are set by reconstruction
- * callback in libmv side and passing to an interface.
- */
void BKE_tracking_reconstruction_solve(MovieReconstructContext *context,
short *stop,
short *do_update,
@@ -542,9 +526,6 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context,
context->reprojection_error = error;
}
-/* Finish reconstruction process by copying reconstructed data
- * to an actual movie clip datablock.
- */
bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking)
{
MovieTrackingReconstruction *reconstruction;
@@ -608,9 +589,6 @@ static void tracking_scale_reconstruction(ListBase *tracksbase,
}
}
-/* Apply scale on all reconstructed cameras and bundles,
- * used by camera scale apply operator.
- */
void BKE_tracking_reconstruction_scale(MovieTracking *tracking, float scale[3])
{
LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index d5585116f7e..fe9a2f2268a 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -1252,24 +1252,6 @@ static StabContext *init_stabilizer(MovieClip *clip, int size, float aspect)
/* === public interface functions === */
-/* Get stabilization data (translation, scaling and angle) for a given frame.
- * Returned data describes how to compensate the detected movement, but with any
- * chosen scale factor already applied and any target frame position already
- * compensated. In case stabilization fails or is disabled, neutral values are
- * returned.
- *
- * framenr is a frame number, relative to the clip (not relative to the scene
- * timeline)
- * width is an effective width of the canvas (square pixels), used to scale the
- * determined translation
- *
- * Outputs:
- * - translation of the lateral shift, absolute canvas coordinates
- * (square pixels).
- * - scale of the scaling to apply
- * - angle of the rotation angle, relative to the frame center
- */
-/* TODO(sergey): Use r_ prefix for output parameters here. */
void BKE_tracking_stabilization_data_get(MovieClip *clip,
int framenr,
int width,
@@ -1307,7 +1289,7 @@ void BKE_tracking_stabilization_data_get(MovieClip *clip,
discard_stabilization_working_context(ctx);
}
-typedef void (*interpolation_func)(struct ImBuf *, struct ImBuf *, float, float, int, int);
+typedef void (*interpolation_func)(const struct ImBuf *, struct ImBuf *, float, float, int, int);
typedef struct TrackingStabilizeFrameInterpolationData {
ImBuf *ibuf;
@@ -1336,12 +1318,6 @@ static void tracking_stabilize_frame_interpolation_cb(
}
}
-/* Stabilize given image buffer using stabilization data for a specified
- * frame number.
- *
- * NOTE: frame number should be in clip space, not scene space.
- */
-/* TODO(sergey): Use r_ prefix for output parameters here. */
ImBuf *BKE_tracking_stabilize_frame(
MovieClip *clip, int framenr, ImBuf *ibuf, float translation[2], float *scale, float *angle)
{
@@ -1449,16 +1425,6 @@ ImBuf *BKE_tracking_stabilize_frame(
return tmpibuf;
}
-/* Build a 4x4 transformation matrix based on the given 2D stabilization data.
- * mat is a 4x4 matrix in homogeneous coordinates, adapted to the
- * final image buffer size and compensated for pixel aspect ratio,
- * ready for direct OpenGL drawing.
- *
- * TODO(sergey): The signature of this function should be changed. we actually
- * don't need the dimensions of the image buffer. Instead we
- * should consider to provide the pivot point of the rotation as a
- * further stabilization data parameter.
- */
void BKE_tracking_stabilization_data_to_mat4(int buffer_width,
int buffer_height,
float pixel_aspect,
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index 16b36e94328..f1fd3a13e0e 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -338,11 +338,6 @@ static void search_pixel_to_marker_unified(int frame_width,
sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
}
-/* Each marker has 5 coordinates associated with it that get warped with
- * tracking: the four corners ("pattern_corners"), and the center ("pos").
- * This function puts those 5 points into the appropriate frame for tracking
- * (the "search" coordinate frame).
- */
void tracking_get_marker_coords_for_tracking(int frame_width,
int frame_height,
const MovieTrackingMarker *marker,
@@ -369,7 +364,6 @@ void tracking_get_marker_coords_for_tracking(int frame_width,
search_pixel_y[4] = pixel_coords[1] - 0.5f;
}
-/* Inverse of above. */
void tracking_set_marker_coords_from_tracking(int frame_width,
int frame_height,
MovieTrackingMarker *marker,
@@ -411,15 +405,6 @@ void tracking_set_marker_coords_from_tracking(int frame_width,
/** \name General Purpose Utility Functions
* \{ */
-/* Place a disabled marker before or after specified ref_marker.
- *
- * If before is truth, disabled marker is placed before reference
- * one, and it's placed after it otherwise.
- *
- * If there's already a marker at the frame where disabled one
- * is expected to be placed, nothing will happen if overwrite
- * is false.
- */
void tracking_marker_insert_disabled(MovieTrackingTrack *track,
const MovieTrackingMarker *ref_marker,
bool before,
@@ -526,7 +511,6 @@ static void distortion_model_parameters_from_options(
BLI_assert_msg(0, "Unknown distortion model");
}
-/* Fill in Libmv C-API camera intrinsics options from tracking structure. */
void tracking_cameraIntrinscisOptionsFromTracking(
MovieTracking *tracking,
int calibration_width,
@@ -563,7 +547,6 @@ void tracking_trackingCameraFromIntrinscisOptions(
distortion_model_parameters_from_options(camera_intrinsics_options, camera);
}
-/* Get previous keyframed marker. */
MovieTrackingMarker *tracking_get_keyframed_marker(MovieTrackingTrack *track,
int current_frame,
bool backwards)
diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc
new file mode 100644
index 00000000000..b23220286e6
--- /dev/null
+++ b/source/blender/blenkernel/intern/type_conversions.cc
@@ -0,0 +1,364 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BKE_type_conversions.hh"
+
+#include "FN_multi_function_builder.hh"
+
+#include "BLI_color.hh"
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
+
+namespace blender::bke {
+
+using fn::MFDataType;
+
+template<typename From, typename To, To (*ConversionF)(const From &)>
+static void add_implicit_conversion(DataTypeConversions &conversions)
+{
+ static const CPPType &from_type = CPPType::get<From>();
+ static const CPPType &to_type = CPPType::get<To>();
+ static const std::string conversion_name = from_type.name() + " to " + to_type.name();
+
+ static fn::CustomMF_SI_SO<From, To> multi_function{conversion_name.c_str(), ConversionF};
+ static auto convert_single_to_initialized = [](const void *src, void *dst) {
+ *(To *)dst = ConversionF(*(const From *)src);
+ };
+ static auto convert_single_to_uninitialized = [](const void *src, void *dst) {
+ new (dst) To(ConversionF(*(const From *)src));
+ };
+ conversions.add(fn::MFDataType::ForSingle<From>(),
+ fn::MFDataType::ForSingle<To>(),
+ multi_function,
+ convert_single_to_initialized,
+ convert_single_to_uninitialized);
+}
+
+static float2 float_to_float2(const float &a)
+{
+ return float2(a);
+}
+static float3 float_to_float3(const float &a)
+{
+ return float3(a);
+}
+static int32_t float_to_int(const float &a)
+{
+ return (int32_t)a;
+}
+static bool float_to_bool(const float &a)
+{
+ return a > 0.0f;
+}
+static ColorGeometry4f float_to_color(const float &a)
+{
+ return ColorGeometry4f(a, a, a, 1.0f);
+}
+
+static float3 float2_to_float3(const float2 &a)
+{
+ return float3(a.x, a.y, 0.0f);
+}
+static float float2_to_float(const float2 &a)
+{
+ return (a.x + a.y) / 2.0f;
+}
+static int float2_to_int(const float2 &a)
+{
+ return (int32_t)((a.x + a.y) / 2.0f);
+}
+static bool float2_to_bool(const float2 &a)
+{
+ return !is_zero_v2(a);
+}
+static ColorGeometry4f float2_to_color(const float2 &a)
+{
+ return ColorGeometry4f(a.x, a.y, 0.0f, 1.0f);
+}
+
+static bool float3_to_bool(const float3 &a)
+{
+ return !is_zero_v3(a);
+}
+static float float3_to_float(const float3 &a)
+{
+ return (a.x + a.y + a.z) / 3.0f;
+}
+static int float3_to_int(const float3 &a)
+{
+ return (int)((a.x + a.y + a.z) / 3.0f);
+}
+static float2 float3_to_float2(const float3 &a)
+{
+ return float2(a);
+}
+static ColorGeometry4f float3_to_color(const float3 &a)
+{
+ return ColorGeometry4f(a.x, a.y, a.z, 1.0f);
+}
+
+static bool int_to_bool(const int32_t &a)
+{
+ return a > 0;
+}
+static float int_to_float(const int32_t &a)
+{
+ return (float)a;
+}
+static float2 int_to_float2(const int32_t &a)
+{
+ return float2((float)a);
+}
+static float3 int_to_float3(const int32_t &a)
+{
+ return float3((float)a);
+}
+static ColorGeometry4f int_to_color(const int32_t &a)
+{
+ return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
+}
+
+static float bool_to_float(const bool &a)
+{
+ return (bool)a;
+}
+static int32_t bool_to_int(const bool &a)
+{
+ return (int32_t)a;
+}
+static float2 bool_to_float2(const bool &a)
+{
+ return (a) ? float2(1.0f) : float2(0.0f);
+}
+static float3 bool_to_float3(const bool &a)
+{
+ return (a) ? float3(1.0f) : float3(0.0f);
+}
+static ColorGeometry4f bool_to_color(const bool &a)
+{
+ return (a) ? ColorGeometry4f(1.0f, 1.0f, 1.0f, 1.0f) : ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f);
+}
+
+static bool color_to_bool(const ColorGeometry4f &a)
+{
+ return rgb_to_grayscale(a) > 0.0f;
+}
+static float color_to_float(const ColorGeometry4f &a)
+{
+ return rgb_to_grayscale(a);
+}
+static int32_t color_to_int(const ColorGeometry4f &a)
+{
+ return (int)rgb_to_grayscale(a);
+}
+static float2 color_to_float2(const ColorGeometry4f &a)
+{
+ return float2(a.r, a.g);
+}
+static float3 color_to_float3(const ColorGeometry4f &a)
+{
+ return float3(a.r, a.g, a.b);
+}
+
+static DataTypeConversions create_implicit_conversions()
+{
+ DataTypeConversions conversions;
+
+ add_implicit_conversion<float, float2, float_to_float2>(conversions);
+ add_implicit_conversion<float, float3, float_to_float3>(conversions);
+ add_implicit_conversion<float, int32_t, float_to_int>(conversions);
+ add_implicit_conversion<float, bool, float_to_bool>(conversions);
+ add_implicit_conversion<float, ColorGeometry4f, float_to_color>(conversions);
+
+ add_implicit_conversion<float2, float3, float2_to_float3>(conversions);
+ add_implicit_conversion<float2, float, float2_to_float>(conversions);
+ add_implicit_conversion<float2, int32_t, float2_to_int>(conversions);
+ add_implicit_conversion<float2, bool, float2_to_bool>(conversions);
+ add_implicit_conversion<float2, ColorGeometry4f, float2_to_color>(conversions);
+
+ add_implicit_conversion<float3, bool, float3_to_bool>(conversions);
+ add_implicit_conversion<float3, float, float3_to_float>(conversions);
+ add_implicit_conversion<float3, int32_t, float3_to_int>(conversions);
+ add_implicit_conversion<float3, float2, float3_to_float2>(conversions);
+ add_implicit_conversion<float3, ColorGeometry4f, float3_to_color>(conversions);
+
+ add_implicit_conversion<int32_t, bool, int_to_bool>(conversions);
+ add_implicit_conversion<int32_t, float, int_to_float>(conversions);
+ add_implicit_conversion<int32_t, float2, int_to_float2>(conversions);
+ add_implicit_conversion<int32_t, float3, int_to_float3>(conversions);
+ add_implicit_conversion<int32_t, ColorGeometry4f, int_to_color>(conversions);
+
+ add_implicit_conversion<bool, float, bool_to_float>(conversions);
+ add_implicit_conversion<bool, int32_t, bool_to_int>(conversions);
+ add_implicit_conversion<bool, float2, bool_to_float2>(conversions);
+ add_implicit_conversion<bool, float3, bool_to_float3>(conversions);
+ add_implicit_conversion<bool, ColorGeometry4f, bool_to_color>(conversions);
+
+ add_implicit_conversion<ColorGeometry4f, bool, color_to_bool>(conversions);
+ add_implicit_conversion<ColorGeometry4f, float, color_to_float>(conversions);
+ add_implicit_conversion<ColorGeometry4f, int32_t, color_to_int>(conversions);
+ add_implicit_conversion<ColorGeometry4f, float2, color_to_float2>(conversions);
+ add_implicit_conversion<ColorGeometry4f, float3, color_to_float3>(conversions);
+
+ return conversions;
+}
+
+const DataTypeConversions &get_implicit_type_conversions()
+{
+ static const DataTypeConversions conversions = create_implicit_conversions();
+ return conversions;
+}
+
+void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
+ const CPPType &to_type,
+ const void *from_value,
+ void *to_value) const
+{
+ if (from_type == to_type) {
+ from_type.copy_construct(from_value, to_value);
+ return;
+ }
+
+ const ConversionFunctions *functions = this->get_conversion_functions(
+ MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type));
+ BLI_assert(functions != nullptr);
+
+ functions->convert_single_to_uninitialized(from_value, to_value);
+}
+
+void DataTypeConversions::convert_to_initialized_n(fn::GSpan from_span,
+ fn::GMutableSpan to_span) const
+{
+ const CPPType &from_type = from_span.type();
+ const CPPType &to_type = to_span.type();
+ BLI_assert(from_span.size() == to_span.size());
+ BLI_assert(this->is_convertible(from_type, to_type));
+ const fn::MultiFunction *fn = this->get_conversion_multi_function(
+ MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type));
+ fn::MFParamsBuilder params{*fn, from_span.size()};
+ params.add_readonly_single_input(from_span);
+ to_type.destruct_n(to_span.data(), to_span.size());
+ params.add_uninitialized_single_output(to_span);
+ fn::MFContextBuilder context;
+ fn->call_auto(IndexRange(from_span.size()), params, context);
+}
+
+class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl {
+ private:
+ fn::GVArray varray_;
+ const CPPType &from_type_;
+ ConversionFunctions old_to_new_conversions_;
+
+ public:
+ GVArray_For_ConvertedGVArray(fn::GVArray varray,
+ const CPPType &to_type,
+ const DataTypeConversions &conversions)
+ : 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(const int64_t index, void *r_value) const override
+ {
+ BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
+ varray_.get(index, buffer);
+ old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
+ from_type_.destruct(buffer);
+ }
+
+ 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);
+ old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
+ from_type_.destruct(buffer);
+ }
+};
+
+class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl {
+ private:
+ fn::GVMutableArray varray_;
+ const CPPType &from_type_;
+ ConversionFunctions old_to_new_conversions_;
+ ConversionFunctions new_to_old_conversions_;
+
+ public:
+ GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray,
+ const CPPType &to_type,
+ const DataTypeConversions &conversions)
+ : fn::GVMutableArrayImpl(to_type, varray.size()),
+ varray_(std::move(varray)),
+ 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(const int64_t index, void *r_value) const override
+ {
+ BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
+ varray_.get(index, buffer);
+ old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
+ from_type_.destruct(buffer);
+ }
+
+ 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);
+ old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
+ from_type_.destruct(buffer);
+ }
+
+ 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);
+ }
+};
+
+fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const
+{
+ const CPPType &from_type = varray.type();
+ if (from_type == to_type) {
+ return varray;
+ }
+ if (!this->is_convertible(from_type, to_type)) {
+ return {};
+ }
+ return fn::GVArray::For<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
+}
+
+fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray,
+ const CPPType &to_type) const
+{
+ const CPPType &from_type = varray.type();
+ if (from_type == to_type) {
+ return varray;
+ }
+ if (!this->is_convertible(from_type, to_type)) {
+ return {};
+ }
+ return fn::GVMutableArray::For<GVMutableArray_For_ConvertedGVMutableArray>(
+ std::move(varray), to_type, *this);
+}
+
+} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 26d37489e35..3e263fafe28 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -61,13 +61,39 @@
static CLG_LogRef LOG = {"bke.undosys"};
/* -------------------------------------------------------------------- */
+/** \name Undo Types
+ * \{ */
+
+const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_PARTICLE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_SCULPT = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_TEXT = NULL;
+
+static ListBase g_undo_types = {NULL, NULL};
+
+static const UndoType *BKE_undosys_type_from_context(bContext *C)
+{
+ LISTBASE_FOREACH (const UndoType *, ut, &g_undo_types) {
+ /* No poll means we don't check context. */
+ if (ut->poll && ut->poll(C)) {
+ return ut;
+ }
+ }
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Internal Nested Undo Checks
*
* Make sure we're not running undo operations from 'step_encode', 'step_decode' callbacks.
* bugs caused by this situation aren't _that_ hard to spot but aren't always so obvious.
* Best we have a check which shows the problem immediately.
- *
* \{ */
+
#define WITH_NESTED_UNDO_CHECK
#ifdef WITH_NESTED_UNDO_CHECK
@@ -90,36 +116,9 @@ static bool g_undo_callback_running = false;
# define UNDO_NESTED_CHECK_BEGIN ((void)0)
# define UNDO_NESTED_CHECK_END ((void)0)
#endif
-/** \} */
-/* -------------------------------------------------------------------- */
-/** \name Public Undo Types
- *
- * Unfortunately we need this for a handful of places.
- * \{ */
-const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL;
-const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL;
-const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL;
-const UndoType *BKE_UNDOSYS_TYPE_PARTICLE = NULL;
-const UndoType *BKE_UNDOSYS_TYPE_SCULPT = NULL;
-const UndoType *BKE_UNDOSYS_TYPE_TEXT = NULL;
/** \} */
-/* UndoType */
-
-static ListBase g_undo_types = {NULL, NULL};
-
-static const UndoType *BKE_undosys_type_from_context(bContext *C)
-{
- LISTBASE_FOREACH (const UndoType *, ut, &g_undo_types) {
- /* No poll means we don't check context. */
- if (ut->poll && ut->poll(C)) {
- return ut;
- }
- }
- return NULL;
-}
-
/* -------------------------------------------------------------------- */
/** \name Internal Callback Wrappers
*
@@ -358,7 +357,6 @@ void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain)
undosys_stack_push_main(ustack, IFACE_("Original"), bmain);
}
-/* called after 'BKE_undosys_stack_init_from_main' */
void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C)
{
const UndoType *ut = BKE_undosys_type_from_context(C);
@@ -367,7 +365,6 @@ void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C)
}
}
-/* name optional */
bool BKE_undosys_stack_has_undo(const UndoStack *ustack, const char *name)
{
if (name) {
@@ -397,10 +394,6 @@ UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const Un
return BKE_undosys_stack_active_with_type(ustack, ut);
}
-/**
- * \param steps: Limit the number of undo steps.
- * \param memory_limit: Limit the amount of memory used by the undo stack.
- */
void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit)
{
UNDO_NESTED_ASSERT(false);
@@ -455,6 +448,10 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Undo Step
+ * \{ */
+
UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
bContext *C,
const char *name,
@@ -497,9 +494,6 @@ UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, bContext *C, const char
return BKE_undosys_step_push_init_with_type(ustack, C, name, ut);
}
-/**
- * \param C: Can be NULL from some callers if their encoding function doesn't need it
- */
eUndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack,
bContext *C,
const char *name,
@@ -613,9 +607,6 @@ eUndoPushReturn BKE_undosys_step_push(UndoStack *ustack, bContext *C, const char
return BKE_undosys_step_push_with_type(ustack, C, name, ut);
}
-/**
- * Useful when we want to diff against previous undo data but can't be sure the types match.
- */
UndoStep *BKE_undosys_step_same_type_next(UndoStep *us)
{
if (us) {
@@ -629,9 +620,6 @@ UndoStep *BKE_undosys_step_same_type_next(UndoStep *us)
return us;
}
-/**
- * Useful when we want to diff against previous undo data but can't be sure the types match.
- */
UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us)
{
if (us) {
@@ -674,14 +662,6 @@ UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut)
return NULL;
}
-/**
- * Return direction of the undo/redo from `us_reference` (or `ustack->step_active` if NULL), and
- * `us_target`.
- *
- * \note If `us_reference` and `us_target` are the same, we consider this is an undo.
- *
- * \return -1 for undo, 1 for redo, 0 in case of error.
- */
eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack,
const UndoStep *us_target,
const UndoStep *us_reference)
@@ -741,19 +721,6 @@ static UndoStep *undosys_step_iter_first(UndoStep *us_reference, const eUndoStep
return (undo_dir == -1) ? us_reference->prev : us_reference->next;
}
-/**
- * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
- *
- * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target`
- * will become the active step.
- *
- * \note In case `use_skip` is true, the final target will always be **beyond** the given one
- * (if the given one has to be skipped).
- *
- * \param us_reference: If NULL, will be set to current active step in the undo stack. Otherwise,
- * it is assumed to match the current state, and will be used as basis for the undo/redo process
- * (i.e. all steps in-between `us_reference` and `us_target` will be processed).
- */
bool BKE_undosys_step_load_data_ex(UndoStack *ustack,
bContext *C,
UndoStep *us_target,
@@ -842,37 +809,22 @@ bool BKE_undosys_step_load_data_ex(UndoStack *ustack,
return false;
}
-/**
- * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
- */
bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us_target)
{
/* Note that here we do not skip 'skipped' steps by default. */
return BKE_undosys_step_load_data_ex(ustack, C, us_target, NULL, false);
}
-/**
- * Undo/Redo until the step matching given `index` in the undo stack becomes the active (currently
- * loaded) one.
- */
void BKE_undosys_step_load_from_index(UndoStack *ustack, bContext *C, const int index)
{
UndoStep *us_target = BLI_findlink(&ustack->steps, index);
BLI_assert(us_target->skip == false);
+ if (us_target == ustack->step_active) {
+ return;
+ }
BKE_undosys_step_load_data(ustack, C, us_target);
}
-/**
- * Undo until `us_target` step becomes the active (currently loaded) one.
- *
- * \warning This function assumes that the given target step is _before_ current active one.
- *
- * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the
- * active step.
- *
- * \note In case `use_skip` is true, the final target will always be **before** the given one (if
- * the given one has to be skipped).
- */
bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
bContext *C,
UndoStep *us_target,
@@ -888,19 +840,11 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
return BKE_undosys_step_load_data_ex(ustack, C, us_target, us_reference, use_skip);
}
-/**
- * Undo until `us_target` step becomes the active (currently loaded) one.
- *
- * \note See #BKE_undosys_step_undo_with_data_ex for details.
- */
bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target)
{
return BKE_undosys_step_undo_with_data_ex(ustack, C, us_target, true);
}
-/**
- * Undo one step from current active (currently loaded) one.
- */
bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C)
{
if (ustack->step_active != NULL) {
@@ -909,17 +853,6 @@ bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C)
return false;
}
-/**
- * Redo until `us_target` step becomes the active (currently loaded) one.
- *
- * \warning This function assumes that the given target step is _after_ current active one.
- *
- * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the
- * active step.
- *
- * \note In case `use_skip` is true, the final target will always be **after** the given one (if
- * the given one has to be skipped).
- */
bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
bContext *C,
UndoStep *us_target,
@@ -934,19 +867,11 @@ bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
return BKE_undosys_step_load_data_ex(ustack, C, us_target, us_reference, use_skip);
}
-/**
- * Redo until `us_target` step becomes the active (currently loaded) one.
- *
- * \note See #BKE_undosys_step_redo_with_data_ex for details.
- */
bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target)
{
return BKE_undosys_step_redo_with_data_ex(ustack, C, us_target, true);
}
-/**
- * Redo one step from current active one.
- */
bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C)
{
if (ustack->step_active != NULL) {
@@ -955,9 +880,6 @@ bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C)
return false;
}
-/**
- * Similar to #WM_operatortype_append
- */
UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *))
{
UndoType *ut;
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 4e9a3c9fb2e..fde3ac13ceb 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -1091,22 +1091,6 @@ double BKE_unit_apply_preferred_unit(const struct UnitSettings *settings, int ty
return value * scalar + bias;
}
-/**
- * Make a copy of the string that replaces the units with numbers.
- *
- * This is only used when evaluating user input and can afford to be a bit slower
- *
- * This is to be used before python evaluation so..
- * 10.1km -> 10.1*1000.0
- * ...will be resolved by python.
- *
- * Values will be split by an add sign.
- * 5'2" -> 5*0.3048 + 2*0.0254
- *
- * \param str_prev: is optional, when valid it is used to get a base unit when none is set.
- *
- * \return True of a change was made.
- */
bool BKE_unit_replace_string(
char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
{
@@ -1196,7 +1180,6 @@ bool BKE_unit_replace_string(
return changed;
}
-/* 45µm --> 45um */
void BKE_unit_name_to_alt(char *str, int len_max, const char *orig_str, int system, int type)
{
const bUnitCollection *usys = unit_get_system(system, type);
diff --git a/source/blender/blenkernel/intern/vfont.c b/source/blender/blenkernel/intern/vfont.c
index 43c8a59baad..4a598288ee6 100644
--- a/source/blender/blenkernel/intern/vfont.c
+++ b/source/blender/blenkernel/intern/vfont.c
@@ -49,6 +49,7 @@
#include "DNA_vfont_types.h"
#include "BKE_anim_path.h"
+#include "BKE_bpath.h"
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
@@ -123,6 +124,21 @@ static void vfont_free_data(ID *id)
}
}
+static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ VFont *vfont = (VFont *)id;
+
+ if (vfont->packedfile != NULL && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
+ return;
+ }
+
+ if (BKE_vfont_is_builtin(vfont)) {
+ return;
+ }
+
+ BKE_bpath_foreach_path_fixed_process(bpath_data, vfont->filepath);
+}
+
static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
VFont *vf = (VFont *)id;
@@ -162,6 +178,7 @@ IDTypeInfo IDType_ID_VF = {
.name_plural = "fonts",
.translation_context = BLT_I18NCONTEXT_ID_VFONT,
.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = vfont_init_data,
.copy_data = vfont_copy_data,
@@ -169,6 +186,7 @@ IDTypeInfo IDType_ID_VF = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
+ .foreach_path = vfont_foreach_path,
.owner_get = NULL,
.blend_write = vfont_blend_write,
@@ -183,7 +201,6 @@ IDTypeInfo IDType_ID_VF = {
/***************************** VFont *******************************/
-/* The vfont code */
void BKE_vfont_free_data(struct VFont *vfont)
{
if (vfont->data) {
@@ -1743,10 +1760,6 @@ bool BKE_vfont_to_curve_nubase(Object *ob, int mode, ListBase *r_nubase)
return BKE_vfont_to_curve_ex(ob, ob->data, mode, r_nubase, NULL, NULL, NULL, NULL);
}
-/**
- * Warning: expects to have access to evaluated data
- * (i.e. passed object should be evaluated one...).
- */
bool BKE_vfont_to_curve(Object *ob, int mode)
{
Curve *cu = ob->data;
diff --git a/source/blender/blenkernel/intern/vfontdata_freetype.c b/source/blender/blenkernel/intern/vfontdata_freetype.c
index bd58d156d06..9b79d5635d1 100644
--- a/source/blender/blenkernel/intern/vfontdata_freetype.c
+++ b/source/blender/blenkernel/intern/vfontdata_freetype.c
@@ -396,14 +396,6 @@ static bool check_freetypefont(PackedFile *pf)
return success;
}
-/**
- * Construct a new VFontData structure from
- * Freetype font data in a PackedFile.
- *
- * \param pf: The font data.
- * \retval A new VFontData structure, or NULL
- * if unable to load.
- */
VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
{
VFontData *vfd = NULL;
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index a72b5268e1d..130aa957491 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -41,6 +41,7 @@
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
+#include "BKE_bpath.h"
#include "BKE_geometry_set.hh"
#include "BKE_global.h"
#include "BKE_idtype.h"
@@ -576,6 +577,18 @@ static void volume_foreach_cache(ID *id,
function_callback(id, &key, (void **)&volume->runtime.grids, 0, user_data);
}
+static void volume_foreach_path(ID *id, BPathForeachPathData *bpath_data)
+{
+ Volume *volume = reinterpret_cast<Volume *>(id);
+
+ if (volume->packedfile != nullptr &&
+ (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
+ return;
+ }
+
+ BKE_bpath_foreach_path_fixed_process(bpath_data, volume->filepath);
+}
+
static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Volume *volume = (Volume *)id;
@@ -645,6 +658,7 @@ IDTypeInfo IDType_ID_VO = {
/* name_plural */ "volumes",
/* translation_context */ BLT_I18NCONTEXT_ID_VOLUME,
/* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ /* asset_type_info */ nullptr,
/* init_data */ volume_init_data,
/* copy_data */ volume_copy_data,
@@ -652,6 +666,7 @@ IDTypeInfo IDType_ID_VO = {
/* make_local */ nullptr,
/* foreach_id */ volume_foreach_id,
/* foreach_cache */ volume_foreach_cache,
+ /* foreach_path */ volume_foreach_path,
/* owner_get */ nullptr,
/* blend_write */ volume_blend_write,
@@ -1225,7 +1240,6 @@ const VolumeGrid *BKE_volume_grid_active_get_for_read(const Volume *volume)
return BKE_volume_grid_get_for_read(volume, index);
}
-/* Tries to find a grid with the given name. Make sure that the volume has been loaded. */
const VolumeGrid *BKE_volume_grid_find_for_read(const Volume *volume, const char *name)
{
int num_grids = BKE_volume_num_grids(volume);
@@ -1365,7 +1379,6 @@ int BKE_volume_grid_channels(const VolumeGrid *grid)
return 0;
}
-/* Transformation from index space to object space. */
void BKE_volume_grid_transform_matrix(const VolumeGrid *volume_grid, float mat[4][4])
{
#ifdef WITH_OPENVDB
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 6269cfc4349..e3fe1e04368 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -187,6 +187,7 @@ IDTypeInfo IDType_ID_WS = {
.name_plural = "workspaces",
.translation_context = BLT_I18NCONTEXT_ID_WORKSPACE,
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_ONLY_APPEND | IDTYPE_FLAGS_NO_ANIMDATA,
+ .asset_type_info = NULL,
.init_data = workspace_init_data,
.copy_data = NULL,
@@ -194,6 +195,7 @@ IDTypeInfo IDType_ID_WS = {
.make_local = NULL,
.foreach_id = workspace_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = workspace_blend_write,
@@ -319,13 +321,6 @@ WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
return new_workspace;
}
-/**
- * Remove \a workspace by freeing itself and its data. This is a higher-level wrapper that
- * calls #workspace_free_data (through #BKE_id_free) to free the workspace data, and frees
- * other data-blocks owned by \a workspace and its layouts (currently that is screens only).
- *
- * Always use this to remove (and free) workspaces. Don't free non-ID workspace members here.
- */
void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
{
for (WorkSpaceLayout *layout = workspace->layouts.first, *layout_next; layout;
@@ -369,9 +364,6 @@ void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *
MEM_freeN(hook);
}
-/**
- * Add a new layout to \a workspace for \a screen.
- */
WorkSpaceLayout *BKE_workspace_layout_add(Main *bmain,
WorkSpace *workspace,
bScreen *screen,
@@ -434,13 +426,6 @@ WorkSpaceLayout *BKE_workspace_layout_find(const WorkSpace *workspace, const bSc
return NULL;
}
-/**
- * Find the layout for \a screen without knowing which workspace to look in.
- * Can also be used to find the workspace that contains \a screen.
- *
- * \param r_workspace: Optionally return the workspace that contains the
- * looked up layout (if found).
- */
WorkSpaceLayout *BKE_workspace_layout_find_global(const Main *bmain,
const bScreen *screen,
WorkSpace **r_workspace)
@@ -464,15 +449,6 @@ WorkSpaceLayout *BKE_workspace_layout_find_global(const Main *bmain,
return NULL;
}
-/**
- * Circular workspace layout iterator.
- *
- * \param callback: Custom function which gets executed for each layout.
- * Can return false to stop iterating.
- * \param arg: Custom data passed to each \a callback call.
- *
- * \return the layout at which \a callback returned false.
- */
WorkSpaceLayout *BKE_workspace_layout_iter_circular(const WorkSpace *workspace,
WorkSpaceLayout *start,
bool (*callback)(const WorkSpaceLayout *layout,
@@ -564,18 +540,11 @@ void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
}
}
-/**
- * Get the layout that is active for \a hook (which is the visible layout for the active workspace
- * in \a hook).
- */
WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
{
return hook->act_layout;
}
-/**
- * Get the layout to be activated should \a workspace become or be the active workspace in \a hook.
- */
WorkSpaceLayout *BKE_workspace_active_layout_for_workspace_get(const WorkSpaceInstanceHook *hook,
const WorkSpace *workspace)
{
@@ -588,17 +557,6 @@ WorkSpaceLayout *BKE_workspace_active_layout_for_workspace_get(const WorkSpaceIn
return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
}
-/**
- * \brief Activate a layout
- *
- * Sets \a layout as active for \a workspace when activated through or already active in \a hook.
- * So when the active workspace of \a hook is \a workspace, \a layout becomes the active layout of
- * \a hook too. See #BKE_workspace_active_set().
- *
- * \a workspace does not need to be active for this.
- *
- * WorkSpaceInstanceHook.act_layout should only be modified directly to update the layout pointer.
- */
void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook,
const int winid,
WorkSpace *workspace,
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 2f0a282a298..b2e90b7ba12 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -192,6 +192,7 @@ IDTypeInfo IDType_ID_WO = {
.name_plural = "worlds",
.translation_context = BLT_I18NCONTEXT_ID_WORLD,
.flags = IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ .asset_type_info = NULL,
.init_data = world_init_data,
.copy_data = world_copy_data,
@@ -199,6 +200,7 @@ IDTypeInfo IDType_ID_WO = {
.make_local = NULL,
.foreach_id = world_foreach_id,
.foreach_cache = NULL,
+ .foreach_path = NULL,
.owner_get = NULL,
.blend_write = world_blend_write,
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index 4635db98514..a4f20f980b4 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -315,7 +315,6 @@ static void context_free_avi(void *context_v)
#endif /* WITH_AVI */
-/* similar to BKE_image_path_from_imformat() */
void BKE_movie_filepath_get(char *string, const RenderData *rd, bool preview, const char *suffix)
{
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index a20c918c517..035e56993f9 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -87,6 +87,7 @@ typedef struct FFMpegContext {
AVStream *video_stream;
AVStream *audio_stream;
AVFrame *current_frame; /* Image frame in output pixel format. */
+ int video_time;
/* Image frame in Blender's own pixel format, may need conversion to the output pixel format. */
AVFrame *img_convert_frame;
@@ -96,6 +97,7 @@ typedef struct FFMpegContext {
uint8_t *audio_deinterleave_buffer;
int audio_input_samples;
double audio_time;
+ double audio_time_total;
bool audio_deinterleave;
int audio_sample_size;
@@ -318,14 +320,15 @@ static const char **get_file_extensions(int format)
}
/* Write a frame to the output file */
-static int write_video_frame(FFMpegContext *context, int cfra, AVFrame *frame, ReportList *reports)
+static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList *reports)
{
int ret, success = 1;
AVPacket *packet = av_packet_alloc();
AVCodecContext *c = context->video_codec;
- frame->pts = cfra;
+ frame->pts = context->video_time;
+ context->video_time++;
ret = avcodec_send_frame(c, frame);
if (ret < 0) {
@@ -804,6 +807,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
avcodec_parameters_from_context(st->codecpar, c);
+ context->video_time = 0.0f;
+
return st;
}
@@ -1397,9 +1402,10 @@ static void write_audio_frames(FFMpegContext *context, double to_pts)
AVCodecContext *c = context->audio_codec;
while (context->audio_stream) {
- if ((context->audio_time >= to_pts) || !write_audio_frame(context)) {
+ if ((context->audio_time_total >= to_pts) || !write_audio_frame(context)) {
break;
}
+ context->audio_time_total += (double)context->audio_input_samples / (double)c->sample_rate;
context->audio_time += (double)context->audio_input_samples / (double)c->sample_rate;
}
}
@@ -1423,22 +1429,23 @@ int BKE_ffmpeg_append(void *context_v,
if (context->video_stream) {
avframe = generate_video_frame(context, (unsigned char *)pixels);
- success = (avframe && write_video_frame(context, frame - start_frame, avframe, reports));
+ success = (avframe && write_video_frame(context, avframe, reports));
+# ifdef WITH_AUDASPACE
+ /* Add +1 frame because we want to encode audio up until the next video frame. */
+ write_audio_frames(
+ context, (frame - start_frame + 1) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
+# endif
if (context->ffmpeg_autosplit) {
if (avio_tell(context->outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
end_ffmpeg_impl(context, true);
context->ffmpeg_autosplit_count++;
+
success &= start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
}
}
}
-# ifdef WITH_AUDASPACE
- /* Add +1 frame because we want to encode audio up until the next video frame. */
- write_audio_frames(
- context, (frame - start_frame + 1) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
-# endif
return success;
}
@@ -1881,6 +1888,7 @@ void *BKE_ffmpeg_context_create(void)
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = false;
context->stamp_data = NULL;
+ context->audio_time_total = 0.0;
return context;
}
diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h
index 3e13ba602a4..93014c1b859 100644
--- a/source/blender/blenkernel/nla_private.h
+++ b/source/blender/blenkernel/nla_private.h
@@ -165,18 +165,30 @@ typedef struct NlaKeyframingContext {
/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */
-/* convert from strip time <-> global time */
+/**
+ * Convert non clipped mapping for strip-time <-> global time:
+ * `mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*`
+ *
+ * Only secure for 'internal' (i.e. within AnimSys evaluation) operations,
+ * but should not be directly relied on for stuff which interacts with editors.
+ */
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode);
/* --------------- NLA Evaluation (very-private stuff) ----------------------- */
/* these functions are only defined here to avoid problems with the order
* in which they get defined. */
+/**
+ * Gets the strip active at the current time for a list of strips for evaluation purposes.
+ */
NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
ListBase *strips,
short index,
const struct AnimationEvalContext *anim_eval_context,
const bool flush_to_original);
+/**
+ * Evaluates the given evaluation strip.
+ */
void nlastrip_evaluate(PointerRNA *ptr,
NlaEvalData *channels,
ListBase *modifiers,
@@ -184,6 +196,9 @@ void nlastrip_evaluate(PointerRNA *ptr,
NlaEvalSnapshot *snapshot,
const struct AnimationEvalContext *anim_eval_context,
const bool flush_to_original);
+/**
+ * write the accumulated settings to.
+ */
void nladata_flush_channels(PointerRNA *ptr,
NlaEvalData *channels,
NlaEvalSnapshot *snapshot,
@@ -193,6 +208,14 @@ void nlasnapshot_enable_all_blend_domain(NlaEvalSnapshot *snapshot);
void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapshot);
+/**
+ * Blends the \a lower_snapshot with the \a upper_snapshot into \a r_blended_snapshot according
+ * to the given \a upper_blendmode and \a upper_influence.
+ *
+ * For \a upper_snapshot, blending limited to values in the \a blend_domain.
+ * For Replace blend-mode, this allows the upper snapshot to have a location XYZ channel
+ * where only a subset of values are blended.
+ */
void nlasnapshot_blend(NlaEvalData *eval_data,
NlaEvalSnapshot *lower_snapshot,
NlaEvalSnapshot *upper_snapshot,
@@ -200,6 +223,14 @@ void nlasnapshot_blend(NlaEvalData *eval_data,
const float upper_influence,
NlaEvalSnapshot *r_blended_snapshot);
+/**
+ * Using \a blended_snapshot and \a lower_snapshot, we can solve for the \a r_upper_snapshot.
+ *
+ * Only channels that exist within \a blended_snapshot are inverted.
+ *
+ * For \a r_upper_snapshot, disables \a NlaEvalChannelSnapshot->remap_domain for failed inversions.
+ * Only values within the \a remap_domain are processed.
+ */
void nlasnapshot_blend_get_inverted_upper_snapshot(NlaEvalData *eval_data,
NlaEvalSnapshot *lower_snapshot,
NlaEvalSnapshot *blended_snapshot,
diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h
index 8de6ec93a7c..0c1f73fa4b6 100644
--- a/source/blender/blenkernel/tracking_private.h
+++ b/source/blender/blenkernel/tracking_private.h
@@ -78,12 +78,21 @@ void tracking_get_search_origin_frame_pixel(int frame_width,
const struct MovieTrackingMarker *marker,
float frame_pixel[2]);
+/**
+ * Each marker has 5 coordinates associated with it that get warped with
+ * tracking: the four corners ("pattern_corners"), and the center ("pos").
+ * This function puts those 5 points into the appropriate frame for tracking
+ * (the "search" coordinate frame).
+ */
void tracking_get_marker_coords_for_tracking(int frame_width,
int frame_height,
const struct MovieTrackingMarker *marker,
double search_pixel_x[5],
double search_pixel_y[5]);
+/**
+ * Inverse of #tracking_get_marker_coords_for_tracking.
+ */
void tracking_set_marker_coords_from_tracking(int frame_width,
int frame_height,
struct MovieTrackingMarker *marker,
@@ -92,11 +101,23 @@ void tracking_set_marker_coords_from_tracking(int frame_width,
/*********************** General purpose utility functions *************************/
+/**
+ * Place a disabled marker before or after specified ref_marker.
+ *
+ * If before is truth, disabled marker is placed before reference
+ * one, and it's placed after it otherwise.
+ *
+ * If there's already a marker at the frame where disabled one is expected to be placed,
+ * nothing will happen if overwrite is false.
+ */
void tracking_marker_insert_disabled(struct MovieTrackingTrack *track,
const struct MovieTrackingMarker *ref_marker,
bool before,
bool overwrite);
+/**
+ * Fill in Libmv C-API camera intrinsics options from tracking structure.
+ */
void tracking_cameraIntrinscisOptionsFromTracking(
struct MovieTracking *tracking,
int calibration_width,
@@ -109,17 +130,26 @@ void tracking_trackingCameraFromIntrinscisOptions(
struct libmv_TrackRegionOptions;
+/**
+ * Fill in libmv tracker options structure with settings need to be used to perform track.
+ */
void tracking_configure_tracker(const MovieTrackingTrack *track,
float *mask,
bool is_backwards,
struct libmv_TrackRegionOptions *options);
+/**
+ * Get previous keyframed marker.
+ */
struct MovieTrackingMarker *tracking_get_keyframed_marker(struct MovieTrackingTrack *track,
int current_frame,
bool backwards);
/*********************** Masking *************************/
+/**
+ * Region is in pixel space, relative to marker's center.
+ */
float *tracking_track_get_mask_for_region(int frame_width,
int frame_height,
const float region_min[2],
@@ -145,11 +175,13 @@ typedef struct TrackingImageAccessor {
SpinLock cache_lock;
} TrackingImageAccessor;
-/* Clips are used to access images of an actual footage.
+/**
+ * Clips are used to access images of an actual footage.
* Tracks are used to access masks associated with the tracks.
*
- * NOTE: Both clips and tracks arrays are copied into the image accessor. It means that the caller
- * is allowed to pass temporary arrays which are only valid during initialization. */
+ * \note Both clips and tracks arrays are copied into the image accessor. It means that the caller
+ * is allowed to pass temporary arrays which are only valid during initialization.
+ */
TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
int num_clips,
MovieTrackingTrack **tracks,