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:
authorClément Foucault <foucault.clem@gmail.com>2020-02-11 16:57:41 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-02-11 16:57:41 +0300
commit30f65b54a78edc2a974ba93fefa86534fe2b7ff4 (patch)
tree030cf43b7c2cbd649a2e8758bf319a5b76a29aef
parent9052c6fafa87654c9a45ce0d5b9ecee073ec1a5b (diff)
parent3657bb514130ce2d28c407432d6f10202a68c92a (diff)
Merge branch 'master' into draw-colormanagementdraw-colormanagement
-rw-r--r--CMakeLists.txt36
-rw-r--r--build_files/build_environment/cmake/clang.cmake4
-rw-r--r--build_files/build_environment/cmake/freetype.cmake1
-rw-r--r--build_files/build_environment/cmake/llvm.cmake2
-rw-r--r--build_files/build_environment/cmake/osl.cmake5
-rw-r--r--build_files/build_environment/cmake/sqlite.cmake6
-rw-r--r--build_files/build_environment/cmake/versions.cmake22
-rwxr-xr-xbuild_files/build_environment/install_deps.sh162
-rw-r--r--build_files/build_environment/patches/freetype.diff18
-rw-r--r--build_files/build_environment/patches/opencollada.diff37
-rw-r--r--build_files/build_environment/patches/openimagedenoise.diff12
-rw-r--r--build_files/build_environment/patches/openimageio_idiff.diff13
-rw-r--r--build_files/build_environment/patches/osl.diff24
-rw-r--r--build_files/cmake/Modules/FindUSD.cmake2
-rw-r--r--build_files/cmake/macros.cmake10
-rw-r--r--build_files/cmake/platform/platform_apple.cmake15
-rw-r--r--build_files/cmake/platform/platform_unix.cmake11
-rw-r--r--build_files/cmake/platform/platform_win32.cmake14
-rw-r--r--build_files/windows/configure_msbuild.cmd14
-rw-r--r--build_files/windows/configure_ninja.cmd5
-rw-r--r--doc/python_api/examples/bpy.app.handlers.2.py23
-rw-r--r--doc/python_api/rst/info_quickstart.rst7
-rwxr-xr-xdoc/python_api/sphinx_doc_update.py8
-rw-r--r--extern/glew/CMakeLists.txt10
-rw-r--r--extern/mantaflow/preprocessed/fileio/iogrids.cpp73
-rw-r--r--extern/mantaflow/preprocessed/fileio/ioparticles.cpp2
-rw-r--r--extern/mantaflow/preprocessed/fluidsolver.cpp2
-rw-r--r--extern/mantaflow/preprocessed/gitinfo.h2
-rw-r--r--extern/mantaflow/preprocessed/plugin/flip.cpp1
-rw-r--r--extern/mantaflow/preprocessed/plugin/fluidguiding.cpp1
-rw-r--r--extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp5
-rw-r--r--intern/cycles/app/cycles_xml.cpp8
-rw-r--r--intern/cycles/blender/CMakeLists.txt5
-rw-r--r--intern/cycles/blender/blender_curves.cpp293
-rw-r--r--intern/cycles/blender/blender_geometry.cpp176
-rw-r--r--intern/cycles/blender/blender_id_map.h299
-rw-r--r--intern/cycles/blender/blender_image.cpp360
-rw-r--r--intern/cycles/blender/blender_light.cpp212
-rw-r--r--intern/cycles/blender/blender_mesh.cpp267
-rw-r--r--intern/cycles/blender/blender_object.cpp273
-rw-r--r--intern/cycles/blender/blender_object_cull.cpp1
-rw-r--r--intern/cycles/blender/blender_particles.cpp6
-rw-r--r--intern/cycles/blender/blender_python.cpp1
-rw-r--r--intern/cycles/blender/blender_session.cpp342
-rw-r--r--intern/cycles/blender/blender_shader.cpp4
-rw-r--r--intern/cycles/blender/blender_sync.cpp23
-rw-r--r--intern/cycles/blender/blender_sync.h70
-rw-r--r--intern/cycles/blender/blender_util.h237
-rw-r--r--intern/cycles/blender/blender_volume.cpp95
-rw-r--r--intern/cycles/bvh/bvh.cpp82
-rw-r--r--intern/cycles/bvh/bvh.h10
-rw-r--r--intern/cycles/bvh/bvh2.cpp4
-rw-r--r--intern/cycles/bvh/bvh2.h4
-rw-r--r--intern/cycles/bvh/bvh4.cpp4
-rw-r--r--intern/cycles/bvh/bvh4.h4
-rw-r--r--intern/cycles/bvh/bvh8.cpp29
-rw-r--r--intern/cycles/bvh/bvh8.h4
-rw-r--r--intern/cycles/bvh/bvh_build.cpp79
-rw-r--r--intern/cycles/bvh/bvh_build.h6
-rw-r--r--intern/cycles/bvh/bvh_embree.cpp167
-rw-r--r--intern/cycles/bvh/bvh_embree.h10
-rw-r--r--intern/cycles/bvh/bvh_optix.cpp129
-rw-r--r--intern/cycles/bvh/bvh_optix.h7
-rw-r--r--intern/cycles/bvh/bvh_params.h5
-rw-r--r--intern/cycles/bvh/bvh_split.cpp41
-rw-r--r--intern/cycles/bvh/bvh_split.h6
-rw-r--r--intern/cycles/bvh/bvh_unaligned.cpp14
-rw-r--r--intern/cycles/device/device_optix.cpp286
-rw-r--r--intern/cycles/graph/node.cpp10
-rw-r--r--intern/cycles/graph/node.h3
-rw-r--r--intern/cycles/graph/node_type.cpp11
-rw-r--r--intern/cycles/graph/node_type.h16
-rw-r--r--intern/cycles/graph/node_xml.cpp4
-rw-r--r--intern/cycles/kernel/filter/filter_features_sse.h1
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h10
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h30
-rw-r--r--intern/cycles/kernel/geom/geom_motion_curve.h2
-rw-r--r--intern/cycles/kernel/geom/geom_subd_triangle.h32
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h32
-rw-r--r--intern/cycles/kernel/kernel_types.h3
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp4
-rw-r--r--intern/cycles/render/CMakeLists.txt4
-rw-r--r--intern/cycles/render/attribute.cpp156
-rw-r--r--intern/cycles/render/attribute.h24
-rw-r--r--intern/cycles/render/bake.cpp4
-rw-r--r--intern/cycles/render/camera.cpp2
-rw-r--r--intern/cycles/render/film.cpp6
-rw-r--r--intern/cycles/render/geometry.cpp1469
-rw-r--r--intern/cycles/render/geometry.h202
-rw-r--r--intern/cycles/render/hair.cpp487
-rw-r--r--intern/cycles/render/hair.h151
-rw-r--r--intern/cycles/render/light.cpp16
-rw-r--r--intern/cycles/render/mesh.cpp1899
-rw-r--r--intern/cycles/render/mesh.h239
-rw-r--r--intern/cycles/render/mesh_displace.cpp6
-rw-r--r--intern/cycles/render/mesh_volume.cpp2
-rw-r--r--intern/cycles/render/nodes.cpp6
-rw-r--r--intern/cycles/render/object.cpp240
-rw-r--r--intern/cycles/render/object.h4
-rw-r--r--intern/cycles/render/scene.cpp24
-rw-r--r--intern/cycles/render/scene.h8
-rw-r--r--intern/cycles/render/session.cpp27
-rw-r--r--intern/cycles/render/shader.cpp16
-rw-r--r--intern/cycles/render/shader.h2
-rw-r--r--intern/cycles/test/CMakeLists.txt12
-rw-r--r--intern/cycles/test/util_avxf_avx2_test.cpp21
-rw-r--r--intern/cycles/test/util_avxf_avx_test.cpp21
-rw-r--r--intern/cycles/test/util_avxf_test.h220
-rw-r--r--intern/eigen/CMakeLists.txt6
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h2
-rw-r--r--intern/mantaflow/CMakeLists.txt30
-rw-r--r--intern/mantaflow/extern/manta_fluid_API.h2
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp498
-rw-r--r--intern/mantaflow/intern/MANTA_main.h8
-rw-r--r--intern/mantaflow/intern/manta_fluid_API.cpp14
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h25
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h2
m---------release/datafiles/locale0
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c2
m---------release/scripts/addons0
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py2
-rw-r--r--release/scripts/modules/rna_manual_reference.py213
-rw-r--r--release/scripts/presets/keyconfig/blender.py40
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py74
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py42
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py138
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py8
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--source/blender/alembic/intern/abc_mball.cc2
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc2
-rw-r--r--source/blender/alembic/intern/abc_object.cc2
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc2
-rw-r--r--source/blender/blenkernel/BKE_deform.h10
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h4
-rw-r--r--source/blender/blenkernel/BKE_global.h1
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h263
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h114
-rw-r--r--source/blender/blenkernel/BKE_lib_query.h (renamed from source/blender/blenkernel/BKE_library_query.h)18
-rw-r--r--source/blender/blenkernel/BKE_lib_remap.h (renamed from source/blender/blenkernel/BKE_library_remap.h)22
-rw-r--r--source/blender/blenkernel/BKE_library.h223
-rw-r--r--source/blender/blenkernel/BKE_library_override.h99
-rw-r--r--source/blender/blenkernel/BKE_main.h19
-rw-r--r--source/blender/blenkernel/BKE_main_idmap.h (renamed from source/blender/blenkernel/BKE_library_idmap.h)16
-rw-r--r--source/blender/blenkernel/BKE_mesh.h4
-rw-r--r--source/blender/blenkernel/BKE_modifier.h10
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h5
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h6
-rw-r--r--source/blender/blenkernel/BKE_tracking.h4
-rw-r--r--source/blender/blenkernel/CMakeLists.txt20
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c2
-rw-r--r--source/blender/blenkernel/intern/action.c4
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c6
-rw-r--r--source/blender/blenkernel/intern/armature.c8
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c1
-rw-r--r--source/blender/blenkernel/intern/brush.c8
-rw-r--r--source/blender/blenkernel/intern/cachefile.c4
-rw-r--r--source/blender/blenkernel/intern/camera.c4
-rw-r--r--source/blender/blenkernel/intern/collection.c6
-rw-r--r--source/blender/blenkernel/intern/constraint.c26
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c2
-rw-r--r--source/blender/blenkernel/intern/curve.c4
-rw-r--r--source/blender/blenkernel/intern/deform.c7
-rw-r--r--source/blender/blenkernel/intern/displist.c2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c2
-rw-r--r--source/blender/blenkernel/intern/editmesh.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c680
-rw-r--r--source/blender/blenkernel/intern/fluid.c65
-rw-r--r--source/blender/blenkernel/intern/font.c2
-rw-r--r--source/blender/blenkernel/intern/freestyle.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil.c4
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c4
-rw-r--r--source/blender/blenkernel/intern/idprop.c2
-rw-r--r--source/blender/blenkernel/intern/image.c4
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/key.c4
-rw-r--r--source/blender/blenkernel/intern/lattice.c15
-rw-r--r--source/blender/blenkernel/intern/layer.c4
-rw-r--r--source/blender/blenkernel/intern/lib_id.c2606
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c538
-rw-r--r--source/blender/blenkernel/intern/lib_intern.h (renamed from source/blender/blenlib/BLI_temporary_allocator_cxx.h)25
-rw-r--r--source/blender/blenkernel/intern/lib_override.c (renamed from source/blender/blenkernel/intern/library_override.c)148
-rw-r--r--source/blender/blenkernel/intern/lib_query.c (renamed from source/blender/blenkernel/intern/library_query.c)8
-rw-r--r--source/blender/blenkernel/intern/lib_remap.c (renamed from source/blender/blenkernel/intern/library_remap.c)525
-rw-r--r--source/blender/blenkernel/intern/library.c2581
-rw-r--r--source/blender/blenkernel/intern/light.c4
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c4
-rw-r--r--source/blender/blenkernel/intern/linestyle.c4
-rw-r--r--source/blender/blenkernel/intern/main.c4
-rw-r--r--source/blender/blenkernel/intern/main_idmap.c (renamed from source/blender/blenkernel/intern/library_idmap.c)2
-rw-r--r--source/blender/blenkernel/intern/mask.c4
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c2
-rw-r--r--source/blender/blenkernel/intern/material.c4
-rw-r--r--source/blender/blenkernel/intern/mball.c4
-rw-r--r--source/blender/blenkernel/intern/mesh.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_merge.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_mirror.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c10
-rw-r--r--source/blender/blenkernel/intern/modifier.c4
-rw-r--r--source/blender/blenkernel/intern/movieclip.c4
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c8
-rw-r--r--source/blender/blenkernel/intern/node.c30
-rw-r--r--source/blender/blenkernel/intern/object.c8
-rw-r--r--source/blender/blenkernel/intern/paint.c10
-rw-r--r--source/blender/blenkernel/intern/paint_toolslots.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c14
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c5
-rw-r--r--source/blender/blenkernel/intern/pbvh.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c4
-rw-r--r--source/blender/blenkernel/intern/scene.c8
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c2
-rw-r--r--source/blender/blenkernel/intern/seqprefetch.c2
-rw-r--r--source/blender/blenkernel/intern/sequencer.c142
-rw-r--r--source/blender/blenkernel/intern/shader_fx.c4
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c2
-rw-r--r--source/blender/blenkernel/intern/sound.c4
-rw-r--r--source/blender/blenkernel/intern/speaker.c4
-rw-r--r--source/blender/blenkernel/intern/studiolight.c62
-rw-r--r--source/blender/blenkernel/intern/text.c4
-rw-r--r--source/blender/blenkernel/intern/texture.c4
-rw-r--r--source/blender/blenkernel/intern/tracking.c165
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c31
-rw-r--r--source/blender/blenkernel/intern/tracking_detect.c7
-rw-r--r--source/blender/blenkernel/intern/tracking_plane_tracker.c19
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c8
-rw-r--r--source/blender/blenkernel/intern/tracking_solver.c35
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c33
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c27
-rw-r--r--source/blender/blenkernel/intern/undo_system.c6
-rw-r--r--source/blender/blenkernel/intern/workspace.c2
-rw-r--r--source/blender/blenkernel/intern/world.c4
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c2
-rw-r--r--source/blender/blenlib/BLI_allocator.h26
-rw-r--r--source/blender/blenlib/BLI_array_cxx.h73
-rw-r--r--source/blender/blenlib/BLI_array_ref.h129
-rw-r--r--source/blender/blenlib/BLI_hash_cxx.h1
-rw-r--r--source/blender/blenlib/BLI_index_range.h15
-rw-r--r--source/blender/blenlib/BLI_kdtree.h8
-rw-r--r--source/blender/blenlib/BLI_listbase_wrapper.h13
-rw-r--r--source/blender/blenlib/BLI_map.h13
-rw-r--r--source/blender/blenlib/BLI_math_color_blend.h64
-rw-r--r--source/blender/blenlib/BLI_memory_utils_cxx.h37
-rw-r--r--source/blender/blenlib/BLI_open_addressing.h4
-rw-r--r--source/blender/blenlib/BLI_optional.h199
-rw-r--r--source/blender/blenlib/BLI_rand.h2
-rw-r--r--source/blender/blenlib/BLI_stack_cxx.h9
-rw-r--r--source/blender/blenlib/BLI_string_map.h46
-rw-r--r--source/blender/blenlib/BLI_string_ref.h8
-rw-r--r--source/blender/blenlib/BLI_string_utils.h8
-rw-r--r--source/blender/blenlib/BLI_temporary_allocator.h64
-rw-r--r--source/blender/blenlib/BLI_utility_mixins.h52
-rw-r--r--source/blender/blenlib/BLI_vector.h73
-rw-r--r--source/blender/blenlib/BLI_vector_set.h6
-rw-r--r--source/blender/blenlib/CMakeLists.txt5
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c10
-rw-r--r--source/blender/blenlib/intern/BLI_index_range.cc4
-rw-r--r--source/blender/blenlib/intern/BLI_temporary_allocator.cc115
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.c3
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c2
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c200
-rw-r--r--source/blender/blenlib/intern/math_geom.c31
-rw-r--r--source/blender/blenlib/intern/math_vector.c34
-rw-r--r--source/blender/blenlib/intern/string_utf8.c2
-rw-r--r--source/blender/blenlib/intern/string_utils.c18
-rw-r--r--source/blender/blenloader/intern/blend_validate.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c432
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/versioning_280.c4
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c14
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h2
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c2
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c933
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c4
-rw-r--r--source/blender/collada/BCAnimationSampler.cpp2
-rw-r--r--source/blender/collada/BCAnimationSampler.h2
-rw-r--r--source/blender/collada/ControllerExporter.cpp29
-rw-r--r--source/blender/collada/DocumentImporter.cpp2
-rw-r--r--source/blender/collada/ErrorHandler.cpp3
-rw-r--r--source/blender/collada/GeometryExporter.cpp2
-rw-r--r--source/blender/collada/MeshImporter.cpp6
-rw-r--r--source/blender/collada/SceneExporter.cpp2
-rw-r--r--source/blender/collada/collada_utils.cpp2
-rw-r--r--source/blender/depsgraph/CMakeLists.txt2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_facing.c15
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_studiolight.c57
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c6
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c2
-rw-r--r--source/blender/editors/animation/keyframes_edit.c6
-rw-r--r--source/blender/editors/armature/pose_lib.c2
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c2
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h10
-rw-r--r--source/blender/editors/interface/interface_ops.c14
-rw-r--r--source/blender/editors/interface/interface_templates.c12
-rw-r--r--source/blender/editors/interface/view2d.c6
-rw-r--r--source/blender/editors/io/io_cache.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c4
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c12
-rw-r--r--source/blender/editors/mesh/meshtools.c2
-rw-r--r--source/blender/editors/object/object_add.c6
-rw-r--r--source/blender/editors/object/object_bake_api.c2
-rw-r--r--source/blender/editors/object/object_collection.c2
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/object/object_relations.c29
-rw-r--r--source/blender/editors/object/object_remesh.c2
-rw-r--r--source/blender/editors/object/object_select.c2
-rw-r--r--source/blender/editors/object/object_transform.c2
-rw-r--r--source/blender/editors/object/object_vgroup.c10
-rw-r--r--source/blender/editors/physics/particle_object.c2
-rw-r--r--source/blender/editors/physics/physics_fluid.c4
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c2
-rw-r--r--source/blender/editors/physics/rigidbody_object.c2
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/render/render_opengl.c2
-rw-r--r--source/blender/editors/render/render_preview.c5
-rw-r--r--source/blender/editors/render/render_shading.c2
-rw-r--r--source/blender/editors/scene/scene_edit.c2
-rw-r--r--source/blender/editors/screen/area.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c3
-rw-r--r--source/blender/editors/screen/workspace_edit.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c52
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c32
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h2
-rw-r--r--source/blender/editors/sound/sound_ops.c2
-rw-r--r--source/blender/editors/space_action/action_data.c2
-rw-r--r--source/blender/editors/space_clip/clip_editor.c2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c8
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c2
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c49
-rw-r--r--source/blender/editors/space_graph/graph_draw.c21
-rw-r--r--source/blender/editors/space_image/image_draw.c26
-rw-r--r--source/blender/editors/space_image/image_edit.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c13
-rw-r--r--source/blender/editors/space_image/space_image.c2
-rw-r--r--source/blender/editors/space_info/info_ops.c2
-rw-r--r--source/blender/editors/space_nla/nla_edit.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c25
-rw-r--r--source/blender/editors/space_node/node_add.c2
-rw-r--r--source/blender/editors/space_node/node_draw.c14
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/node_group.c2
-rw-r--r--source/blender/editors/space_node/node_relationships.c2
-rw-r--r--source/blender/editors/space_node/node_templates.c2
-rw-r--r--source/blender/editors/space_node/space_node.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c15
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c30
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c52
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c2
-rw-r--r--source/blender/editors/space_text/space_text.c2
-rw-r--r--source/blender/editors/space_text/text_draw.c6
-rw-r--r--source/blender/editors/space_text/text_ops.c5
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawobject.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c485
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c578
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c95
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c98
-rw-r--r--source/blender/editors/transform/transform_convert.h28
-rw-r--r--source/blender/editors/transform/transform_generics.c2
-rw-r--r--source/blender/editors/transform/transform_snap_object.c2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp2
-rw-r--r--source/blender/freestyle/intern/system/PythonInterpreter.h2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.cpp4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c32
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c2
-rw-r--r--source/blender/gpu/GPU_texture.h2
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h8
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h21
-rw-r--r--source/blender/makesrna/RNA_access.h10
-rw-r--r--source/blender/makesrna/intern/makesrna.c2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c13
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c20
-rw-r--r--source/blender/makesrna/intern/rna_brush.c6
-rw-r--r--source/blender/makesrna/intern/rna_layer.c15
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_pose.c3
-rw-r--r--source/blender/makesrna/intern/rna_rna.c76
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c8
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h8
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c4
-rw-r--r--source/blender/modifiers/intern/MOD_array.c4
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c4
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c4
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c4
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c2
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c14
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c4
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c4
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c2
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c2
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c2
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c4
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c14
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c4
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c4
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c4
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c4
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c4
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c4
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c4
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c7
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c2
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c4
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c2
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weld.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_movieclip.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_moviedistortion.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_stabilize2d.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c2
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c2
-rw-r--r--source/blender/python/intern/bpy_app.c6
-rw-r--r--source/blender/python/intern/bpy_library_load.c2
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c2
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c4
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c2
-rw-r--r--source/blender/render/intern/source/bake_api.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c4
-rw-r--r--source/blender/shader_fx/intern/FX_shader_light.c2
-rw-r--r--source/blender/shader_fx/intern/FX_shader_shadow.c2
-rw-r--r--source/blender/shader_fx/intern/FX_shader_swirl.c2
-rw-r--r--source/blender/usd/intern/usd_writer_mesh.cc4
-rw-r--r--source/blender/windowmanager/intern/wm.c4
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c11
-rw-r--r--source/blender/windowmanager/intern/wm_files.c4
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c8
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c4
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c2
-rw-r--r--source/creator/CMakeLists.txt2
-rw-r--r--source/creator/creator_args.c6
-rw-r--r--tests/gtests/blenlib/BLI_array_ref_test.cc56
-rw-r--r--tests/gtests/blenlib/BLI_index_range_test.cc9
-rw-r--r--tests/gtests/blenlib/BLI_optional_test.cc74
-rw-r--r--tests/gtests/blenlib/BLI_stack_cxx_test.cc15
-rw-r--r--tests/gtests/blenlib/BLI_string_map_test.cc26
-rw-r--r--tests/gtests/blenlib/BLI_string_ref_test.cc9
-rw-r--r--tests/gtests/blenlib/BLI_vector_test.cc48
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt1
-rw-r--r--tests/python/CMakeLists.txt5
-rw-r--r--tests/python/bl_bundled_modules.py30
513 files changed, 13856 insertions, 11194 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 509de9943e2..820fea6982c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -613,29 +613,25 @@ endif()
# enable boost for cycles, audaspace or i18n
# otherwise if the user disabled
-if(NOT WITH_BOOST)
- # Explicitly disabled. so disable all deps.
- macro(set_and_warn
- _setting _val)
- if(${${_setting}})
- message(STATUS "'WITH_BOOST' is disabled: forcing 'set(${_setting} ${_val})'")
- endif()
- set(${_setting} ${_val})
- endmacro()
-
- set_and_warn(WITH_CYCLES OFF)
- set_and_warn(WITH_INTERNATIONAL OFF)
- set_and_warn(WITH_OPENVDB OFF)
- set_and_warn(WITH_OPENCOLORIO OFF)
- set_and_warn(WITH_QUADRIFLOW OFF)
-elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
- WITH_OPENVDB OR WITH_OPENCOLORIO)
- # Keep enabled
-else()
- # Disable boost if not needed.
+
+set_and_warn_dependency(WITH_BOOST WITH_CYCLES OFF)
+set_and_warn_dependency(WITH_BOOST WITH_INTERNATIONAL OFF)
+set_and_warn_dependency(WITH_BOOST WITH_OPENVDB OFF)
+set_and_warn_dependency(WITH_BOOST WITH_OPENCOLORIO OFF)
+set_and_warn_dependency(WITH_BOOST WITH_QUADRIFLOW OFF)
+set_and_warn_dependency(WITH_BOOST WITH_USD OFF)
+
+if(WITH_BOOST AND NOT (WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
+ WITH_OPENVDB OR WITH_OPENCOLORIO OR WITH_USD))
+ message(STATUS "No dependencies need 'WITH_BOOST' forcing WITH_BOOST=OFF")
set(WITH_BOOST OFF)
endif()
+set_and_warn_dependency(WITH_TBB WITH_USD OFF)
+set_and_warn_dependency(WITH_TBB WITH_OPENIMAGEDENOISE OFF)
+set_and_warn_dependency(WITH_TBB WITH_OPENVDB OFF)
+set_and_warn_dependency(WITH_TBB WITH_MOD_FLUID OFF)
+
# auto enable openimageio for cycles
if(WITH_CYCLES)
set(WITH_OPENIMAGEIO ON)
diff --git a/build_files/build_environment/cmake/clang.cmake b/build_files/build_environment/cmake/clang.cmake
index 3231a339e17..f7dfd434d4a 100644
--- a/build_files/build_environment/cmake/clang.cmake
+++ b/build_files/build_environment/cmake/clang.cmake
@@ -46,9 +46,7 @@ if(MSVC)
set(CLANG_HARVEST_COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/clang/ ${HARVEST_TARGET}/llvm/)
else()
set(CLANG_HARVEST_COMMAND
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/clang/lib/ ${HARVEST_TARGET}/llvm/debug/lib/ &&
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/clang/bin/ ${HARVEST_TARGET}/llvm/debug/bin/ &&
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/clang/include/ ${HARVEST_TARGET}/llvm/debug/include/
+ ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/clang/lib/ ${HARVEST_TARGET}/llvm/debug/lib/
)
endif()
ExternalProject_Add_Step(external_clang after_install
diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake
index f998c94706f..30dd2eed676 100644
--- a/build_files/build_environment/cmake/freetype.cmake
+++ b/build_files/build_environment/cmake/freetype.cmake
@@ -32,7 +32,6 @@ ExternalProject_Add(external_freetype
URL_HASH MD5=${FREETYPE_HASH}
PREFIX ${BUILD_DIR}/freetype
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/freetype ${DEFAULT_CMAKE_FLAGS} ${FREETYPE_EXTRA_ARGS}
- PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/freetype/src/external_freetype < ${PATCH_DIR}/freetype.diff
INSTALL_DIR ${LIBDIR}/freetype
)
diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake
index dc1a5cf8a80..3ef0445201f 100644
--- a/build_files/build_environment/cmake/llvm.cmake
+++ b/build_files/build_environment/cmake/llvm.cmake
@@ -23,6 +23,8 @@ set(LLVM_EXTRA_ARGS
-DLLVM_TARGETS_TO_BUILD=X86
-DLLVM_INCLUDE_EXAMPLES=OFF
-DLLVM_ENABLE_TERMINFO=OFF
+ -DLLVM_BUILD_LLVM_C_DYLIB=OFF
+ -DLLVM_ENABLE_UNWIND_TABLES=OFF
)
if(WIN32)
diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake
index 5113f9ded48..19636304c21 100644
--- a/build_files/build_environment/cmake/osl.cmake
+++ b/build_files/build_environment/cmake/osl.cmake
@@ -18,7 +18,7 @@
if(WIN32)
set(OSL_CMAKE_CXX_STANDARD_LIBRARIES "kernel32${LIBEXT} user32${LIBEXT} gdi32${LIBEXT} winspool${LIBEXT} shell32${LIBEXT} ole32${LIBEXT} oleaut32${LIBEXT} uuid${LIBEXT} comdlg32${LIBEXT} advapi32${LIBEXT} psapi${LIBEXT}")
- set(OSL_FLEX_BISON -DFLEX_EXECUTABLE=${LIBDIR}/flexbison/win_flex.exe -DFLEX_EXTRA_OPTIONS="--wincompat" -DBISON_EXECUTABLE=${LIBDIR}/flexbison/win_bison.exe)
+ set(OSL_FLEX_BISON -DFLEX_EXECUTABLE=${LIBDIR}/flexbison/win_flex.exe -DBISON_EXECUTABLE=${LIBDIR}/flexbison/win_bison.exe)
set(OSL_OPENIMAGEIO_LIBRARY "${LIBDIR}/openimageio/lib/${LIBPREFIX}OpenImageIO${LIBEXT};${LIBDIR}/openimageio/lib/${LIBPREFIX}OpenImageIO_Util${LIBEXT};${LIBDIR}/png/lib/libpng16${LIBEXT};${LIBDIR}/jpg/lib/${LIBPREFIX}jpeg${LIBEXT};${LIBDIR}/tiff/lib/${LIBPREFIX}tiff${LIBEXT};${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf${OPENEXR_VERSION_POSTFIX}${LIBEXT}")
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
set(OSL_SIMD_FLAGS -DOIIO_NOSIMD=1 -DOIIO_SIMD=0)
@@ -59,11 +59,12 @@ set(OSL_EXTRA_ARGS
-DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/
-DOPENEXR_ILMIMF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf${OPENEXR_VERSION_POSTFIX}${LIBEXT}
-DOSL_BUILD_TESTS=OFF
+ -DOSL_BUILD_MATERIALX=OFF
-DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
-DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
-DOPENIMAGEIOHOME=${LIBDIR}/openimageio/
+ -DOPENIMAGEIO_INCLUDE_DIR=${LIBDIR}/openimageio/include
-DOPENIMAGEIO_LIBRARY=${OSL_OPENIMAGEIO_LIBRARY}
- -DOPENIMAGEIO_INCLUDES=${LIBDIR}/openimageio/include
${OSL_FLEX_BISON}
-DCMAKE_CXX_STANDARD_LIBRARIES=${OSL_CMAKE_CXX_STANDARD_LIBRARIES}
-DBUILDSTATIC=ON
diff --git a/build_files/build_environment/cmake/sqlite.cmake b/build_files/build_environment/cmake/sqlite.cmake
index 647e50b315a..9fa2fa7c708 100644
--- a/build_files/build_environment/cmake/sqlite.cmake
+++ b/build_files/build_environment/cmake/sqlite.cmake
@@ -19,8 +19,10 @@
set(SQLITE_CONFIGURE_ENV echo .)
set(SQLITE_CONFIGURATION_ARGS)
-if(UNIX AND NOT APPLE)
- set(SQLITE_LDFLAGS -Wl,--as-needed)
+if(UNIX)
+ if(NOT APPLE)
+ set(SQLITE_LDFLAGS -Wl,--as-needed)
+ endif()
set(SQLITE_CFLAGS
"-DSQLITE_SECURE_DELETE -DSQLITE_ENABLE_COLUMN_METADATA \
-DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index fda65922a7f..58c76b6e263 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -66,9 +66,9 @@ else()
set(OPENEXR_VERSION_POSTFIX)
endif()
-set(FREETYPE_VERSION 2.9.1)
+set(FREETYPE_VERSION 2.10.1)
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
-set(FREETYPE_HASH 3adb0e35d3c100c456357345ccfa8056)
+set(FREETYPE_HASH c50a3c9e5e62bdc938a6e1598a782947)
set(GLEW_VERSION 1.13.0)
set(GLEW_URI http://prdownloads.sourceforge.net/glew/glew/${GLEW_VERSION}/glew-${GLEW_VERSION}.tgz)
@@ -117,15 +117,15 @@ set(OPENCOLORIO_VERSION 1.1.0)
set(OPENCOLORIO_URI https://github.com/imageworks/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz)
set(OPENCOLORIO_HASH 802d8f5b1d1fe316ec5f76511aa611b8)
-set(LLVM_VERSION 6.0.1)
-set(LLVM_URI http://releases.llvm.org/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz)
-set(LLVM_HASH c88c98709300ce2c285391f387fecce0)
+set(LLVM_VERSION 9.0.1)
+set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz)
+set(LLVM_HASH 31eb9ce73dd2a0f8dcab8319fb03f8fc)
-set(CLANG_URI http://releases.llvm.org/${LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.xz)
-set(CLANG_HASH 4e419bd4e3b55aa06d872320f754bd85)
+set(CLANG_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/clang-${LLVM_VERSION}.src.tar.xz)
+set(CLANG_HASH 13468e4a44940efef1b75e8641752f90)
-set(OPENMP_URI http://releases.llvm.org/${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz)
-set(OPENMP_HASH 4826402ae3633c36c51ba4d0e5527d30)
+set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz)
+set(OPENMP_HASH 6eade16057edbdecb3c4eef9daa2bfcf)
set(OPENIMAGEIO_VERSION 1.8.13)
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/Release-${OPENIMAGEIO_VERSION}.tar.gz)
@@ -135,9 +135,9 @@ set(TIFF_VERSION 4.0.9)
set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_HASH 54bad211279cc93eb4fca31ba9bfdc79)
-set(OSL_VERSION 1.9.9)
+set(OSL_VERSION 1.10.9)
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
-set(OSL_HASH 44ad511e424965a10fce051a053b0605)
+set(OSL_HASH a94f1e8506f7e8f5e993653de5c5fa00)
set(PYTHON_VERSION 3.7.4)
set(PYTHON_SHORT_VERSION 3.7)
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index bc9ee802810..2f27eab8e3f 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -55,13 +55,13 @@ with-all,with-opencollada,with-jack,with-embree,with-oidn,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
force-all,force-python,force-numpy,force-boost,\
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
-force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,\
+force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-usd,\
build-all,build-python,build-numpy,build-boost,\
build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
-build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,\
+build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-usd,\
skip-python,skip-numpy,skip-boost,\
skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
-skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn \
+skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd \
-- "$@" \
)
@@ -221,6 +221,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--build-ffmpeg
Force the build of FFMpeg.
+ --build-usd
+ Force the build of Universal Scene Description.
+
Note about the --build-foo options:
* They force the script to prefer building dependencies rather than using available packages.
This may make things simpler and allow working around some distribution bugs, but on the other hand it will
@@ -279,6 +282,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-ffmpeg
Force the rebuild of FFMpeg.
+ --force-usd
+ Force the rebuild of Universal Scene Description.
+
Note about the --force-foo options:
* They obviously only have an effect if those libraries are built by this script
(i.e. if there is no available and satisfactory package)!
@@ -328,7 +334,10 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
Unconditionally skip OpenImageDenoise installation/building.
--skip-ffmpeg
- Unconditionally skip FFMpeg installation/building.\""
+ Unconditionally skip FFMpeg installation/building.
+
+ --skip-usd
+ Unconditionally skip Universal Scene Description installation/building.\""
# ----------------------------------------------------------------------------
# Main Vars
@@ -383,7 +392,7 @@ OIIO_FORCE_BUILD=false
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
-LLVM_VERSION="6.0.1"
+LLVM_VERSION="9.0.1"
LLVM_VERSION_MIN="6.0"
LLVM_VERSION_FOUND=""
LLVM_FORCE_BUILD=false
@@ -391,7 +400,7 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.9.9"
+OSL_VERSION="1.10.9"
OSL_VERSION_MIN=$OSL_VERSION
OSL_FORCE_BUILD=false
OSL_FORCE_REBUILD=false
@@ -420,6 +429,11 @@ ALEMBIC_FORCE_BUILD=false
ALEMBIC_FORCE_REBUILD=false
ALEMBIC_SKIP=false
+USD_VERSION="19.11"
+USD_FORCE_BUILD=false
+USD_FORCE_REBUILD=false
+USD_SKIP=false
+
OPENCOLLADA_VERSION="1.6.68"
OPENCOLLADA_FORCE_BUILD=false
OPENCOLLADA_FORCE_REBUILD=false
@@ -628,6 +642,7 @@ while true; do
OIDN_FORCE_BUILD=true
FFMPEG_FORCE_BUILD=true
ALEMBIC_FORCE_BUILD=true
+ USD_FORCE_BUILD=true
shift; continue
;;
--build-python)
@@ -679,6 +694,9 @@ while true; do
--build-alembic)
ALEMBIC_FORCE_BUILD=true; shift; continue
;;
+ --build-usd)
+ USD_FORCE_BUILD=true; shift; continue
+ ;;
--force-all)
PYTHON_FORCE_REBUILD=true
NUMPY_FORCE_REBUILD=true
@@ -695,6 +713,7 @@ while true; do
OIDN_FORCE_REBUILD=true
FFMPEG_FORCE_REBUILD=true
ALEMBIC_FORCE_REBUILD=true
+ USD_FORCE_REBUILD=true
shift; continue
;;
--force-python)
@@ -744,6 +763,9 @@ while true; do
--force-alembic)
ALEMBIC_FORCE_REBUILD=true; shift; continue
;;
+ --force-usd)
+ USD_FORCE_REBUILD=true; shift; continue
+ ;;
--skip-python)
PYTHON_SKIP=true; shift; continue
;;
@@ -789,6 +811,9 @@ while true; do
--skip-alembic)
ALEMBIC_SKIP=true; shift; continue
;;
+ --skip-usd)
+ USD_SKIP=true; shift; continue
+ ;;
--)
# no more arguments to parse
break
@@ -895,6 +920,8 @@ ALEMBIC_SOURCE=( "https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.
# ALEMBIC_SOURCE_REPO_UID="e6c90d4faa32c4550adeaaf3f556dad4b73a92bb"
# ALEMBIC_SOURCE_REPO_BRANCH="master"
+USD_SOURCE=( "https://github.com/PixarAnimationStudios/USD/archive/v${USD_VERSION}.tar.gz" )
+
OPENCOLLADA_USE_REPO=false
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA/archive/v${OPENCOLLADA_VERSION}.tar.gz" )
#~ OPENCOLLADA_SOURCE_REPO=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
@@ -956,7 +983,8 @@ You may also want to build them yourself (optional ones are [between brackets]):
* [OpenCollada $OPENCOLLADA_VERSION] (from $OPENCOLLADA_SOURCE).
* [Embree $EMBREE_VERSION] (from $EMBREE_SOURCE).
* [OpenImageDenoise $OIDN_VERSION] (from $OIDN_SOURCE).
- * [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).\""
+ * [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).
+ * [Universal Scene Description $USD_VERSION] (from $USD_SOURCE).\""
if [ "$DO_SHOW_DEPS" = true ]; then
PRINT ""
@@ -2053,7 +2081,7 @@ compile_OSL() {
fi
if [ -d $INST/oiio ]; then
- cmake_d="$cmake_d -D OPENIMAGEIOHOME=$INST/oiio"
+ cmake_d="$cmake_d -D OPENIMAGEIO_ROOT_DIR=$INST/oiio"
fi
if [ ! -z $LLVM_VERSION_FOUND ]; then
@@ -2477,9 +2505,90 @@ compile_ALEMBIC() {
run_ldconfig "alembic"
}
+#### Build USD ####
+_init_usd() {
+ _src=$SRC/USD-$USD_VERSION
+ _git=false
+ _inst=$INST/usd-$USD_VERSION
+ _inst_shortcut=$INST/usd
+}
+
+clean_USD() {
+ _init_usd
+ _clean
+}
+
+compile_USD() {
+ if [ "$NO_BUILD" = true ]; then
+ WARNING "--no-build enabled, USD will not be compiled!"
+ return
+ fi
+
+ # To be changed each time we make edits that would modify the compiled result!
+ usd_magic=1
+ _init_usd
+
+ # Clean install if needed!
+ magic_compile_check usd-$USD_VERSION $usd_magic
+ if [ $? -eq 1 -o "$USD_FORCE_REBUILD" = true ]; then
+ clean_USD
+ fi
+
+ if [ ! -d $_inst ]; then
+ INFO "Building USD-$USD_VERSION"
+
+ prepare_opt
+
+ if [ ! -d $_src ]; then
+ mkdir -p $SRC
+ download USD_SOURCE[@] "$_src.tar.gz"
+
+ INFO "Unpacking USD-$USD_VERSION"
+ tar -C $SRC -xf $_src.tar.gz
+ patch -d $_src -p1 < $SCRIPT_DIR/patches/usd.diff
+ fi
+
+ cd $_src
+
+ cmake_d="-D CMAKE_INSTALL_PREFIX=$_inst"
+ # For the reasoning behind these options, please see usd.cmake.
+ if [ -d $INST/boost ]; then
+ cmake_d="$cmake_d $cmake_d -D BOOST_ROOT=$INST/boost"
+ fi
+ cmake_d="$cmake_d -DPXR_SET_INTERNAL_NAMESPACE=usdBlender"
+ cmake_d="$cmake_d -DPXR_ENABLE_PYTHON_SUPPORT=OFF"
+ cmake_d="$cmake_d -DPXR_BUILD_IMAGING=OFF"
+ cmake_d="$cmake_d -DPXR_BUILD_TESTS=OFF"
+ cmake_d="$cmake_d -DBUILD_SHARED_LIBS=ON"
+ cmake_d="$cmake_d -DPXR_BUILD_MONOLITHIC=ON"
+ cmake_d="$cmake_d -DPXR_BUILD_USD_TOOLS=OFF"
+ cmake_d="$cmake_d -DCMAKE_DEBUG_POSTFIX=_d"
+
+ cmake $cmake_d ./
+ make -j$THREADS install
+ make clean
+
+ if [ -d $_inst ]; then
+ _create_inst_shortcut
+ else
+ ERROR "USD-$USD_VERSION failed to compile, exiting"
+ exit 1
+ fi
+
+ magic_compile_set usd-$USD_VERSION $usd_magic
+
+ cd $CWD
+ INFO "Done compiling USD-$USD_VERSION!"
+ else
+ INFO "Own USD-$USD_VERSION is up to date, nothing to do!"
+ INFO "If you want to force rebuild of this lib, use the --force-usd option."
+ fi
+
+ run_ldconfig "usd"
+}
+
# ----------------------------------------------------------------------------
# Build OpenCOLLADA
-
_init_opencollada() {
_src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION
_git=true
@@ -3332,6 +3441,15 @@ install_DEB() {
compile_ALEMBIC
fi
+ PRINT ""
+ if [ "$USD_SKIP" = true ]; then
+ WARNING "Skipping USD installation, as requested..."
+ elif [ "$USD_FORCE_BUILD" = true ]; then
+ INFO "Forced USD building, as requested..."
+ compile_USD
+ else
+ compile_USD
+ fi
if [ "$WITH_OPENCOLLADA" = true ]; then
_do_compile_collada=false
@@ -3936,6 +4054,15 @@ install_RPM() {
compile_ALEMBIC
fi
+ PRINT ""
+ if [ "$USD_SKIP" = true ]; then
+ WARNING "Skipping USD installation, as requested..."
+ elif [ "$USD_FORCE_BUILD" = true ]; then
+ INFO "Forced USD building, as requested..."
+ compile_USD
+ else
+ compile_USD
+ fi
if [ "$WITH_OPENCOLLADA" = true ]; then
PRINT ""
@@ -4418,6 +4545,15 @@ install_ARCH() {
compile_ALEMBIC
fi
+ PRINT ""
+ if [ "$USD_SKIP" = true ]; then
+ WARNING "Skipping USD installation, as requested..."
+ elif [ "$USD_FORCE_BUILD" = true ]; then
+ INFO "Forced USD building, as requested..."
+ compile_USD
+ else
+ compile_USD
+ fi
if [ "$WITH_OPENCOLLADA" = true ]; then
PRINT ""
@@ -4785,7 +4921,7 @@ print_info() {
_buildargs="-U *SNDFILE* -U *PYTHON* -U *BOOST* -U *Boost*"
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
- _buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
+ _buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
_1="-D WITH_CODEC_SNDFILE=ON"
PRINT " $_1"
@@ -4942,6 +5078,12 @@ print_info() {
fi
fi
+ if [ "$USD_SKIP" = false ]; then
+ _1="-D WITH_USD=ON"
+ PRINT " $_1"
+ _buildargs="$_buildargs $_1"
+ fi
+
if [ "$NO_SYSTEM_GLEW" = true ]; then
_1="-D WITH_SYSTEM_GLEW=OFF"
PRINT " $_1"
diff --git a/build_files/build_environment/patches/freetype.diff b/build_files/build_environment/patches/freetype.diff
deleted file mode 100644
index cf952234795..00000000000
--- a/build_files/build_environment/patches/freetype.diff
+++ /dev/null
@@ -1,18 +0,0 @@
-diff -NaurBb b/CMakeLists.txt a/CMakeLists.txt
---- b/CMakeLists.txt 2018-05-01 12:45:46 -0600
-+++ a/CMakeLists.txt 2018-08-08 13:03:22 -0600
-@@ -229,9 +229,12 @@
- endif ()
- string(REPLACE "/undef " "#undef "
- FTCONFIG_H "${FTCONFIG_H}")
-- file(WRITE "${PROJECT_BINARY_DIR}/include/freetype/config/ftconfig.h"
-- "${FTCONFIG_H}")
-+else()
-+ file(READ "${PROJECT_SOURCE_DIR}/include/freetype/config/ftconfig.h"
-+ FTCONFIG_H)
- endif ()
-+file(WRITE "${PROJECT_BINARY_DIR}/include/freetype/config/ftconfig.h"
-+ "${FTCONFIG_H}")
-
-
- # Create the options file
diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff
index 56f352febfc..e7f563acaa1 100644
--- a/build_files/build_environment/patches/opencollada.diff
+++ b/build_files/build_environment/patches/opencollada.diff
@@ -3,19 +3,19 @@ index 95abbe2..4f14f30 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -254,11 +254,11 @@ if(USE_STATIC_MSVC_RUNTIME)
- endif()
-
- #adding PCRE
--find_package(PCRE)
-+#find_package(PCRE)
- if (PCRE_FOUND)
- message(STATUS "SUCCESSFUL: PCRE found")
- else () # if pcre not found building its local copy from ./Externals
-- if (WIN32 OR APPLE)
-+ if (1)
- message("WARNING: Native PCRE not found, taking PCRE from ./Externals")
- add_definitions(-DPCRE_STATIC)
- add_subdirectory(${EXTERNAL_LIBRARIES}/pcre)
+ endif()
+
+ #adding PCRE
+-find_package(PCRE)
++#find_package(PCRE)
+ if (PCRE_FOUND)
+ message(STATUS "SUCCESSFUL: PCRE found")
+ else () # if pcre not found building its local copy from ./Externals
+- if (WIN32 OR APPLE)
++ if (1)
+ message("WARNING: Native PCRE not found, taking PCRE from ./Externals")
+ add_definitions(-DPCRE_STATIC)
+ add_subdirectory(${EXTERNAL_LIBRARIES}/pcre)
diff --git a/DAEValidator/library/include/no_warning_begin b/DAEValidator/library/include/no_warning_begin
index 7a69c32..defb315 100644
--- a/DAEValidator/library/include/no_warning_begin
@@ -74,3 +74,14 @@ index 897e4dcf..98a69ff1 100644
#endif
namespace opencollada
+diff -Naur orig/Externals/LibXML/CMakeLists.txt external_opencollada/Externals/LibXML/CMakeLists.txt
+--- orig/Externals/LibXML/CMakeLists.txt 2018-11-26 15:43:10 -0700
++++ external_opencollada/Externals/LibXML/CMakeLists.txt 2020-01-21 14:15:04 -0700
+@@ -9,6 +9,7 @@
+ -DLIBXML_SCHEMAS_ENABLED
+ -DLIBXML_XPATH_ENABLED
+ -DLIBXML_TREE_ENABLED
++ -DLIBXML_STATIC
+ )
+
+ if(USE_STATIC_MSVC_RUNTIME)
diff --git a/build_files/build_environment/patches/openimagedenoise.diff b/build_files/build_environment/patches/openimagedenoise.diff
index 08d7a397a6d..f83b0776c30 100644
--- a/build_files/build_environment/patches/openimagedenoise.diff
+++ b/build_files/build_environment/patches/openimagedenoise.diff
@@ -117,3 +117,15 @@ diff '--ignore-matching-lines=:' -ur '--exclude=*.svn*' -u -r
if(OIDN_STATIC_LIB)
set(OIDN_LIB_TYPE STATIC)
else()
+diff -Naur orig/core/api.cpp external_openimagedenoise/core/api.cpp
+--- orig/core/api.cpp 2019-07-19 08:37:04 -0600
++++ external_openimagedenoise/core/api.cpp 2020-01-21 15:10:56 -0700
+@@ -15,7 +15,7 @@
+ // ======================================================================== //
+
+ #ifdef _WIN32
+-# define OIDN_API extern "C" __declspec(dllexport)
++# define OIDN_API extern "C"
+ #else
+ # define OIDN_API extern "C" __attribute__ ((visibility ("default")))
+ #endif
diff --git a/build_files/build_environment/patches/openimageio_idiff.diff b/build_files/build_environment/patches/openimageio_idiff.diff
deleted file mode 100644
index ae1884f76b5..00000000000
--- a/build_files/build_environment/patches/openimageio_idiff.diff
+++ /dev/null
@@ -1,13 +0,0 @@
---- idiff.cpp 2016-11-18 11:42:01 -0700
-+++ idiff.cpp 2016-11-18 11:41:25 -0700
-@@ -308,8 +308,10 @@
- // printed with three digit exponent. We change this behaviour to fit
- // Linux way
- #ifdef _MSC_VER
-+#if _MSC_VER < 1900
- _set_output_format(_TWO_DIGIT_EXPONENT);
- #endif
-+#endif
- std::streamsize precis = std::cout.precision();
- std::cout << " " << cr.nwarn << " pixels ("
- << std::setprecision(3) << (100.0*cr.nwarn / npels)
diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff
index 36cda06f394..b9b5937ae2b 100644
--- a/build_files/build_environment/patches/osl.diff
+++ b/build_files/build_environment/patches/osl.diff
@@ -1,15 +1,3 @@
-diff -Naur OpenShadingLanguage-Release-1.9.9/src/cmake/flexbison.cmake external_osl/src/cmake/flexbison.cmake
---- OpenShadingLanguage-Release-1.9.9/src/cmake/flexbison.cmake 2018-05-01 16:39:02 -0600
-+++ external_osl/src/cmake/flexbison.cmake 2018-08-23 15:42:27 -0600
-@@ -77,7 +77,7 @@
- DEPENDS ${${compiler_headers}}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
- ADD_CUSTOM_COMMAND ( OUTPUT ${flexoutputcxx}
-- COMMAND ${FLEX_EXECUTABLE} -o ${flexoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${flexsrc}"
-+ COMMAND ${FLEX_EXECUTABLE} ${FLEX_EXTRA_OPTIONS} -o ${flexoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${flexsrc}"
- MAIN_DEPENDENCY ${flexsrc}
- DEPENDS ${${compiler_headers}}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
diff -Naur OpenShadingLanguage-Release-1.9.9/src/cmake/flexbison.cmake.rej external_osl/src/cmake/flexbison.cmake.rej
--- OpenShadingLanguage-Release-1.9.9/src/cmake/flexbison.cmake.rej 1969-12-31 17:00:00 -0700
+++ external_osl/src/cmake/flexbison.cmake.rej 2018-08-24 17:42:11 -0600
@@ -45,18 +33,6 @@ diff -Naur OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h externa
private:
class MemoryManager;
-diff -Naur OpenShadingLanguage-Release-1.9.9/src/include/OSL/oslnoise.h external_osl/src/include/OSL/oslnoise.h
---- OpenShadingLanguage-Release-1.9.9/src/include/OSL/oslnoise.h 2018-05-01 16:39:02 -0600
-+++ external_osl/src/include/OSL/oslnoise.h 2018-08-24 17:42:11 -0600
-@@ -762,7 +762,7 @@
- // packed into a float4. We assume T is float and VECTYPE is float4,
- // but it also works if T is Dual2<float> and VECTYPE is Dual2<float4>.
- template<typename T, typename VECTYPE>
--OIIO_FORCEINLINE T bilerp (VECTYPE abcd, T u, T v) {
-+OIIO_FORCEINLINE T bilerp (VECTYPE& abcd, T u, T v) {
- VECTYPE xx = OIIO::lerp (abcd, OIIO::simd::shuffle<1,1,3,3>(abcd), u);
- return OIIO::simd::extract<0>(OIIO::lerp (xx,OIIO::simd::shuffle<2>(xx), v));
- }
diff -Naur OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp
--- OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp 2018-05-01 16:39:02 -0600
+++ external_osl/src/liboslexec/llvm_util.cpp 2018-08-25 14:04:27 -0600
diff --git a/build_files/cmake/Modules/FindUSD.cmake b/build_files/cmake/Modules/FindUSD.cmake
index f14843c657e..97830af1dd9 100644
--- a/build_files/cmake/Modules/FindUSD.cmake
+++ b/build_files/cmake/Modules/FindUSD.cmake
@@ -42,7 +42,7 @@ FIND_PATH(USD_INCLUDE_DIR
FIND_LIBRARY(USD_LIBRARY
NAMES
- usd_m
+ usd_m usd_ms
HINTS
${_usd_SEARCH_DIRS}
PATH_SUFFIXES
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 2d13476f09a..daf156bc3f2 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -1157,3 +1157,13 @@ macro(blender_precompile_headers target cpp header)
set_source_files_properties(${cpp} PROPERTIES COMPILE_FLAGS "/Yc${header} /Fp${pchfinal}")
endif()
endmacro()
+
+macro(set_and_warn_dependency
+ _dependency _setting _val)
+ # when $_dependency is disabled, forces $_setting = $_val
+ if(NOT ${${_dependency}} AND ${${_setting}})
+ message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'")
+ set(${_setting} ${_val})
+ endif()
+endmacro()
+
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index a4de3876243..b231a2b6fa4 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -398,21 +398,6 @@ if(WITH_TBB)
find_package(TBB)
endif()
-if(NOT WITH_TBB OR NOT TBB_FOUND)
- if(WITH_OPENIMAGEDENOISE)
- message(STATUS "TBB not found, disabling OpenImageDenoise")
- set(WITH_OPENIMAGEDENOISE OFF)
- endif()
- if(WITH_OPENVDB)
- message(STATUS "TBB not found, disabling OpenVDB")
- set(WITH_OPENVDB OFF)
- endif()
- if(WITH_MOD_FLUID)
- message(STATUS "TBB not found, disabling Fluid modifier")
- set(WITH_MOD_FLUID OFF)
- endif()
-endif()
-
# CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags.
if(WITH_OPENMP)
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 2f9f39b46d9..91f836d5265 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -448,17 +448,6 @@ if(WITH_TBB)
find_package_wrapper(TBB)
endif()
-if(NOT WITH_TBB OR NOT TBB_FOUND)
- if(WITH_OPENIMAGEDENOISE)
- message(STATUS "TBB not found, disabling OpenImageDenoise")
- set(WITH_OPENIMAGEDENOISE OFF)
- endif()
- if(WITH_OPENVDB)
- message(STATUS "TBB not found, disabling OpenVDB")
- set(WITH_OPENVDB OFF)
- endif()
-endif()
-
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
if(HAIKU)
list(APPEND PLATFORM_LINKLIBS -lnetwork)
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 04e5848dcfe..653b3a9f508 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -570,19 +570,6 @@ if(WITH_TBB)
if(WITH_TBB_MALLOC_PROXY)
add_definitions(-DWITH_TBB_MALLOC)
endif()
-else()
- if(WITH_OPENIMAGEDENOISE)
- message(STATUS "TBB disabled, also disabling OpenImageDenoise")
- set(WITH_OPENIMAGEDENOISE OFF)
- endif()
- if(WITH_OPENVDB)
- message(STATUS "TBB disabled, also disabling OpenVDB")
- set(WITH_OPENVDB OFF)
- endif()
- if(WITH_MOD_FLUID)
- message(STATUS "TBB disabled, disabling Fluid modifier")
- set(WITH_MOD_FLUID OFF)
- endif()
endif()
# used in many places so include globally, like OpenGL
@@ -674,6 +661,7 @@ if(WITH_USD)
set(USD_INCLUDE_DIRS ${LIBDIR}/usd/include)
set(USD_RELEASE_LIB ${LIBDIR}/usd/lib/libusd_m.lib)
set(USD_DEBUG_LIB ${LIBDIR}/usd/lib/libusd_m_d.lib)
+ set(USD_LIBRARY_DIR ${LIBDIR}/usd/lib/usd)
set(USD_LIBRARIES
debug ${USD_DEBUG_LIB}
optimized ${USD_RELEASE_LIB}
diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd
index 7cb0a4df689..3c1194011cd 100644
--- a/build_files/windows/configure_msbuild.cmd
+++ b/build_files/windows/configure_msbuild.cmd
@@ -59,21 +59,17 @@ if "%MUST_CONFIGURE%"=="1" (
exit /b 1
)
)
-
-echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd
+echo echo off > %BUILD_DIR%\rebuild.cmd
+echo if "%%VSCMD_VER%%" == "" ^( >> %BUILD_DIR%\rebuild.cmd
+echo call "%VCVARS%" %BUILD_ARCH% >> %BUILD_DIR%\rebuild.cmd
+echo ^) >> %BUILD_DIR%\rebuild.cmd
echo "%CMAKE%" . >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
echo msbuild ^
- %BUILD_DIR%\Blender.sln ^
- /target:build ^
+ %BUILD_DIR%\INSTALL.vcxproj ^
/property:Configuration=%BUILD_TYPE% ^
/maxcpucount:2 ^
/verbosity:minimal ^
/p:platform=%MSBUILD_PLATFORM% ^
/flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd
-echo msbuild ^
- %BUILD_DIR%\INSTALL.vcxproj ^
- /property:Configuration=%BUILD_TYPE% ^
- /verbosity:minimal ^
- /p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd \ No newline at end of file
diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd
index 8f766e855a6..1650e43cda9 100644
--- a/build_files/windows/configure_ninja.cmd
+++ b/build_files/windows/configure_ninja.cmd
@@ -80,7 +80,10 @@ if "%MUST_CONFIGURE%"=="1" (
)
)
-echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd
+echo echo off > %BUILD_DIR%\rebuild.cmd
+echo if "%%VSCMD_VER%%" == "" ^( >> %BUILD_DIR%\rebuild.cmd
+echo call "%VCVARS%" %BUILD_ARCH% >> %BUILD_DIR%\rebuild.cmd
+echo ^) >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
echo ninja install >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd \ No newline at end of file
diff --git a/doc/python_api/examples/bpy.app.handlers.2.py b/doc/python_api/examples/bpy.app.handlers.2.py
new file mode 100644
index 00000000000..aaaedeabecb
--- /dev/null
+++ b/doc/python_api/examples/bpy.app.handlers.2.py
@@ -0,0 +1,23 @@
+"""
+Note on Altering Data
++++++++++++++++++++++
+
+Altering data from handlers should be done carefully. While rendering the
+``frame_change_pre`` and ``frame_change_post`` handlers are called from one
+thread and the viewport updates from a different thread. If the handler changes
+data that is accessed by the viewport, this can cause a crash of Blender. In
+such cases, lock the interface (Render → Lock Interface or
+:data:`bpy.types.RenderSettings.use_lock_interface`) before starting a render.
+
+Below is an example of a mesh that is altered from a handler:
+"""
+
+def frame_change_pre(scene):
+ # A triangle that shifts in the z direction
+ zshift = scene.frame_current * 0.1
+ vertices = [(-1, -1, zshift), (1, -1, zshift), (0, 1, zshift)]
+ triangles = [(0, 1, 2)]
+
+ object = bpy.data.objects["The Object"]
+ object.data.clear_geometry()
+ object.data.from_pydata(vertices, [], triangles)
diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst
index 75aeb765f53..f4de6b955e5 100644
--- a/doc/python_api/rst/info_quickstart.rst
+++ b/doc/python_api/rst/info_quickstart.rst
@@ -228,13 +228,12 @@ Note that the context is read-only.
These values cannot be modified directly,
though they may be changed by running API functions or by using the data API.
-So ``bpy.context.object = obj`` will raise an error.
-
-But ``bpy.context.scene.objects.active = obj`` will work as expected.
+So ``bpy.context.active_object = obj`` will raise an error.
+But ``bpy.context.view_layer.objects.active = obj`` works as expected.
The context attributes change depending on where they are accessed.
-The 3D view has different context members than the console,
+The 3D Viewport has different context members than the Python Console,
so take care when accessing context attributes that the user state is known.
See :mod:`bpy.context` API reference.
diff --git a/doc/python_api/sphinx_doc_update.py b/doc/python_api/sphinx_doc_update.py
index 78bfd3c85b8..d3f42b1d26f 100755
--- a/doc/python_api/sphinx_doc_update.py
+++ b/doc/python_api/sphinx_doc_update.py
@@ -27,7 +27,7 @@ You'll need to specify your user login and password, obviously.
Example usage:
- ./sphinx_doc_update.py --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo
+ ./sphinx_doc_update.py --jobs 16 --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo
"""
@@ -82,6 +82,10 @@ def argparse_create():
"--password", dest="password",
metavar='PASSWORD', type=str, required=True,
help=("Password to login on rsync server"))
+ parser.add_argument(
+ "--jobs", dest="jobs_nr",
+ metavar='NR', type=int, required=False, default=1,
+ help="Number of sphinx building jobs to launch in parallel")
return parser
@@ -141,7 +145,7 @@ def main():
# IV) Build doc.
curr_dir = os.getcwd()
os.chdir(tmp_dir)
- sphinx_cmd = ("sphinx-build", "-b", "html", "sphinx-in", "sphinx-out")
+ sphinx_cmd = ("sphinx-build", "-j", str(args.jobs_nr), "-b", "html", "sphinx-in", "sphinx-out")
subprocess.run(sphinx_cmd)
shutil.rmtree(os.path.join("sphinx-out", ".doctrees"))
os.chdir(curr_dir)
diff --git a/extern/glew/CMakeLists.txt b/extern/glew/CMakeLists.txt
index 18ca88e6fec..59f13eb73c7 100644
--- a/extern/glew/CMakeLists.txt
+++ b/extern/glew/CMakeLists.txt
@@ -25,6 +25,16 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
)
endif()
+# MSVC's inliner is not having a happy time with glewIsSupported
+# causing this to be one of the most expensive things to build
+# in blender. Optimize for size rather than speed sidesteps this
+# problem, more details at
+# https://developercommunity.visualstudio.com/content/problem/732941/slow-compilation-of-glewc-for-visual-studio-2019-x.html
+
+if(MSVC)
+ add_c_flag("/Os")
+endif()
+
set(INC
include
)
diff --git a/extern/mantaflow/preprocessed/fileio/iogrids.cpp b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
index 2f6cdaa6209..2b8ee905f99 100644
--- a/extern/mantaflow/preprocessed/fileio/iogrids.cpp
+++ b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
@@ -954,6 +954,79 @@ template<class T> void readGridVDB(const string &name, Grid<T> *grid)
1);
}
+template<> void writeGridVDB(const string &name, Grid<int> *grid)
+{
+ debMsg("Writing int grid " << grid->getName() << " to vdb file " << name, 1);
+
+ // Create an empty int32-point grid with background value 0.
+ openvdb::initialize();
+ openvdb::Int32Grid::Ptr gridVDB = openvdb::Int32Grid::create();
+ gridVDB->setTransform(
+ openvdb::math::Transform::createLinearTransform(1. / grid->getSizeX())); // voxel size
+
+ // Get an accessor for coordinate-based access to voxels.
+ openvdb::Int32Grid::Accessor accessor = gridVDB->getAccessor();
+
+ gridVDB->setGridClass(openvdb::GRID_UNKNOWN);
+
+ // Name the grid "density".
+ gridVDB->setName(grid->getName());
+
+ openvdb::io::File file(name);
+
+ FOR_IJK(*grid)
+ {
+ openvdb::Coord xyz(i, j, k);
+ accessor.setValue(xyz, (*grid)(i, j, k));
+ }
+
+ // Add the grid pointer to a container.
+ openvdb::GridPtrVec gridsVDB;
+ gridsVDB.push_back(gridVDB);
+
+ // Write out the contents of the container.
+ file.write(gridsVDB);
+ file.close();
+}
+
+template<> void readGridVDB(const string &name, Grid<int> *grid)
+{
+ debMsg("Reading int grid " << grid->getName() << " from vdb file " << name, 1);
+
+ openvdb::initialize();
+ openvdb::io::File file(name);
+ file.open();
+
+ openvdb::GridBase::Ptr baseGrid;
+ for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
+ ++nameIter) {
+# ifndef BLENDER
+ // Read in only the grid we are interested in.
+ if (nameIter.gridName() == grid->getName()) {
+ baseGrid = file.readGrid(nameIter.gridName());
+ }
+ else {
+ debMsg("skipping grid " << nameIter.gridName(), 1);
+ }
+# else
+ // For Blender, skip name check and pick first grid from loop
+ baseGrid = file.readGrid(nameIter.gridName());
+ break;
+# endif
+ }
+ file.close();
+ openvdb::Int32Grid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::Int32Grid>(baseGrid);
+
+ openvdb::Int32Grid::Accessor accessor = gridVDB->getAccessor();
+
+ FOR_IJK(*grid)
+ {
+ openvdb::Coord xyz(i, j, k);
+ int v = accessor.getValue(xyz);
+ (*grid)(i, j, k) = v;
+ }
+}
+
template<> void writeGridVDB(const string &name, Grid<Real> *grid)
{
debMsg("Writing real grid " << grid->getName() << " to vdb file " << name, 1);
diff --git a/extern/mantaflow/preprocessed/fileio/ioparticles.cpp b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
index 432cbc9f100..a6cc7583327 100644
--- a/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
+++ b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
@@ -310,6 +310,8 @@ template<class T> void readPdataUni(const std::string &name, ParticleDataImpl<T>
UniPartHeader head;
assertMsg(gzread(gzf, &head, sizeof(UniPartHeader)) == sizeof(UniPartHeader),
"can't read file, no header present");
+ pdata->resize(head.dim);
+
assertMsg(head.dim == pdata->size(), "pdata size doesn't match");
# if FLOATINGPOINT_PRECISION != 1
ParticleDataImpl<T> temp(pdata->getParent());
diff --git a/extern/mantaflow/preprocessed/fluidsolver.cpp b/extern/mantaflow/preprocessed/fluidsolver.cpp
index 814d5444b15..8c48e60760b 100644
--- a/extern/mantaflow/preprocessed/fluidsolver.cpp
+++ b/extern/mantaflow/preprocessed/fluidsolver.cpp
@@ -136,9 +136,9 @@ FluidSolver::FluidSolver(Vec3i gridsize, int dim, int fourthDim)
mDtMin(1.),
mDtMax(1.),
mFrameLength(1.),
+ mTimePerFrame(0.),
mGridSize(gridsize),
mDim(dim),
- mTimePerFrame(0.),
mLockDt(false),
mFourthDim(fourthDim)
{
diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h
index 6d3abd1e88e..943840958f6 100644
--- a/extern/mantaflow/preprocessed/gitinfo.h
+++ b/extern/mantaflow/preprocessed/gitinfo.h
@@ -1,3 +1,3 @@
-#define MANTA_GIT_VERSION "commit 3f5c7989fd82920f0c509844a06e97dd1069191c"
+#define MANTA_GIT_VERSION "commit abfff159b5ea8cee93d858f4b8be2a308b58b51d"
diff --git a/extern/mantaflow/preprocessed/plugin/flip.cpp b/extern/mantaflow/preprocessed/plugin/flip.cpp
index f6d082900b5..4dfeff1d0ac 100644
--- a/extern/mantaflow/preprocessed/plugin/flip.cpp
+++ b/extern/mantaflow/preprocessed/plugin/flip.cpp
@@ -1407,7 +1407,6 @@ struct correctLevelset : public KernelBase {
{
if (rAcc(i, j, k) <= VECTOR_EPSILON)
return; // outside nothing happens
- Real x = pAcc(i, j, k).x;
// create jacobian of pAcc via central differences
Matrix3x3f jacobian = Matrix3x3f(0.5 * (pAcc(i + 1, j, k).x - pAcc(i - 1, j, k).x),
diff --git a/extern/mantaflow/preprocessed/plugin/fluidguiding.cpp b/extern/mantaflow/preprocessed/plugin/fluidguiding.cpp
index 13383581123..18a5a37771f 100644
--- a/extern/mantaflow/preprocessed/plugin/fluidguiding.cpp
+++ b/extern/mantaflow/preprocessed/plugin/fluidguiding.cpp
@@ -381,7 +381,6 @@ void getSpiralVelocity(const FlagGrid &flags,
nz = flags.getSizeZ();
Real midX = 0.5 * (Real)(nx - 1);
Real midY = 0.5 * (Real)(ny - 1);
- Real midZ = 0.5 * (Real)(nz - 1);
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
for (int k = 0; k < nz; k++) {
diff --git a/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp b/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp
index 281e12ef04b..18582d57e64 100644
--- a/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp
+++ b/extern/mantaflow/preprocessed/plugin/secondaryparticles.cpp
@@ -1099,7 +1099,7 @@ void PbRegister_flipSampleSecondaryParticles()
// evaluates cubic spline with radius h and distance l in dim dimensions
Real cubicSpline(const Real h, const Real l, const int dim)
{
- const Real h2 = square(h), h3 = h2 * h, h4 = h3 * h, h5 = h4 * h;
+ const Real h2 = square(h), h3 = h2 * h;
const Real c[] = {
Real(2e0 / (3e0 * h)), Real(10e0 / (7e0 * M_PI * h2)), Real(1e0 / (M_PI * h3))};
const Real q = l / h;
@@ -1175,9 +1175,6 @@ struct knFlipUpdateSecondaryParticlesLinear : public KernelBase {
}
Vec3i gridpos = toVec3i(pts_sec[idx].pos);
- int i = gridpos.x;
- int j = gridpos.y;
- int k = gridpos.z;
// spray particle
if (neighborRatio(gridpos) < c_s) {
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 1dbe8a30ff2..2540786a014 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -326,6 +326,10 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node
fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str());
continue;
}
+ else if (node_type->create == NULL) {
+ fprintf(stderr, "Can't create abstract node type \"%s\".\n", node_type->name.c_str());
+ continue;
+ }
snode = (ShaderNode *)node_type->create(node_type);
}
@@ -376,11 +380,11 @@ static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm)
{
/* create mesh */
Mesh *mesh = new Mesh();
- scene->meshes.push_back(mesh);
+ scene->geometry.push_back(mesh);
/* create object*/
Object *object = new Object();
- object->mesh = mesh;
+ object->geometry = mesh;
object->tfm = tfm;
scene->objects.push_back(object);
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 0888eeb78bb..d9a2ebf8571 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -18,6 +18,9 @@ set(INC_SYS
set(SRC
blender_camera.cpp
blender_device.cpp
+ blender_image.cpp
+ blender_geometry.cpp
+ blender_light.cpp
blender_mesh.cpp
blender_object.cpp
blender_object_cull.cpp
@@ -30,9 +33,11 @@ set(SRC
blender_sync.cpp
blender_texture.cpp
blender_viewport.cpp
+ blender_volume.cpp
CCL_api.h
blender_device.h
+ blender_id_map.h
blender_object_cull.h
blender_sync.h
blender_session.h
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 78db1d5c832..affd5685337 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -17,6 +17,7 @@
#include "render/attribute.h"
#include "render/camera.h"
#include "render/curves.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/object.h"
#include "render/scene.h"
@@ -107,12 +108,12 @@ static void InterpolateKeySegments(
}
static bool ObtainCacheParticleData(
- Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background)
+ Geometry *geom, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background)
{
int curvenum = 0;
int keyno = 0;
- if (!(mesh && b_mesh && b_ob && CData))
+ if (!(geom && b_mesh && b_ob && CData))
return false;
Transform tfm = get_transform(b_ob->matrix_world());
@@ -128,7 +129,7 @@ static bool ObtainCacheParticleData(
if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
(b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int shader = clamp(b_part.material() - 1, 0, mesh->used_shaders.size() - 1);
+ int shader = clamp(b_part.material() - 1, 0, geom->used_shaders.size() - 1);
int display_step = background ? b_part.render_step() : b_part.display_step();
int totparts = b_psys.particles.length();
int totchild = background ? b_psys.child_particles.length() :
@@ -202,14 +203,14 @@ static bool ObtainCacheParticleData(
return true;
}
-static bool ObtainCacheParticleUV(Mesh *mesh,
+static bool ObtainCacheParticleUV(Geometry *geom,
BL::Mesh *b_mesh,
BL::Object *b_ob,
ParticleCurveData *CData,
bool background,
int uv_num)
{
- if (!(mesh && b_mesh && b_ob && CData))
+ if (!(geom && b_mesh && b_ob && CData))
return false;
CData->curve_uv.clear();
@@ -265,14 +266,14 @@ static bool ObtainCacheParticleUV(Mesh *mesh,
return true;
}
-static bool ObtainCacheParticleVcol(Mesh *mesh,
+static bool ObtainCacheParticleVcol(Geometry *geom,
BL::Mesh *b_mesh,
BL::Object *b_ob,
ParticleCurveData *CData,
bool background,
int vcol_num)
{
- if (!(mesh && b_mesh && b_ob && CData))
+ if (!(geom && b_mesh && b_ob && CData))
return false;
CData->curve_vcol.clear();
@@ -594,21 +595,55 @@ static void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, in
/* texture coords still needed */
}
-static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
+static void export_hair_motion_validate_attribute(Hair *hair,
+ int motion_step,
+ int num_motion_keys,
+ bool have_motion)
+{
+ Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ const int num_keys = hair->curve_keys.size();
+
+ if (num_motion_keys != num_keys || !have_motion) {
+ /* No motion or hair "topology" changed, remove attributes again. */
+ if (num_motion_keys != num_keys) {
+ VLOG(1) << "Hair topology changed, removing attribute.";
+ }
+ else {
+ VLOG(1) << "No motion, removing attribute.";
+ }
+ hair->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+ else if (motion_step > 0) {
+ VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step;
+
+ /* Motion, fill up previous steps that we might have skipped because
+ * they had no motion, but we need them anyway now. */
+ for (int step = 0; step < motion_step; step++) {
+ float4 *mP = attr_mP->data_float4() + step * num_keys;
+
+ for (int key = 0; key < num_keys; key++) {
+ mP[key] = float3_to_float4(hair->curve_keys[key]);
+ mP[key].w = hair->curve_radius[key];
+ }
+ }
+ }
+}
+
+static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CData)
{
int num_keys = 0;
int num_curves = 0;
- if (mesh->num_curves())
+ if (hair->num_curves())
return;
Attribute *attr_intercept = NULL;
Attribute *attr_random = NULL;
- if (mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
- attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
- if (mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
- attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM);
+ if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
+ attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT);
+ if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
+ attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM);
/* compute and reserve size of arrays */
for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
@@ -621,10 +656,10 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
}
if (num_curves > 0) {
- VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
+ VLOG(1) << "Exporting curve segments for mesh " << hair->name;
}
- mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);
+ hair->reserve_curves(hair->num_curves() + num_curves, hair->curve_keys.size() + num_keys);
num_keys = 0;
num_curves = 0;
@@ -649,7 +684,7 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) {
radius = 0.0f;
}
- mesh->add_curve_key(ickey_loc, radius);
+ hair->add_curve_key(ickey_loc, radius);
if (attr_intercept)
attr_intercept->add(time);
@@ -660,16 +695,16 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
attr_random->add(hash_uint2_to_float(num_curves, 0));
}
- mesh->add_curve(num_keys, CData->psys_shader[sys]);
+ hair->add_curve(num_keys, CData->psys_shader[sys]);
num_keys += num_curve_keys;
num_curves++;
}
}
/* check allocation */
- if ((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
+ if ((hair->curve_keys.size() != num_keys) || (hair->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";
- mesh->clear();
+ hair->clear();
}
}
@@ -713,24 +748,24 @@ static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int cu
return lerp(mP, mP2, remainder);
}
-static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step)
+static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int motion_step)
{
- VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name << ", motion step "
+ VLOG(1) << "Exporting curve motion segments for hair " << hair->name << ", motion step "
<< motion_step;
/* find attribute */
- Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
bool new_attribute = false;
/* add new attribute if it doesn't exist already */
if (!attr_mP) {
VLOG(1) << "Creating new motion vertex position attribute";
- attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ attr_mP = hair->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
new_attribute = true;
}
/* export motion vectors for curve keys */
- size_t numkeys = mesh->curve_keys.size();
+ size_t numkeys = hair->curve_keys.size();
float4 *mP = attr_mP->data_float4() + motion_step * numkeys;
bool have_motion = false;
int i = 0;
@@ -741,24 +776,24 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int
curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
curve++) {
/* Curve lengths may not match! Curves can be clipped. */
- int curve_key_end = (num_curves + 1 < (int)mesh->curve_first_key.size() ?
- mesh->curve_first_key[num_curves + 1] :
- (int)mesh->curve_keys.size());
- const int num_center_curve_keys = curve_key_end - mesh->curve_first_key[num_curves];
+ int curve_key_end = (num_curves + 1 < (int)hair->curve_first_key.size() ?
+ hair->curve_first_key[num_curves + 1] :
+ (int)hair->curve_keys.size());
+ const int num_center_curve_keys = curve_key_end - hair->curve_first_key[num_curves];
const int is_num_keys_different = CData->curve_keynum[curve] - num_center_curve_keys;
if (!is_num_keys_different) {
for (int curvekey = CData->curve_firstkey[curve];
curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
curvekey++) {
- if (i < mesh->curve_keys.size()) {
+ if (i < hair->curve_keys.size()) {
mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey);
if (!have_motion) {
/* unlike mesh coordinates, these tend to be slightly different
* between frames due to particle transforms into/out of object
* space, so we use an epsilon to detect actual changes */
- float4 curve_key = float3_to_float4(mesh->curve_keys[i]);
- curve_key.w = mesh->curve_radius[i];
+ float4 curve_key = float3_to_float4(hair->curve_keys[i]);
+ curve_key.w = hair->curve_radius[i];
if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f)
have_motion = true;
}
@@ -784,40 +819,15 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int
/* in case of new attribute, we verify if there really was any motion */
if (new_attribute) {
- if (i != numkeys || !have_motion) {
- /* No motion or hair "topology" changed, remove attributes again. */
- if (i != numkeys) {
- VLOG(1) << "Hair topology changed, removing attribute.";
- }
- else {
- VLOG(1) << "No motion, removing attribute.";
- }
- mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
- }
- else if (motion_step > 0) {
- VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step;
- /* motion, fill up previous steps that we might have skipped because
- * they had no motion, but we need them anyway now */
- for (int step = 0; step < motion_step; step++) {
- float4 *mP = attr_mP->data_float4() + step * numkeys;
-
- for (int key = 0; key < numkeys; key++) {
- mP[key] = float3_to_float4(mesh->curve_keys[key]);
- mP[key].w = mesh->curve_radius[key];
- }
- }
- }
+ export_hair_motion_validate_attribute(hair, motion_step, i, have_motion);
}
}
-static void ExportCurveTriangleUV(ParticleCurveData *CData,
- int vert_offset,
- int resol,
- float2 *uvdata)
+static void ExportCurveTriangleUV(ParticleCurveData *CData, int resol, float2 *uvdata)
{
if (uvdata == NULL)
return;
- int vertexindex = vert_offset;
+ int vertexindex = 0;
for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
for (int curve = CData->psys_firstcurve[sys];
@@ -845,15 +855,12 @@ static void ExportCurveTriangleUV(ParticleCurveData *CData,
}
}
-static void ExportCurveTriangleVcol(ParticleCurveData *CData,
- int vert_offset,
- int resol,
- uchar4 *cdata)
+static void ExportCurveTriangleVcol(ParticleCurveData *CData, int resol, uchar4 *cdata)
{
if (cdata == NULL)
return;
- int vertexindex = vert_offset;
+ int vertexindex = 0;
for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
for (int curve = CData->psys_firstcurve[sys];
@@ -952,7 +959,7 @@ void BlenderSync::sync_curve_settings()
if ((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) &&
(b_psys->settings().type() == BL::ParticleSettings::type_HAIR)) {
BL::ID key = BKE_object_is_modified(*b_ob) ? *b_ob : b_ob->data();
- mesh_map.set_recalc(key);
+ geometry_map.set_recalc(key);
object_map.set_recalc(*b_ob);
}
}
@@ -964,42 +971,51 @@ void BlenderSync::sync_curve_settings()
curve_system_manager->tag_update(scene);
}
-void BlenderSync::sync_curves(
- Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step)
+bool BlenderSync::object_has_particle_hair(BL::Object b_ob)
{
- if (!motion) {
- /* Clear stored curve data */
- mesh->curve_keys.clear();
- mesh->curve_radius.clear();
- mesh->curve_first_key.clear();
- mesh->curve_shader.clear();
- mesh->curve_attributes.clear();
+ /* Test if the object has a particle modifier with hair. */
+ BL::Object::modifiers_iterator b_mod;
+ for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
+ (preview ? b_mod->show_viewport() : b_mod->show_render())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
+ (b_part.type() == BL::ParticleSettings::type_HAIR)) {
+ return true;
+ }
+ }
}
- /* obtain general settings */
- const bool use_curves = scene->curve_system_manager->use_curves;
+ return false;
+}
+
+/* Old particle hair. */
+void BlenderSync::sync_particle_hair(
+ Geometry *geom, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step)
+{
+ Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL;
+ Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL;
- if (!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT && b_ob.mode() != b_ob.mode_EDIT)) {
- if (!motion)
- mesh->compute_bounds();
+ /* obtain general settings */
+ if (b_ob.mode() == b_ob.mode_PARTICLE_EDIT || b_ob.mode() == b_ob.mode_EDIT) {
return;
}
- const int primitive = scene->curve_system_manager->primitive;
const int triangle_method = scene->curve_system_manager->triangle_method;
const int resolution = scene->curve_system_manager->resolution;
- const size_t vert_num = mesh->verts.size();
- const size_t tri_num = mesh->num_triangles();
int used_res = 1;
/* extract particle hair data - should be combined with connecting to mesh later*/
ParticleCurveData CData;
- ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
+ ObtainCacheParticleData(geom, &b_mesh, &b_ob, &CData, !preview);
/* add hair geometry to mesh */
- if (primitive == CURVE_TRIANGLES) {
+ if (mesh) {
if (triangle_method == CURVE_CAMERA_TRIANGLES) {
/* obtain camera parameters */
float3 RotCam;
@@ -1023,31 +1039,31 @@ void BlenderSync::sync_curves(
}
else {
if (motion)
- ExportCurveSegmentsMotion(mesh, &CData, motion_step);
+ ExportCurveSegmentsMotion(hair, &CData, motion_step);
else
- ExportCurveSegments(scene, mesh, &CData);
+ ExportCurveSegments(scene, hair, &CData);
}
/* generated coordinates from first key. we should ideally get this from
* blender to handle deforming objects */
if (!motion) {
- if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+ if (geom->need_attribute(scene, ATTR_STD_GENERATED)) {
float3 loc, size;
mesh_texture_space(b_mesh, loc, size);
- if (primitive == CURVE_TRIANGLES) {
+ if (mesh) {
Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED);
float3 *generated = attr_generated->data_float3();
- for (size_t i = vert_num; i < mesh->verts.size(); i++)
+ for (size_t i = 0; i < mesh->verts.size(); i++)
generated[i] = mesh->verts[i] * size - loc;
}
else {
- Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
+ Attribute *attr_generated = hair->attributes.add(ATTR_STD_GENERATED);
float3 *generated = attr_generated->data_float3();
- for (size_t i = 0; i < mesh->num_curves(); i++) {
- float3 co = mesh->curve_keys[mesh->get_curve(i).first_key];
+ for (size_t i = 0; i < hair->num_curves(); i++) {
+ float3 co = hair->curve_keys[hair->get_curve(i).first_key];
generated[i] = co * size - loc;
}
}
@@ -1060,21 +1076,21 @@ void BlenderSync::sync_curves(
int vcol_num = 0;
for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
- if (!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ if (!geom->need_attribute(scene, ustring(l->name().c_str())))
continue;
- ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
+ ObtainCacheParticleVcol(geom, &b_mesh, &b_ob, &CData, !preview, vcol_num);
- if (primitive == CURVE_TRIANGLES) {
+ if (mesh) {
Attribute *attr_vcol = mesh->attributes.add(
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
uchar4 *cdata = attr_vcol->data_uchar4();
- ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
+ ExportCurveTriangleVcol(&CData, used_res, cdata);
}
else {
- Attribute *attr_vcol = mesh->curve_attributes.add(
+ Attribute *attr_vcol = hair->attributes.add(
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
float3 *fdata = attr_vcol->data_float3();
@@ -1102,12 +1118,12 @@ void BlenderSync::sync_curves(
ustring name = ustring(l->name().c_str());
/* UV map */
- if (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
+ if (geom->need_attribute(scene, name) || geom->need_attribute(scene, std)) {
Attribute *attr_uv;
- ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);
+ ObtainCacheParticleUV(geom, &b_mesh, &b_ob, &CData, !preview, uv_num);
- if (primitive == CURVE_TRIANGLES) {
+ if (mesh) {
if (active_render)
attr_uv = mesh->attributes.add(std, name);
else
@@ -1115,13 +1131,13 @@ void BlenderSync::sync_curves(
float2 *uv = attr_uv->data_float2();
- ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
+ ExportCurveTriangleUV(&CData, used_res, uv);
}
else {
if (active_render)
- attr_uv = mesh->curve_attributes.add(std, name);
+ attr_uv = hair->attributes.add(std, name);
else
- attr_uv = mesh->curve_attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
+ attr_uv = hair->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
float2 *uv = attr_uv->data_float2();
@@ -1136,8 +1152,77 @@ void BlenderSync::sync_curves(
}
}
}
+}
+
+void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom)
+{
+ Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL;
+ Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL;
+
+ /* Compares curve_keys rather than strands in order to handle quick hair
+ * adjustments in dynamic BVH - other methods could probably do this better. */
+ array<float3> oldcurve_keys;
+ array<float> oldcurve_radius;
+ array<int> oldtriangles;
+ if (hair) {
+ oldcurve_keys.steal_data(hair->curve_keys);
+ oldcurve_radius.steal_data(hair->curve_radius);
+ }
+ else {
+ oldtriangles.steal_data(mesh->triangles);
+ }
+
+ if (view_layer.use_hair && scene->curve_system_manager->use_curves) {
+ /* Particle hair. */
+ bool need_undeformed = geom->need_attribute(scene, ATTR_STD_GENERATED);
+ BL::Mesh b_mesh = object_to_mesh(
+ b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
+
+ if (b_mesh) {
+ sync_particle_hair(geom, b_mesh, b_ob, false);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
+ }
+ }
+
+ /* tag update */
+ const bool rebuild = (hair && ((oldcurve_keys != hair->curve_keys) ||
+ (oldcurve_radius != hair->curve_radius))) ||
+ (mesh && (oldtriangles != mesh->triangles));
+
+ geom->tag_update(scene, rebuild);
+}
- mesh->compute_bounds();
+void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
+ BL::Object b_ob,
+ Geometry *geom,
+ int motion_step)
+{
+ Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL;
+ Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL;
+
+ /* Skip if nothing exported. */
+ if ((hair && hair->num_keys() == 0) || (mesh && mesh->verts.size() == 0)) {
+ return;
+ }
+
+ /* Export deformed coordinates. */
+ if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
+ /* Particle hair. */
+ BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
+ if (b_mesh) {
+ sync_particle_hair(geom, b_mesh, b_ob, true, motion_step);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
+ return;
+ }
+ }
+
+ /* No deformation on this frame, copy coordinates if other frames did have it. */
+ if (hair) {
+ hair->copy_center_to_motion_step(motion_step);
+ }
+ else {
+ mesh->copy_center_to_motion_step(motion_step);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
new file mode 100644
index 00000000000..8b803835b62
--- /dev/null
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -0,0 +1,176 @@
+
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/curves.h"
+#include "render/hair.h"
+#include "render/mesh.h"
+#include "render/object.h"
+
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
+
+CCL_NAMESPACE_BEGIN
+
+Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
+ bool object_updated,
+ bool use_particle_hair)
+{
+ /* Test if we can instance or if the object is modified. */
+ BL::ID b_ob_data = b_ob.data();
+ BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
+ GeometryKey key(b_key_id.ptr.data, use_particle_hair);
+ BL::Material material_override = view_layer.material_override;
+ Shader *default_shader = scene->default_surface;
+ Geometry::Type geom_type = (use_particle_hair &&
+ (scene->curve_system_manager->primitive != CURVE_TRIANGLES)) ?
+ Geometry::HAIR :
+ Geometry::MESH;
+
+ /* Find shader indices. */
+ vector<Shader *> used_shaders;
+
+ BL::Object::material_slots_iterator slot;
+ for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
+ if (material_override) {
+ find_shader(material_override, used_shaders, default_shader);
+ }
+ else {
+ BL::ID b_material(slot->material());
+ find_shader(b_material, used_shaders, default_shader);
+ }
+ }
+
+ if (used_shaders.size() == 0) {
+ if (material_override)
+ find_shader(material_override, used_shaders, default_shader);
+ else
+ used_shaders.push_back(default_shader);
+ }
+
+ /* Test if we need to sync. */
+ Geometry *geom = geometry_map.find(key);
+ bool sync = true;
+ if (geom == NULL) {
+ /* Add new geometry if it did not exist yet. */
+ if (geom_type == Geometry::HAIR) {
+ geom = new Hair();
+ }
+ else {
+ geom = new Mesh();
+ }
+ geometry_map.add(key, geom);
+ }
+ else {
+ /* Test if we need to update existing geometry. */
+ sync = geometry_map.update(geom, b_key_id);
+ }
+
+ if (!sync) {
+ /* If transform was applied to geometry, need full update. */
+ if (object_updated && geom->transform_applied) {
+ ;
+ }
+ /* Test if shaders changed, these can be object level so geometry
+ * does not get tagged for recalc. */
+ else if (geom->used_shaders != used_shaders) {
+ ;
+ }
+ else {
+ /* Even if not tagged for recalc, we may need to sync anyway
+ * because the shader needs different geometry attributes. */
+ bool attribute_recalc = false;
+
+ foreach (Shader *shader, geom->used_shaders) {
+ if (shader->need_update_geometry) {
+ attribute_recalc = true;
+ }
+ }
+
+ if (!attribute_recalc) {
+ return geom;
+ }
+ }
+ }
+
+ /* Ensure we only sync instanced geometry once. */
+ if (geometry_synced.find(geom) != geometry_synced.end()) {
+ return geom;
+ }
+
+ progress.set_sync_status("Synchronizing object", b_ob.name());
+
+ geometry_synced.insert(geom);
+
+ geom->clear();
+ geom->used_shaders = used_shaders;
+ geom->name = ustring(b_ob_data.name().c_str());
+
+ if (use_particle_hair) {
+ sync_hair(b_depsgraph, b_ob, geom);
+ }
+ else if (object_fluid_gas_domain_find(b_ob)) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_volume(b_ob, mesh);
+ }
+ else {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_mesh(b_depsgraph, b_ob, mesh);
+ }
+
+ return geom;
+}
+
+void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
+ BL::Object &b_ob,
+ Object *object,
+ float motion_time,
+ bool use_particle_hair)
+{
+ /* Ensure we only sync instanced geometry once. */
+ Geometry *geom = object->geometry;
+
+ if (geometry_motion_synced.find(geom) != geometry_motion_synced.end())
+ return;
+
+ geometry_motion_synced.insert(geom);
+
+ /* Ensure we only motion sync geometry that also had geometry synced, to avoid
+ * unnecessary work and to ensure that its attributes were clear. */
+ if (geometry_synced.find(geom) == geometry_synced.end())
+ return;
+
+ /* Find time matching motion step required by geometry. */
+ int motion_step = geom->motion_step(motion_time);
+ if (motion_step < 0) {
+ return;
+ }
+
+ if (use_particle_hair) {
+ sync_hair_motion(b_depsgraph, b_ob, geom, motion_step);
+ }
+ else if (object_fluid_gas_domain_find(b_ob)) {
+ /* No volume motion blur support yet. */
+ }
+ else {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_id_map.h b/intern/cycles/blender/blender_id_map.h
new file mode 100644
index 00000000000..3bc42e349ae
--- /dev/null
+++ b/intern/cycles/blender/blender_id_map.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BLENDER_ID_MAP_H__
+#define __BLENDER_ID_MAP_H__
+
+#include <string.h>
+
+#include "util/util_map.h"
+#include "util/util_set.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* ID Map
+ *
+ * Utility class to map between Blender datablocks and Cycles data structures,
+ * and keep track of recalc tags from the dependency graph. */
+
+template<typename K, typename T> class id_map {
+ public:
+ id_map(vector<T *> *scene_data_)
+ {
+ scene_data = scene_data_;
+ }
+
+ T *find(const BL::ID &id)
+ {
+ return find(id.ptr.owner_id);
+ }
+
+ T *find(const K &key)
+ {
+ if (b_map.find(key) != b_map.end()) {
+ T *data = b_map[key];
+ return data;
+ }
+
+ return NULL;
+ }
+
+ void set_recalc(const BL::ID &id)
+ {
+ b_recalc.insert(id.ptr.data);
+ }
+
+ void set_recalc(void *id_ptr)
+ {
+ b_recalc.insert(id_ptr);
+ }
+
+ bool has_recalc()
+ {
+ return !(b_recalc.empty());
+ }
+
+ void pre_sync()
+ {
+ used_set.clear();
+ }
+
+ /* Add new data. */
+ void add(const K &key, T *data)
+ {
+ assert(find(key) == NULL);
+ scene_data->push_back(data);
+ b_map[key] = data;
+ used(data);
+ }
+
+ /* Update existing data. */
+ bool update(T *data, const BL::ID &id)
+ {
+ return update(data, id, id);
+ }
+ bool update(T *data, const BL::ID &id, const BL::ID &parent)
+ {
+ bool recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
+ if (parent.ptr.data && parent.ptr.data != id.ptr.data) {
+ recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
+ }
+ used(data);
+ return recalc;
+ }
+
+ /* Combined add and update as needed. */
+ bool add_or_update(T **r_data, const BL::ID &id)
+ {
+ return add_or_update(r_data, id, id, id.ptr.owner_id);
+ }
+ bool add_or_update(T **r_data, const BL::ID &id, const K &key)
+ {
+ return add_or_update(r_data, id, id, key);
+ }
+ bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
+ {
+ T *data = find(key);
+ bool recalc;
+
+ if (!data) {
+ /* Add data if it didn't exist yet. */
+ data = new T();
+ add(key, data);
+ recalc = true;
+ }
+ else {
+ /* check if updated needed. */
+ recalc = update(data, id, parent);
+ }
+
+ *r_data = data;
+ return recalc;
+ }
+
+ /* Combined add or update for convenience. */
+
+ bool is_used(const K &key)
+ {
+ T *data = find(key);
+ return (data) ? used_set.find(data) != used_set.end() : false;
+ }
+
+ void used(T *data)
+ {
+ /* tag data as still in use */
+ used_set.insert(data);
+ }
+
+ void set_default(T *data)
+ {
+ b_map[NULL] = data;
+ }
+
+ bool post_sync(bool do_delete = true)
+ {
+ /* remove unused data */
+ vector<T *> new_scene_data;
+ typename vector<T *>::iterator it;
+ bool deleted = false;
+
+ for (it = scene_data->begin(); it != scene_data->end(); it++) {
+ T *data = *it;
+
+ if (do_delete && used_set.find(data) == used_set.end()) {
+ delete data;
+ deleted = true;
+ }
+ else
+ new_scene_data.push_back(data);
+ }
+
+ *scene_data = new_scene_data;
+
+ /* update mapping */
+ map<K, T *> new_map;
+ typedef pair<const K, T *> TMapPair;
+ typename map<K, T *>::iterator jt;
+
+ for (jt = b_map.begin(); jt != b_map.end(); jt++) {
+ TMapPair &pair = *jt;
+
+ if (used_set.find(pair.second) != used_set.end())
+ new_map[pair.first] = pair.second;
+ }
+
+ used_set.clear();
+ b_recalc.clear();
+ b_map = new_map;
+
+ return deleted;
+ }
+
+ const map<K, T *> &key_to_scene_data()
+ {
+ return b_map;
+ }
+
+ protected:
+ vector<T *> *scene_data;
+ map<K, T *> b_map;
+ set<T *> used_set;
+ set<void *> b_recalc;
+};
+
+/* Object Key
+ *
+ * To uniquely identify instances, we use the parent, object and persistent instance ID.
+ * We also export separate object for a mesh and its particle hair. */
+
+enum { OBJECT_PERSISTENT_ID_SIZE = 16 };
+
+struct ObjectKey {
+ void *parent;
+ int id[OBJECT_PERSISTENT_ID_SIZE];
+ void *ob;
+ bool use_particle_hair;
+
+ ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_)
+ : parent(parent_), ob(ob_), use_particle_hair(use_particle_hair_)
+ {
+ if (id_)
+ memcpy(id, id_, sizeof(id));
+ else
+ memset(id, 0, sizeof(id));
+ }
+
+ bool operator<(const ObjectKey &k) const
+ {
+ if (ob < k.ob) {
+ return true;
+ }
+ else if (ob == k.ob) {
+ if (parent < k.parent) {
+ return true;
+ }
+ else if (parent == k.parent) {
+ if (use_particle_hair < k.use_particle_hair) {
+ return true;
+ }
+ else if (use_particle_hair == k.use_particle_hair) {
+ return memcmp(id, k.id, sizeof(id)) < 0;
+ }
+ }
+ }
+
+ return false;
+ }
+};
+
+/* Geometry Key
+ *
+ * We export separate geometry for a mesh and its particle hair, so key needs to
+ * distinguish between them. */
+
+struct GeometryKey {
+ void *id;
+ bool use_particle_hair;
+
+ GeometryKey(void *id, bool use_particle_hair) : id(id), use_particle_hair(use_particle_hair)
+ {
+ }
+
+ bool operator<(const GeometryKey &k) const
+ {
+ if (id < k.id) {
+ return true;
+ }
+ else if (id == k.id) {
+ if (use_particle_hair < k.use_particle_hair) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+/* Particle System Key */
+
+struct ParticleSystemKey {
+ void *ob;
+ int id[OBJECT_PERSISTENT_ID_SIZE];
+
+ ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
+ {
+ if (id_)
+ memcpy(id, id_, sizeof(id));
+ else
+ memset(id, 0, sizeof(id));
+ }
+
+ bool operator<(const ParticleSystemKey &k) const
+ {
+ /* first id is particle index, we don't compare that */
+ if (ob < k.ob)
+ return true;
+ else if (ob == k.ob)
+ return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
+
+ return false;
+ }
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __BLENDER_ID_MAP_H__ */
diff --git a/intern/cycles/blender/blender_image.cpp b/intern/cycles/blender/blender_image.cpp
new file mode 100644
index 00000000000..55ce6a295d1
--- /dev/null
+++ b/intern/cycles/blender/blender_image.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/image.h"
+
+#include "blender/blender_sync.h"
+#include "blender/blender_session.h"
+#include "blender/blender_util.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* builtin image file name is actually an image datablock name with
+ * absolute sequence frame number concatenated via '@' character
+ *
+ * this function splits frame from builtin name
+ */
+int BlenderSession::builtin_image_frame(const string &builtin_name)
+{
+ int last = builtin_name.find_last_of('@');
+ return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
+}
+
+void BlenderSession::builtin_image_info(const string &builtin_name,
+ void *builtin_data,
+ ImageMetaData &metadata)
+{
+ /* empty image */
+ metadata.width = 1;
+ metadata.height = 1;
+
+ if (!builtin_data)
+ return;
+
+ /* recover ID pointer */
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID *)builtin_data, &ptr);
+ BL::ID b_id(ptr);
+
+ if (b_id.is_a(&RNA_Image)) {
+ /* image data */
+ BL::Image b_image(b_id);
+
+ metadata.builtin_free_cache = !b_image.has_data();
+ metadata.is_float = b_image.is_float();
+ metadata.width = b_image.size()[0];
+ metadata.height = b_image.size()[1];
+ metadata.depth = 1;
+ metadata.channels = b_image.channels();
+
+ if (metadata.is_float) {
+ /* Float images are already converted on the Blender side,
+ * no need to do anything in Cycles. */
+ metadata.colorspace = u_colorspace_raw;
+ }
+ }
+ else if (b_id.is_a(&RNA_Object)) {
+ /* smoke volume data */
+ BL::Object b_ob(b_id);
+ BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
+
+ metadata.is_float = true;
+ metadata.depth = 1;
+ metadata.channels = 1;
+
+ if (!b_domain)
+ return;
+
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
+ metadata.channels = 1;
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
+ metadata.channels = 4;
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY))
+ metadata.channels = 3;
+ else
+ return;
+
+ int3 resolution = get_int3(b_domain.domain_resolution());
+ int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1;
+
+ /* Velocity and heat data is always low-resolution. */
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+ amplify = 1;
+ }
+
+ metadata.width = resolution.x * amplify;
+ metadata.height = resolution.y * amplify;
+ metadata.depth = resolution.z * amplify;
+ }
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ metadata.channels = 4;
+ metadata.width = b_point_density_node.resolution();
+ metadata.height = metadata.width;
+ metadata.depth = metadata.width;
+ metadata.is_float = true;
+ }
+ }
+}
+
+bool BlenderSession::builtin_image_pixels(const string &builtin_name,
+ void *builtin_data,
+ int tile,
+ unsigned char *pixels,
+ const size_t pixels_size,
+ const bool associate_alpha,
+ const bool free_cache)
+{
+ if (!builtin_data) {
+ return false;
+ }
+
+ const int frame = builtin_image_frame(builtin_name);
+
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID *)builtin_data, &ptr);
+ BL::Image b_image(ptr);
+
+ const int width = b_image.size()[0];
+ const int height = b_image.size()[1];
+ const int channels = b_image.channels();
+
+ unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile);
+ const size_t num_pixels = ((size_t)width) * height;
+
+ if (image_pixels && num_pixels * channels == pixels_size) {
+ memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
+ }
+ else {
+ if (channels == 1) {
+ memset(pixels, 0, pixels_size * sizeof(unsigned char));
+ }
+ else {
+ const size_t num_pixels_safe = pixels_size / channels;
+ unsigned char *cp = pixels;
+ for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
+ cp[0] = 255;
+ cp[1] = 0;
+ cp[2] = 255;
+ if (channels == 4) {
+ cp[3] = 255;
+ }
+ }
+ }
+ }
+
+ if (image_pixels) {
+ MEM_freeN(image_pixels);
+ }
+
+ /* Free image buffers to save memory during render. */
+ if (free_cache) {
+ b_image.buffers_free();
+ }
+
+ if (associate_alpha) {
+ /* Premultiply, byte images are always straight for Blender. */
+ unsigned char *cp = pixels;
+ for (size_t i = 0; i < num_pixels; i++, cp += channels) {
+ cp[0] = (cp[0] * cp[3]) >> 8;
+ cp[1] = (cp[1] * cp[3]) >> 8;
+ cp[2] = (cp[2] * cp[3]) >> 8;
+ }
+ }
+ return true;
+}
+
+bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
+ void *builtin_data,
+ int tile,
+ float *pixels,
+ const size_t pixels_size,
+ const bool,
+ const bool free_cache)
+{
+ if (!builtin_data) {
+ return false;
+ }
+
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID *)builtin_data, &ptr);
+ BL::ID b_id(ptr);
+
+ if (b_id.is_a(&RNA_Image)) {
+ /* image data */
+ BL::Image b_image(b_id);
+ int frame = builtin_image_frame(builtin_name);
+
+ const int width = b_image.size()[0];
+ const int height = b_image.size()[1];
+ const int channels = b_image.channels();
+
+ float *image_pixels;
+ image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile);
+ const size_t num_pixels = ((size_t)width) * height;
+
+ if (image_pixels && num_pixels * channels == pixels_size) {
+ memcpy(pixels, image_pixels, pixels_size * sizeof(float));
+ }
+ else {
+ if (channels == 1) {
+ memset(pixels, 0, num_pixels * sizeof(float));
+ }
+ else {
+ const size_t num_pixels_safe = pixels_size / channels;
+ float *fp = pixels;
+ for (int i = 0; i < num_pixels_safe; i++, fp += channels) {
+ fp[0] = 1.0f;
+ fp[1] = 0.0f;
+ fp[2] = 1.0f;
+ if (channels == 4) {
+ fp[3] = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (image_pixels) {
+ MEM_freeN(image_pixels);
+ }
+
+ /* Free image buffers to save memory during render. */
+ if (free_cache) {
+ b_image.buffers_free();
+ }
+
+ return true;
+ }
+ else if (b_id.is_a(&RNA_Object)) {
+ /* smoke volume data */
+ BL::Object b_ob(b_id);
+ BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
+
+ if (!b_domain) {
+ return false;
+ }
+#ifdef WITH_FLUID
+ int3 resolution = get_int3(b_domain.domain_resolution());
+ int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1;
+
+ /* Velocity and heat data is always low-resolution. */
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+ amplify = 1;
+ }
+
+ const int width = resolution.x * amplify;
+ const int height = resolution.y * amplify;
+ const int depth = resolution.z * amplify;
+ const size_t num_pixels = ((size_t)width) * height * depth;
+
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
+ FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ FluidDomainSettings_density_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
+ /* this is in range 0..1, and interpreted by the OpenGL smoke viewer
+ * as 1500..3000 K with the first part faded to zero density */
+ FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ FluidDomainSettings_flame_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
+ /* the RGB is "premultiplied" by density for better interpolation results */
+ FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels * 4) {
+ FluidDomainSettings_color_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
+ FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels * 3) {
+ FluidDomainSettings_velocity_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+ FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ FluidDomainSettings_heat_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
+ FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ FluidDomainSettings_temperature_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else {
+ fprintf(
+ stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str());
+ pixels[0] = 0.0f;
+ return false;
+ }
+#endif
+ fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
+ }
+ else {
+ /* We originally were passing view_layer here but in reality we need a
+ * a depsgraph to pass to the RE_point_density_minmax() function.
+ */
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ int length;
+ b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels);
+ }
+ }
+
+ return false;
+}
+
+void BlenderSession::builtin_images_load()
+{
+ /* Force builtin images to be loaded along with Blender data sync. This
+ * is needed because we may be reading from depsgraph evaluated data which
+ * can be freed by Blender before Cycles reads it.
+ *
+ * TODO: the assumption that no further access to builtin image data will
+ * happen is really weak, and likely to break in the future. We should find
+ * a better solution to hand over the data directly to the image manager
+ * instead of through callbacks whose timing is difficult to control. */
+ ImageManager *manager = session->scene->image_manager;
+ Device *device = session->device;
+ manager->device_load_builtin(device, session->scene, session->progress);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
new file mode 100644
index 00000000000..6f95821e31e
--- /dev/null
+++ b/intern/cycles/blender/blender_light.cpp
@@ -0,0 +1,212 @@
+
+
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/light.h"
+
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
+
+#include "util/util_hash.h"
+
+CCL_NAMESPACE_BEGIN
+
+void BlenderSync::sync_light(BL::Object &b_parent,
+ int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
+ int random_id,
+ Transform &tfm,
+ bool *use_portal)
+{
+ /* test if we need to sync */
+ Light *light;
+ ObjectKey key(b_parent, persistent_id, b_ob_instance, false);
+ BL::Light b_light(b_ob.data());
+
+ /* Update if either object or light data changed. */
+ if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
+ Shader *shader;
+ if (!shader_map.add_or_update(&shader, b_light)) {
+ if (light->is_portal)
+ *use_portal = true;
+ return;
+ }
+ }
+
+ /* type */
+ switch (b_light.type()) {
+ case BL::Light::type_POINT: {
+ BL::PointLight b_point_light(b_light);
+ light->size = b_point_light.shadow_soft_size();
+ light->type = LIGHT_POINT;
+ break;
+ }
+ case BL::Light::type_SPOT: {
+ BL::SpotLight b_spot_light(b_light);
+ light->size = b_spot_light.shadow_soft_size();
+ light->type = LIGHT_SPOT;
+ light->spot_angle = b_spot_light.spot_size();
+ light->spot_smooth = b_spot_light.spot_blend();
+ break;
+ }
+ /* Hemi were removed from 2.8 */
+ // case BL::Light::type_HEMI: {
+ // light->type = LIGHT_DISTANT;
+ // light->size = 0.0f;
+ // break;
+ // }
+ case BL::Light::type_SUN: {
+ BL::SunLight b_sun_light(b_light);
+ light->angle = b_sun_light.angle();
+ light->type = LIGHT_DISTANT;
+ break;
+ }
+ case BL::Light::type_AREA: {
+ BL::AreaLight b_area_light(b_light);
+ light->size = 1.0f;
+ light->axisu = transform_get_column(&tfm, 0);
+ light->axisv = transform_get_column(&tfm, 1);
+ light->sizeu = b_area_light.size();
+ switch (b_area_light.shape()) {
+ case BL::AreaLight::shape_SQUARE:
+ light->sizev = light->sizeu;
+ light->round = false;
+ break;
+ case BL::AreaLight::shape_RECTANGLE:
+ light->sizev = b_area_light.size_y();
+ light->round = false;
+ break;
+ case BL::AreaLight::shape_DISK:
+ light->sizev = light->sizeu;
+ light->round = true;
+ break;
+ case BL::AreaLight::shape_ELLIPSE:
+ light->sizev = b_area_light.size_y();
+ light->round = true;
+ break;
+ }
+ light->type = LIGHT_AREA;
+ break;
+ }
+ }
+
+ /* strength */
+ light->strength = get_float3(b_light.color());
+ light->strength *= BL::PointLight(b_light).energy();
+
+ /* location and (inverted!) direction */
+ light->co = transform_get_column(&tfm, 3);
+ light->dir = -transform_get_column(&tfm, 2);
+ light->tfm = tfm;
+
+ /* shader */
+ vector<Shader *> used_shaders;
+ find_shader(b_light, used_shaders, scene->default_light);
+ light->shader = used_shaders[0];
+
+ /* shadow */
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
+ light->cast_shadow = get_boolean(clight, "cast_shadow");
+ light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
+
+ int samples = get_int(clight, "samples");
+ if (get_boolean(cscene, "use_square_samples"))
+ light->samples = samples * samples;
+ else
+ light->samples = samples;
+
+ light->max_bounces = get_int(clight, "max_bounces");
+
+ if (b_ob != b_ob_instance) {
+ light->random_id = random_id;
+ }
+ else {
+ light->random_id = hash_uint2(hash_string(b_ob.name().c_str()), 0);
+ }
+
+ if (light->type == LIGHT_AREA)
+ light->is_portal = get_boolean(clight, "is_portal");
+ else
+ light->is_portal = false;
+
+ if (light->is_portal)
+ *use_portal = true;
+
+ /* visibility */
+ uint visibility = object_ray_visibility(b_ob);
+ light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
+ light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
+ light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
+ light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;
+
+ /* tag */
+ light->tag_update(scene);
+}
+
+void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
+{
+ BL::World b_world = b_scene.world();
+
+ if (b_world) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
+
+ enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM };
+ int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC);
+ bool sample_as_light = (sampling_method != SAMPLING_NONE);
+
+ if (sample_as_light || use_portal) {
+ /* test if we need to sync */
+ Light *light;
+ ObjectKey key(b_world, 0, b_world, false);
+
+ if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc ||
+ b_world.ptr.data != world_map) {
+ light->type = LIGHT_BACKGROUND;
+ if (sampling_method == SAMPLING_MANUAL) {
+ light->map_resolution = get_int(cworld, "sample_map_resolution");
+ }
+ else {
+ light->map_resolution = 0;
+ }
+ light->shader = scene->default_background;
+ light->use_mis = sample_as_light;
+ light->max_bounces = get_int(cworld, "max_bounces");
+
+ /* force enable light again when world is resynced */
+ light->is_enabled = true;
+
+ int samples = get_int(cworld, "samples");
+ if (get_boolean(cscene, "use_square_samples"))
+ light->samples = samples * samples;
+ else
+ light->samples = samples;
+
+ light->tag_update(scene);
+ light_map.set_recalc(b_world);
+ }
+ }
+ }
+
+ world_map = b_world.ptr.data;
+ world_recalc = false;
+ viewport_parameters = BlenderViewportParameters(b_v3d);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index b18f9a37948..332c26161dc 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -278,54 +278,6 @@ static void mikk_compute_tangents(
genTangSpaceDefault(&context);
}
-/* Create Volume Attribute */
-
-static void create_mesh_volume_attribute(
- BL::Object &b_ob, Mesh *mesh, ImageManager *image_manager, AttributeStandard std, float frame)
-{
- BL::FluidDomainSettings b_domain = object_fluid_domain_find(b_ob);
-
- if (!b_domain)
- return;
-
- mesh->volume_isovalue = b_domain.clipping();
-
- Attribute *attr = mesh->attributes.add(std);
- VoxelAttribute *volume_data = attr->data_voxel();
- ImageMetaData metadata;
- bool animated = false;
-
- volume_data->manager = image_manager;
- volume_data->slot = image_manager->add_image(Attribute::standard_name(std),
- b_ob.ptr.data,
- animated,
- frame,
- INTERPOLATION_LINEAR,
- EXTENSION_CLIP,
- IMAGE_ALPHA_AUTO,
- u_colorspace_raw,
- metadata);
-}
-
-static void create_mesh_volume_attributes(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame)
-{
- /* for smoke volume rendering */
- if (mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY, frame);
- if (mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR, frame);
- if (mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame);
- if (mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame);
- if (mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE))
- create_mesh_volume_attribute(
- b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame);
- if (mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY))
- create_mesh_volume_attribute(
- b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
-}
-
/* Create vertex color attributes. */
static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
{
@@ -859,9 +811,9 @@ static void create_mesh(Scene *scene,
attr_create_uv_map(scene, mesh, b_mesh);
}
- /* for volume objects, create a matrix to transform from object space to
+ /* For volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can
- * probably only be done well with a volume grid mapping of coordinates */
+ * probably only be done well with a volume grid mapping of coordinates. */
if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
Transform *tfm = attr->data_transform();
@@ -930,7 +882,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
if (scene->need_motion() == Scene::MOTION_NONE)
return;
- BL::FluidDomainSettings b_fluid_domain = object_fluid_domain_find(b_ob);
+ BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob);
if (!b_fluid_domain)
return;
@@ -963,82 +915,8 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
}
}
-Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph,
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
- bool object_updated,
- bool show_self,
- bool show_particles)
+void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh)
{
- /* test if we can instance or if the object is modified */
- BL::ID b_ob_data = b_ob.data();
- BL::ID key = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
- BL::Material material_override = view_layer.material_override;
-
- /* find shader indices */
- vector<Shader *> used_shaders;
-
- BL::Object::material_slots_iterator slot;
- for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
- if (material_override) {
- find_shader(material_override, used_shaders, scene->default_surface);
- }
- else {
- BL::ID b_material(slot->material());
- find_shader(b_material, used_shaders, scene->default_surface);
- }
- }
-
- if (used_shaders.size() == 0) {
- if (material_override)
- find_shader(material_override, used_shaders, scene->default_surface);
- else
- used_shaders.push_back(scene->default_surface);
- }
-
- /* test if we need to sync */
- int requested_geometry_flags = Mesh::GEOMETRY_NONE;
- if (view_layer.use_surfaces) {
- requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES;
- }
- if (view_layer.use_hair) {
- requested_geometry_flags |= Mesh::GEOMETRY_CURVES;
- }
- Mesh *mesh;
-
- if (!mesh_map.sync(&mesh, key)) {
- /* if transform was applied to mesh, need full update */
- if (object_updated && mesh->transform_applied)
- ;
- /* test if shaders changed, these can be object level so mesh
- * does not get tagged for recalc */
- else if (mesh->used_shaders != used_shaders)
- ;
- else if (requested_geometry_flags != mesh->geometry_flags)
- ;
- else {
- /* even if not tagged for recalc, we may need to sync anyway
- * because the shader needs different mesh attributes */
- bool attribute_recalc = false;
-
- foreach (Shader *shader, mesh->used_shaders)
- if (shader->need_update_mesh)
- attribute_recalc = true;
-
- if (!attribute_recalc)
- return mesh;
- }
- }
-
- /* ensure we only sync instanced meshes once */
- if (mesh_synced.find(mesh) != mesh_synced.end())
- return mesh;
-
- progress.set_sync_status("Synchronizing object", b_ob.name());
-
- mesh_synced.insert(mesh);
-
- /* create derived mesh */
array<int> oldtriangles;
array<Mesh::SubdFace> oldsubd_faces;
array<int> oldsubd_face_corners;
@@ -1046,150 +924,64 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph,
oldsubd_faces.steal_data(mesh->subd_faces);
oldsubd_face_corners.steal_data(mesh->subd_face_corners);
- /* compares curve_keys rather than strands in order to handle quick hair
- * adjustments in dynamic BVH - other methods could probably do this better*/
- array<float3> oldcurve_keys;
- array<float> oldcurve_radius;
- oldcurve_keys.steal_data(mesh->curve_keys);
- oldcurve_radius.steal_data(mesh->curve_radius);
-
- /* ensure bvh rebuild (instead of refit) if has_voxel_attributes() changed */
- bool oldhas_voxel_attributes = mesh->has_voxel_attributes();
-
- mesh->clear();
- mesh->used_shaders = used_shaders;
- mesh->name = ustring(b_ob_data.name().c_str());
+ mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
- if (requested_geometry_flags != Mesh::GEOMETRY_NONE) {
+ if (view_layer.use_surfaces) {
/* Adaptive subdivision setup. Not for baking since that requires
* exact mapping to the Blender mesh. */
- if (scene->bake_manager->get_baking()) {
- mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
- }
- else {
+ if (!scene->bake_manager->get_baking()) {
mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
}
/* For some reason, meshes do not need this... */
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
-
BL::Mesh b_mesh = object_to_mesh(
b_data, b_ob, b_depsgraph, need_undeformed, mesh->subdivision_type);
if (b_mesh) {
/* Sync mesh itself. */
- if (view_layer.use_surfaces && show_self) {
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
- create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, dicing_rate, max_subdivisions);
- else
- create_mesh(scene, mesh, b_mesh, used_shaders, false);
-
- create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current());
- }
-
- /* Sync hair curves. */
- if (view_layer.use_hair && show_particles &&
- mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
- sync_curves(mesh, b_mesh, b_ob, false);
- }
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
+ create_subd_mesh(
+ scene, mesh, b_ob, b_mesh, mesh->used_shaders, dicing_rate, max_subdivisions);
+ else
+ create_mesh(scene, mesh, b_mesh, mesh->used_shaders, false);
free_object_to_mesh(b_data, b_ob, b_mesh);
}
}
- mesh->geometry_flags = requested_geometry_flags;
/* mesh fluid motion mantaflow */
sync_mesh_fluid_motion(b_ob, scene, mesh);
/* tag update */
bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) ||
- (oldsubd_face_corners != mesh->subd_face_corners) ||
- (oldcurve_keys != mesh->curve_keys) || (oldcurve_radius != mesh->curve_radius) ||
- (oldhas_voxel_attributes != mesh->has_voxel_attributes());
+ (oldsubd_face_corners != mesh->subd_face_corners);
mesh->tag_update(scene, rebuild);
-
- return mesh;
}
-void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph,
- BL::Object &b_ob,
- Object *object,
- float motion_time)
+void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
+ BL::Object b_ob,
+ Mesh *mesh,
+ int motion_step)
{
- /* ensure we only sync instanced meshes once */
- Mesh *mesh = object->mesh;
-
- if (mesh_motion_synced.find(mesh) != mesh_motion_synced.end())
- return;
-
- mesh_motion_synced.insert(mesh);
-
- /* ensure we only motion sync meshes that also had mesh synced, to avoid
- * unnecessary work and to ensure that its attributes were clear */
- if (mesh_synced.find(mesh) == mesh_synced.end())
- return;
-
- /* Find time matching motion step required by mesh. */
- int motion_step = mesh->motion_step(motion_time);
- if (motion_step < 0) {
+ /* Skip if no vertices were exported. */
+ size_t numverts = mesh->verts.size();
+ if (numverts == 0) {
return;
}
- /* skip empty meshes */
- const size_t numverts = mesh->verts.size();
- const size_t numkeys = mesh->curve_keys.size();
-
- if (!numverts && !numkeys)
- return;
-
- /* skip objects without deforming modifiers. this is not totally reliable,
- * would need a more extensive check to see which objects are animated */
+ /* Skip objects without deforming modifiers. this is not totally reliable,
+ * would need a more extensive check to see which objects are animated. */
BL::Mesh b_mesh(PointerRNA_NULL);
-
- /* manta motion is exported immediate with mesh, skip here */
- BL::FluidDomainSettings b_fluid_domain = object_fluid_domain_find(b_ob);
- if (b_fluid_domain)
- return;
-
if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
/* get derived mesh */
b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
}
- if (!b_mesh) {
- /* if we have no motion blur on this frame, but on other frames, copy */
- if (numverts) {
- /* triangles */
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if (attr_mP) {
- Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
- Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
- float3 *P = &mesh->verts[0];
- float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
-
- memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts);
- if (attr_mN)
- memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts);
- }
- }
-
- if (numkeys) {
- /* curves */
- Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if (attr_mP) {
- float3 *keys = &mesh->curve_keys[0];
- memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys);
- }
- }
-
- return;
- }
-
/* TODO(sergey): Perform preliminary check for number of vertices. */
- if (numverts) {
+ if (b_mesh) {
+ /* Export deformed coordinates. */
/* Find attributes. */
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
@@ -1254,14 +1046,13 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph,
}
}
}
- }
- /* hair motion */
- if (numkeys)
- sync_curves(mesh, b_mesh, b_ob, true, motion_step);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
+ return;
+ }
- /* free derived mesh */
- free_object_to_mesh(b_data, b_ob, b_mesh);
+ /* No deformation on this frame, copy coordinates if other frames did have it. */
+ mesh->copy_center_to_motion_step(motion_step);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 6981412bb88..2b1d1eff7e5 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -88,215 +88,13 @@ bool BlenderSync::object_is_light(BL::Object &b_ob)
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
}
-static uint object_ray_visibility(BL::Object &b_ob)
-{
- PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
- uint flag = 0;
-
- flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0;
- flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0;
- flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0;
- flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0;
- flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0;
- flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0;
-
- return flag;
-}
-
-/* Light */
-
-void BlenderSync::sync_light(BL::Object &b_parent,
- int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
- int random_id,
- Transform &tfm,
- bool *use_portal)
-{
- /* test if we need to sync */
- Light *light;
- ObjectKey key(b_parent, persistent_id, b_ob_instance);
- BL::Light b_light(b_ob.data());
-
- /* Update if either object or light data changed. */
- if (!light_map.sync(&light, b_ob, b_parent, key)) {
- Shader *shader;
- if (!shader_map.sync(&shader, b_light)) {
- if (light->is_portal)
- *use_portal = true;
- return;
- }
- }
-
- /* type */
- switch (b_light.type()) {
- case BL::Light::type_POINT: {
- BL::PointLight b_point_light(b_light);
- light->size = b_point_light.shadow_soft_size();
- light->type = LIGHT_POINT;
- break;
- }
- case BL::Light::type_SPOT: {
- BL::SpotLight b_spot_light(b_light);
- light->size = b_spot_light.shadow_soft_size();
- light->type = LIGHT_SPOT;
- light->spot_angle = b_spot_light.spot_size();
- light->spot_smooth = b_spot_light.spot_blend();
- break;
- }
- /* Hemi were removed from 2.8 */
- // case BL::Light::type_HEMI: {
- // light->type = LIGHT_DISTANT;
- // light->size = 0.0f;
- // break;
- // }
- case BL::Light::type_SUN: {
- BL::SunLight b_sun_light(b_light);
- light->angle = b_sun_light.angle();
- light->type = LIGHT_DISTANT;
- break;
- }
- case BL::Light::type_AREA: {
- BL::AreaLight b_area_light(b_light);
- light->size = 1.0f;
- light->axisu = transform_get_column(&tfm, 0);
- light->axisv = transform_get_column(&tfm, 1);
- light->sizeu = b_area_light.size();
- switch (b_area_light.shape()) {
- case BL::AreaLight::shape_SQUARE:
- light->sizev = light->sizeu;
- light->round = false;
- break;
- case BL::AreaLight::shape_RECTANGLE:
- light->sizev = b_area_light.size_y();
- light->round = false;
- break;
- case BL::AreaLight::shape_DISK:
- light->sizev = light->sizeu;
- light->round = true;
- break;
- case BL::AreaLight::shape_ELLIPSE:
- light->sizev = b_area_light.size_y();
- light->round = true;
- break;
- }
- light->type = LIGHT_AREA;
- break;
- }
- }
-
- /* strength */
- light->strength = get_float3(b_light.color());
- light->strength *= BL::PointLight(b_light).energy();
-
- /* location and (inverted!) direction */
- light->co = transform_get_column(&tfm, 3);
- light->dir = -transform_get_column(&tfm, 2);
- light->tfm = tfm;
-
- /* shader */
- vector<Shader *> used_shaders;
- find_shader(b_light, used_shaders, scene->default_light);
- light->shader = used_shaders[0];
-
- /* shadow */
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
- light->cast_shadow = get_boolean(clight, "cast_shadow");
- light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
-
- int samples = get_int(clight, "samples");
- if (get_boolean(cscene, "use_square_samples"))
- light->samples = samples * samples;
- else
- light->samples = samples;
-
- light->max_bounces = get_int(clight, "max_bounces");
-
- if (b_ob != b_ob_instance) {
- light->random_id = random_id;
- }
- else {
- light->random_id = hash_uint2(hash_string(b_ob.name().c_str()), 0);
- }
-
- if (light->type == LIGHT_AREA)
- light->is_portal = get_boolean(clight, "is_portal");
- else
- light->is_portal = false;
-
- if (light->is_portal)
- *use_portal = true;
-
- /* visibility */
- uint visibility = object_ray_visibility(b_ob);
- light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
- light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
- light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
- light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;
-
- /* tag */
- light->tag_update(scene);
-}
-
-void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
-{
- BL::World b_world = b_scene.world();
-
- if (b_world) {
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
-
- enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM };
- int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC);
- bool sample_as_light = (sampling_method != SAMPLING_NONE);
-
- if (sample_as_light || use_portal) {
- /* test if we need to sync */
- Light *light;
- ObjectKey key(b_world, 0, b_world);
-
- if (light_map.sync(&light, b_world, b_world, key) || world_recalc ||
- b_world.ptr.data != world_map) {
- light->type = LIGHT_BACKGROUND;
- if (sampling_method == SAMPLING_MANUAL) {
- light->map_resolution = get_int(cworld, "sample_map_resolution");
- }
- else {
- light->map_resolution = 0;
- }
- light->shader = scene->default_background;
- light->use_mis = sample_as_light;
- light->max_bounces = get_int(cworld, "max_bounces");
-
- /* force enable light again when world is resynced */
- light->is_enabled = true;
-
- int samples = get_int(cworld, "samples");
- if (get_boolean(cscene, "use_square_samples"))
- light->samples = samples * samples;
- else
- light->samples = samples;
-
- light->tag_update(scene);
- light_map.set_recalc(b_world);
- }
- }
- }
-
- world_map = b_world.ptr.data;
- world_recalc = false;
- viewport_parameters = BlenderViewportParameters(b_v3d);
-}
-
/* Object */
Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
BL::ViewLayer &b_view_layer,
BL::DepsgraphObjectInstance &b_instance,
float motion_time,
- bool show_self,
- bool show_particles,
+ bool use_particle_hair,
bool show_lights,
BlenderObjectCulling &culling,
bool *use_portal)
@@ -378,7 +176,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
}
/* key to lookup object */
- ObjectKey key(b_parent, persistent_id, b_ob_instance);
+ ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair);
Object *object;
/* motion vector case */
@@ -393,8 +191,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
}
/* mesh deformation */
- if (object->mesh)
- sync_mesh_motion(b_depsgraph, b_ob, object, motion_time);
+ if (object->geometry)
+ sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair);
}
return object;
@@ -403,12 +201,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* test if we need to sync */
bool object_updated = false;
- if (object_map.sync(&object, b_ob, b_parent, key))
+ if (object_map.add_or_update(&object, b_ob, b_parent, key))
object_updated = true;
/* mesh sync */
- object->mesh = sync_mesh(
- b_depsgraph, b_ob, b_ob_instance, object_updated, show_self, show_particles);
+ object->geometry = sync_geometry(
+ b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair);
/* special case not tracked by object update flags */
@@ -450,7 +248,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* object sync
* transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
- if (object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
+ if (object_updated || (object->geometry && object->geometry->need_update) ||
+ tfm != object->tfm) {
object->name = b_ob.name().c_str();
object->pass_id = b_ob.pass_index();
object->color = get_float3(b_ob.color());
@@ -459,23 +258,23 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* motion blur */
Scene::MotionType need_motion = scene->need_motion();
- if (need_motion != Scene::MOTION_NONE && object->mesh) {
- Mesh *mesh = object->mesh;
- mesh->use_motion_blur = false;
- mesh->motion_steps = 0;
+ if (need_motion != Scene::MOTION_NONE && object->geometry) {
+ Geometry *geom = object->geometry;
+ geom->use_motion_blur = false;
+ geom->motion_steps = 0;
uint motion_steps;
if (need_motion == Scene::MOTION_BLUR) {
motion_steps = object_motion_steps(b_parent, b_ob);
- mesh->motion_steps = motion_steps;
+ geom->motion_steps = motion_steps;
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
- mesh->use_motion_blur = true;
+ geom->use_motion_blur = true;
}
}
else {
motion_steps = 3;
- mesh->motion_steps = motion_steps;
+ geom->motion_steps = motion_steps;
}
object->motion.clear();
@@ -526,13 +325,13 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
if (!motion) {
/* prepare for sync */
light_map.pre_sync();
- mesh_map.pre_sync();
+ geometry_map.pre_sync();
object_map.pre_sync();
particle_system_map.pre_sync();
motion_times.clear();
}
else {
- mesh_motion_synced.clear();
+ geometry_motion_synced.clear();
}
/* initialize culling */
@@ -552,22 +351,34 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
BL::Object b_ob = b_instance.object();
- /* load per-object culling data */
+ /* Viewport visibility. */
+ const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d);
+ if (show_in_viewport == false) {
+ continue;
+ }
+
+ /* Load per-object culling data. */
culling.init_object(scene, b_ob);
- /* test if object needs to be hidden */
- const bool show_self = b_instance.show_self();
- const bool show_particles = b_instance.show_particles();
- const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d);
+ /* Object itself. */
+ if (b_instance.show_self()) {
+ sync_object(b_depsgraph,
+ b_view_layer,
+ b_instance,
+ motion_time,
+ false,
+ show_lights,
+ culling,
+ &use_portal);
+ }
- if (show_in_viewport && (show_self || show_particles)) {
- /* object itself */
+ /* Particle hair as separate object. */
+ if (b_instance.show_particles() && object_has_particle_hair(b_ob)) {
sync_object(b_depsgraph,
b_view_layer,
b_instance,
motion_time,
- show_self,
- show_particles,
+ true,
show_lights,
culling,
&use_portal);
@@ -584,8 +395,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
/* handle removed data and modified pointers */
if (light_map.post_sync())
scene->light_manager->tag_update(scene);
- if (mesh_map.post_sync())
- scene->mesh_manager->tag_update(scene);
+ if (geometry_map.post_sync())
+ scene->geometry_manager->tag_update(scene);
if (object_map.post_sync())
scene->object_manager->tag_update(scene);
if (particle_system_map.post_sync())
@@ -593,7 +404,7 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
}
if (motion)
- mesh_motion_synced.clear();
+ geometry_motion_synced.clear();
}
void BlenderSync::sync_motion(BL::RenderSettings &b_render,
diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp
index 74f8fb1dc53..bebecb364eb 100644
--- a/intern/cycles/blender/blender_object_cull.cpp
+++ b/intern/cycles/blender/blender_object_cull.cpp
@@ -19,6 +19,7 @@
#include "render/camera.h"
#include "blender/blender_object_cull.h"
+#include "blender/blender_util.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index d74f132ed60..e5eab1ae62b 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -39,7 +39,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
object->hide_on_missing_motion = true;
/* test if we need particle data */
- if (!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE))
+ if (!object->geometry->need_attribute(scene, ATTR_STD_PARTICLE))
return false;
/* don't handle child particles yet */
@@ -53,10 +53,10 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
ParticleSystem *psys;
bool first_use = !particle_system_map.is_used(key);
- bool need_update = particle_system_map.sync(&psys, b_ob, b_instance.object(), key);
+ bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key);
/* no update needed? */
- if (!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
+ if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update)
return true;
/* first time used in this sync loop? clear and tag update */
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 335d4daf09c..816b4552fff 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -21,6 +21,7 @@
#include "blender/blender_device.h"
#include "blender/blender_sync.h"
#include "blender/blender_session.h"
+#include "blender/blender_util.h"
#include "render/denoising.h"
#include "render/merge.h"
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index e2dea24fdd1..1490348743e 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -720,9 +720,12 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
int tri_offset = 0;
for (size_t i = 0; i < scene->objects.size(); i++) {
- if (strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
+ const Object *object = scene->objects[i];
+ const Geometry *geom = object->geometry;
+ if (object->name == b_object.name() && geom->type == Geometry::MESH) {
+ const Mesh *mesh = static_cast<const Mesh *>(geom);
object_index = i;
- tri_offset = scene->objects[i]->mesh->tri_offset;
+ tri_offset = mesh->prim_offset;
break;
}
}
@@ -1112,341 +1115,6 @@ void BlenderSession::test_cancel()
session->progress.set_cancel("Cancelled");
}
-/* builtin image file name is actually an image datablock name with
- * absolute sequence frame number concatenated via '@' character
- *
- * this function splits frame from builtin name
- */
-int BlenderSession::builtin_image_frame(const string &builtin_name)
-{
- int last = builtin_name.find_last_of('@');
- return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
-}
-
-void BlenderSession::builtin_image_info(const string &builtin_name,
- void *builtin_data,
- ImageMetaData &metadata)
-{
- /* empty image */
- metadata.width = 1;
- metadata.height = 1;
-
- if (!builtin_data)
- return;
-
- /* recover ID pointer */
- PointerRNA ptr;
- RNA_id_pointer_create((ID *)builtin_data, &ptr);
- BL::ID b_id(ptr);
-
- if (b_id.is_a(&RNA_Image)) {
- /* image data */
- BL::Image b_image(b_id);
-
- metadata.builtin_free_cache = !b_image.has_data();
- metadata.is_float = b_image.is_float();
- metadata.width = b_image.size()[0];
- metadata.height = b_image.size()[1];
- metadata.depth = 1;
- metadata.channels = b_image.channels();
-
- if (metadata.is_float) {
- /* Float images are already converted on the Blender side,
- * no need to do anything in Cycles. */
- metadata.colorspace = u_colorspace_raw;
- }
- }
- else if (b_id.is_a(&RNA_Object)) {
- /* smoke volume data */
- BL::Object b_ob(b_id);
- BL::FluidDomainSettings b_domain = object_fluid_domain_find(b_ob);
-
- metadata.is_float = true;
- metadata.depth = 1;
- metadata.channels = 1;
-
- if (!b_domain)
- return;
-
- if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
- metadata.channels = 1;
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
- metadata.channels = 4;
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY))
- metadata.channels = 3;
- else
- return;
-
- int3 resolution = get_int3(b_domain.domain_resolution());
- int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1;
-
- /* Velocity and heat data is always low-resolution. */
- if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
- amplify = 1;
- }
-
- metadata.width = resolution.x * amplify;
- metadata.height = resolution.y * amplify;
- metadata.depth = resolution.z * amplify;
- }
- else {
- /* TODO(sergey): Check we're indeed in shader node tree. */
- PointerRNA ptr;
- RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
- BL::Node b_node(ptr);
- if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
- BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
- metadata.channels = 4;
- metadata.width = b_point_density_node.resolution();
- metadata.height = metadata.width;
- metadata.depth = metadata.width;
- metadata.is_float = true;
- }
- }
-}
-
-bool BlenderSession::builtin_image_pixels(const string &builtin_name,
- void *builtin_data,
- int tile,
- unsigned char *pixels,
- const size_t pixels_size,
- const bool associate_alpha,
- const bool free_cache)
-{
- if (!builtin_data) {
- return false;
- }
-
- const int frame = builtin_image_frame(builtin_name);
-
- PointerRNA ptr;
- RNA_id_pointer_create((ID *)builtin_data, &ptr);
- BL::Image b_image(ptr);
-
- const int width = b_image.size()[0];
- const int height = b_image.size()[1];
- const int channels = b_image.channels();
-
- unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile);
- const size_t num_pixels = ((size_t)width) * height;
-
- if (image_pixels && num_pixels * channels == pixels_size) {
- memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
- }
- else {
- if (channels == 1) {
- memset(pixels, 0, pixels_size * sizeof(unsigned char));
- }
- else {
- const size_t num_pixels_safe = pixels_size / channels;
- unsigned char *cp = pixels;
- for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
- cp[0] = 255;
- cp[1] = 0;
- cp[2] = 255;
- if (channels == 4) {
- cp[3] = 255;
- }
- }
- }
- }
-
- if (image_pixels) {
- MEM_freeN(image_pixels);
- }
-
- /* Free image buffers to save memory during render. */
- if (free_cache) {
- b_image.buffers_free();
- }
-
- if (associate_alpha) {
- /* Premultiply, byte images are always straight for Blender. */
- unsigned char *cp = pixels;
- for (size_t i = 0; i < num_pixels; i++, cp += channels) {
- cp[0] = (cp[0] * cp[3]) >> 8;
- cp[1] = (cp[1] * cp[3]) >> 8;
- cp[2] = (cp[2] * cp[3]) >> 8;
- }
- }
- return true;
-}
-
-bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
- void *builtin_data,
- int tile,
- float *pixels,
- const size_t pixels_size,
- const bool,
- const bool free_cache)
-{
- if (!builtin_data) {
- return false;
- }
-
- PointerRNA ptr;
- RNA_id_pointer_create((ID *)builtin_data, &ptr);
- BL::ID b_id(ptr);
-
- if (b_id.is_a(&RNA_Image)) {
- /* image data */
- BL::Image b_image(b_id);
- int frame = builtin_image_frame(builtin_name);
-
- const int width = b_image.size()[0];
- const int height = b_image.size()[1];
- const int channels = b_image.channels();
-
- float *image_pixels;
- image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile);
- const size_t num_pixels = ((size_t)width) * height;
-
- if (image_pixels && num_pixels * channels == pixels_size) {
- memcpy(pixels, image_pixels, pixels_size * sizeof(float));
- }
- else {
- if (channels == 1) {
- memset(pixels, 0, num_pixels * sizeof(float));
- }
- else {
- const size_t num_pixels_safe = pixels_size / channels;
- float *fp = pixels;
- for (int i = 0; i < num_pixels_safe; i++, fp += channels) {
- fp[0] = 1.0f;
- fp[1] = 0.0f;
- fp[2] = 1.0f;
- if (channels == 4) {
- fp[3] = 1.0f;
- }
- }
- }
- }
-
- if (image_pixels) {
- MEM_freeN(image_pixels);
- }
-
- /* Free image buffers to save memory during render. */
- if (free_cache) {
- b_image.buffers_free();
- }
-
- return true;
- }
- else if (b_id.is_a(&RNA_Object)) {
- /* smoke volume data */
- BL::Object b_ob(b_id);
- BL::FluidDomainSettings b_domain = object_fluid_domain_find(b_ob);
-
- if (!b_domain) {
- return false;
- }
-#if WITH_FLUID
- int3 resolution = get_int3(b_domain.domain_resolution());
- int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1;
-
- /* Velocity and heat data is always low-resolution. */
- if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
- amplify = 1;
- }
-
- const int width = resolution.x * amplify;
- const int height = resolution.y * amplify;
- const int depth = resolution.z * amplify;
- const size_t num_pixels = ((size_t)width) * height * depth;
-
- if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
- FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
- if (length == num_pixels) {
- FluidDomainSettings_density_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
- /* this is in range 0..1, and interpreted by the OpenGL smoke viewer
- * as 1500..3000 K with the first part faded to zero density */
- FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
- if (length == num_pixels) {
- FluidDomainSettings_flame_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
- /* the RGB is "premultiplied" by density for better interpolation results */
- FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
- if (length == num_pixels * 4) {
- FluidDomainSettings_color_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
- FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length);
- if (length == num_pixels * 3) {
- FluidDomainSettings_velocity_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
- FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length);
- if (length == num_pixels) {
- FluidDomainSettings_heat_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
- FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
- if (length == num_pixels) {
- FluidDomainSettings_temperature_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else {
- fprintf(
- stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str());
- pixels[0] = 0.0f;
- return false;
- }
-#endif
- fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
- }
- else {
- /* We originally were passing view_layer here but in reality we need a
- * a depsgraph to pass to the RE_point_density_minmax() function.
- */
- /* TODO(sergey): Check we're indeed in shader node tree. */
- PointerRNA ptr;
- RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
- BL::Node b_node(ptr);
- if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
- BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
- int length;
- b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels);
- }
- }
-
- return false;
-}
-
-void BlenderSession::builtin_images_load()
-{
- /* Force builtin images to be loaded along with Blender data sync. This
- * is needed because we may be reading from depsgraph evaluated data which
- * can be freed by Blender before Cycles reads it.
- *
- * TODO: the assumption that no further access to builtin image data will
- * happen is really weak, and likely to break in the future. We should find
- * a better solution to hand over the data directly to the image manager
- * instead of through callbacks whose timing is difficult to control. */
- ImageManager *manager = session->scene->image_manager;
- Device *device = session->device;
- manager->device_load_builtin(device, session->scene, session->progress);
-}
-
void BlenderSession::update_resumable_tile_manager(int num_samples)
{
const int num_resumable_chunks = BlenderSession::num_resumable_chunks,
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 206058259af..635405e42c7 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -1255,7 +1255,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.sync(&shader, b_mat) || shader->need_sync_object || update_all) {
+ if (shader_map.add_or_update(&shader, b_mat) || shader->need_sync_object || update_all) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@@ -1480,7 +1480,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.sync(&shader, b_light) || update_all) {
+ if (shader_map.add_or_update(&shader, b_light) || update_all) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 20dbe23cdb7..8960c84567e 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -56,7 +56,7 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
b_scene(b_scene),
shader_map(&scene->shaders),
object_map(&scene->objects),
- mesh_map(&scene->meshes),
+ geometry_map(&scene->geometry),
light_map(&scene->lights),
particle_system_map(&scene->particle_systems),
world_map(NULL),
@@ -108,10 +108,15 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
}
if (dicing_prop_changed) {
- for (const pair<void *, Mesh *> &iter : mesh_map.key_to_scene_data()) {
- Mesh *mesh = iter.second;
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
- mesh_map.set_recalc(iter.first);
+ for (const pair<GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
+ Geometry *geom = iter.second;
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ PointerRNA id_ptr;
+ RNA_id_pointer_create((::ID *)iter.first.id, &id_ptr);
+ geometry_map.set_recalc(BL::ID(id_ptr));
+ }
}
}
}
@@ -146,7 +151,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
if (updated_geometry ||
(object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) {
BL::ID key = BKE_object_is_modified(b_ob) ? b_ob : b_ob.data();
- mesh_map.set_recalc(key);
+ geometry_map.set_recalc(key);
}
}
else if (object_is_light(b_ob)) {
@@ -164,7 +169,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
/* Mesh */
else if (b_id.is_a(&RNA_Mesh)) {
BL::Mesh b_mesh(b_id);
- mesh_map.set_recalc(b_mesh);
+ geometry_map.set_recalc(b_mesh);
}
/* World */
else if (b_id.is_a(&RNA_World)) {
@@ -211,7 +216,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
sync_images();
sync_curve_settings();
- mesh_synced.clear(); /* use for objects and motion sync */
+ geometry_synced.clear(); /* use for objects and motion sync */
if (scene->need_motion() == Scene::MOTION_PASS || scene->need_motion() == Scene::MOTION_NONE ||
scene->camera->motion_position == Camera::MOTION_POSITION_CENTER) {
@@ -219,7 +224,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
}
sync_motion(b_render, b_depsgraph, b_v3d, b_override, width, height, python_thread_state);
- mesh_synced.clear();
+ geometry_synced.clear();
/* Shader sync done at the end, since object sync uses it.
* false = don't delete unused shaders, not supported. */
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index a80f484fb92..f8134ff8b5c 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -22,7 +22,7 @@
#include "RNA_access.h"
#include "RNA_blender_cpp.h"
-#include "blender/blender_util.h"
+#include "blender/blender_id_map.h"
#include "blender/blender_viewport.h"
#include "render/scene.h"
@@ -40,6 +40,7 @@ class BlenderObjectCulling;
class BlenderViewportParameters;
class Camera;
class Film;
+class Hair;
class Light;
class Mesh;
class Object;
@@ -118,28 +119,57 @@ class BlenderSync {
void **python_thread_state);
void sync_film(BL::SpaceView3D &b_v3d);
void sync_view();
+
+ /* Shader */
void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
- void sync_curve_settings();
-
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
- Mesh *sync_mesh(BL::Depsgraph &b_depsgrpah,
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
- bool object_updated,
- bool show_self,
- bool show_particles);
- void sync_curves(
- Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
+
+ /* Object */
Object *sync_object(BL::Depsgraph &b_depsgraph,
BL::ViewLayer &b_view_layer,
BL::DepsgraphObjectInstance &b_instance,
float motion_time,
- bool show_self,
- bool show_particles,
+ bool use_particle_hair,
bool show_lights,
BlenderObjectCulling &culling,
bool *use_portal);
+
+ /* Volume */
+ void sync_volume(BL::Object &b_ob, Mesh *mesh);
+
+ /* Mesh */
+ void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh);
+ void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step);
+
+ /* Hair */
+ void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom);
+ void sync_hair_motion(BL::Depsgraph b_depsgraph,
+ BL::Object b_ob,
+ Geometry *geom,
+ int motion_step);
+ void sync_particle_hair(
+ Geometry *geom, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
+ void sync_curve_settings();
+ bool object_has_particle_hair(BL::Object b_ob);
+
+ /* Camera */
+ void sync_camera_motion(
+ BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time);
+
+ /* Geometry */
+ Geometry *sync_geometry(BL::Depsgraph &b_depsgrpah,
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
+ bool object_updated,
+ bool use_particle_hair);
+ void sync_geometry_motion(BL::Depsgraph &b_depsgraph,
+ BL::Object &b_ob,
+ Object *object,
+ float motion_time,
+ bool use_particle_hair);
+
+ /* Light */
void sync_light(BL::Object &b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BL::Object &b_ob,
@@ -148,14 +178,8 @@ class BlenderSync {
Transform &tfm,
bool *use_portal);
void sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal);
- void sync_mesh_motion(BL::Depsgraph &b_depsgraph,
- BL::Object &b_ob,
- Object *object,
- float motion_time);
- void sync_camera_motion(
- BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time);
- /* particles */
+ /* Particles */
bool sync_dupli_particle(BL::Object &b_ob,
BL::DepsgraphObjectInstance &b_instance,
Object *object);
@@ -179,11 +203,11 @@ class BlenderSync {
id_map<void *, Shader> shader_map;
id_map<ObjectKey, Object> object_map;
- id_map<void *, Mesh> mesh_map;
+ id_map<GeometryKey, Geometry> geometry_map;
id_map<ObjectKey, Light> light_map;
id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
- set<Mesh *> mesh_synced;
- set<Mesh *> mesh_motion_synced;
+ set<Geometry *> geometry_synced;
+ set<Geometry *> geometry_motion_synced;
set<float> motion_times;
void *world_map;
bool world_recalc;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index bea30a20b8c..cb7d1c62f60 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -531,7 +531,7 @@ static inline bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_
return use_deform_motion;
}
-static inline BL::FluidDomainSettings object_fluid_domain_find(BL::Object &b_ob)
+static inline BL::FluidDomainSettings object_fluid_liquid_domain_find(BL::Object &b_ob)
{
BL::Object::modifiers_iterator b_mod;
@@ -539,8 +539,28 @@ static inline BL::FluidDomainSettings object_fluid_domain_find(BL::Object &b_ob)
if (b_mod->is_a(&RNA_FluidModifier)) {
BL::FluidModifier b_mmd(*b_mod);
- if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN)
+ if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN &&
+ b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_LIQUID) {
return b_mmd.domain_settings();
+ }
+ }
+ }
+
+ return BL::FluidDomainSettings(PointerRNA_NULL);
+}
+
+static inline BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob)
+{
+ BL::Object::modifiers_iterator b_mod;
+
+ for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if (b_mod->is_a(&RNA_FluidModifier)) {
+ BL::FluidModifier b_mmd(*b_mod);
+
+ if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN &&
+ b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_GAS) {
+ return b_mmd.domain_settings();
+ }
}
}
@@ -573,209 +593,20 @@ static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob,
return Mesh::SUBDIVISION_NONE;
}
-/* ID Map
- *
- * Utility class to keep in sync with blender data.
- * Used for objects, meshes, lights and shaders. */
-
-template<typename K, typename T> class id_map {
- public:
- id_map(vector<T *> *scene_data_)
- {
- scene_data = scene_data_;
- }
-
- T *find(const BL::ID &id)
- {
- return find(id.ptr.owner_id);
- }
-
- T *find(const K &key)
- {
- if (b_map.find(key) != b_map.end()) {
- T *data = b_map[key];
- return data;
- }
-
- return NULL;
- }
-
- void set_recalc(const BL::ID &id)
- {
- b_recalc.insert(id.ptr.data);
- }
-
- void set_recalc(void *id_ptr)
- {
- b_recalc.insert(id_ptr);
- }
-
- bool has_recalc()
- {
- return !(b_recalc.empty());
- }
-
- void pre_sync()
- {
- used_set.clear();
- }
-
- bool sync(T **r_data, const BL::ID &id)
- {
- return sync(r_data, id, id, id.ptr.owner_id);
- }
-
- bool sync(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
- {
- T *data = find(key);
- bool recalc;
-
- if (!data) {
- /* add data if it didn't exist yet */
- data = new T();
- scene_data->push_back(data);
- b_map[key] = data;
- recalc = true;
- }
- else {
- recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
- if (parent.ptr.data)
- recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
- }
-
- used(data);
-
- *r_data = data;
- return recalc;
- }
-
- bool is_used(const K &key)
- {
- T *data = find(key);
- return (data) ? used_set.find(data) != used_set.end() : false;
- }
-
- void used(T *data)
- {
- /* tag data as still in use */
- used_set.insert(data);
- }
-
- void set_default(T *data)
- {
- b_map[NULL] = data;
- }
-
- bool post_sync(bool do_delete = true)
- {
- /* remove unused data */
- vector<T *> new_scene_data;
- typename vector<T *>::iterator it;
- bool deleted = false;
-
- for (it = scene_data->begin(); it != scene_data->end(); it++) {
- T *data = *it;
-
- if (do_delete && used_set.find(data) == used_set.end()) {
- delete data;
- deleted = true;
- }
- else
- new_scene_data.push_back(data);
- }
-
- *scene_data = new_scene_data;
-
- /* update mapping */
- map<K, T *> new_map;
- typedef pair<const K, T *> TMapPair;
- typename map<K, T *>::iterator jt;
-
- for (jt = b_map.begin(); jt != b_map.end(); jt++) {
- TMapPair &pair = *jt;
-
- if (used_set.find(pair.second) != used_set.end())
- new_map[pair.first] = pair.second;
- }
-
- used_set.clear();
- b_recalc.clear();
- b_map = new_map;
-
- return deleted;
- }
-
- const map<K, T *> &key_to_scene_data()
- {
- return b_map;
- }
-
- protected:
- vector<T *> *scene_data;
- map<K, T *> b_map;
- set<T *> used_set;
- set<void *> b_recalc;
-};
-
-/* Object Key */
-
-enum { OBJECT_PERSISTENT_ID_SIZE = 16 };
-
-struct ObjectKey {
- void *parent;
- int id[OBJECT_PERSISTENT_ID_SIZE];
- void *ob;
-
- ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_)
- : parent(parent_), ob(ob_)
- {
- if (id_)
- memcpy(id, id_, sizeof(id));
- else
- memset(id, 0, sizeof(id));
- }
-
- bool operator<(const ObjectKey &k) const
- {
- if (ob < k.ob) {
- return true;
- }
- else if (ob == k.ob) {
- if (parent < k.parent)
- return true;
- else if (parent == k.parent)
- return memcmp(id, k.id, sizeof(id)) < 0;
- }
-
- return false;
- }
-};
-
-/* Particle System Key */
-
-struct ParticleSystemKey {
- void *ob;
- int id[OBJECT_PERSISTENT_ID_SIZE];
-
- ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
- {
- if (id_)
- memcpy(id, id_, sizeof(id));
- else
- memset(id, 0, sizeof(id));
- }
+static inline uint object_ray_visibility(BL::Object &b_ob)
+{
+ PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
+ uint flag = 0;
- bool operator<(const ParticleSystemKey &k) const
- {
- /* first id is particle index, we don't compare that */
- if (ob < k.ob)
- return true;
- else if (ob == k.ob)
- return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
+ flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0;
+ flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0;
+ flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0;
+ flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0;
+ flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0;
+ flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0;
- return false;
- }
-};
+ return flag;
+}
class EdgeMap {
public:
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp
new file mode 100644
index 00000000000..87fb9620725
--- /dev/null
+++ b/intern/cycles/blender/blender_volume.cpp
@@ -0,0 +1,95 @@
+
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/colorspace.h"
+#include "render/mesh.h"
+#include "render/object.h"
+
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
+
+CCL_NAMESPACE_BEGIN
+
+static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame)
+{
+ BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
+ if (!b_domain) {
+ return;
+ }
+
+ ImageManager *image_manager = scene->image_manager;
+ AttributeStandard attributes[] = {ATTR_STD_VOLUME_DENSITY,
+ ATTR_STD_VOLUME_COLOR,
+ ATTR_STD_VOLUME_FLAME,
+ ATTR_STD_VOLUME_HEAT,
+ ATTR_STD_VOLUME_TEMPERATURE,
+ ATTR_STD_VOLUME_VELOCITY,
+ ATTR_STD_NONE};
+
+ for (int i = 0; attributes[i] != ATTR_STD_NONE; i++) {
+ AttributeStandard std = attributes[i];
+ if (!mesh->need_attribute(scene, std)) {
+ continue;
+ }
+
+ mesh->volume_isovalue = b_domain.clipping();
+
+ Attribute *attr = mesh->attributes.add(std);
+ VoxelAttribute *volume_data = attr->data_voxel();
+ ImageMetaData metadata;
+ bool animated = false;
+
+ volume_data->manager = image_manager;
+ volume_data->slot = image_manager->add_image(Attribute::standard_name(std),
+ b_ob.ptr.data,
+ animated,
+ frame,
+ INTERPOLATION_LINEAR,
+ EXTENSION_CLIP,
+ IMAGE_ALPHA_AUTO,
+ u_colorspace_raw,
+ metadata);
+ }
+
+ /* Create a matrix to transform from object space to mesh texture space.
+ * This does not work with deformations but that can probably only be done
+ * well with a volume grid mapping of coordinates. */
+ if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
+ Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
+ Transform *tfm = attr->data_transform();
+
+ BL::Mesh b_mesh(b_ob.data());
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
+
+ *tfm = transform_translate(-loc) * transform_scale(size);
+ }
+}
+
+void BlenderSync::sync_volume(BL::Object &b_ob, Mesh *mesh)
+{
+ bool old_has_voxel_attributes = mesh->has_voxel_attributes();
+
+ /* Smoke domain. */
+ sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current());
+
+ /* Tag update. */
+ bool rebuild = (old_has_voxel_attributes != mesh->has_voxel_attributes());
+ mesh->tag_update(scene, rebuild);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 16c721da06a..3a8b0fe7fa2 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -17,6 +17,7 @@
#include "bvh/bvh.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/object.h"
@@ -99,31 +100,33 @@ int BVHStackEntry::encodeIdx() const
/* BVH */
-BVH::BVH(const BVHParams &params_, const vector<Mesh *> &meshes_, const vector<Object *> &objects_)
- : params(params_), meshes(meshes_), objects(objects_)
+BVH::BVH(const BVHParams &params_,
+ const vector<Geometry *> &geometry_,
+ const vector<Object *> &objects_)
+ : params(params_), geometry(geometry_), objects(objects_)
{
}
BVH *BVH::create(const BVHParams &params,
- const vector<Mesh *> &meshes,
+ const vector<Geometry *> &geometry,
const vector<Object *> &objects)
{
switch (params.bvh_layout) {
case BVH_LAYOUT_BVH2:
- return new BVH2(params, meshes, objects);
+ return new BVH2(params, geometry, objects);
case BVH_LAYOUT_BVH4:
- return new BVH4(params, meshes, objects);
+ return new BVH4(params, geometry, objects);
case BVH_LAYOUT_BVH8:
- return new BVH8(params, meshes, objects);
+ return new BVH8(params, geometry, objects);
case BVH_LAYOUT_EMBREE:
#ifdef WITH_EMBREE
- return new BVHEmbree(params, meshes, objects);
+ return new BVHEmbree(params, geometry, objects);
#else
break;
#endif
case BVH_LAYOUT_OPTIX:
#ifdef WITH_OPTIX
- return new BVHOptiX(params, meshes, objects);
+ return new BVHOptiX(params, geometry, objects);
#else
break;
#endif
@@ -217,36 +220,36 @@ void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility)
}
else {
/* Primitives. */
- const Mesh *mesh = ob->mesh;
-
if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* Curves. */
- int str_offset = (params.top_level) ? mesh->curve_offset : 0;
- Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
+ const Hair *hair = static_cast<const Hair *>(ob->geometry);
+ int prim_offset = (params.top_level) ? hair->prim_offset : 0;
+ Hair::Curve curve = hair->get_curve(pidx - prim_offset);
int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
- curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
+ curve.bounds_grow(k, &hair->curve_keys[0], &hair->curve_radius[0], bbox);
visibility |= PATH_RAY_CURVE;
/* Motion curves. */
- if (mesh->use_motion_blur) {
- Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (hair->use_motion_blur) {
+ Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr) {
- size_t mesh_size = mesh->curve_keys.size();
- size_t steps = mesh->motion_steps - 1;
+ size_t hair_size = hair->curve_keys.size();
+ size_t steps = hair->motion_steps - 1;
float3 *key_steps = attr->data_float3();
for (size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox);
+ curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox);
}
}
}
else {
/* Triangles. */
- int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
- Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
+ const Mesh *mesh = static_cast<const Mesh *>(ob->geometry);
+ int prim_offset = (params.top_level) ? mesh->prim_offset : 0;
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset);
const float3 *vpos = &mesh->verts[0];
triangle.bounds_grow(vpos, bbox);
@@ -276,7 +279,7 @@ void BVH::pack_triangle(int idx, float4 tri_verts[3])
{
int tob = pack.prim_object[idx];
assert(tob >= 0 && tob < objects.size());
- const Mesh *mesh = objects[tob]->mesh;
+ const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->geometry);
int tidx = pack.prim_index[idx];
Mesh::Triangle t = mesh->get_triangle(tidx);
@@ -347,15 +350,13 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8);
/* Adjust primitive index to point to the triangle in the global array, for
- * meshes with transform applied and already in the top level BVH.
+ * geometry with transform applied and already in the top level BVH.
*/
- for (size_t i = 0; i < pack.prim_index.size(); i++)
+ for (size_t i = 0; i < pack.prim_index.size(); i++) {
if (pack.prim_index[i] != -1) {
- if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
- else
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+ pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset;
}
+ }
/* track offsets of instanced BVH data in global array */
size_t prim_offset = pack.prim_index.size();
@@ -375,10 +376,10 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
size_t pack_leaf_nodes_offset = leaf_nodes_size;
size_t object_offset = 0;
- foreach (Mesh *mesh, meshes) {
- BVH *bvh = mesh->bvh;
+ foreach (Geometry *geom, geometry) {
+ BVH *bvh = geom->bvh;
- if (mesh->need_build_bvh(params.bvh_layout)) {
+ if (geom->need_build_bvh(params.bvh_layout)) {
prim_index_size += bvh->pack.prim_index.size();
prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
nodes_size += bvh->pack.nodes.size();
@@ -410,36 +411,35 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
int4 *pack_leaf_nodes = (pack.leaf_nodes.size()) ? &pack.leaf_nodes[0] : NULL;
float2 *pack_prim_time = (pack.prim_time.size()) ? &pack.prim_time[0] : NULL;
- map<Mesh *, int> mesh_map;
+ map<Geometry *, int> geometry_map;
/* merge */
foreach (Object *ob, objects) {
- Mesh *mesh = ob->mesh;
+ Geometry *geom = ob->geometry;
/* We assume that if mesh doesn't need own BVH it was already included
* into a top-level BVH and no packing here is needed.
*/
- if (!mesh->need_build_bvh(params.bvh_layout)) {
+ if (!geom->need_build_bvh(params.bvh_layout)) {
pack.object_node[object_offset++] = 0;
continue;
}
/* if mesh already added once, don't add it again, but used set
* node offset for this object */
- map<Mesh *, int>::iterator it = mesh_map.find(mesh);
+ map<Geometry *, int>::iterator it = geometry_map.find(geom);
- if (mesh_map.find(mesh) != mesh_map.end()) {
+ if (geometry_map.find(geom) != geometry_map.end()) {
int noffset = it->second;
pack.object_node[object_offset++] = noffset;
continue;
}
- BVH *bvh = mesh->bvh;
+ BVH *bvh = geom->bvh;
int noffset = nodes_offset;
int noffset_leaf = nodes_leaf_offset;
- int mesh_tri_offset = mesh->tri_offset;
- int mesh_curve_offset = mesh->curve_offset;
+ int geom_prim_offset = geom->prim_offset;
/* fill in node indexes for instances */
if (bvh->pack.root_index == -1)
@@ -447,7 +447,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
else
pack.object_node[object_offset++] = noffset;
- mesh_map[mesh] = pack.object_node[object_offset - 1];
+ geometry_map[geom] = pack.object_node[object_offset - 1];
/* merge primitive, object and triangle indexes */
if (bvh->pack.prim_index.size()) {
@@ -460,11 +460,11 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
for (size_t i = 0; i < bvh_prim_index_size; i++) {
if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
pack_prim_tri_index[pack_prim_index_offset] = -1;
}
else {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
pack_prim_tri_verts_offset;
}
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 92082e4de86..bdde38640c9 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -33,7 +33,7 @@ struct BVHStackEntry;
class BVHParams;
class BoundBox;
class LeafNode;
-class Mesh;
+class Geometry;
class Object;
class Progress;
@@ -84,11 +84,11 @@ class BVH {
public:
PackedBVH pack;
BVHParams params;
- vector<Mesh *> meshes;
+ vector<Geometry *> geometry;
vector<Object *> objects;
static BVH *create(const BVHParams &params,
- const vector<Mesh *> &meshes,
+ const vector<Geometry *> &geometry,
const vector<Object *> &objects);
virtual ~BVH()
{
@@ -102,7 +102,9 @@ class BVH {
void refit(Progress &progress);
protected:
- BVH(const BVHParams &params, const vector<Mesh *> &meshes, const vector<Object *> &objects);
+ BVH(const BVHParams &params,
+ const vector<Geometry *> &geometry,
+ const vector<Object *> &objects);
/* Refit range of primitives. */
void refit_primitives(int start, int end, BoundBox &bbox, uint &visibility);
diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp
index b1a9148c297..c903070429e 100644
--- a/intern/cycles/bvh/bvh2.cpp
+++ b/intern/cycles/bvh/bvh2.cpp
@@ -26,9 +26,9 @@
CCL_NAMESPACE_BEGIN
BVH2::BVH2(const BVHParams &params_,
- const vector<Mesh *> &meshes_,
+ const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
- : BVH(params_, meshes_, objects_)
+ : BVH(params_, geometry_, objects_)
{
}
diff --git a/intern/cycles/bvh/bvh2.h b/intern/cycles/bvh/bvh2.h
index a3eaff9cf65..fa3e45b72d2 100644
--- a/intern/cycles/bvh/bvh2.h
+++ b/intern/cycles/bvh/bvh2.h
@@ -46,7 +46,9 @@ class BVH2 : public BVH {
protected:
/* constructor */
friend class BVH;
- BVH2(const BVHParams &params, const vector<Mesh *> &meshes, const vector<Object *> &objects);
+ BVH2(const BVHParams &params,
+ const vector<Geometry *> &geometry,
+ const vector<Object *> &objects);
/* Building process. */
virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
diff --git a/intern/cycles/bvh/bvh4.cpp b/intern/cycles/bvh/bvh4.cpp
index 89b42ee1d21..143c3e54f94 100644
--- a/intern/cycles/bvh/bvh4.cpp
+++ b/intern/cycles/bvh/bvh4.cpp
@@ -32,9 +32,9 @@ CCL_NAMESPACE_BEGIN
*/
BVH4::BVH4(const BVHParams &params_,
- const vector<Mesh *> &meshes_,
+ const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
- : BVH(params_, meshes_, objects_)
+ : BVH(params_, geometry_, objects_)
{
params.bvh_layout = BVH_LAYOUT_BVH4;
}
diff --git a/intern/cycles/bvh/bvh4.h b/intern/cycles/bvh/bvh4.h
index c44f2833c84..afbb9007afb 100644
--- a/intern/cycles/bvh/bvh4.h
+++ b/intern/cycles/bvh/bvh4.h
@@ -46,7 +46,9 @@ class BVH4 : public BVH {
protected:
/* constructor */
friend class BVH;
- BVH4(const BVHParams &params, const vector<Mesh *> &meshes, const vector<Object *> &objects);
+ BVH4(const BVHParams &params,
+ const vector<Geometry *> &geometry,
+ const vector<Object *> &objects);
/* Building process. */
virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
diff --git a/intern/cycles/bvh/bvh8.cpp b/intern/cycles/bvh/bvh8.cpp
index d3516525f78..342dd9e85a5 100644
--- a/intern/cycles/bvh/bvh8.cpp
+++ b/intern/cycles/bvh/bvh8.cpp
@@ -28,6 +28,7 @@
#include "bvh/bvh8.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/object.h"
@@ -37,9 +38,9 @@
CCL_NAMESPACE_BEGIN
BVH8::BVH8(const BVHParams &params_,
- const vector<Mesh *> &meshes_,
+ const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
- : BVH(params_, meshes_, objects_)
+ : BVH(params_, geometry_, objects_)
{
}
@@ -429,37 +430,37 @@ void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
}
else {
/* Primitives. */
- const Mesh *mesh = ob->mesh;
-
if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* Curves. */
- int str_offset = (params.top_level) ? mesh->curve_offset : 0;
- Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
+ const Hair *hair = static_cast<const Hair *>(ob->geometry);
+ int prim_offset = (params.top_level) ? hair->prim_offset : 0;
+ Hair::Curve curve = hair->get_curve(pidx - prim_offset);
int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
- curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
+ curve.bounds_grow(k, &hair->curve_keys[0], &hair->curve_radius[0], bbox);
visibility |= PATH_RAY_CURVE;
/* Motion curves. */
- if (mesh->use_motion_blur) {
- Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (hair->use_motion_blur) {
+ Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr) {
- size_t mesh_size = mesh->curve_keys.size();
- size_t steps = mesh->motion_steps - 1;
+ size_t hair_size = hair->curve_keys.size();
+ size_t steps = hair->motion_steps - 1;
float3 *key_steps = attr->data_float3();
for (size_t i = 0; i < steps; i++) {
- curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox);
+ curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox);
}
}
}
}
else {
/* Triangles. */
- int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
- Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
+ const Mesh *mesh = static_cast<const Mesh *>(ob->geometry);
+ int prim_offset = (params.top_level) ? mesh->prim_offset : 0;
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset);
const float3 *vpos = &mesh->verts[0];
triangle.bounds_grow(vpos, bbox);
diff --git a/intern/cycles/bvh/bvh8.h b/intern/cycles/bvh/bvh8.h
index 5f26fd423e1..d23fa528e3e 100644
--- a/intern/cycles/bvh/bvh8.h
+++ b/intern/cycles/bvh/bvh8.h
@@ -57,7 +57,9 @@ class BVH8 : public BVH {
protected:
/* constructor */
friend class BVH;
- BVH8(const BVHParams &params, const vector<Mesh *> &meshes, const vector<Object *> &objects);
+ BVH8(const BVHParams &params,
+ const vector<Geometry *> &geometry,
+ const vector<Object *> &objects);
/* Building process. */
virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 1d9b006e8cb..b472c55d156 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -22,6 +22,7 @@
#include "bvh/bvh_params.h"
#include "bvh_split.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/object.h"
#include "render/scene.h"
@@ -194,21 +195,21 @@ void BVHBuild::add_reference_triangles(BoundBox &root, BoundBox &center, Mesh *m
}
}
-void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh, int i)
+void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair, int i)
{
const Attribute *curve_attr_mP = NULL;
- if (mesh->has_motion_blur()) {
- curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (hair->has_motion_blur()) {
+ curve_attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
}
- const size_t num_curves = mesh->num_curves();
+ const size_t num_curves = hair->num_curves();
for (uint j = 0; j < num_curves; j++) {
- const Mesh::Curve curve = mesh->get_curve(j);
- const float *curve_radius = &mesh->curve_radius[0];
+ const Hair::Curve curve = hair->get_curve(j);
+ const float *curve_radius = &hair->curve_radius[0];
for (int k = 0; k < curve.num_keys - 1; k++) {
if (curve_attr_mP == NULL) {
/* Really simple logic for static hair. */
BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds);
+ curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds);
if (bounds.valid()) {
int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k);
references.push_back(BVHReference(bounds, j, i, packed_type));
@@ -223,9 +224,9 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh
*/
/* TODO(sergey): Support motion steps for spatially split BVH. */
BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds);
- const size_t num_keys = mesh->curve_keys.size();
- const size_t num_steps = mesh->motion_steps;
+ curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds);
+ const size_t num_keys = hair->curve_keys.size();
+ const size_t num_steps = hair->motion_steps;
const float3 *key_steps = curve_attr_mP->data_float3();
for (size_t step = 0; step < num_steps - 1; step++) {
curve.bounds_grow(k, key_steps + step * num_keys, curve_radius, bounds);
@@ -244,10 +245,10 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh
*/
const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
- const size_t num_steps = mesh->motion_steps;
- const float3 *curve_keys = &mesh->curve_keys[0];
+ const size_t num_steps = hair->motion_steps;
+ const float3 *curve_keys = &hair->curve_keys[0];
const float3 *key_steps = curve_attr_mP->data_float3();
- const size_t num_keys = mesh->curve_keys.size();
+ const size_t num_keys = hair->curve_keys.size();
/* Calculate bounding box of the previous time step.
* Will be reused later to avoid duplicated work on
* calculating BVH time step boundbox.
@@ -302,13 +303,15 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh
}
}
-void BVHBuild::add_reference_mesh(BoundBox &root, BoundBox &center, Mesh *mesh, int i)
+void BVHBuild::add_reference_geometry(BoundBox &root, BoundBox &center, Geometry *geom, int i)
{
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
add_reference_triangles(root, center, mesh, i);
}
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- add_reference_curves(root, center, mesh, i);
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ add_reference_curves(root, center, hair, i);
}
}
@@ -319,16 +322,30 @@ void BVHBuild::add_reference_object(BoundBox &root, BoundBox &center, Object *ob
center.grow(ob->bounds.center2());
}
-static size_t count_curve_segments(Mesh *mesh)
+static size_t count_curve_segments(Hair *hair)
{
- size_t num = 0, num_curves = mesh->num_curves();
+ size_t num = 0, num_curves = hair->num_curves();
for (size_t i = 0; i < num_curves; i++)
- num += mesh->get_curve(i).num_keys - 1;
+ num += hair->get_curve(i).num_keys - 1;
return num;
}
+static size_t count_primitives(Geometry *geom)
+{
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ return mesh->num_triangles();
+ }
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ return count_curve_segments(hair);
+ }
+
+ return 0;
+}
+
void BVHBuild::add_references(BVHRange &root)
{
/* reserve space for references */
@@ -339,24 +356,14 @@ void BVHBuild::add_references(BVHRange &root)
if (!ob->is_traceable()) {
continue;
}
- if (!ob->mesh->is_instanced()) {
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- num_alloc_references += ob->mesh->num_triangles();
- }
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- num_alloc_references += count_curve_segments(ob->mesh);
- }
+ if (!ob->geometry->is_instanced()) {
+ num_alloc_references += count_primitives(ob->geometry);
}
else
num_alloc_references++;
}
else {
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- num_alloc_references += ob->mesh->num_triangles();
- }
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- num_alloc_references += count_curve_segments(ob->mesh);
- }
+ num_alloc_references += count_primitives(ob->geometry);
}
}
@@ -372,13 +379,13 @@ void BVHBuild::add_references(BVHRange &root)
++i;
continue;
}
- if (!ob->mesh->is_instanced())
- add_reference_mesh(bounds, center, ob->mesh, i);
+ if (!ob->geometry->is_instanced())
+ add_reference_geometry(bounds, center, ob->geometry, i);
else
add_reference_object(bounds, center, ob, i);
}
else
- add_reference_mesh(bounds, center, ob->mesh, i);
+ add_reference_geometry(bounds, center, ob->geometry, i);
i++;
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index 9685e26cfac..3fe4c3799e2 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -35,6 +35,8 @@ class BVHNode;
class BVHSpatialSplitBuildTask;
class BVHParams;
class InnerNode;
+class Geometry;
+class Hair;
class Mesh;
class Object;
class Progress;
@@ -65,8 +67,8 @@ class BVHBuild {
/* Adding references. */
void add_reference_triangles(BoundBox &root, BoundBox &center, Mesh *mesh, int i);
- void add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh, int i);
- void add_reference_mesh(BoundBox &root, BoundBox &center, Mesh *mesh, int i);
+ void add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair, int i);
+ void add_reference_geometry(BoundBox &root, BoundBox &center, Geometry *geom, int i);
void add_reference_object(BoundBox &root, BoundBox &center, Object *ob, int i);
void add_references(BVHRange &root);
diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp
index 3e4978a2c0a..851fdad7842 100644
--- a/intern/cycles/bvh/bvh_embree.cpp
+++ b/intern/cycles/bvh/bvh_embree.cpp
@@ -49,6 +49,7 @@
# include "kernel/kernel_globals.h"
# include "kernel/kernel_random.h"
+# include "render/hair.h"
# include "render/mesh.h"
# include "render/object.h"
# include "util/util_foreach.h"
@@ -301,10 +302,24 @@ RTCDevice BVHEmbree::rtc_shared_device = NULL;
int BVHEmbree::rtc_shared_users = 0;
thread_mutex BVHEmbree::rtc_shared_mutex;
+static size_t count_primitives(Geometry *geom)
+{
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ return mesh->num_triangles();
+ }
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ return hair->num_segments();
+ }
+
+ return 0;
+}
+
BVHEmbree::BVHEmbree(const BVHParams &params_,
- const vector<Mesh *> &meshes_,
+ const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
- : BVH(params_, meshes_, objects_),
+ : BVH(params_, geometry_, objects_),
scene(NULL),
mem_used(0),
top_level(NULL),
@@ -325,7 +340,7 @@ BVHEmbree::BVHEmbree(const BVHParams &params_,
if (ret != 1) {
assert(0);
VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag."
- "Ray visiblity will not work.";
+ "Ray visibility will not work.";
}
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED);
if (ret != 1) {
@@ -436,29 +451,15 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
if (!ob->is_traceable()) {
continue;
}
- if (!ob->mesh->is_instanced()) {
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- prim_count += ob->mesh->num_triangles();
- }
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
- prim_count += ob->mesh->get_curve(j).num_segments();
- }
- }
+ if (!ob->geometry->is_instanced()) {
+ prim_count += count_primitives(ob->geometry);
}
else {
++prim_count;
}
}
else {
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
- prim_count += ob->mesh->num_triangles();
- }
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
- prim_count += ob->mesh->get_curve(j).num_segments();
- }
- }
+ prim_count += count_primitives(ob->geometry);
}
}
@@ -477,7 +478,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
++i;
continue;
}
- if (!ob->mesh->is_instanced()) {
+ if (!ob->geometry->is_instanced()) {
add_object(ob, i);
}
else {
@@ -528,22 +529,29 @@ BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/)
void BVHEmbree::add_object(Object *ob, int i)
{
- Mesh *mesh = ob->mesh;
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
- add_triangles(ob, i);
+ Geometry *geom = ob->geometry;
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->num_triangles() > 0) {
+ add_triangles(ob, mesh, i);
+ }
}
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
- add_curves(ob, i);
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ if (hair->num_curves() > 0) {
+ add_curves(ob, hair, i);
+ }
}
}
void BVHEmbree::add_instance(Object *ob, int i)
{
- if (!ob || !ob->mesh) {
+ if (!ob || !ob->geometry) {
assert(0);
return;
}
- BVHEmbree *instance_bvh = (BVHEmbree *)(ob->mesh->bvh);
+ BVHEmbree *instance_bvh = (BVHEmbree *)(ob->geometry->bvh);
if (instance_bvh->top_level != this) {
instance_bvh->top_level = this;
@@ -577,10 +585,9 @@ void BVHEmbree::add_instance(Object *ob, int i)
rtcReleaseGeometry(geom_id);
}
-void BVHEmbree::add_triangles(Object *ob, int i)
+void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
{
size_t prim_offset = pack.prim_index.size();
- Mesh *mesh = ob->mesh;
const Attribute *attr_mP = NULL;
size_t num_motion_steps = 1;
if (mesh->has_motion_blur()) {
@@ -684,31 +691,31 @@ void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh)
}
}
-void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh)
+void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair)
{
const Attribute *attr_mP = NULL;
size_t num_motion_steps = 1;
- if (mesh->has_motion_blur()) {
- attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (hair->has_motion_blur()) {
+ attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_motion_steps = mesh->motion_steps;
+ num_motion_steps = hair->motion_steps;
}
}
- const size_t num_curves = mesh->num_curves();
+ const size_t num_curves = hair->num_curves();
size_t num_keys = 0;
for (size_t j = 0; j < num_curves; ++j) {
- const Mesh::Curve c = mesh->get_curve(j);
+ const Hair::Curve c = hair->get_curve(j);
num_keys += c.num_keys;
}
/* Copy the CV data to Embree */
const int t_mid = (num_motion_steps - 1) / 2;
- const float *curve_radius = &mesh->curve_radius[0];
+ const float *curve_radius = &hair->curve_radius[0];
for (int t = 0; t < num_motion_steps; ++t) {
const float3 *verts;
if (t == t_mid || attr_mP == NULL) {
- verts = &mesh->curve_keys[0];
+ verts = &hair->curve_keys[0];
}
else {
int t_ = (t > t_mid) ? (t - 1) : t;
@@ -726,9 +733,9 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh
assert(rtc_verts);
if (rtc_verts) {
if (use_curves && rtc_tangents) {
- const size_t num_curves = mesh->num_curves();
+ const size_t num_curves = hair->num_curves();
for (size_t j = 0; j < num_curves; ++j) {
- Mesh::Curve c = mesh->get_curve(j);
+ Hair::Curve c = hair->get_curve(j);
int fk = c.first_key;
rtc_verts[0] = float3_to_float4(verts[fk]);
rtc_verts[0].w = curve_radius[fk];
@@ -760,23 +767,22 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh
}
}
-void BVHEmbree::add_curves(Object *ob, int i)
+void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
{
size_t prim_offset = pack.prim_index.size();
- const Mesh *mesh = ob->mesh;
const Attribute *attr_mP = NULL;
size_t num_motion_steps = 1;
- if (mesh->has_motion_blur()) {
- attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (hair->has_motion_blur()) {
+ attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_motion_steps = mesh->motion_steps;
+ num_motion_steps = hair->motion_steps;
}
}
- const size_t num_curves = mesh->num_curves();
+ const size_t num_curves = hair->num_curves();
size_t num_segments = 0;
for (size_t j = 0; j < num_curves; ++j) {
- Mesh::Curve c = mesh->get_curve(j);
+ Hair::Curve c = hair->get_curve(j);
assert(c.num_segments() > 0);
num_segments += c.num_segments();
}
@@ -802,7 +808,7 @@ void BVHEmbree::add_curves(Object *ob, int i)
geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
size_t rtc_index = 0;
for (size_t j = 0; j < num_curves; ++j) {
- Mesh::Curve c = mesh->get_curve(j);
+ Hair::Curve c = hair->get_curve(j);
for (size_t k = 0; k < c.num_segments(); ++k) {
rtc_indices[rtc_index] = c.first_key + k;
/* Cycles specific data. */
@@ -819,7 +825,7 @@ void BVHEmbree::add_curves(Object *ob, int i)
rtcSetGeometryBuildQuality(geom_id, build_quality);
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
- update_curve_vertex_buffer(geom_id, mesh);
+ update_curve_vertex_buffer(geom_id, hair);
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
@@ -840,10 +846,7 @@ void BVHEmbree::pack_nodes(const BVHNode *)
for (size_t i = 0; i < pack.prim_index.size(); ++i) {
if (pack.prim_index[i] != -1) {
- if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
- else
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+ pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset;
}
}
@@ -857,22 +860,22 @@ void BVHEmbree::pack_nodes(const BVHNode *)
size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
size_t object_offset = 0;
- map<Mesh *, int> mesh_map;
+ map<Geometry *, int> geometry_map;
foreach (Object *ob, objects) {
- Mesh *mesh = ob->mesh;
- BVH *bvh = mesh->bvh;
+ Geometry *geom = ob->geometry;
+ BVH *bvh = geom->bvh;
- if (mesh->need_build_bvh(BVH_LAYOUT_EMBREE)) {
- if (mesh_map.find(mesh) == mesh_map.end()) {
+ if (geom->need_build_bvh(BVH_LAYOUT_EMBREE)) {
+ if (geometry_map.find(geom) == geometry_map.end()) {
prim_index_size += bvh->pack.prim_index.size();
prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
- mesh_map[mesh] = 1;
+ geometry_map[geom] = 1;
}
}
}
- mesh_map.clear();
+ geometry_map.clear();
pack.prim_index.resize(prim_index_size);
pack.prim_type.resize(prim_index_size);
@@ -890,38 +893,37 @@ void BVHEmbree::pack_nodes(const BVHNode *)
/* merge */
foreach (Object *ob, objects) {
- Mesh *mesh = ob->mesh;
+ Geometry *geom = ob->geometry;
/* We assume that if mesh doesn't need own BVH it was already included
* into a top-level BVH and no packing here is needed.
*/
- if (!mesh->need_build_bvh(BVH_LAYOUT_EMBREE)) {
+ if (!geom->need_build_bvh(BVH_LAYOUT_EMBREE)) {
pack.object_node[object_offset++] = prim_offset;
continue;
}
- /* if mesh already added once, don't add it again, but used set
+ /* if geom already added once, don't add it again, but used set
* node offset for this object */
- map<Mesh *, int>::iterator it = mesh_map.find(mesh);
+ map<Geometry *, int>::iterator it = geometry_map.find(geom);
- if (mesh_map.find(mesh) != mesh_map.end()) {
+ if (geometry_map.find(geom) != geometry_map.end()) {
int noffset = it->second;
pack.object_node[object_offset++] = noffset;
continue;
}
- BVHEmbree *bvh = (BVHEmbree *)mesh->bvh;
+ BVHEmbree *bvh = (BVHEmbree *)geom->bvh;
rtc_memory_monitor_func(stats, unaccounted_mem, true);
unaccounted_mem = 0;
- int mesh_tri_offset = mesh->tri_offset;
- int mesh_curve_offset = mesh->curve_offset;
+ int geom_prim_offset = geom->prim_offset;
/* fill in node indexes for instances */
pack.object_node[object_offset++] = prim_offset;
- mesh_map[mesh] = pack.object_node[object_offset - 1];
+ geometry_map[geom] = pack.object_node[object_offset - 1];
/* merge primitive, object and triangle indexes */
if (bvh->pack.prim_index.size()) {
@@ -932,11 +934,11 @@ void BVHEmbree::pack_nodes(const BVHNode *)
for (size_t i = 0; i < bvh_prim_index_size; ++i) {
if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
pack_prim_tri_index[pack_prim_index_offset] = -1;
}
else {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + geom_prim_offset;
pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
pack_prim_tri_verts_offset;
}
@@ -966,15 +968,22 @@ void BVHEmbree::refit_nodes()
/* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
unsigned geom_id = 0;
foreach (Object *ob, objects) {
- if (!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) {
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
- update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh);
- rtcCommitGeometry(rtcGetGeometry(scene, geom_id));
+ if (!params.top_level || (ob->is_traceable() && !ob->geometry->is_instanced())) {
+ Geometry *geom = ob->geometry;
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->num_triangles() > 0) {
+ update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), mesh);
+ rtcCommitGeometry(rtcGetGeometry(scene, geom_id));
+ }
}
-
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) {
- update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), ob->mesh);
- rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1));
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ if (hair->num_curves() > 0) {
+ update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), hair);
+ rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1));
+ }
}
}
geom_id += 2;
diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h
index 123e87dd9b0..eb121d060b7 100644
--- a/intern/cycles/bvh/bvh_embree.h
+++ b/intern/cycles/bvh/bvh_embree.h
@@ -31,6 +31,8 @@
CCL_NAMESPACE_BEGIN
+class Geometry;
+class Hair;
class Mesh;
class BVHEmbree : public BVH {
@@ -47,7 +49,7 @@ class BVHEmbree : public BVH {
protected:
friend class BVH;
BVHEmbree(const BVHParams &params,
- const vector<Mesh *> &meshes,
+ const vector<Geometry *> &geometry,
const vector<Object *> &objects);
virtual void pack_nodes(const BVHNode *) override;
@@ -55,8 +57,8 @@ class BVHEmbree : public BVH {
void add_object(Object *ob, int i);
void add_instance(Object *ob, int i);
- void add_curves(Object *ob, int i);
- void add_triangles(Object *ob, int i);
+ void add_curves(const Object *ob, const Hair *hair, int i);
+ void add_triangles(const Object *ob, const Mesh *mesh, int i);
ssize_t mem_used;
@@ -69,7 +71,7 @@ class BVHEmbree : public BVH {
private:
void delete_rtcScene();
void update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh);
- void update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh);
+ void update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair);
static RTCDevice rtc_shared_device;
static int rtc_shared_users;
diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp
index 86d755ab06a..a3b6261dcad 100644
--- a/intern/cycles/bvh/bvh_optix.cpp
+++ b/intern/cycles/bvh/bvh_optix.cpp
@@ -18,6 +18,8 @@
#ifdef WITH_OPTIX
# include "bvh/bvh_optix.h"
+# include "render/hair.h"
+# include "render/geometry.h"
# include "render/mesh.h"
# include "render/object.h"
# include "util/util_logging.h"
@@ -26,9 +28,9 @@
CCL_NAMESPACE_BEGIN
BVHOptiX::BVHOptiX(const BVHParams &params_,
- const vector<Mesh *> &meshes_,
+ const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
- : BVH(params_, meshes_, objects_)
+ : BVH(params_, geometry_, objects_)
{
}
@@ -56,47 +58,52 @@ void BVHOptiX::copy_to_device(Progress &progress, DeviceScene *dscene)
void BVHOptiX::pack_blas()
{
// Bottom-level BVH can contain multiple primitive types, so merge them:
- assert(meshes.size() == 1 && objects.size() == 1); // These are build per-mesh
- Mesh *const mesh = meshes[0];
-
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
- const size_t num_curves = mesh->num_curves();
- const size_t num_segments = mesh->num_segments();
- pack.prim_type.reserve(pack.prim_type.size() + num_segments);
- pack.prim_index.reserve(pack.prim_index.size() + num_segments);
- pack.prim_object.reserve(pack.prim_object.size() + num_segments);
- // 'pack.prim_time' is only used in geom_curve_intersect.h
- // It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH
-
- uint type = PRIMITIVE_CURVE;
- if (mesh->use_motion_blur && mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
- type = PRIMITIVE_MOTION_CURVE;
-
- for (size_t j = 0; j < num_curves; ++j) {
- const Mesh::Curve curve = mesh->get_curve(j);
- for (size_t k = 0; k < curve.num_segments(); ++k) {
- pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k));
- // Each curve segment points back to its curve index
- pack.prim_index.push_back_reserved(j);
- pack.prim_object.push_back_reserved(0);
+ assert(geometry.size() == 1 && objects.size() == 1); // These are built per-mesh
+ Geometry *const geom = geometry[0];
+
+ if (geom->type == Geometry::HAIR) {
+ Hair *const hair = static_cast<Hair *const>(geom);
+ if (hair->num_curves() > 0) {
+ const size_t num_curves = hair->num_curves();
+ const size_t num_segments = hair->num_segments();
+ pack.prim_type.reserve(pack.prim_type.size() + num_segments);
+ pack.prim_index.reserve(pack.prim_index.size() + num_segments);
+ pack.prim_object.reserve(pack.prim_object.size() + num_segments);
+ // 'pack.prim_time' is only used in geom_curve_intersect.h
+ // It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH
+
+ uint type = PRIMITIVE_CURVE;
+ if (hair->use_motion_blur && hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
+ type = PRIMITIVE_MOTION_CURVE;
+
+ for (size_t j = 0; j < num_curves; ++j) {
+ const Hair::Curve curve = hair->get_curve(j);
+ for (size_t k = 0; k < curve.num_segments(); ++k) {
+ pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k));
+ // Each curve segment points back to its curve index
+ pack.prim_index.push_back_reserved(j);
+ pack.prim_object.push_back_reserved(0);
+ }
}
}
}
-
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
- const size_t num_triangles = mesh->num_triangles();
- pack.prim_type.reserve(pack.prim_type.size() + num_triangles);
- pack.prim_index.reserve(pack.prim_index.size() + num_triangles);
- pack.prim_object.reserve(pack.prim_object.size() + num_triangles);
-
- uint type = PRIMITIVE_TRIANGLE;
- if (mesh->use_motion_blur && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
- type = PRIMITIVE_MOTION_TRIANGLE;
-
- for (size_t k = 0; k < num_triangles; ++k) {
- pack.prim_type.push_back_reserved(type);
- pack.prim_index.push_back_reserved(k);
- pack.prim_object.push_back_reserved(0);
+ else if (geom->type == Geometry::MESH) {
+ Mesh *const mesh = static_cast<Mesh *const>(geom);
+ if (mesh->num_triangles() > 0) {
+ const size_t num_triangles = mesh->num_triangles();
+ pack.prim_type.reserve(pack.prim_type.size() + num_triangles);
+ pack.prim_index.reserve(pack.prim_index.size() + num_triangles);
+ pack.prim_object.reserve(pack.prim_object.size() + num_triangles);
+
+ uint type = PRIMITIVE_TRIANGLE;
+ if (mesh->use_motion_blur && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
+ type = PRIMITIVE_MOTION_TRIANGLE;
+
+ for (size_t k = 0; k < num_triangles; ++k) {
+ pack.prim_type.push_back_reserved(type);
+ pack.prim_index.push_back_reserved(k);
+ pack.prim_object.push_back_reserved(0);
+ }
}
}
@@ -116,8 +123,8 @@ void BVHOptiX::pack_tlas()
// Calculate total packed size
size_t prim_index_size = 0;
size_t prim_tri_verts_size = 0;
- foreach (Mesh *mesh, meshes) {
- BVH *const bvh = mesh->bvh;
+ foreach (Geometry *geom, geometry) {
+ BVH *const bvh = geom->bvh;
prim_index_size += bvh->pack.prim_index.size();
prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
}
@@ -141,13 +148,12 @@ void BVHOptiX::pack_tlas()
pack.prim_tri_verts.resize(prim_tri_verts_size);
float4 *pack_prim_tri_verts = pack.prim_tri_verts.data();
- // Top-level BVH should only contain instances, see 'Mesh::need_build_bvh'
+ // Top-level BVH should only contain instances, see 'Geometry::need_build_bvh'
// Iterate over scene mesh list instead of objects, since the 'prim_offset' is calculated based
// on that list, which may be ordered differently from the object list.
- foreach (Mesh *mesh, meshes) {
- PackedBVH &bvh_pack = mesh->bvh->pack;
- int mesh_tri_offset = mesh->tri_offset;
- int mesh_curve_offset = mesh->curve_offset;
+ foreach (Geometry *geom, geometry) {
+ PackedBVH &bvh_pack = geom->bvh->pack;
+ int geom_prim_offset = geom->prim_offset;
// Merge primitive, object and triangle indexes
if (!bvh_pack.prim_index.empty()) {
@@ -158,16 +164,16 @@ void BVHOptiX::pack_tlas()
for (size_t i = 0; i < bvh_pack.prim_index.size(); i++, pack_offset++) {
if (bvh_pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_offset] = bvh_prim_index[i] + mesh_curve_offset;
+ pack_prim_index[pack_offset] = bvh_prim_index[i] + geom_prim_offset;
pack_prim_tri_index[pack_offset] = -1;
}
else {
- pack_prim_index[pack_offset] = bvh_prim_index[i] + mesh_tri_offset;
+ pack_prim_index[pack_offset] = bvh_prim_index[i] + geom_prim_offset;
pack_prim_tri_index[pack_offset] = bvh_prim_tri_index[i] + pack_verts_offset;
}
pack_prim_type[pack_offset] = bvh_prim_type[i];
- pack_prim_object[pack_offset] = 0; // Unused for instanced meshes
+ pack_prim_object[pack_offset] = 0; // Unused for instanced geometry
pack_prim_visibility[pack_offset] = bvh_prim_visibility[i];
}
}
@@ -182,15 +188,24 @@ void BVHOptiX::pack_tlas()
}
}
- // Merge visibility flags of all objects and fix object indices for non-instanced meshes
+ // Merge visibility flags of all objects and fix object indices for non-instanced geometry
foreach (Object *ob, objects) {
- Mesh *const mesh = ob->mesh;
- for (size_t i = 0; i < mesh->num_primitives(); ++i) {
- if (!ob->mesh->is_instanced()) {
- assert(pack.prim_object[mesh->prim_offset + i] == 0);
- pack.prim_object[mesh->prim_offset + i] = ob->get_device_index();
+ Geometry *const geom = ob->geometry;
+ size_t num_primitives = 0;
+
+ if (geom->type == Geometry::MESH) {
+ num_primitives = static_cast<Mesh *const>(geom)->num_triangles();
+ }
+ else if (geom->type == Geometry::HAIR) {
+ num_primitives = static_cast<Hair *const>(geom)->num_segments();
+ }
+
+ for (size_t i = 0; i < num_primitives; ++i) {
+ if (!geom->is_instanced()) {
+ assert(pack.prim_object[geom->optix_prim_offset + i] == 0);
+ pack.prim_object[geom->optix_prim_offset + i] = ob->get_device_index();
}
- pack.prim_visibility[mesh->prim_offset + i] |= ob->visibility_for_tracing();
+ pack.prim_visibility[geom->optix_prim_offset + i] |= ob->visibility_for_tracing();
}
}
}
diff --git a/intern/cycles/bvh/bvh_optix.h b/intern/cycles/bvh/bvh_optix.h
index 35033fe635f..e4745b093b5 100644
--- a/intern/cycles/bvh/bvh_optix.h
+++ b/intern/cycles/bvh/bvh_optix.h
@@ -26,11 +26,16 @@
CCL_NAMESPACE_BEGIN
+class Geometry;
+class Optix;
+
class BVHOptiX : public BVH {
friend class BVH;
public:
- BVHOptiX(const BVHParams &params, const vector<Mesh *> &meshes, const vector<Object *> &objects);
+ BVHOptiX(const BVHParams &params,
+ const vector<Geometry *> &geometry,
+ const vector<Object *> &objects);
virtual ~BVHOptiX();
virtual void build(Progress &progress, Stats *) override;
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 2731662a39d..5e2c4b63f1b 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -69,9 +69,6 @@ class BVHParams {
/* BVH layout to be built. */
BVHLayout bvh_layout;
- /* Mask of primitives to be included into the BVH. */
- int primitive_mask;
-
/* Use unaligned bounding boxes.
* Only used for curves BVH.
*/
@@ -120,8 +117,6 @@ class BVHParams {
bvh_layout = BVH_LAYOUT_BVH2;
use_unaligned_nodes = false;
- primitive_mask = PRIMITIVE_ALL;
-
num_motion_curve_steps = 0;
num_motion_triangle_steps = 0;
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index bd261c10d55..acdca0f13ad 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -20,6 +20,7 @@
#include "bvh/bvh_build.h"
#include "bvh/bvh_sort.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/object.h"
@@ -378,7 +379,7 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
}
}
-void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
+void BVHSpatialSplit::split_curve_primitive(const Hair *hair,
const Transform *tfm,
int prim_index,
int segment_index,
@@ -388,11 +389,11 @@ void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
BoundBox &right_bounds)
{
/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
- Mesh::Curve curve = mesh->get_curve(prim_index);
+ Hair::Curve curve = hair->get_curve(prim_index);
const int k0 = curve.first_key + segment_index;
const int k1 = k0 + 1;
- float3 v0 = mesh->curve_keys[k0];
- float3 v1 = mesh->curve_keys[k1];
+ float3 v0 = hair->curve_keys[k0];
+ float3 v1 = hair->curve_keys[k1];
if (tfm != NULL) {
v0 = transform_point(tfm, v0);
@@ -436,13 +437,13 @@ void BVHSpatialSplit::split_triangle_reference(const BVHReference &ref,
}
void BVHSpatialSplit::split_curve_reference(const BVHReference &ref,
- const Mesh *mesh,
+ const Hair *hair,
int dim,
float pos,
BoundBox &left_bounds,
BoundBox &right_bounds)
{
- split_curve_primitive(mesh,
+ split_curve_primitive(hair,
NULL,
ref.prim_index(),
PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()),
@@ -455,15 +456,22 @@ void BVHSpatialSplit::split_curve_reference(const BVHReference &ref,
void BVHSpatialSplit::split_object_reference(
const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds)
{
- Mesh *mesh = object->mesh;
- for (int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) {
- split_triangle_primitive(mesh, &object->tfm, tri_idx, dim, pos, left_bounds, right_bounds);
+ Geometry *geom = object->geometry;
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ for (int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) {
+ split_triangle_primitive(mesh, &object->tfm, tri_idx, dim, pos, left_bounds, right_bounds);
+ }
}
- for (int curve_idx = 0; curve_idx < mesh->num_curves(); ++curve_idx) {
- Mesh::Curve curve = mesh->get_curve(curve_idx);
- for (int segment_idx = 0; segment_idx < curve.num_keys - 1; ++segment_idx) {
- split_curve_primitive(
- mesh, &object->tfm, curve_idx, segment_idx, dim, pos, left_bounds, right_bounds);
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ for (int curve_idx = 0; curve_idx < hair->num_curves(); ++curve_idx) {
+ Hair::Curve curve = hair->get_curve(curve_idx);
+ for (int segment_idx = 0; segment_idx < curve.num_keys - 1; ++segment_idx) {
+ split_curve_primitive(
+ hair, &object->tfm, curve_idx, segment_idx, dim, pos, left_bounds, right_bounds);
+ }
}
}
}
@@ -481,13 +489,14 @@ void BVHSpatialSplit::split_reference(const BVHBuild &builder,
/* loop over vertices/edges. */
const Object *ob = builder.objects[ref.prim_object()];
- const Mesh *mesh = ob->mesh;
if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
+ Mesh *mesh = static_cast<Mesh *>(ob->geometry);
split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
}
else if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
- split_curve_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
+ Hair *hair = static_cast<Hair *>(ob->geometry);
+ split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds);
}
else {
split_object_reference(ob, dim, pos, left_bounds, right_bounds);
diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h
index eddd1c27f49..5f2e41cf343 100644
--- a/intern/cycles/bvh/bvh_split.h
+++ b/intern/cycles/bvh/bvh_split.h
@@ -24,6 +24,8 @@
CCL_NAMESPACE_BEGIN
class BVHBuild;
+class Hair;
+class Mesh;
struct Transform;
/* Object Split */
@@ -113,7 +115,7 @@ class BVHSpatialSplit {
float pos,
BoundBox &left_bounds,
BoundBox &right_bounds);
- void split_curve_primitive(const Mesh *mesh,
+ void split_curve_primitive(const Hair *hair,
const Transform *tfm,
int prim_index,
int segment_index,
@@ -134,7 +136,7 @@ class BVHSpatialSplit {
BoundBox &left_bounds,
BoundBox &right_bounds);
void split_curve_reference(const BVHReference &ref,
- const Mesh *mesh,
+ const Hair *hair,
int dim,
float pos,
BoundBox &left_bounds,
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp
index 1843ca403a5..f0995f343fe 100644
--- a/intern/cycles/bvh/bvh_unaligned.cpp
+++ b/intern/cycles/bvh/bvh_unaligned.cpp
@@ -16,7 +16,7 @@
#include "bvh/bvh_unaligned.h"
-#include "render/mesh.h"
+#include "render/hair.h"
#include "render/object.h"
#include "bvh/bvh_binning.h"
@@ -71,10 +71,10 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali
if (type & PRIMITIVE_CURVE) {
const int curve_index = ref.prim_index();
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
- const Mesh *mesh = object->mesh;
- const Mesh::Curve &curve = mesh->get_curve(curve_index);
+ const Hair *hair = static_cast<const Hair *>(object->geometry);
+ const Hair::Curve &curve = hair->get_curve(curve_index);
const int key = curve.first_key + segment;
- const float3 v1 = mesh->curve_keys[key], v2 = mesh->curve_keys[key + 1];
+ const float3 v1 = hair->curve_keys[key], v2 = hair->curve_keys[key + 1];
float length;
const float3 axis = normalize_len(v2 - v1, &length);
if (length > 1e-6f) {
@@ -96,10 +96,10 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim,
if (type & PRIMITIVE_CURVE) {
const int curve_index = prim.prim_index();
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
- const Mesh *mesh = object->mesh;
- const Mesh::Curve &curve = mesh->get_curve(curve_index);
+ const Hair *hair = static_cast<const Hair *>(object->geometry);
+ const Hair::Curve &curve = hair->get_curve(curve_index);
curve.bounds_grow(
- segment, &mesh->curve_keys[0], &mesh->curve_radius[0], aligned_space, bounds);
+ segment, &hair->curve_keys[0], &hair->curve_radius[0], aligned_space, bounds);
}
else {
bounds = prim.bounds().transformed(&aligned_space);
diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp
index f479cbd7414..98469fb37b0 100644
--- a/intern/cycles/device/device_optix.cpp
+++ b/intern/cycles/device/device_optix.cpp
@@ -22,6 +22,7 @@
# include "device/device_denoising.h"
# include "bvh/bvh.h"
# include "render/scene.h"
+# include "render/hair.h"
# include "render/mesh.h"
# include "render/object.h"
# include "render/buffers.h"
@@ -1229,8 +1230,8 @@ class OptiXDevice : public Device {
assert(bvh->params.top_level);
unsigned int num_instances = 0;
- unordered_map<Mesh *, vector<OptixTraversableHandle>> meshes;
- meshes.reserve(bvh->meshes.size());
+ unordered_map<Geometry *, OptixTraversableHandle> geometry;
+ geometry.reserve(bvh->geometry.size());
// Free all previous acceleration structures
for (CUdeviceptr mem : as_mem) {
@@ -1241,23 +1242,25 @@ class OptiXDevice : public Device {
// Build bottom level acceleration structures (BLAS)
// Note: Always keep this logic in sync with bvh_optix.cpp!
for (Object *ob : bvh->objects) {
- // Skip meshes for which acceleration structure already exists
- if (meshes.find(ob->mesh) != meshes.end())
+ // Skip geometry for which acceleration structure already exists
+ Geometry *geom = ob->geometry;
+ if (geometry.find(geom) != geometry.end())
continue;
- Mesh *const mesh = ob->mesh;
- vector<OptixTraversableHandle> handles;
- handles.reserve(2);
+ if (geom->type == Geometry::HAIR) {
+ // Build BLAS for curve primitives
+ Hair *const hair = static_cast<Hair *const>(ob->geometry);
+ if (hair->num_curves() == 0) {
+ continue;
+ }
- // Build BLAS for curve primitives
- if (bvh->params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
- const size_t num_curves = mesh->num_curves();
- const size_t num_segments = mesh->num_segments();
+ const size_t num_curves = hair->num_curves();
+ const size_t num_segments = hair->num_segments();
size_t num_motion_steps = 1;
- Attribute *motion_keys = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (motion_blur && mesh->use_motion_blur && motion_keys) {
- num_motion_steps = mesh->motion_steps;
+ Attribute *motion_keys = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (motion_blur && hair->use_motion_blur && motion_keys) {
+ num_motion_steps = hair->motion_steps;
}
device_vector<OptixAabb> aabb_data(this, "temp_aabb_data", MEM_READ_ONLY);
@@ -1266,21 +1269,21 @@ class OptiXDevice : public Device {
// Get AABBs for each motion step
for (size_t step = 0; step < num_motion_steps; ++step) {
// The center step for motion vertices is not stored in the attribute
- const float3 *keys = mesh->curve_keys.data();
+ const float3 *keys = hair->curve_keys.data();
size_t center_step = (num_motion_steps - 1) / 2;
if (step != center_step) {
size_t attr_offset = (step > center_step) ? step - 1 : step;
// Technically this is a float4 array, but sizeof(float3) is the same as sizeof(float4)
- keys = motion_keys->data_float3() + attr_offset * mesh->curve_keys.size();
+ keys = motion_keys->data_float3() + attr_offset * hair->curve_keys.size();
}
size_t i = step * num_segments;
for (size_t j = 0; j < num_curves; ++j) {
- const Mesh::Curve c = mesh->get_curve(j);
+ const Hair::Curve c = hair->get_curve(j);
for (size_t k = 0; k < c.num_segments(); ++i, ++k) {
BoundBox bounds = BoundBox::empty;
- c.bounds_grow(k, keys, mesh->curve_radius.data(), bounds);
+ c.bounds_grow(k, keys, hair->curve_radius.data(), bounds);
aabb_data[i].minX = bounds.min.x;
aabb_data[i].minY = bounds.min.y;
@@ -1311,16 +1314,24 @@ class OptiXDevice : public Device {
build_input.aabbArray.strideInBytes = sizeof(OptixAabb);
build_input.aabbArray.flags = &build_flags;
build_input.aabbArray.numSbtRecords = 1;
- build_input.aabbArray.primitiveIndexOffset = mesh->prim_offset;
+ build_input.aabbArray.primitiveIndexOffset = hair->optix_prim_offset;
// Allocate memory for new BLAS and build it
- handles.emplace_back();
- if (!build_optix_bvh(build_input, num_motion_steps, handles.back()))
+ OptixTraversableHandle handle;
+ if (build_optix_bvh(build_input, num_motion_steps, handle)) {
+ geometry.insert({ob->geometry, handle});
+ }
+ else {
return false;
+ }
}
+ else if (geom->type == Geometry::MESH) {
+ // Build BLAS for triangle primitives
+ Mesh *const mesh = static_cast<Mesh *const>(ob->geometry);
+ if (mesh->num_triangles() == 0) {
+ continue;
+ }
- // Build BLAS for triangle primitives
- if (bvh->params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
const size_t num_verts = mesh->verts.size();
size_t num_motion_steps = 1;
@@ -1375,23 +1386,24 @@ class OptiXDevice : public Device {
// buffers for that purpose. OptiX does not allow this to be zero though, so just pass in
// one and rely on that having the same meaning in this case.
build_input.triangleArray.numSbtRecords = 1;
- // Triangle primitives are packed right after the curve primitives of this mesh
- build_input.triangleArray.primitiveIndexOffset = mesh->prim_offset + mesh->num_segments();
+ build_input.triangleArray.primitiveIndexOffset = mesh->optix_prim_offset;
// Allocate memory for new BLAS and build it
- handles.emplace_back();
- if (!build_optix_bvh(build_input, num_motion_steps, handles.back()))
+ OptixTraversableHandle handle;
+ if (build_optix_bvh(build_input, num_motion_steps, handle)) {
+ geometry.insert({ob->geometry, handle});
+ }
+ else {
return false;
+ }
}
-
- meshes.insert({mesh, handles});
}
// Fill instance descriptions
device_vector<OptixAabb> aabbs(this, "tlas_aabbs", MEM_READ_ONLY);
- aabbs.alloc(bvh->objects.size() * 2);
+ aabbs.alloc(bvh->objects.size());
device_vector<OptixInstance> instances(this, "tlas_instances", MEM_READ_ONLY);
- instances.alloc(bvh->objects.size() * 2);
+ instances.alloc(bvh->objects.size());
for (Object *ob : bvh->objects) {
// Skip non-traceable objects
@@ -1399,113 +1411,117 @@ class OptiXDevice : public Device {
continue;
// Create separate instance for triangle/curve meshes of an object
- for (OptixTraversableHandle handle : meshes[ob->mesh]) {
- OptixAabb &aabb = aabbs[num_instances];
- aabb.minX = ob->bounds.min.x;
- aabb.minY = ob->bounds.min.y;
- aabb.minZ = ob->bounds.min.z;
- aabb.maxX = ob->bounds.max.x;
- aabb.maxY = ob->bounds.max.y;
- aabb.maxZ = ob->bounds.max.z;
-
- OptixInstance &instance = instances[num_instances++];
- memset(&instance, 0, sizeof(instance));
-
- // Clear transform to identity matrix
- instance.transform[0] = 1.0f;
- instance.transform[5] = 1.0f;
- instance.transform[10] = 1.0f;
-
- // Set user instance ID to object index
- instance.instanceId = ob->get_device_index();
-
- // Volumes have a special bit set in the visibility mask so a trace can mask only volumes
- // See 'scene_intersect_volume' in bvh.h
- instance.visibilityMask = (ob->mesh->has_volume ? 3 : 1);
-
- // Insert motion traversable if object has motion
- if (motion_blur && ob->use_motion()) {
- size_t motion_keys = max(ob->motion.size(), 2) - 2;
- size_t motion_transform_size = sizeof(OptixSRTMotionTransform) +
- motion_keys * sizeof(OptixSRTData);
-
- const CUDAContextScope scope(cuda_context);
-
- CUdeviceptr motion_transform_gpu = 0;
- check_result_cuda_ret(cuMemAlloc(&motion_transform_gpu, motion_transform_size));
- as_mem.push_back(motion_transform_gpu);
-
- // Allocate host side memory for motion transform and fill it with transform data
- OptixSRTMotionTransform &motion_transform = *reinterpret_cast<OptixSRTMotionTransform *>(
- new uint8_t[motion_transform_size]);
- motion_transform.child = handle;
- motion_transform.motionOptions.numKeys = ob->motion.size();
- motion_transform.motionOptions.flags = OPTIX_MOTION_FLAG_NONE;
- motion_transform.motionOptions.timeBegin = 0.0f;
- motion_transform.motionOptions.timeEnd = 1.0f;
-
- OptixSRTData *const srt_data = motion_transform.srtData;
- array<DecomposedTransform> decomp(ob->motion.size());
- transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size());
-
- for (size_t i = 0; i < ob->motion.size(); ++i) {
- // Scale
- srt_data[i].sx = decomp[i].y.w; // scale.x.x
- srt_data[i].sy = decomp[i].z.w; // scale.y.y
- srt_data[i].sz = decomp[i].w.w; // scale.z.z
-
- // Shear
- srt_data[i].a = decomp[i].z.x; // scale.x.y
- srt_data[i].b = decomp[i].z.y; // scale.x.z
- srt_data[i].c = decomp[i].w.x; // scale.y.z
- assert(decomp[i].z.z == 0.0f); // scale.y.x
- assert(decomp[i].w.y == 0.0f); // scale.z.x
- assert(decomp[i].w.z == 0.0f); // scale.z.y
-
- // Pivot point
- srt_data[i].pvx = 0.0f;
- srt_data[i].pvy = 0.0f;
- srt_data[i].pvz = 0.0f;
-
- // Rotation
- srt_data[i].qx = decomp[i].x.x;
- srt_data[i].qy = decomp[i].x.y;
- srt_data[i].qz = decomp[i].x.z;
- srt_data[i].qw = decomp[i].x.w;
-
- // Translation
- srt_data[i].tx = decomp[i].y.x;
- srt_data[i].ty = decomp[i].y.y;
- srt_data[i].tz = decomp[i].y.z;
- }
+ auto handle_it = geometry.find(ob->geometry);
+ if (handle_it == geometry.end()) {
+ continue;
+ }
+ OptixTraversableHandle handle = handle_it->second;
- // Upload motion transform to GPU
- cuMemcpyHtoD(motion_transform_gpu, &motion_transform, motion_transform_size);
- delete[] reinterpret_cast<uint8_t *>(&motion_transform);
+ OptixAabb &aabb = aabbs[num_instances];
+ aabb.minX = ob->bounds.min.x;
+ aabb.minY = ob->bounds.min.y;
+ aabb.minZ = ob->bounds.min.z;
+ aabb.maxX = ob->bounds.max.x;
+ aabb.maxY = ob->bounds.max.y;
+ aabb.maxZ = ob->bounds.max.z;
- // Disable instance transform if object uses motion transform already
- instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM;
+ OptixInstance &instance = instances[num_instances++];
+ memset(&instance, 0, sizeof(instance));
- // Get traversable handle to motion transform
- optixConvertPointerToTraversableHandle(context,
- motion_transform_gpu,
- OPTIX_TRAVERSABLE_TYPE_SRT_MOTION_TRANSFORM,
- &instance.traversableHandle);
+ // Clear transform to identity matrix
+ instance.transform[0] = 1.0f;
+ instance.transform[5] = 1.0f;
+ instance.transform[10] = 1.0f;
+
+ // Set user instance ID to object index
+ instance.instanceId = ob->get_device_index();
+
+ // Volumes have a special bit set in the visibility mask so a trace can mask only volumes
+ // See 'scene_intersect_volume' in bvh.h
+ instance.visibilityMask = (ob->geometry->has_volume ? 3 : 1);
+
+ // Insert motion traversable if object has motion
+ if (motion_blur && ob->use_motion()) {
+ size_t motion_keys = max(ob->motion.size(), 2) - 2;
+ size_t motion_transform_size = sizeof(OptixSRTMotionTransform) +
+ motion_keys * sizeof(OptixSRTData);
+
+ const CUDAContextScope scope(cuda_context);
+
+ CUdeviceptr motion_transform_gpu = 0;
+ check_result_cuda_ret(cuMemAlloc(&motion_transform_gpu, motion_transform_size));
+ as_mem.push_back(motion_transform_gpu);
+
+ // Allocate host side memory for motion transform and fill it with transform data
+ OptixSRTMotionTransform &motion_transform = *reinterpret_cast<OptixSRTMotionTransform *>(
+ new uint8_t[motion_transform_size]);
+ motion_transform.child = handle;
+ motion_transform.motionOptions.numKeys = ob->motion.size();
+ motion_transform.motionOptions.flags = OPTIX_MOTION_FLAG_NONE;
+ motion_transform.motionOptions.timeBegin = 0.0f;
+ motion_transform.motionOptions.timeEnd = 1.0f;
+
+ OptixSRTData *const srt_data = motion_transform.srtData;
+ array<DecomposedTransform> decomp(ob->motion.size());
+ transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size());
+
+ for (size_t i = 0; i < ob->motion.size(); ++i) {
+ // Scale
+ srt_data[i].sx = decomp[i].y.w; // scale.x.x
+ srt_data[i].sy = decomp[i].z.w; // scale.y.y
+ srt_data[i].sz = decomp[i].w.w; // scale.z.z
+
+ // Shear
+ srt_data[i].a = decomp[i].z.x; // scale.x.y
+ srt_data[i].b = decomp[i].z.y; // scale.x.z
+ srt_data[i].c = decomp[i].w.x; // scale.y.z
+ assert(decomp[i].z.z == 0.0f); // scale.y.x
+ assert(decomp[i].w.y == 0.0f); // scale.z.x
+ assert(decomp[i].w.z == 0.0f); // scale.z.y
+
+ // Pivot point
+ srt_data[i].pvx = 0.0f;
+ srt_data[i].pvy = 0.0f;
+ srt_data[i].pvz = 0.0f;
+
+ // Rotation
+ srt_data[i].qx = decomp[i].x.x;
+ srt_data[i].qy = decomp[i].x.y;
+ srt_data[i].qz = decomp[i].x.z;
+ srt_data[i].qw = decomp[i].x.w;
+
+ // Translation
+ srt_data[i].tx = decomp[i].y.x;
+ srt_data[i].ty = decomp[i].y.y;
+ srt_data[i].tz = decomp[i].y.z;
}
- else {
- instance.traversableHandle = handle;
- if (ob->mesh->is_instanced()) {
- // Set transform matrix
- memcpy(instance.transform, &ob->tfm, sizeof(instance.transform));
- }
- else {
- // Disable instance transform if mesh already has it applied to vertex data
- instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM;
- // Non-instanced objects read ID from prim_object, so
- // distinguish them from instanced objects with high bit set
- instance.instanceId |= 0x800000;
- }
+ // Upload motion transform to GPU
+ cuMemcpyHtoD(motion_transform_gpu, &motion_transform, motion_transform_size);
+ delete[] reinterpret_cast<uint8_t *>(&motion_transform);
+
+ // Disable instance transform if object uses motion transform already
+ instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM;
+
+ // Get traversable handle to motion transform
+ optixConvertPointerToTraversableHandle(context,
+ motion_transform_gpu,
+ OPTIX_TRAVERSABLE_TYPE_SRT_MOTION_TRANSFORM,
+ &instance.traversableHandle);
+ }
+ else {
+ instance.traversableHandle = handle;
+
+ if (ob->geometry->is_instanced()) {
+ // Set transform matrix
+ memcpy(instance.transform, &ob->tfm, sizeof(instance.transform));
+ }
+ else {
+ // Disable instance transform if geometry already has it applied to vertex data
+ instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM;
+ // Non-instanced objects read ID from prim_object, so
+ // distinguish them from instanced objects with high bit set
+ instance.instanceId |= 0x800000;
}
}
}
@@ -2603,8 +2619,8 @@ bool device_optix_init()
# ifdef WITH_CUDA_DYNLOAD
// Load NVRTC function pointers for adaptive kernel compilation
if (DebugFlags().cuda.adaptive_compile && cuewInit(CUEW_INIT_NVRTC) != CUEW_SUCCESS) {
- VLOG(1)
- << "CUEW initialization failed for NVRTC. Adaptive kernel compilation won't be available.";
+ VLOG(1) << "CUEW initialization failed for NVRTC. Adaptive kernel compilation won't be "
+ "available.";
}
# endif
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index 4f79a7518dc..1439fb5a407 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -669,4 +669,14 @@ size_t Node::get_total_size_in_bytes() const
return total_size;
}
+bool Node::is_a(const NodeType *type_)
+{
+ for (const NodeType *base = type; base; base = base->base) {
+ if (base == type_) {
+ return true;
+ }
+ }
+ return false;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index d35a1bb489c..4473b8aca28 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -94,6 +94,9 @@ struct Node {
/* Get total size of this node. */
size_t get_total_size_in_bytes() const;
+ /* Type testing, taking into account base classes. */
+ bool is_a(const NodeType *type);
+
ustring name;
const NodeType *type;
};
diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp
index f46d4e48026..0283ed7c817 100644
--- a/intern/cycles/graph/node_type.cpp
+++ b/intern/cycles/graph/node_type.cpp
@@ -135,8 +135,13 @@ bool SocketType::is_float3(Type type)
/* Node Type */
-NodeType::NodeType(Type type_) : type(type_)
+NodeType::NodeType(Type type, const NodeType *base) : type(type), base(base)
{
+ if (base) {
+ /* Inherit sockets. */
+ inputs = base->inputs;
+ outputs = base->outputs;
+ }
}
NodeType::~NodeType()
@@ -209,7 +214,7 @@ unordered_map<ustring, NodeType, ustringHash> &NodeType::types()
return _types;
}
-NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_)
+NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_, const NodeType *base_)
{
ustring name(name_);
@@ -219,7 +224,7 @@ NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_)
return NULL;
}
- types()[name] = NodeType(type_);
+ types()[name] = NodeType(type_, base_);
NodeType *type = &types()[name];
type->name = name;
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index e9496a42658..a79d44b82f3 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -103,7 +103,7 @@ struct SocketType {
struct NodeType {
enum Type { NONE, SHADER };
- explicit NodeType(Type type = NONE);
+ explicit NodeType(Type type = NONE, const NodeType *base = NULL);
~NodeType();
void register_input(ustring name,
@@ -124,11 +124,15 @@ struct NodeType {
ustring name;
Type type;
+ const NodeType *base;
vector<SocketType, std::allocator<SocketType>> inputs;
vector<SocketType, std::allocator<SocketType>> outputs;
CreateFunc create;
- static NodeType *add(const char *name, CreateFunc create, Type type = NONE);
+ static NodeType *add(const char *name,
+ CreateFunc create,
+ Type type = NONE,
+ const NodeType *base = NULL);
static const NodeType *find(ustring name);
static unordered_map<ustring, NodeType, ustringHash> &types();
};
@@ -148,6 +152,14 @@ struct NodeType {
} \
template<typename T> const NodeType *structname::register_type()
+#define NODE_ABSTRACT_DECLARE \
+ template<typename T> static const NodeType *register_base_type(); \
+ static const NodeType *node_base_type;
+
+#define NODE_ABSTRACT_DEFINE(structname) \
+ const NodeType *structname::node_base_type = structname::register_base_type<structname>(); \
+ template<typename T> const NodeType *structname::register_base_type()
+
/* Sock Definition Macros */
#define SOCKET_OFFSETOF(T, name) (((char *)&(((T *)1)->name)) - (char *)1)
diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp
index a96970cc904..d333400cc4a 100644
--- a/intern/cycles/graph/node_xml.cpp
+++ b/intern/cycles/graph/node_xml.cpp
@@ -200,7 +200,7 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
map<ustring, Node *>::iterator it = reader.node_map.find(value);
if (it != reader.node_map.end()) {
Node *value_node = it->second;
- if (value_node->type == *(socket.node_type))
+ if (value_node->is_a(*(socket.node_type)))
node->set(socket, it->second);
}
break;
@@ -215,7 +215,7 @@ void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i]));
if (it != reader.node_map.end()) {
Node *value_node = it->second;
- value[i] = (value_node->type == *(socket.node_type)) ? value_node : NULL;
+ value[i] = (value_node->is_a(*(socket.node_type))) ? value_node : NULL;
}
else {
value[i] = NULL;
diff --git a/intern/cycles/kernel/filter/filter_features_sse.h b/intern/cycles/kernel/filter/filter_features_sse.h
index 7bbd17066fd..59d4ace2bef 100644
--- a/intern/cycles/kernel/filter/filter_features_sse.h
+++ b/intern/cycles/kernel/filter/filter_features_sse.h
@@ -109,7 +109,6 @@ ccl_device_inline void filter_calculate_scale_sse(float4 *scale, bool use_time)
scale[2] = rcp(max(reduce_max(scale[2]), make_float4(0.01f)));
if (use_time) {
scale[10] = rcp(max(reduce_max(scale[6]), make_float4(0.01f)));
- ;
}
scale[6] = rcp(max(reduce_max(scale[4]), make_float4(0.01f)));
scale[7] = scale[8] = scale[9] = rcp(max(reduce_max(sqrt(scale[5])), make_float4(0.01f)));
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index 456608bfa22..e1b0e6fb81c 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -29,17 +29,11 @@ ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *
ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderData *sd)
{
-#ifdef __HAIR__
- if (sd->type & PRIMITIVE_ALL_CURVE) {
- return ATTR_PRIM_CURVE;
- }
- else
-#endif
- if (subd_triangle_patch(kg, sd) != ~0) {
+ if ((sd->type & PRIMITIVE_ALL_TRIANGLE) && subd_triangle_patch(kg, sd) != ~0) {
return ATTR_PRIM_SUBD;
}
else {
- return ATTR_PRIM_TRIANGLE;
+ return ATTR_PRIM_GEOMETRY;
}
}
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index e0aacb434eb..928cad58452 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -83,6 +83,16 @@ ccl_device float curve_attribute_float(
return (1.0f - sd->u) * f0 + sd->u * f1;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+# endif
+
+ return kernel_tex_fetch(__attributes_float, desc.offset);
+ }
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -133,6 +143,16 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg,
return (1.0f - sd->u) * f0 + sd->u * f1;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+# endif
+
+ return kernel_tex_fetch(__attributes_float2, desc.offset);
+ }
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -183,6 +203,16 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg,
return (1.0f - sd->u) * f0 + sd->u * f1;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+# endif
+
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset));
+ }
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
diff --git a/intern/cycles/kernel/geom/geom_motion_curve.h b/intern/cycles/kernel/geom/geom_motion_curve.h
index 7380c506bf4..0e2a00e9d2e 100644
--- a/intern/cycles/kernel/geom/geom_motion_curve.h
+++ b/intern/cycles/kernel/geom/geom_motion_curve.h
@@ -36,7 +36,7 @@ ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg,
* zero iterations and rendering is really slow with motion curves. For until other
* areas are speed up it's probably not so crucial to optimize this out.
*/
- uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_CURVE;
+ uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_GEOMETRY;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while (attr_map.x != id) {
diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h
index 81bac6e6ee1..3eef9857ae3 100644
--- a/intern/cycles/kernel/geom/geom_subd_triangle.h
+++ b/intern/cycles/kernel/geom/geom_subd_triangle.h
@@ -217,6 +217,14 @@ ccl_device_noinline float subd_triangle_attribute_float(
return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+
+ return kernel_tex_fetch(__attributes_float, desc.offset);
+ }
else {
if (dx)
*dx = 0.0f;
@@ -352,6 +360,14 @@ ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals *kg,
return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+
+ return kernel_tex_fetch(__attributes_float2, desc.offset);
+ }
else {
if (dx)
*dx = make_float2(0.0f, 0.0f);
@@ -486,6 +502,14 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg,
return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset));
+ }
else {
if (dx)
*dx = make_float3(0.0f, 0.0f, 0.0f);
@@ -584,6 +608,14 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg,
return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ return color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset));
+ }
else {
if (dx)
*dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index fdb7f655f64..a2731bf2bd0 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -153,6 +153,14 @@ ccl_device float triangle_attribute_float(
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+
+ return kernel_tex_fetch(__attributes_float, desc.offset);
+ }
else {
if (dx)
*dx = 0.0f;
@@ -212,6 +220,14 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals *kg,
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+
+ return kernel_tex_fetch(__attributes_float2, desc.offset);
+ }
else {
if (dx)
*dx = make_float2(0.0f, 0.0f);
@@ -272,6 +288,14 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset));
+ }
else {
if (dx)
*dx = make_float3(0.0f, 0.0f, 0.0f);
@@ -304,6 +328,14 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg,
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
+ else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
+ if (dx)
+ *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ return color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset));
+ }
else {
if (dx)
*dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 4cac6e9ca5f..bf34450df4b 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -725,8 +725,7 @@ typedef enum PrimitiveType {
/* Attributes */
typedef enum AttributePrimitive {
- ATTR_PRIM_TRIANGLE = 0,
- ATTR_PRIM_CURVE,
+ ATTR_PRIM_GEOMETRY = 0,
ATTR_PRIM_SUBD,
ATTR_PRIM_TYPES
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index db5ad06d3fc..0994bfaf950 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -382,10 +382,6 @@ int OSLShader::find_attribute(KernelGlobals *kg,
{
/* for OSL, a hash map is used to lookup the attribute by name. */
int object = sd->object * ATTR_PRIM_TYPES;
-#ifdef __HAIR__
- if (sd->type & PRIMITIVE_ALL_CURVE)
- object += ATTR_PRIM_CURVE;
-#endif
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
ustring stdname(std::string("geom:") +
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 92578b888a6..9e876b8d95c 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -19,7 +19,9 @@ set(SRC
coverage.cpp
denoising.cpp
film.cpp
+ geometry.cpp
graph.cpp
+ hair.cpp
image.cpp
integrator.cpp
light.cpp
@@ -54,7 +56,9 @@ set(SRC_HEADERS
coverage.h
denoising.h
film.h
+ geometry.h
graph.h
+ hair.h
image.h
integrator.h
light.h
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index b65c2faa788..05c0b5693bc 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -15,6 +15,7 @@
*/
#include "render/image.h"
+#include "render/hair.h"
#include "render/mesh.h"
#include "render/attribute.h"
@@ -52,13 +53,13 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
type == TypeRGBA);
}
-void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
+void Attribute::resize(Geometry *geom, AttributePrimitive prim, bool reserve_only)
{
if (reserve_only) {
- buffer.reserve(buffer_size(mesh, prim));
+ buffer.reserve(buffer_size(geom, prim));
}
else {
- buffer.resize(buffer_size(mesh, prim), 0);
+ buffer.resize(buffer_size(geom, prim), 0);
}
}
@@ -157,13 +158,13 @@ size_t Attribute::data_sizeof() const
return sizeof(float3);
}
-size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
+size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const
{
if (flags & ATTR_FINAL_SIZE) {
return buffer.size() / data_sizeof();
}
- size_t size;
+ size_t size = 0;
switch (element) {
case ATTR_ELEMENT_OBJECT:
@@ -172,54 +173,74 @@ size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
size = 1;
break;
case ATTR_ELEMENT_VERTEX:
- size = mesh->verts.size() + mesh->num_ngons;
- if (prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts;
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ size = mesh->verts.size() + mesh->num_ngons;
+ if (prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts;
+ }
}
break;
case ATTR_ELEMENT_VERTEX_MOTION:
- size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
- if (prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
+ if (prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
+ }
}
break;
case ATTR_ELEMENT_FACE:
- if (prim == ATTR_PRIM_TRIANGLE) {
- size = mesh->num_triangles();
- }
- else {
- size = mesh->subd_faces.size() + mesh->num_ngons;
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (prim == ATTR_PRIM_GEOMETRY) {
+ size = mesh->num_triangles();
+ }
+ else {
+ size = mesh->subd_faces.size() + mesh->num_ngons;
+ }
}
break;
case ATTR_ELEMENT_CORNER:
case ATTR_ELEMENT_CORNER_BYTE:
- if (prim == ATTR_PRIM_TRIANGLE) {
- size = mesh->num_triangles() * 3;
- }
- else {
- size = mesh->subd_face_corners.size() + mesh->num_ngons;
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (prim == ATTR_PRIM_GEOMETRY) {
+ size = mesh->num_triangles() * 3;
+ }
+ else {
+ size = mesh->subd_face_corners.size() + mesh->num_ngons;
+ }
}
break;
case ATTR_ELEMENT_CURVE:
- size = mesh->num_curves();
+ if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ size = hair->num_curves();
+ }
break;
case ATTR_ELEMENT_CURVE_KEY:
- size = mesh->curve_keys.size();
+ if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ size = hair->curve_keys.size();
+ }
break;
case ATTR_ELEMENT_CURVE_KEY_MOTION:
- size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
+ if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ size = hair->curve_keys.size() * (hair->motion_steps - 1);
+ }
break;
default:
- size = 0;
break;
}
return size;
}
-size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
+size_t Attribute::buffer_size(Geometry *geom, AttributePrimitive prim) const
{
- return element_size(mesh, prim) * data_sizeof();
+ return element_size(geom, prim) * data_sizeof();
}
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
@@ -336,13 +357,42 @@ AttributeStandard Attribute::name_standard(const char *name)
return ATTR_STD_NONE;
}
+void Attribute::get_uv_tiles(Geometry *geom,
+ AttributePrimitive prim,
+ unordered_set<int> &tiles) const
+{
+ if (type != TypeFloat2) {
+ return;
+ }
+
+ const int num = element_size(geom, prim);
+ const float2 *uv = data_float2();
+ for (int i = 0; i < num; i++, uv++) {
+ float u = uv->x, v = uv->y;
+ int x = (int)u, y = (int)v;
+
+ if (x < 0 || y < 0 || x >= 10) {
+ continue;
+ }
+
+ /* Be conservative in corners - precisely touching the right or upper edge of a tile
+ * should not load its right/upper neighbor as well. */
+ if (x > 0 && (u < x + 1e-6f)) {
+ x--;
+ }
+ if (y > 0 && (v < y + 1e-6f)) {
+ y--;
+ }
+
+ tiles.insert(1001 + 10 * y + x);
+ }
+}
+
/* Attribute Set */
-AttributeSet::AttributeSet()
+AttributeSet::AttributeSet(Geometry *geometry, AttributePrimitive prim)
+ : geometry(geometry), prim(prim)
{
- triangle_mesh = NULL;
- curve_mesh = NULL;
- subd_mesh = NULL;
}
AttributeSet::~AttributeSet()
@@ -376,12 +426,7 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
#endif
/* this is weak .. */
- if (triangle_mesh)
- attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
- if (curve_mesh)
- attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
- if (subd_mesh)
- attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
+ attr->resize(geometry, prim, false);
return attr;
}
@@ -418,7 +463,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
if (name == ustring())
name = Attribute::standard_name(std);
- if (triangle_mesh || subd_mesh) {
+ if (geometry->type == Geometry::MESH) {
switch (std) {
case ATTR_STD_VERTEX_NORMAL:
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
@@ -478,7 +523,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
break;
}
}
- else if (curve_mesh) {
+ else if (geometry->type == Geometry::HAIR) {
switch (std) {
case ATTR_STD_UV:
attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
@@ -561,12 +606,7 @@ void AttributeSet::remove(Attribute *attribute)
void AttributeSet::resize(bool reserve_only)
{
foreach (Attribute &attr, attributes) {
- if (triangle_mesh)
- attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
- if (curve_mesh)
- attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
- if (subd_mesh)
- attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
+ attr.resize(geometry, prim, reserve_only);
}
}
@@ -596,15 +636,10 @@ AttributeRequest::AttributeRequest(ustring name_)
name = name_;
std = ATTR_STD_NONE;
- triangle_type = TypeDesc::TypeFloat;
- triangle_desc.element = ATTR_ELEMENT_NONE;
- triangle_desc.offset = 0;
- triangle_desc.type = NODE_ATTR_FLOAT;
-
- curve_type = TypeDesc::TypeFloat;
- curve_desc.element = ATTR_ELEMENT_NONE;
- curve_desc.offset = 0;
- curve_desc.type = NODE_ATTR_FLOAT;
+ type = TypeDesc::TypeFloat;
+ desc.element = ATTR_ELEMENT_NONE;
+ desc.offset = 0;
+ desc.type = NODE_ATTR_FLOAT;
subd_type = TypeDesc::TypeFloat;
subd_desc.element = ATTR_ELEMENT_NONE;
@@ -617,15 +652,10 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
name = ustring();
std = std_;
- triangle_type = TypeDesc::TypeFloat;
- triangle_desc.element = ATTR_ELEMENT_NONE;
- triangle_desc.offset = 0;
- triangle_desc.type = NODE_ATTR_FLOAT;
-
- curve_type = TypeDesc::TypeFloat;
- curve_desc.element = ATTR_ELEMENT_NONE;
- curve_desc.offset = 0;
- curve_desc.type = NODE_ATTR_FLOAT;
+ type = TypeDesc::TypeFloat;
+ desc.element = ATTR_ELEMENT_NONE;
+ desc.offset = 0;
+ desc.type = NODE_ATTR_FLOAT;
subd_type = TypeDesc::TypeFloat;
subd_desc.element = ATTR_ELEMENT_NONE;
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index ebab0fe7f88..f1fd30fd85a 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -21,6 +21,7 @@
#include "util/util_list.h"
#include "util/util_param.h"
+#include "util/util_set.h"
#include "util/util_types.h"
#include "util/util_vector.h"
@@ -31,6 +32,8 @@ class AttributeRequest;
class AttributeRequestSet;
class AttributeSet;
class ImageManager;
+class Geometry;
+class Hair;
class Mesh;
struct Transform;
@@ -61,12 +64,12 @@ class Attribute {
}
~Attribute();
void set(ustring name, TypeDesc type, AttributeElement element);
- void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only);
+ void resize(Geometry *geom, AttributePrimitive prim, bool reserve_only);
void resize(size_t num_elements);
size_t data_sizeof() const;
- size_t element_size(Mesh *mesh, AttributePrimitive prim) const;
- size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const;
+ size_t element_size(Geometry *geom, AttributePrimitive prim) const;
+ size_t buffer_size(Geometry *geom, AttributePrimitive prim) const;
char *data()
{
@@ -157,6 +160,8 @@ class Attribute {
static bool same_storage(TypeDesc a, TypeDesc b);
static const char *standard_name(AttributeStandard std);
static AttributeStandard name_standard(const char *name);
+
+ void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set<int> &tiles) const;
};
/* Attribute Set
@@ -165,12 +170,11 @@ class Attribute {
class AttributeSet {
public:
- Mesh *triangle_mesh;
- Mesh *curve_mesh;
- Mesh *subd_mesh;
+ Geometry *geometry;
+ AttributePrimitive prim;
list<Attribute> attributes;
- AttributeSet();
+ AttributeSet(Geometry *geometry, AttributePrimitive prim);
~AttributeSet();
Attribute *add(ustring name, TypeDesc type, AttributeElement element);
@@ -200,9 +204,9 @@ class AttributeRequest {
ustring name;
AttributeStandard std;
- /* temporary variables used by MeshManager */
- TypeDesc triangle_type, curve_type, subd_type;
- AttributeDescriptor triangle_desc, curve_desc, subd_desc;
+ /* temporary variables used by GeometryManager */
+ TypeDesc type, subd_type;
+ AttributeDescriptor desc, subd_desc;
explicit AttributeRequest(ustring name_);
explicit AttributeRequest(AttributeStandard std);
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index b906357b7b5..9613da7c152 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -253,8 +253,8 @@ int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType ty
/* Only antialias normal if mesh has bump mapping. */
Object *object = scene->objects[bake_data->object()];
- if (object->mesh) {
- foreach (Shader *shader, object->mesh->used_shaders) {
+ if (object->geometry) {
+ foreach (Shader *shader, object->geometry->used_shaders) {
if (shader->has_bump) {
return scene->integrator->aa_samples;
}
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 38306a63c74..14ccf6696bd 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -498,7 +498,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen
BoundBox viewplane_boundbox = viewplane_bounds_get();
for (size_t i = 0; i < scene->objects.size(); ++i) {
Object *object = scene->objects[i];
- if (object->mesh->has_volume && viewplane_boundbox.intersects(object->bounds)) {
+ if (object->geometry->has_volume && viewplane_boundbox.intersects(object->bounds)) {
/* TODO(sergey): Consider adding more grained check. */
VLOG(1) << "Detected camera inside volume.";
kcam->is_inside_volume = 1;
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 4af0f3c45f0..00356790261 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -593,13 +593,13 @@ bool Film::modified(const Film &film)
void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes)
{
if (Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
- scene->mesh_manager->tag_update(scene);
+ scene->geometry_manager->tag_update(scene);
foreach (Shader *shader, scene->shaders)
- shader->need_update_mesh = true;
+ shader->need_update_geometry = true;
}
else if (Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION)) {
- scene->mesh_manager->tag_update(scene);
+ scene->geometry_manager->tag_update(scene);
}
else if (Pass::contains(passes, PASS_AO) != Pass::contains(passes_, PASS_AO)) {
scene->integrator->tag_update(scene);
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp
new file mode 100644
index 00000000000..880fb7b4c7d
--- /dev/null
+++ b/intern/cycles/render/geometry.cpp
@@ -0,0 +1,1469 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bvh/bvh.h"
+#include "bvh/bvh_build.h"
+
+#ifdef WITH_EMBREE
+# include "bvh/bvh_embree.h"
+#endif
+
+#include "render/attribute.h"
+#include "render/camera.h"
+#include "render/geometry.h"
+#include "render/hair.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/nodes.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/stats.h"
+
+#include "subd/subd_split.h"
+#include "subd/subd_patch_table.h"
+
+#include "kernel/osl/osl_globals.h"
+
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Geometry */
+
+NODE_ABSTRACT_DEFINE(Geometry)
+{
+ NodeType *type = NodeType::add("geometry_base", NULL);
+
+ SOCKET_UINT(motion_steps, "Motion Steps", 3);
+ SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
+
+ return type;
+}
+
+Geometry::Geometry(const NodeType *node_type, const Type type)
+ : Node(node_type), type(type), attributes(this, ATTR_PRIM_GEOMETRY)
+{
+ need_update = true;
+ need_update_rebuild = false;
+
+ transform_applied = false;
+ transform_negative_scaled = false;
+ transform_normal = transform_identity();
+ bounds = BoundBox::empty;
+
+ has_volume = false;
+ has_surface_bssrdf = false;
+
+ bvh = NULL;
+ attr_map_offset = 0;
+ optix_prim_offset = 0;
+ prim_offset = 0;
+}
+
+Geometry::~Geometry()
+{
+ delete bvh;
+}
+
+void Geometry::clear()
+{
+ used_shaders.clear();
+ transform_applied = false;
+ transform_negative_scaled = false;
+ transform_normal = transform_identity();
+}
+
+bool Geometry::need_attribute(Scene *scene, AttributeStandard std)
+{
+ if (std == ATTR_STD_NONE)
+ return false;
+
+ if (scene->need_global_attribute(std))
+ return true;
+
+ foreach (Shader *shader, used_shaders)
+ if (shader->attributes.find(std))
+ return true;
+
+ return false;
+}
+
+bool Geometry::need_attribute(Scene * /*scene*/, ustring name)
+{
+ if (name == ustring())
+ return false;
+
+ foreach (Shader *shader, used_shaders)
+ if (shader->attributes.find(name))
+ return true;
+
+ return false;
+}
+
+float Geometry::motion_time(int step) const
+{
+ return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
+}
+
+int Geometry::motion_step(float time) const
+{
+ if (motion_steps > 1) {
+ int attr_step = 0;
+
+ for (int step = 0; step < motion_steps; step++) {
+ float step_time = motion_time(step);
+ if (step_time == time) {
+ return attr_step;
+ }
+
+ /* Center step is stored in a separate attribute. */
+ if (step != motion_steps / 2) {
+ attr_step++;
+ }
+ }
+ }
+
+ return -1;
+}
+
+bool Geometry::need_build_bvh(BVHLayout layout) const
+{
+ return !transform_applied || has_surface_bssrdf || layout == BVH_LAYOUT_OPTIX;
+}
+
+bool Geometry::is_instanced() const
+{
+ /* Currently we treat subsurface objects as instanced.
+ *
+ * While it might be not very optimal for ray traversal, it avoids having
+ * duplicated BVH in the memory, saving quite some space.
+ */
+ return !transform_applied || has_surface_bssrdf;
+}
+
+bool Geometry::has_true_displacement() const
+{
+ foreach (Shader *shader, used_shaders) {
+ if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Geometry::compute_bvh(
+ Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, int n, int total)
+{
+ if (progress->get_cancel())
+ return;
+
+ compute_bounds();
+
+ const BVHLayout bvh_layout = BVHParams::best_bvh_layout(params->bvh_layout,
+ device->get_bvh_layout_mask());
+ if (need_build_bvh(bvh_layout)) {
+ string msg = "Updating Geometry BVH ";
+ if (name.empty())
+ msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
+ else
+ msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
+
+ Object object;
+ object.geometry = this;
+
+ vector<Geometry *> geometry;
+ geometry.push_back(this);
+ vector<Object *> objects;
+ objects.push_back(&object);
+
+ if (bvh && !need_update_rebuild) {
+ progress->set_status(msg, "Refitting BVH");
+
+ bvh->geometry = geometry;
+ bvh->objects = objects;
+
+ bvh->refit(*progress);
+ }
+ else {
+ progress->set_status(msg, "Building BVH");
+
+ BVHParams bparams;
+ bparams.use_spatial_split = params->use_bvh_spatial_split;
+ bparams.bvh_layout = bvh_layout;
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ params->use_bvh_unaligned_nodes;
+ bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
+ bparams.num_motion_curve_steps = params->num_bvh_time_steps;
+ bparams.bvh_type = params->bvh_type;
+ bparams.curve_flags = dscene->data.curve.curveflags;
+ bparams.curve_subdivisions = dscene->data.curve.subdivisions;
+
+ delete bvh;
+ bvh = BVH::create(bparams, geometry, objects);
+ MEM_GUARDED_CALL(progress, bvh->build, *progress);
+ }
+ }
+
+ need_update = false;
+ need_update_rebuild = false;
+}
+
+bool Geometry::has_motion_blur() const
+{
+ return (use_motion_blur && attributes.find(ATTR_STD_MOTION_VERTEX_POSITION));
+}
+
+bool Geometry::has_voxel_attributes() const
+{
+ foreach (const Attribute &attr, attributes.attributes) {
+ if (attr.element == ATTR_ELEMENT_VOXEL) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Geometry::tag_update(Scene *scene, bool rebuild)
+{
+ need_update = true;
+
+ if (rebuild) {
+ need_update_rebuild = true;
+ scene->light_manager->need_update = true;
+ }
+ else {
+ foreach (Shader *shader, used_shaders)
+ if (shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
+
+ scene->geometry_manager->need_update = true;
+ scene->object_manager->need_update = true;
+}
+
+/* Geometry Manager */
+
+GeometryManager::GeometryManager()
+{
+ need_update = true;
+ need_flags_update = true;
+}
+
+GeometryManager::~GeometryManager()
+{
+}
+
+void GeometryManager::update_osl_attributes(Device *device,
+ Scene *scene,
+ vector<AttributeRequestSet> &geom_attributes)
+{
+#ifdef WITH_OSL
+ /* for OSL, a hash map is used to lookup the attribute by name. */
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
+
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+
+ og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES);
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ /* set object name to object index map */
+ Object *object = scene->objects[i];
+ og->object_name_map[object->name] = i;
+ og->object_names.push_back(object->name);
+
+ /* set object attributes */
+ foreach (ParamValue &attr, object->attributes) {
+ OSLGlobals::Attribute osl_attr;
+
+ osl_attr.type = attr.type();
+ osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
+ osl_attr.value = attr;
+ osl_attr.desc.offset = 0;
+ osl_attr.desc.flags = 0;
+
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][attr.name()] = osl_attr;
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr;
+ }
+
+ /* find geometry attributes */
+ size_t j;
+
+ for (j = 0; j < scene->geometry.size(); j++)
+ if (scene->geometry[j] == object->geometry)
+ break;
+
+ AttributeRequestSet &attributes = geom_attributes[j];
+
+ /* set object attributes */
+ foreach (AttributeRequest &req, attributes.requests) {
+ OSLGlobals::Attribute osl_attr;
+
+ if (req.desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.desc;
+
+ if (req.type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else if (req.type == TypeFloat2)
+ osl_attr.type = TypeFloat2;
+ else if (req.type == TypeRGBA)
+ osl_attr.type = TypeRGBA;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by geometry attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][req.name] = osl_attr;
+ }
+ }
+
+ if (req.subd_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.subd_desc;
+
+ if (req.subd_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.subd_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else if (req.subd_type == TypeFloat2)
+ osl_attr.type = TypeFloat2;
+ else if (req.subd_type == TypeRGBA)
+ osl_attr.type = TypeRGBA;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by geometry attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr;
+ }
+ }
+ }
+ }
+#else
+ (void)device;
+ (void)scene;
+ (void)geom_attributes;
+#endif
+}
+
+void GeometryManager::update_svm_attributes(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ vector<AttributeRequestSet> &geom_attributes)
+{
+ /* for SVM, the attributes_map table is used to lookup the offset of an
+ * attribute, based on a unique shader attribute id. */
+
+ /* compute array stride */
+ int attr_map_size = 0;
+
+ for (size_t i = 0; i < scene->geometry.size(); i++) {
+ Geometry *geom = scene->geometry[i];
+ geom->attr_map_offset = attr_map_size;
+ attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
+ }
+
+ if (attr_map_size == 0)
+ return;
+
+ /* create attribute map */
+ uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
+ memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint));
+
+ for (size_t i = 0; i < scene->geometry.size(); i++) {
+ Geometry *geom = scene->geometry[i];
+ AttributeRequestSet &attributes = geom_attributes[i];
+
+ /* set object attributes */
+ int index = geom->attr_map_offset;
+
+ foreach (AttributeRequest &req, attributes.requests) {
+ uint id;
+
+ if (req.std == ATTR_STD_NONE)
+ id = scene->shader_manager->get_attribute_id(req.name);
+ else
+ id = scene->shader_manager->get_attribute_id(req.std);
+
+ attr_map[index].x = id;
+ attr_map[index].y = req.desc.element;
+ attr_map[index].z = as_uint(req.desc.offset);
+
+ if (req.type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else if (req.type == TypeRGBA)
+ attr_map[index].w = NODE_ATTR_RGBA;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
+
+ attr_map[index].w |= req.desc.flags << 8;
+
+ index++;
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->subd_faces.size()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.subd_desc.element;
+ attr_map[index].z = as_uint(req.subd_desc.offset);
+
+ if (req.subd_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.subd_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.subd_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else if (req.subd_type == TypeRGBA)
+ attr_map[index].w = NODE_ATTR_RGBA;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
+
+ attr_map[index].w |= req.subd_desc.flags << 8;
+ }
+ }
+
+ index++;
+ }
+
+ /* terminator */
+ for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
+ attr_map[index].x = ATTR_STD_NONE;
+ attr_map[index].y = 0;
+ attr_map[index].z = 0;
+ attr_map[index].w = 0;
+
+ index++;
+ }
+ }
+
+ /* copy to device */
+ dscene->attributes_map.copy_to_device();
+}
+
+static void update_attribute_element_size(Geometry *geom,
+ Attribute *mattr,
+ AttributePrimitive prim,
+ size_t *attr_float_size,
+ size_t *attr_float2_size,
+ size_t *attr_float3_size,
+ size_t *attr_uchar4_size)
+{
+ if (mattr) {
+ size_t size = mattr->element_size(geom, prim);
+
+ if (mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* pass */
+ }
+ else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ *attr_uchar4_size += size;
+ }
+ else if (mattr->type == TypeDesc::TypeFloat) {
+ *attr_float_size += size;
+ }
+ else if (mattr->type == TypeFloat2) {
+ *attr_float2_size += size;
+ }
+ else if (mattr->type == TypeDesc::TypeMatrix) {
+ *attr_float3_size += size * 4;
+ }
+ else {
+ *attr_float3_size += size;
+ }
+ }
+}
+
+static void update_attribute_element_offset(Geometry *geom,
+ device_vector<float> &attr_float,
+ size_t &attr_float_offset,
+ device_vector<float2> &attr_float2,
+ size_t &attr_float2_offset,
+ device_vector<float4> &attr_float3,
+ size_t &attr_float3_offset,
+ device_vector<uchar4> &attr_uchar4,
+ size_t &attr_uchar4_offset,
+ Attribute *mattr,
+ AttributePrimitive prim,
+ TypeDesc &type,
+ AttributeDescriptor &desc)
+{
+ if (mattr) {
+ /* store element and type */
+ desc.element = mattr->element;
+ desc.flags = mattr->flags;
+ type = mattr->type;
+
+ /* store attribute data in arrays */
+ size_t size = mattr->element_size(geom, prim);
+
+ AttributeElement &element = desc.element;
+ int &offset = desc.offset;
+
+ if (mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* store slot in offset value */
+ VoxelAttribute *voxel_data = mattr->data_voxel();
+ offset = voxel_data->slot;
+ }
+ else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ uchar4 *data = mattr->data_uchar4();
+ offset = attr_uchar4_offset;
+
+ assert(attr_uchar4.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_uchar4[offset + k] = data[k];
+ }
+ attr_uchar4_offset += size;
+ }
+ else if (mattr->type == TypeDesc::TypeFloat) {
+ float *data = mattr->data_float();
+ offset = attr_float_offset;
+
+ assert(attr_float.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float[offset + k] = data[k];
+ }
+ attr_float_offset += size;
+ }
+ else if (mattr->type == TypeFloat2) {
+ float2 *data = mattr->data_float2();
+ offset = attr_float2_offset;
+
+ assert(attr_float2.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float2[offset + k] = data[k];
+ }
+ attr_float2_offset += size;
+ }
+ else if (mattr->type == TypeDesc::TypeMatrix) {
+ Transform *tfm = mattr->data_transform();
+ offset = attr_float3_offset;
+
+ assert(attr_float3.size() >= offset + size * 3);
+ for (size_t k = 0; k < size * 3; k++) {
+ attr_float3[offset + k] = (&tfm->x)[k];
+ }
+ attr_float3_offset += size * 3;
+ }
+ else {
+ float4 *data = mattr->data_float4();
+ offset = attr_float3_offset;
+
+ assert(attr_float3.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float3[offset + k] = data[k];
+ }
+ attr_float3_offset += size;
+ }
+
+ /* mesh vertex/curve index is global, not per object, so we sneak
+ * a correction for that in here */
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
+ desc.flags & ATTR_SUBDIVIDED) {
+ /* indices for subdivided attributes are retrieved
+ * from patch table so no need for correction here*/
+ }
+ else if (element == ATTR_ELEMENT_VERTEX)
+ offset -= mesh->vert_offset;
+ else if (element == ATTR_ELEMENT_VERTEX_MOTION)
+ offset -= mesh->vert_offset;
+ else if (element == ATTR_ELEMENT_FACE) {
+ if (prim == ATTR_PRIM_GEOMETRY)
+ offset -= mesh->prim_offset;
+ else
+ offset -= mesh->face_offset;
+ }
+ else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
+ if (prim == ATTR_PRIM_GEOMETRY)
+ offset -= 3 * mesh->prim_offset;
+ else
+ offset -= mesh->corner_offset;
+ }
+ }
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ if (element == ATTR_ELEMENT_CURVE)
+ offset -= hair->prim_offset;
+ else if (element == ATTR_ELEMENT_CURVE_KEY)
+ offset -= hair->curvekey_offset;
+ else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
+ offset -= hair->curvekey_offset;
+ }
+ }
+ else {
+ /* attribute not found */
+ desc.element = ATTR_ELEMENT_NONE;
+ desc.offset = 0;
+ }
+}
+
+void GeometryManager::device_update_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ progress.set_status("Updating Mesh", "Computing attributes");
+
+ /* gather per mesh requested attributes. as meshes may have multiple
+ * shaders assigned, this merges the requested attributes that have
+ * been set per shader by the shader manager */
+ vector<AttributeRequestSet> geom_attributes(scene->geometry.size());
+
+ for (size_t i = 0; i < scene->geometry.size(); i++) {
+ Geometry *geom = scene->geometry[i];
+
+ scene->need_global_attributes(geom_attributes[i]);
+
+ foreach (Shader *shader, geom->used_shaders) {
+ geom_attributes[i].add(shader->attributes);
+ }
+ }
+
+ /* mesh attribute are stored in a single array per data type. here we fill
+ * those arrays, and set the offset and element type to create attribute
+ * maps next */
+
+ /* Pre-allocate attributes to avoid arrays re-allocation which would
+ * take 2x of overall attribute memory usage.
+ */
+ size_t attr_float_size = 0;
+ size_t attr_float2_size = 0;
+ size_t attr_float3_size = 0;
+ size_t attr_uchar4_size = 0;
+ for (size_t i = 0; i < scene->geometry.size(); i++) {
+ Geometry *geom = scene->geometry[i];
+ AttributeRequestSet &attributes = geom_attributes[i];
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *attr = geom->attributes.find(req);
+
+ update_attribute_element_size(geom,
+ attr,
+ ATTR_PRIM_GEOMETRY,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ Attribute *subd_attr = mesh->subd_attributes.find(req);
+
+ update_attribute_element_size(mesh,
+ subd_attr,
+ ATTR_PRIM_SUBD,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ }
+ }
+ }
+
+ dscene->attributes_float.alloc(attr_float_size);
+ dscene->attributes_float2.alloc(attr_float2_size);
+ dscene->attributes_float3.alloc(attr_float3_size);
+ dscene->attributes_uchar4.alloc(attr_uchar4_size);
+
+ size_t attr_float_offset = 0;
+ size_t attr_float2_offset = 0;
+ size_t attr_float3_offset = 0;
+ size_t attr_uchar4_offset = 0;
+
+ /* Fill in attributes. */
+ for (size_t i = 0; i < scene->geometry.size(); i++) {
+ Geometry *geom = scene->geometry[i];
+ AttributeRequestSet &attributes = geom_attributes[i];
+
+ /* todo: we now store std and name attributes from requests even if
+ * they actually refer to the same mesh attributes, optimize */
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *attr = geom->attributes.find(req);
+ update_attribute_element_offset(geom,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ attr,
+ ATTR_PRIM_GEOMETRY,
+ req.type,
+ req.desc);
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ Attribute *subd_attr = mesh->subd_attributes.find(req);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ subd_attr,
+ ATTR_PRIM_SUBD,
+ req.subd_type,
+ req.subd_desc);
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* create attribute lookup maps */
+ if (scene->shader_manager->use_osl())
+ update_osl_attributes(device, scene, geom_attributes);
+
+ update_svm_attributes(device, dscene, scene, geom_attributes);
+
+ if (progress.get_cancel())
+ return;
+
+ /* copy to device */
+ progress.set_status("Updating Mesh", "Copying Attributes to device");
+
+ if (dscene->attributes_float.size()) {
+ dscene->attributes_float.copy_to_device();
+ }
+ if (dscene->attributes_float2.size()) {
+ dscene->attributes_float2.copy_to_device();
+ }
+ if (dscene->attributes_float3.size()) {
+ dscene->attributes_float3.copy_to_device();
+ }
+ if (dscene->attributes_uchar4.size()) {
+ dscene->attributes_uchar4.copy_to_device();
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ /* After mesh attributes and patch tables have been copied to device memory,
+ * we need to update offsets in the objects. */
+ scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
+}
+
+void GeometryManager::mesh_calc_offset(Scene *scene)
+{
+ size_t vert_size = 0;
+ size_t tri_size = 0;
+
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
+ size_t patch_size = 0;
+ size_t face_size = 0;
+ size_t corner_size = 0;
+
+ size_t optix_prim_size = 0;
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+
+ mesh->vert_offset = vert_size;
+ mesh->prim_offset = tri_size;
+
+ mesh->patch_offset = patch_size;
+ mesh->face_offset = face_size;
+ mesh->corner_offset = corner_size;
+
+ vert_size += mesh->verts.size();
+ tri_size += mesh->num_triangles();
+
+ if (mesh->subd_faces.size()) {
+ Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
+
+ /* patch tables are stored in same array so include them in patch_size */
+ if (mesh->patch_table) {
+ mesh->patch_table_offset = patch_size;
+ patch_size += mesh->patch_table->total_size();
+ }
+ }
+
+ face_size += mesh->subd_faces.size();
+ corner_size += mesh->subd_face_corners.size();
+
+ mesh->optix_prim_offset = optix_prim_size;
+ optix_prim_size += mesh->num_triangles();
+ }
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+
+ hair->curvekey_offset = curve_key_size;
+ hair->prim_offset = curve_size;
+
+ curve_key_size += hair->curve_keys.size();
+ curve_size += hair->num_curves();
+
+ hair->optix_prim_offset = optix_prim_size;
+ optix_prim_size += hair->num_segments();
+ }
+ }
+}
+
+void GeometryManager::device_update_mesh(
+ Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress)
+{
+ /* Count. */
+ size_t vert_size = 0;
+ size_t tri_size = 0;
+
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
+ size_t patch_size = 0;
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+
+ vert_size += mesh->verts.size();
+ tri_size += mesh->num_triangles();
+
+ if (mesh->subd_faces.size()) {
+ Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
+
+ /* patch tables are stored in same array so include them in patch_size */
+ if (mesh->patch_table) {
+ mesh->patch_table_offset = patch_size;
+ patch_size += mesh->patch_table->total_size();
+ }
+ }
+ }
+ else if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+
+ curve_key_size += hair->curve_keys.size();
+ curve_size += hair->num_curves();
+ }
+ }
+
+ /* Create mapping from triangle to primitive triangle array. */
+ vector<uint> tri_prim_index(tri_size);
+ if (for_displacement) {
+ /* For displacement kernels we do some trickery to make them believe
+ * we've got all required data ready. However, that data is different
+ * from final render kernels since we don't have BVH yet, so can't
+ * really use same semantic of arrays.
+ */
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ for (size_t i = 0; i < mesh->num_triangles(); ++i) {
+ tri_prim_index[i + mesh->prim_offset] = 3 * (i + mesh->prim_offset);
+ }
+ }
+ }
+ }
+ else {
+ for (size_t i = 0; i < dscene->prim_index.size(); ++i) {
+ if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i];
+ }
+ }
+ }
+
+ /* Fill in all the arrays. */
+ if (tri_size != 0) {
+ /* normals */
+ progress.set_status("Updating Mesh", "Computing normals");
+
+ uint *tri_shader = dscene->tri_shader.alloc(tri_size);
+ float4 *vnormal = dscene->tri_vnormal.alloc(vert_size);
+ uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
+ uint *tri_patch = dscene->tri_patch.alloc(tri_size);
+ float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]);
+ mesh->pack_normals(&vnormal[mesh->vert_offset]);
+ mesh->pack_verts(tri_prim_index,
+ &tri_vindex[mesh->prim_offset],
+ &tri_patch[mesh->prim_offset],
+ &tri_patch_uv[mesh->vert_offset],
+ mesh->vert_offset,
+ mesh->prim_offset);
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* vertex coordinates */
+ progress.set_status("Updating Mesh", "Copying Mesh to device");
+
+ dscene->tri_shader.copy_to_device();
+ dscene->tri_vnormal.copy_to_device();
+ dscene->tri_vindex.copy_to_device();
+ dscene->tri_patch.copy_to_device();
+ dscene->tri_patch_uv.copy_to_device();
+ }
+
+ if (curve_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Strands to device");
+
+ float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
+ float4 *curves = dscene->curves.alloc(curve_size);
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ hair->pack_curves(scene,
+ &curve_keys[hair->curvekey_offset],
+ &curves[hair->prim_offset],
+ hair->curvekey_offset);
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ dscene->curve_keys.copy_to_device();
+ dscene->curves.copy_to_device();
+ }
+
+ if (patch_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Patches to device");
+
+ uint *patch_data = dscene->patches.alloc(patch_size);
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ mesh->pack_patches(&patch_data[mesh->patch_offset],
+ mesh->vert_offset,
+ mesh->face_offset,
+ mesh->corner_offset);
+
+ if (mesh->patch_table) {
+ mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset],
+ mesh->patch_table_offset);
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ dscene->patches.copy_to_device();
+ }
+
+ if (for_displacement) {
+ float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ for (size_t i = 0; i < mesh->num_triangles(); ++i) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ size_t offset = 3 * (i + mesh->prim_offset);
+ prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
+ prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
+ prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
+ }
+ }
+ }
+ dscene->prim_tri_verts.copy_to_device();
+ }
+}
+
+void GeometryManager::device_update_bvh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ /* bvh build */
+ progress.set_status("Updating Scene BVH", "Building");
+
+ BVHParams bparams;
+ bparams.top_level = true;
+ bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
+ device->get_bvh_layout_mask());
+ bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ scene->params.use_bvh_unaligned_nodes;
+ bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
+ bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
+ bparams.bvh_type = scene->params.bvh_type;
+ bparams.curve_flags = dscene->data.curve.curveflags;
+ bparams.curve_subdivisions = dscene->data.curve.subdivisions;
+
+ VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
+
+#ifdef WITH_EMBREE
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ if (dscene->data.bvh.scene) {
+ BVHEmbree::destroy(dscene->data.bvh.scene);
+ }
+ }
+#endif
+
+ BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects);
+ bvh->build(progress, &device->stats);
+
+ if (progress.get_cancel()) {
+#ifdef WITH_EMBREE
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ if (dscene->data.bvh.scene) {
+ BVHEmbree::destroy(dscene->data.bvh.scene);
+ }
+ }
+#endif
+ delete bvh;
+ return;
+ }
+
+ /* copy to device */
+ progress.set_status("Updating Scene BVH", "Copying BVH to device");
+
+ PackedBVH &pack = bvh->pack;
+
+ if (pack.nodes.size()) {
+ dscene->bvh_nodes.steal_data(pack.nodes);
+ dscene->bvh_nodes.copy_to_device();
+ }
+ if (pack.leaf_nodes.size()) {
+ dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
+ dscene->bvh_leaf_nodes.copy_to_device();
+ }
+ if (pack.object_node.size()) {
+ dscene->object_node.steal_data(pack.object_node);
+ dscene->object_node.copy_to_device();
+ }
+ if (pack.prim_tri_index.size()) {
+ dscene->prim_tri_index.steal_data(pack.prim_tri_index);
+ dscene->prim_tri_index.copy_to_device();
+ }
+ if (pack.prim_tri_verts.size()) {
+ dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
+ dscene->prim_tri_verts.copy_to_device();
+ }
+ if (pack.prim_type.size()) {
+ dscene->prim_type.steal_data(pack.prim_type);
+ dscene->prim_type.copy_to_device();
+ }
+ if (pack.prim_visibility.size()) {
+ dscene->prim_visibility.steal_data(pack.prim_visibility);
+ dscene->prim_visibility.copy_to_device();
+ }
+ if (pack.prim_index.size()) {
+ dscene->prim_index.steal_data(pack.prim_index);
+ dscene->prim_index.copy_to_device();
+ }
+ if (pack.prim_object.size()) {
+ dscene->prim_object.steal_data(pack.prim_object);
+ dscene->prim_object.copy_to_device();
+ }
+ if (pack.prim_time.size()) {
+ dscene->prim_time.steal_data(pack.prim_time);
+ dscene->prim_time.copy_to_device();
+ }
+
+ dscene->data.bvh.root = pack.root_index;
+ dscene->data.bvh.bvh_layout = bparams.bvh_layout;
+ dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
+
+ bvh->copy_to_device(progress, dscene);
+
+ delete bvh;
+}
+
+void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress)
+{
+ if (!need_update && !need_flags_update) {
+ return;
+ }
+
+ progress.set_status("Updating Meshes Flags");
+
+ /* Update flags. */
+ bool volume_images_updated = false;
+
+ foreach (Geometry *geom, scene->geometry) {
+ geom->has_volume = false;
+
+ foreach (const Shader *shader, geom->used_shaders) {
+ if (shader->has_volume) {
+ geom->has_volume = true;
+ }
+ if (shader->has_surface_bssrdf) {
+ geom->has_surface_bssrdf = true;
+ }
+ }
+
+ if (need_update && geom->has_volume && geom->type == Geometry::MESH) {
+ /* Create volume meshes if there is voxel data. */
+ if (geom->has_voxel_attributes()) {
+ if (!volume_images_updated) {
+ progress.set_status("Updating Meshes Volume Bounds");
+ device_update_volume_images(device, scene, progress);
+ volume_images_updated = true;
+ }
+
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ create_volume_mesh(scene, mesh, progress);
+ }
+ }
+ }
+
+ need_flags_update = false;
+}
+
+void GeometryManager::device_update_displacement_images(Device *device,
+ Scene *scene,
+ Progress &progress)
+{
+ progress.set_status("Updating Displacement Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> bump_images;
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->need_update) {
+ foreach (Shader *shader, geom->used_shaders) {
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+ foreach (ShaderNode *node, shader->graph->nodes) {
+ if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
+ continue;
+ }
+
+ ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node);
+ foreach (int slot, image_node->slots) {
+ if (slot != -1) {
+ bump_images.insert(slot);
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach (int slot, bump_images) {
+ pool.push(function_bind(
+ &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
+ }
+ pool.wait_work();
+}
+
+void GeometryManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress)
+{
+ progress.set_status("Updating Volume Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> volume_images;
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (!geom->need_update) {
+ continue;
+ }
+
+ foreach (Attribute &attr, geom->attributes.attributes) {
+ if (attr.element != ATTR_ELEMENT_VOXEL) {
+ continue;
+ }
+
+ VoxelAttribute *voxel = attr.data_voxel();
+
+ if (voxel->slot != -1) {
+ volume_images.insert(voxel->slot);
+ }
+ }
+ }
+
+ foreach (int slot, volume_images) {
+ pool.push(function_bind(
+ &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
+ }
+ pool.wait_work();
+}
+
+void GeometryManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ if (!need_update)
+ return;
+
+ VLOG(1) << "Total " << scene->geometry.size() << " meshes.";
+
+ bool true_displacement_used = false;
+ size_t total_tess_needed = 0;
+
+ foreach (Geometry *geom, scene->geometry) {
+ foreach (Shader *shader, geom->used_shaders) {
+ if (shader->need_update_geometry)
+ geom->need_update = true;
+ }
+
+ if (geom->need_update && geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+
+ /* Update normals. */
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+
+ if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
+ mesh->add_undisplaced();
+ }
+
+ /* Test if we need tessellation. */
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
+ mesh->subd_params) {
+ total_tess_needed++;
+ }
+
+ /* Test if we need displacement. */
+ if (mesh->has_true_displacement()) {
+ true_displacement_used = true;
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* Tessellate meshes that are using subdivision */
+ if (total_tess_needed) {
+ Camera *dicing_camera = scene->dicing_camera;
+ dicing_camera->update(scene);
+
+ size_t i = 0;
+ foreach (Geometry *geom, scene->geometry) {
+ if (!(geom->need_update && geom->type == Geometry::MESH)) {
+ continue;
+ }
+
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
+ mesh->subd_params) {
+ string msg = "Tessellating ";
+ if (mesh->name == "")
+ msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
+ else
+ msg += string_printf(
+ "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed);
+
+ progress.set_status("Updating Mesh", msg);
+
+ mesh->subd_params->camera = dicing_camera;
+ DiagSplit dsplit(*mesh->subd_params);
+ mesh->tessellate(&dsplit);
+
+ i++;
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+ }
+
+ /* Update images needed for true displacement. */
+ bool old_need_object_flags_update = false;
+ if (true_displacement_used) {
+ VLOG(1) << "Updating images used for true displacement.";
+ device_update_displacement_images(device, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device, dscene, scene, progress, false);
+ }
+
+ /* Device update. */
+ device_free(device, dscene);
+
+ mesh_calc_offset(scene);
+ if (true_displacement_used) {
+ device_update_mesh(device, dscene, scene, true, progress);
+ }
+ if (progress.get_cancel())
+ return;
+
+ device_update_attributes(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
+ /* Update displacement. */
+ bool displacement_done = false;
+ size_t num_bvh = 0;
+ BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
+ device->get_bvh_layout_mask());
+
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->need_update) {
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (displace(device, dscene, scene, mesh, progress)) {
+ displacement_done = true;
+ }
+ }
+
+ if (geom->need_build_bvh(bvh_layout)) {
+ num_bvh++;
+ }
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ /* Device re-update after displacement. */
+ if (displacement_done) {
+ device_free(device, dscene);
+
+ device_update_attributes(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+ }
+
+ TaskPool pool;
+
+ size_t i = 0;
+ foreach (Geometry *geom, scene->geometry) {
+ if (geom->need_update) {
+ pool.push(function_bind(
+ &Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh));
+ if (geom->need_build_bvh(bvh_layout)) {
+ i++;
+ }
+ }
+ }
+
+ TaskPool::Summary summary;
+ pool.wait_work(&summary);
+ VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report();
+
+ foreach (Shader *shader, scene->shaders) {
+ shader->need_update_geometry = false;
+ }
+
+ Scene::MotionType need_motion = scene->need_motion();
+ bool motion_blur = need_motion == Scene::MOTION_BLUR;
+
+ /* Update objects. */
+ vector<Object *> volume_objects;
+ foreach (Object *object, scene->objects) {
+ object->compute_bounds(motion_blur);
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ device_update_bvh(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
+ device_update_mesh(device, dscene, scene, false, progress);
+ if (progress.get_cancel())
+ return;
+
+ need_update = false;
+
+ if (true_displacement_used) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
+}
+
+void GeometryManager::device_free(Device *device, DeviceScene *dscene)
+{
+ dscene->bvh_nodes.free();
+ dscene->bvh_leaf_nodes.free();
+ dscene->object_node.free();
+ dscene->prim_tri_verts.free();
+ dscene->prim_tri_index.free();
+ dscene->prim_type.free();
+ dscene->prim_visibility.free();
+ dscene->prim_index.free();
+ dscene->prim_object.free();
+ dscene->prim_time.free();
+ dscene->tri_shader.free();
+ dscene->tri_vnormal.free();
+ dscene->tri_vindex.free();
+ dscene->tri_patch.free();
+ dscene->tri_patch_uv.free();
+ dscene->curves.free();
+ dscene->curve_keys.free();
+ dscene->patches.free();
+ dscene->attributes_map.free();
+ dscene->attributes_float.free();
+ dscene->attributes_float2.free();
+ dscene->attributes_float3.free();
+ dscene->attributes_uchar4.free();
+
+ /* Signal for shaders like displacement not to do ray tracing. */
+ dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE;
+
+#ifdef WITH_OSL
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
+
+ if (og) {
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+ }
+#else
+ (void)device;
+#endif
+}
+
+void GeometryManager::tag_update(Scene *scene)
+{
+ need_update = true;
+ scene->object_manager->need_update = true;
+}
+
+void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats)
+{
+ foreach (Geometry *geometry, scene->geometry) {
+ stats->mesh.geometry.add_entry(
+ NamedSizeEntry(string(geometry->name.c_str()), geometry->get_total_size_in_bytes()));
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h
new file mode 100644
index 00000000000..711da1c81e8
--- /dev/null
+++ b/intern/cycles/render/geometry.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GEOMETRY_H__
+#define __GEOMETRY_H__
+
+#include "graph/node.h"
+
+#include "bvh/bvh_params.h"
+
+#include "render/attribute.h"
+
+#include "util/util_boundbox.h"
+#include "util/util_transform.h"
+#include "util/util_set.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+class BVH;
+class Device;
+class DeviceScene;
+class Mesh;
+class Progress;
+class RenderStats;
+class Scene;
+class SceneParams;
+class Shader;
+
+/* Geometry
+ *
+ * Base class for geometric types like Mesh and Hair. */
+
+class Geometry : public Node {
+ public:
+ NODE_ABSTRACT_DECLARE
+
+ enum Type {
+ MESH,
+ HAIR,
+ };
+
+ Type type;
+
+ /* Attributes */
+ AttributeSet attributes;
+
+ /* Shaders */
+ vector<Shader *> used_shaders;
+
+ /* Transform */
+ BoundBox bounds;
+ bool transform_applied;
+ bool transform_negative_scaled;
+ Transform transform_normal;
+
+ /* Motion Blur */
+ uint motion_steps;
+ bool use_motion_blur;
+
+ /* BVH */
+ BVH *bvh;
+ size_t attr_map_offset;
+ size_t prim_offset;
+ size_t optix_prim_offset;
+
+ /* Shader Properties */
+ bool has_volume; /* Set in the device_update_flags(). */
+ bool has_surface_bssrdf; /* Set in the device_update_flags(). */
+
+ /* Update Flags */
+ bool need_update;
+ bool need_update_rebuild;
+
+ /* Constructor/Destructor */
+ explicit Geometry(const NodeType *node_type, const Type type);
+ virtual ~Geometry();
+
+ /* Geometry */
+ virtual void clear();
+ virtual void compute_bounds() = 0;
+ virtual void apply_transform(const Transform &tfm, const bool apply_to_motion) = 0;
+
+ /* Attribute Requests */
+ bool need_attribute(Scene *scene, AttributeStandard std);
+ bool need_attribute(Scene *scene, ustring name);
+
+ /* UDIM */
+ virtual void get_uv_tiles(ustring map, unordered_set<int> &tiles) = 0;
+
+ /* Convert between normalized -1..1 motion time and index in the
+ * VERTEX_MOTION attribute. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+
+ /* BVH */
+ void compute_bvh(Device *device,
+ DeviceScene *dscene,
+ SceneParams *params,
+ Progress *progress,
+ int n,
+ int total);
+
+ /* Check whether the geometry should have own BVH built separately. Briefly,
+ * own BVH is needed for geometry, if:
+ *
+ * - It is instanced multiple times, so each instance object should share the
+ * same BVH tree.
+ * - Special ray intersection is needed, for example to limit subsurface rays
+ * to only the geometry itself.
+ * - The BVH layout requires the top level to only contain instances.
+ */
+ bool need_build_bvh(BVHLayout layout) const;
+
+ /* Test if the geometry should be treated as instanced. */
+ bool is_instanced() const;
+
+ bool has_true_displacement() const;
+ bool has_motion_blur() const;
+ bool has_voxel_attributes() const;
+
+ /* Updates */
+ void tag_update(Scene *scene, bool rebuild);
+};
+
+/* Geometry Manager */
+
+class GeometryManager {
+ public:
+ /* Update Flags */
+ bool need_update;
+ bool need_flags_update;
+
+ /* Constructor/Destructor */
+ GeometryManager();
+ ~GeometryManager();
+
+ /* Device Updates */
+ void device_update_preprocess(Device *device, Scene *scene, Progress &progress);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
+
+ /* Updates */
+ void tag_update(Scene *scene);
+
+ /* Statistics */
+ void collect_statistics(const Scene *scene, RenderStats *stats);
+
+ protected:
+ bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress);
+
+ void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
+
+ /* Attributes */
+ void update_osl_attributes(Device *device,
+ Scene *scene,
+ vector<AttributeRequestSet> &geom_attributes);
+ void update_svm_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ vector<AttributeRequestSet> &geom_attributes);
+
+ /* Compute verts/triangles/curves offsets in global arrays. */
+ void mesh_calc_offset(Scene *scene);
+
+ void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+
+ void device_update_mesh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ bool for_displacement,
+ Progress &progress);
+
+ void device_update_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+
+ void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+
+ void device_update_displacement_images(Device *device, Scene *scene, Progress &progress);
+
+ void device_update_volume_images(Device *device, Scene *scene, Progress &progress);
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __GEOMETRY_H__ */
diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp
new file mode 100644
index 00000000000..7220fe7093b
--- /dev/null
+++ b/intern/cycles/render/hair.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/curves.h"
+#include "render/hair.h"
+#include "render/scene.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Hair Curve */
+
+void Hair::Curve::bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox &bounds) const
+{
+ float3 P[4];
+
+ P[0] = curve_keys[max(first_key + k - 1, first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
+
+ float3 lower;
+ float3 upper;
+
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
+
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
+
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
+}
+
+void Hair::Curve::bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ const Transform &aligned_space,
+ BoundBox &bounds) const
+{
+ float3 P[4];
+
+ P[0] = curve_keys[max(first_key + k - 1, first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
+
+ P[0] = transform_point(&aligned_space, P[0]);
+ P[1] = transform_point(&aligned_space, P[1]);
+ P[2] = transform_point(&aligned_space, P[2]);
+ P[3] = transform_point(&aligned_space, P[3]);
+
+ float3 lower;
+ float3 upper;
+
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
+
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
+
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
+}
+
+void Hair::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const
+{
+ float3 P[4] = {
+ float4_to_float3(keys[0]),
+ float4_to_float3(keys[1]),
+ float4_to_float3(keys[2]),
+ float4_to_float3(keys[3]),
+ };
+
+ float3 lower;
+ float3 upper;
+
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
+
+ float mr = max(keys[1].w, keys[2].w);
+
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
+}
+
+void Hair::Curve::motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const
+{
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float4 curr_keys[2];
+ float4 next_keys[2];
+ keys_for_step(
+ curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys);
+ keys_for_step(
+ curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys);
+ /* Interpolate between steps. */
+ r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
+ r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
+}
+
+void Hair::Curve::cardinal_motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const
+{
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float4 curr_keys[4];
+ float4 next_keys[4];
+ cardinal_keys_for_step(curve_keys,
+ curve_radius,
+ key_steps,
+ num_curve_keys,
+ num_steps,
+ step,
+ k0,
+ k1,
+ k2,
+ k3,
+ curr_keys);
+ cardinal_keys_for_step(curve_keys,
+ curve_radius,
+ key_steps,
+ num_curve_keys,
+ num_steps,
+ step + 1,
+ k0,
+ k1,
+ k2,
+ k3,
+ next_keys);
+ /* Interpolate between steps. */
+ r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
+ r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
+ r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2];
+ r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3];
+}
+
+void Hair::Curve::keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const
+{
+ k0 = max(k0, 0);
+ k1 = min(k1, num_keys - 1);
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular key location. */
+ /* TODO(sergey): Consider adding make_float4(float3, float)
+ * function.
+ */
+ r_keys[0] = make_float4(curve_keys[first_key + k0].x,
+ curve_keys[first_key + k0].y,
+ curve_keys[first_key + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(curve_keys[first_key + k1].x,
+ curve_keys[first_key + k1].y,
+ curve_keys[first_key + k1].z,
+ curve_radius[first_key + k1]);
+ }
+ else {
+ /* Center step is not stored in this array. */
+ if (step > center_step) {
+ step--;
+ }
+ const size_t offset = first_key + step * num_curve_keys;
+ r_keys[0] = make_float4(key_steps[offset + k0].x,
+ key_steps[offset + k0].y,
+ key_steps[offset + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(key_steps[offset + k1].x,
+ key_steps[offset + k1].y,
+ key_steps[offset + k1].z,
+ curve_radius[first_key + k1]);
+ }
+}
+
+void Hair::Curve::cardinal_keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const
+{
+ k0 = max(k0, 0);
+ k3 = min(k3, num_keys - 1);
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular key location. */
+ r_keys[0] = make_float4(curve_keys[first_key + k0].x,
+ curve_keys[first_key + k0].y,
+ curve_keys[first_key + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(curve_keys[first_key + k1].x,
+ curve_keys[first_key + k1].y,
+ curve_keys[first_key + k1].z,
+ curve_radius[first_key + k1]);
+ r_keys[2] = make_float4(curve_keys[first_key + k2].x,
+ curve_keys[first_key + k2].y,
+ curve_keys[first_key + k2].z,
+ curve_radius[first_key + k2]);
+ r_keys[3] = make_float4(curve_keys[first_key + k3].x,
+ curve_keys[first_key + k3].y,
+ curve_keys[first_key + k3].z,
+ curve_radius[first_key + k3]);
+ }
+ else {
+ /* Center step is not stored in this array. */
+ if (step > center_step) {
+ step--;
+ }
+ const size_t offset = first_key + step * num_curve_keys;
+ r_keys[0] = make_float4(key_steps[offset + k0].x,
+ key_steps[offset + k0].y,
+ key_steps[offset + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(key_steps[offset + k1].x,
+ key_steps[offset + k1].y,
+ key_steps[offset + k1].z,
+ curve_radius[first_key + k1]);
+ r_keys[2] = make_float4(key_steps[offset + k2].x,
+ key_steps[offset + k2].y,
+ key_steps[offset + k2].z,
+ curve_radius[first_key + k2]);
+ r_keys[3] = make_float4(key_steps[offset + k3].x,
+ key_steps[offset + k3].y,
+ key_steps[offset + k3].z,
+ curve_radius[first_key + k3]);
+ }
+}
+
+/* Hair */
+
+NODE_DEFINE(Hair)
+{
+ NodeType *type = NodeType::add("hair", create, NodeType::NONE, Geometry::node_base_type);
+
+ SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
+ SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
+ SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
+ SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
+
+ return type;
+}
+
+Hair::Hair() : Geometry(node_type, Geometry::HAIR)
+{
+ curvekey_offset = 0;
+}
+
+Hair::~Hair()
+{
+}
+
+void Hair::resize_curves(int numcurves, int numkeys)
+{
+ curve_keys.resize(numkeys);
+ curve_radius.resize(numkeys);
+ curve_first_key.resize(numcurves);
+ curve_shader.resize(numcurves);
+
+ attributes.resize();
+}
+
+void Hair::reserve_curves(int numcurves, int numkeys)
+{
+ curve_keys.reserve(numkeys);
+ curve_radius.reserve(numkeys);
+ curve_first_key.reserve(numcurves);
+ curve_shader.reserve(numcurves);
+
+ attributes.resize(true);
+}
+
+void Hair::clear()
+{
+ Geometry::clear();
+
+ curve_keys.clear();
+ curve_radius.clear();
+ curve_first_key.clear();
+ curve_shader.clear();
+
+ attributes.clear();
+}
+
+void Hair::add_curve_key(float3 co, float radius)
+{
+ curve_keys.push_back_reserved(co);
+ curve_radius.push_back_reserved(radius);
+}
+
+void Hair::add_curve(int first_key, int shader)
+{
+ curve_first_key.push_back_reserved(first_key);
+ curve_shader.push_back_reserved(shader);
+}
+
+void Hair::copy_center_to_motion_step(const int motion_step)
+{
+ Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_mP) {
+ float3 *keys = &curve_keys[0];
+ size_t numkeys = curve_keys.size();
+ memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys);
+ }
+}
+
+void Hair::get_uv_tiles(ustring map, unordered_set<int> &tiles)
+{
+ Attribute *attr;
+
+ if (map.empty()) {
+ attr = attributes.find(ATTR_STD_UV);
+ }
+ else {
+ attr = attributes.find(map);
+ }
+
+ if (attr) {
+ attr->get_uv_tiles(this, ATTR_PRIM_GEOMETRY, tiles);
+ }
+}
+
+void Hair::compute_bounds()
+{
+ BoundBox bnds = BoundBox::empty;
+ size_t curve_keys_size = curve_keys.size();
+
+ if (curve_keys_size > 0) {
+ for (size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow(curve_keys[i], curve_radius[i]);
+
+ Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (use_motion_blur && curve_attr) {
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float3 *key_steps = curve_attr->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow(key_steps[i]);
+ }
+
+ if (!bnds.valid()) {
+ bnds = BoundBox::empty;
+
+ /* skip nan or inf coordinates */
+ for (size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow_safe(curve_keys[i], curve_radius[i]);
+
+ if (use_motion_blur && curve_attr) {
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float3 *key_steps = curve_attr->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow_safe(key_steps[i]);
+ }
+ }
+ }
+
+ if (!bnds.valid()) {
+ /* empty mesh */
+ bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
+ }
+
+ bounds = bnds;
+}
+
+void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion)
+{
+ /* compute uniform scale */
+ float3 c0 = transform_get_column(&tfm, 0);
+ float3 c1 = transform_get_column(&tfm, 1);
+ float3 c2 = transform_get_column(&tfm, 2);
+ float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
+
+ /* apply transform to curve keys */
+ for (size_t i = 0; i < curve_keys.size(); i++) {
+ float3 co = transform_point(&tfm, curve_keys[i]);
+ float radius = curve_radius[i] * scalar;
+
+ /* scale for curve radius is only correct for uniform scale */
+ curve_keys[i] = co;
+ curve_radius[i] = radius;
+ }
+
+ if (apply_to_motion) {
+ Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (curve_attr) {
+ /* apply transform to motion curve keys */
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float4 *key_steps = curve_attr->data_float4();
+
+ for (size_t i = 0; i < steps_size; i++) {
+ float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
+ float radius = key_steps[i].w * scalar;
+
+ /* scale for curve radius is only correct for uniform scale */
+ key_steps[i] = float3_to_float4(co);
+ key_steps[i].w = radius;
+ }
+ }
+ }
+}
+
+void Hair::pack_curves(Scene *scene,
+ float4 *curve_key_co,
+ float4 *curve_data,
+ size_t curvekey_offset)
+{
+ size_t curve_keys_size = curve_keys.size();
+
+ /* pack curve keys */
+ if (curve_keys_size) {
+ float3 *keys_ptr = curve_keys.data();
+ float *radius_ptr = curve_radius.data();
+
+ for (size_t i = 0; i < curve_keys_size; i++)
+ curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
+ }
+
+ /* pack curve segments */
+ size_t curve_num = num_curves();
+
+ for (size_t i = 0; i < curve_num; i++) {
+ Curve curve = get_curve(i);
+ int shader_id = curve_shader[i];
+ Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] :
+ scene->default_surface;
+ shader_id = scene->shader_manager->get_shader_id(shader, false);
+
+ curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset),
+ __int_as_float(curve.num_keys),
+ __int_as_float(shader_id),
+ 0.0f);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h
new file mode 100644
index 00000000000..79f77a78753
--- /dev/null
+++ b/intern/cycles/render/hair.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HAIR_H__
+#define __HAIR_H__
+
+#include "render/geometry.h"
+
+CCL_NAMESPACE_BEGIN
+
+class Hair : public Geometry {
+ public:
+ NODE_DECLARE
+
+ /* Hair Curve */
+ struct Curve {
+ int first_key;
+ int num_keys;
+
+ int num_segments() const
+ {
+ return num_keys - 1;
+ }
+
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox &bounds) const;
+ void bounds_grow(float4 keys[4], BoundBox &bounds) const;
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ const Transform &aligned_space,
+ BoundBox &bounds) const;
+
+ void motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const;
+ void cardinal_motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const;
+
+ void keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const;
+ void cardinal_keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const;
+ };
+
+ array<float3> curve_keys;
+ array<float> curve_radius;
+ array<int> curve_first_key;
+ array<int> curve_shader;
+
+ /* BVH */
+ size_t curvekey_offset;
+
+ /* Constructor/Destructor */
+ Hair();
+ ~Hair();
+
+ /* Geometry */
+ void clear() override;
+
+ void resize_curves(int numcurves, int numkeys);
+ void reserve_curves(int numcurves, int numkeys);
+ void add_curve_key(float3 loc, float radius);
+ void add_curve(int first_key, int shader);
+
+ void copy_center_to_motion_step(const int motion_step);
+
+ void compute_bounds() override;
+ void apply_transform(const Transform &tfm, const bool apply_to_motion) override;
+
+ /* Curves */
+ Curve get_curve(size_t i) const
+ {
+ int first = curve_first_key[i];
+ int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] : curve_keys.size();
+
+ Curve curve = {first, next_first - first};
+ return curve;
+ }
+
+ size_t num_keys() const
+ {
+ return curve_keys.size();
+ }
+
+ size_t num_curves() const
+ {
+ return curve_first_key.size();
+ }
+
+ size_t num_segments() const
+ {
+ return curve_keys.size() - curve_first_key.size();
+ }
+
+ /* UDIM */
+ void get_uv_tiles(ustring map, unordered_set<int> &tiles) override;
+
+ /* BVH */
+ void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __HAIR_H__ */
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 664217d6f26..509637aedd9 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -232,7 +232,10 @@ void LightManager::disable_ineffective_light(Scene *scene)
bool LightManager::object_usable_as_light(Object *object)
{
- Mesh *mesh = object->mesh;
+ Geometry *geom = object->geometry;
+ if (geom->type != Geometry::MESH) {
+ return false;
+ }
/* Skip objects with NaNs */
if (!object->bounds.valid()) {
return false;
@@ -243,10 +246,10 @@ bool LightManager::object_usable_as_light(Object *object)
}
/* Skip if we have no emission shaders. */
/* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll
- * iterate all mesh shaders twice (when counting and when calculating
+ * iterate all geometry shaders twice (when counting and when calculating
* triangle area.
*/
- foreach (const Shader *shader, mesh->used_shaders) {
+ foreach (const Shader *shader, geom->used_shaders) {
if (shader->use_mis && shader->has_surface_emission) {
return true;
}
@@ -285,8 +288,9 @@ void LightManager::device_update_distribution(Device *,
if (!object_usable_as_light(object)) {
continue;
}
+
/* Count triangles. */
- Mesh *mesh = object->mesh;
+ Mesh *mesh = static_cast<Mesh *>(object->geometry);
size_t mesh_num_triangles = mesh->num_triangles();
for (size_t i = 0; i < mesh_num_triangles; i++) {
int shader_index = mesh->shader[i];
@@ -320,7 +324,7 @@ void LightManager::device_update_distribution(Device *,
continue;
}
/* Sum area. */
- Mesh *mesh = object->mesh;
+ Mesh *mesh = static_cast<Mesh *>(object->geometry);
bool transform_applied = mesh->transform_applied;
Transform tfm = object->tfm;
int object_id = j;
@@ -352,7 +356,7 @@ void LightManager::device_update_distribution(Device *,
if (shader->use_mis && shader->has_surface_emission) {
distribution[offset].totarea = totarea;
- distribution[offset].prim = i + mesh->tri_offset;
+ distribution[offset].prim = i + mesh->prim_offset;
distribution[offset].mesh_light.shader_flag = shader_flag;
distribution[offset].mesh_light.object_id = object_id;
offset++;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index d9e6d998ebd..e80e87f2980 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -17,19 +17,13 @@
#include "bvh/bvh.h"
#include "bvh/bvh_build.h"
-#include "render/camera.h"
-#include "render/curves.h"
#include "device/device.h"
+
#include "render/graph.h"
-#include "render/shader.h"
-#include "render/light.h"
+#include "render/hair.h"
#include "render/mesh.h"
-#include "render/nodes.h"
#include "render/object.h"
#include "render/scene.h"
-#include "render/stats.h"
-
-#include "kernel/osl/osl_globals.h"
#include "subd/subd_split.h"
#include "subd/subd_patch_table.h"
@@ -39,10 +33,6 @@
#include "util/util_progress.h"
#include "util/util_set.h"
-#ifdef WITH_EMBREE
-# include "bvh/bvh_embree.h"
-#endif
-
CCL_NAMESPACE_BEGIN
/* Triangle */
@@ -120,263 +110,6 @@ bool Mesh::Triangle::valid(const float3 *verts) const
return isfinite3_safe(verts[v[0]]) && isfinite3_safe(verts[v[1]]) && isfinite3_safe(verts[v[2]]);
}
-/* Curve */
-
-void Mesh::Curve::bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- BoundBox &bounds) const
-{
- float3 P[4];
-
- P[0] = curve_keys[max(first_key + k - 1, first_key)];
- P[1] = curve_keys[first_key + k];
- P[2] = curve_keys[first_key + k + 1];
- P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
-
- float3 lower;
- float3 upper;
-
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
-
- float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
-
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
-}
-
-void Mesh::Curve::bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- const Transform &aligned_space,
- BoundBox &bounds) const
-{
- float3 P[4];
-
- P[0] = curve_keys[max(first_key + k - 1, first_key)];
- P[1] = curve_keys[first_key + k];
- P[2] = curve_keys[first_key + k + 1];
- P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
-
- P[0] = transform_point(&aligned_space, P[0]);
- P[1] = transform_point(&aligned_space, P[1]);
- P[2] = transform_point(&aligned_space, P[2]);
- P[3] = transform_point(&aligned_space, P[3]);
-
- float3 lower;
- float3 upper;
-
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
-
- float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
-
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
-}
-
-void Mesh::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const
-{
- float3 P[4] = {
- float4_to_float3(keys[0]),
- float4_to_float3(keys[1]),
- float4_to_float3(keys[2]),
- float4_to_float3(keys[3]),
- };
-
- float3 lower;
- float3 upper;
-
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
-
- float mr = max(keys[1].w, keys[2].w);
-
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
-}
-
-void Mesh::Curve::motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0,
- size_t k1,
- float4 r_keys[2]) const
-{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time * max_step - step;
- /* Fetch vertex coordinates. */
- float4 curr_keys[2];
- float4 next_keys[2];
- keys_for_step(
- curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys);
- keys_for_step(
- curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys);
- /* Interpolate between steps. */
- r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
- r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
-}
-
-void Mesh::Curve::cardinal_motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0,
- size_t k1,
- size_t k2,
- size_t k3,
- float4 r_keys[4]) const
-{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time * max_step - step;
- /* Fetch vertex coordinates. */
- float4 curr_keys[4];
- float4 next_keys[4];
- cardinal_keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step,
- k0,
- k1,
- k2,
- k3,
- curr_keys);
- cardinal_keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step + 1,
- k0,
- k1,
- k2,
- k3,
- next_keys);
- /* Interpolate between steps. */
- r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
- r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
- r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2];
- r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3];
-}
-
-void Mesh::Curve::keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0,
- size_t k1,
- float4 r_keys[2]) const
-{
- k0 = max(k0, 0);
- k1 = min(k1, num_keys - 1);
- const size_t center_step = ((num_steps - 1) / 2);
- if (step == center_step) {
- /* Center step: regular key location. */
- /* TODO(sergey): Consider adding make_float4(float3, float)
- * function.
- */
- r_keys[0] = make_float4(curve_keys[first_key + k0].x,
- curve_keys[first_key + k0].y,
- curve_keys[first_key + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(curve_keys[first_key + k1].x,
- curve_keys[first_key + k1].y,
- curve_keys[first_key + k1].z,
- curve_radius[first_key + k1]);
- }
- else {
- /* Center step is not stored in this array. */
- if (step > center_step) {
- step--;
- }
- const size_t offset = first_key + step * num_curve_keys;
- r_keys[0] = make_float4(key_steps[offset + k0].x,
- key_steps[offset + k0].y,
- key_steps[offset + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(key_steps[offset + k1].x,
- key_steps[offset + k1].y,
- key_steps[offset + k1].z,
- curve_radius[first_key + k1]);
- }
-}
-
-void Mesh::Curve::cardinal_keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0,
- size_t k1,
- size_t k2,
- size_t k3,
- float4 r_keys[4]) const
-{
- k0 = max(k0, 0);
- k3 = min(k3, num_keys - 1);
- const size_t center_step = ((num_steps - 1) / 2);
- if (step == center_step) {
- /* Center step: regular key location. */
- r_keys[0] = make_float4(curve_keys[first_key + k0].x,
- curve_keys[first_key + k0].y,
- curve_keys[first_key + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(curve_keys[first_key + k1].x,
- curve_keys[first_key + k1].y,
- curve_keys[first_key + k1].z,
- curve_radius[first_key + k1]);
- r_keys[2] = make_float4(curve_keys[first_key + k2].x,
- curve_keys[first_key + k2].y,
- curve_keys[first_key + k2].z,
- curve_radius[first_key + k2]);
- r_keys[3] = make_float4(curve_keys[first_key + k3].x,
- curve_keys[first_key + k3].y,
- curve_keys[first_key + k3].z,
- curve_radius[first_key + k3]);
- }
- else {
- /* Center step is not stored in this array. */
- if (step > center_step) {
- step--;
- }
- const size_t offset = first_key + step * num_curve_keys;
- r_keys[0] = make_float4(key_steps[offset + k0].x,
- key_steps[offset + k0].y,
- key_steps[offset + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(key_steps[offset + k1].x,
- key_steps[offset + k1].y,
- key_steps[offset + k1].z,
- curve_radius[first_key + k1]);
- r_keys[2] = make_float4(key_steps[offset + k2].x,
- key_steps[offset + k2].y,
- key_steps[offset + k2].z,
- curve_radius[first_key + k2]);
- r_keys[3] = make_float4(key_steps[offset + k3].x,
- key_steps[offset + k3].y,
- key_steps[offset + k3].z,
- curve_radius[first_key + k3]);
- }
-}
-
/* SubdFace */
float3 Mesh::SubdFace::normal(const Mesh *mesh) const
@@ -392,60 +125,27 @@ float3 Mesh::SubdFace::normal(const Mesh *mesh) const
NODE_DEFINE(Mesh)
{
- NodeType *type = NodeType::add("mesh", create);
-
- SOCKET_UINT(motion_steps, "Motion Steps", 3);
- SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
+ NodeType *type = NodeType::add("mesh", create, NodeType::NONE, Geometry::node_base_type);
SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
SOCKET_INT_ARRAY(shader, "Shader", array<int>());
SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
- SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
- SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
- SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
- SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
-
return type;
}
-Mesh::Mesh() : Node(node_type)
+Mesh::Mesh() : Geometry(node_type, Geometry::MESH), subd_attributes(this, ATTR_PRIM_SUBD)
{
- need_update = true;
- need_update_rebuild = false;
- transform_applied = false;
- transform_negative_scaled = false;
- transform_normal = transform_identity();
- bounds = BoundBox::empty;
-
- bvh = NULL;
-
- tri_offset = 0;
vert_offset = 0;
- curve_offset = 0;
- curvekey_offset = 0;
-
patch_offset = 0;
face_offset = 0;
corner_offset = 0;
- attr_map_offset = 0;
-
- prim_offset = 0;
-
num_subd_verts = 0;
- attributes.triangle_mesh = this;
- curve_attributes.curve_mesh = this;
- subd_attributes.subd_mesh = this;
-
- geometry_flags = GEOMETRY_NONE;
-
volume_isovalue = 0.001f;
- has_volume = false;
- has_surface_bssrdf = false;
num_ngons = 0;
@@ -457,7 +157,6 @@ Mesh::Mesh() : Node(node_type)
Mesh::~Mesh()
{
- delete bvh;
delete patch_table;
delete subd_params;
}
@@ -493,26 +192,6 @@ void Mesh::reserve_mesh(int numverts, int numtris)
attributes.resize(true);
}
-void Mesh::resize_curves(int numcurves, int numkeys)
-{
- curve_keys.resize(numkeys);
- curve_radius.resize(numkeys);
- curve_first_key.resize(numcurves);
- curve_shader.resize(numcurves);
-
- curve_attributes.resize();
-}
-
-void Mesh::reserve_curves(int numcurves, int numkeys)
-{
- curve_keys.reserve(numkeys);
- curve_radius.reserve(numkeys);
- curve_first_key.reserve(numcurves);
- curve_shader.reserve(numcurves);
-
- curve_attributes.resize(true);
-}
-
void Mesh::resize_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
subd_faces.resize(numfaces);
@@ -533,6 +212,8 @@ void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners)
void Mesh::clear(bool preserve_voxel_data)
{
+ Geometry::clear();
+
/* clear all verts and triangles */
verts.clear();
triangles.clear();
@@ -542,11 +223,6 @@ void Mesh::clear(bool preserve_voxel_data)
triangle_patch.clear();
vert_patch_uv.clear();
- curve_keys.clear();
- curve_radius.clear();
- curve_first_key.clear();
- curve_shader.clear();
-
subd_faces.clear();
subd_face_corners.clear();
@@ -554,27 +230,21 @@ void Mesh::clear(bool preserve_voxel_data)
subd_creases.clear();
- curve_attributes.clear();
subd_attributes.clear();
attributes.clear(preserve_voxel_data);
- used_shaders.clear();
-
vert_to_stitching_key_map.clear();
vert_stitching_map.clear();
- if (!preserve_voxel_data) {
- geometry_flags = GEOMETRY_NONE;
- }
-
- transform_applied = false;
- transform_negative_scaled = false;
- transform_normal = transform_identity();
-
delete patch_table;
patch_table = NULL;
}
+void Mesh::clear()
+{
+ clear(false);
+}
+
void Mesh::add_vertex(float3 P)
{
verts.push_back_reserved(P);
@@ -606,18 +276,6 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
}
}
-void Mesh::add_curve_key(float3 co, float radius)
-{
- curve_keys.push_back_reserved(co);
- curve_radius.push_back_reserved(radius);
-}
-
-void Mesh::add_curve(int first_key, int shader)
-{
- curve_first_key.push_back_reserved(first_key);
- curve_shader.push_back_reserved(shader);
-}
-
void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth_)
{
int start_corner = subd_face_corners.size();
@@ -637,47 +295,41 @@ void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth
subd_faces.push_back_reserved(face);
}
-static void get_uv_tiles_from_attribute(Attribute *attr, int num, unordered_set<int> &tiles)
+void Mesh::copy_center_to_motion_step(const int motion_step)
{
- if (attr == NULL) {
- return;
- }
-
- const float2 *uv = attr->data_float2();
- for (int i = 0; i < num; i++, uv++) {
- float u = uv->x, v = uv->y;
- int x = (int)u, y = (int)v;
-
- if (x < 0 || y < 0 || x >= 10) {
- continue;
- }
+ Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- /* Be conservative in corners - precisely touching the right or upper edge of a tile
- * should not load its right/upper neighbor as well. */
- if (x > 0 && (u < x + 1e-6f)) {
- x--;
- }
- if (y > 0 && (v < y + 1e-6f)) {
- y--;
- }
+ if (attr_mP) {
+ Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+ Attribute *attr_N = attributes.find(ATTR_STD_VERTEX_NORMAL);
+ float3 *P = &verts[0];
+ float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
+ size_t numverts = verts.size();
- tiles.insert(1001 + 10 * y + x);
+ memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts);
+ if (attr_mN)
+ memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts);
}
}
void Mesh::get_uv_tiles(ustring map, unordered_set<int> &tiles)
{
+ Attribute *attr, *subd_attr;
+
if (map.empty()) {
- get_uv_tiles_from_attribute(attributes.find(ATTR_STD_UV), num_triangles() * 3, tiles);
- get_uv_tiles_from_attribute(
- subd_attributes.find(ATTR_STD_UV), subd_face_corners.size() + num_ngons, tiles);
- get_uv_tiles_from_attribute(curve_attributes.find(ATTR_STD_UV), num_curves(), tiles);
+ attr = attributes.find(ATTR_STD_UV);
+ subd_attr = subd_attributes.find(ATTR_STD_UV);
}
else {
- get_uv_tiles_from_attribute(attributes.find(map), num_triangles() * 3, tiles);
- get_uv_tiles_from_attribute(
- subd_attributes.find(map), subd_face_corners.size() + num_ngons, tiles);
- get_uv_tiles_from_attribute(curve_attributes.find(map), num_curves(), tiles);
+ attr = attributes.find(map);
+ subd_attr = subd_attributes.find(map);
+ }
+
+ if (attr) {
+ attr->get_uv_tiles(this, ATTR_PRIM_GEOMETRY, tiles);
+ }
+ if (subd_attr) {
+ subd_attr->get_uv_tiles(this, ATTR_PRIM_SUBD, tiles);
}
}
@@ -685,15 +337,11 @@ void Mesh::compute_bounds()
{
BoundBox bnds = BoundBox::empty;
size_t verts_size = verts.size();
- size_t curve_keys_size = curve_keys.size();
- if (verts_size + curve_keys_size > 0) {
+ if (verts_size > 0) {
for (size_t i = 0; i < verts_size; i++)
bnds.grow(verts[i]);
- for (size_t i = 0; i < curve_keys_size; i++)
- bnds.grow(curve_keys[i], curve_radius[i]);
-
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
@@ -703,15 +351,6 @@ void Mesh::compute_bounds()
bnds.grow(vert_steps[i]);
}
- Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (use_motion_blur && curve_attr) {
- size_t steps_size = curve_keys.size() * (motion_steps - 1);
- float3 *key_steps = curve_attr->data_float3();
-
- for (size_t i = 0; i < steps_size; i++)
- bnds.grow(key_steps[i]);
- }
-
if (!bnds.valid()) {
bnds = BoundBox::empty;
@@ -719,9 +358,6 @@ void Mesh::compute_bounds()
for (size_t i = 0; i < verts_size; i++)
bnds.grow_safe(verts[i]);
- for (size_t i = 0; i < curve_keys_size; i++)
- bnds.grow_safe(curve_keys[i], curve_radius[i]);
-
if (use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
@@ -729,14 +365,6 @@ void Mesh::compute_bounds()
for (size_t i = 0; i < steps_size; i++)
bnds.grow_safe(vert_steps[i]);
}
-
- if (use_motion_blur && curve_attr) {
- size_t steps_size = curve_keys.size() * (motion_steps - 1);
- float3 *key_steps = curve_attr->data_float3();
-
- for (size_t i = 0; i < steps_size; i++)
- bnds.grow_safe(key_steps[i]);
- }
}
}
@@ -748,6 +376,38 @@ void Mesh::compute_bounds()
bounds = bnds;
}
+void Mesh::apply_transform(const Transform &tfm, const bool apply_to_motion)
+{
+ transform_normal = transform_transposed_inverse(tfm);
+
+ /* apply to mesh vertices */
+ for (size_t i = 0; i < verts.size(); i++)
+ verts[i] = transform_point(&tfm, verts[i]);
+
+ if (apply_to_motion) {
+ Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t steps_size = verts.size() * (motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ vert_steps[i] = transform_point(&tfm, vert_steps[i]);
+ }
+
+ Attribute *attr_N = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (attr_N) {
+ Transform ntfm = transform_normal;
+ size_t steps_size = verts.size() * (motion_steps - 1);
+ float3 *normal_steps = attr_N->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
+ }
+ }
+}
+
void Mesh::add_face_normals()
{
/* don't compute if already there */
@@ -885,8 +545,7 @@ void Mesh::add_undisplaced()
float3 *data = attr->data_float3();
/* copy verts */
- size_t size = attr->buffer_size(
- this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD);
+ size_t size = attr->buffer_size(this, attrs.prim);
/* Center points for ngons aren't stored in Mesh::verts but are included in size since they will
* be calculated later, we subtract them from size here so we don't have an overflow while
@@ -975,39 +634,6 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index,
}
}
-void Mesh::pack_curves(Scene *scene,
- float4 *curve_key_co,
- float4 *curve_data,
- size_t curvekey_offset)
-{
- size_t curve_keys_size = curve_keys.size();
-
- /* pack curve keys */
- if (curve_keys_size) {
- float3 *keys_ptr = curve_keys.data();
- float *radius_ptr = curve_radius.data();
-
- for (size_t i = 0; i < curve_keys_size; i++)
- curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
- }
-
- /* pack curve segments */
- size_t curve_num = num_curves();
-
- for (size_t i = 0; i < curve_num; i++) {
- Curve curve = get_curve(i);
- int shader_id = curve_shader[i];
- Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] :
- scene->default_surface;
- shader_id = scene->shader_manager->get_shader_id(shader, false);
-
- curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset),
- __int_as_float(curve.num_keys),
- __int_as_float(shader_id),
- 0.0f);
- }
-}
-
void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset)
{
size_t num_faces = subd_faces.size();
@@ -1054,1391 +680,4 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui
}
}
-void Mesh::compute_bvh(
- Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, int n, int total)
-{
- if (progress->get_cancel())
- return;
-
- compute_bounds();
-
- const BVHLayout bvh_layout = BVHParams::best_bvh_layout(params->bvh_layout,
- device->get_bvh_layout_mask());
- if (need_build_bvh(bvh_layout)) {
- string msg = "Updating Mesh BVH ";
- if (name.empty())
- msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
- else
- msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
-
- Object object;
- object.mesh = this;
-
- vector<Mesh *> meshes;
- meshes.push_back(this);
- vector<Object *> objects;
- objects.push_back(&object);
-
- if (bvh && !need_update_rebuild) {
- progress->set_status(msg, "Refitting BVH");
-
- bvh->meshes = meshes;
- bvh->objects = objects;
-
- bvh->refit(*progress);
- }
- else {
- progress->set_status(msg, "Building BVH");
-
- BVHParams bparams;
- bparams.use_spatial_split = params->use_bvh_spatial_split;
- bparams.bvh_layout = bvh_layout;
- bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
- params->use_bvh_unaligned_nodes;
- bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
- bparams.num_motion_curve_steps = params->num_bvh_time_steps;
- bparams.bvh_type = params->bvh_type;
- bparams.curve_flags = dscene->data.curve.curveflags;
- bparams.curve_subdivisions = dscene->data.curve.subdivisions;
-
- delete bvh;
- bvh = BVH::create(bparams, meshes, objects);
- MEM_GUARDED_CALL(progress, bvh->build, *progress);
- }
- }
-
- need_update = false;
- need_update_rebuild = false;
-}
-
-void Mesh::tag_update(Scene *scene, bool rebuild)
-{
- need_update = true;
-
- if (rebuild) {
- need_update_rebuild = true;
- scene->light_manager->need_update = true;
- }
- else {
- foreach (Shader *shader, used_shaders)
- if (shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
-
- scene->mesh_manager->need_update = true;
- scene->object_manager->need_update = true;
-}
-
-bool Mesh::has_motion_blur() const
-{
- return (use_motion_blur && (attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) ||
- curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)));
-}
-
-bool Mesh::has_true_displacement() const
-{
- foreach (Shader *shader, used_shaders) {
- if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
- return true;
- }
- }
-
- return false;
-}
-
-bool Mesh::has_voxel_attributes() const
-{
- foreach (const Attribute &attr, attributes.attributes) {
- if (attr.element == ATTR_ELEMENT_VOXEL) {
- return true;
- }
- }
-
- return false;
-}
-
-float Mesh::motion_time(int step) const
-{
- return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
-}
-
-int Mesh::motion_step(float time) const
-{
- if (motion_steps > 1) {
- int attr_step = 0;
-
- for (int step = 0; step < motion_steps; step++) {
- float step_time = motion_time(step);
- if (step_time == time) {
- return attr_step;
- }
-
- /* Center step is stored in a separate attribute. */
- if (step != motion_steps / 2) {
- attr_step++;
- }
- }
- }
-
- return -1;
-}
-
-bool Mesh::need_build_bvh(BVHLayout layout) const
-{
- return !transform_applied || has_surface_bssrdf || layout == BVH_LAYOUT_OPTIX;
-}
-
-bool Mesh::is_instanced() const
-{
- /* Currently we treat subsurface objects as instanced.
- *
- * While it might be not very optimal for ray traversal, it avoids having
- * duplicated BVH in the memory, saving quite some space.
- */
- return !transform_applied || has_surface_bssrdf;
-}
-
-/* Mesh Manager */
-
-MeshManager::MeshManager()
-{
- need_update = true;
- need_flags_update = true;
-}
-
-MeshManager::~MeshManager()
-{
-}
-
-void MeshManager::update_osl_attributes(Device *device,
- Scene *scene,
- vector<AttributeRequestSet> &mesh_attributes)
-{
-#ifdef WITH_OSL
- /* for OSL, a hash map is used to lookup the attribute by name. */
- OSLGlobals *og = (OSLGlobals *)device->osl_memory();
-
- og->object_name_map.clear();
- og->attribute_map.clear();
- og->object_names.clear();
-
- og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES);
-
- for (size_t i = 0; i < scene->objects.size(); i++) {
- /* set object name to object index map */
- Object *object = scene->objects[i];
- og->object_name_map[object->name] = i;
- og->object_names.push_back(object->name);
-
- /* set object attributes */
- foreach (ParamValue &attr, object->attributes) {
- OSLGlobals::Attribute osl_attr;
-
- osl_attr.type = attr.type();
- osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
- osl_attr.value = attr;
- osl_attr.desc.offset = 0;
- osl_attr.desc.flags = 0;
-
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr;
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr;
- }
-
- /* find mesh attributes */
- size_t j;
-
- for (j = 0; j < scene->meshes.size(); j++)
- if (scene->meshes[j] == object->mesh)
- break;
-
- AttributeRequestSet &attributes = mesh_attributes[j];
-
- /* set object attributes */
- foreach (AttributeRequest &req, attributes.requests) {
- OSLGlobals::Attribute osl_attr;
-
- if (req.triangle_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.triangle_desc;
-
- if (req.triangle_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if (req.triangle_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else if (req.triangle_type == TypeFloat2)
- osl_attr.type = TypeFloat2;
- else if (req.triangle_type == TypeRGBA)
- osl_attr.type = TypeRGBA;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if (req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][stdname] = osl_attr;
- }
- else if (req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr;
- }
- }
-
- if (req.curve_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.curve_desc;
-
- if (req.curve_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if (req.curve_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else if (req.curve_type == TypeFloat2)
- osl_attr.type = TypeFloat2;
- else if (req.curve_type == TypeRGBA)
- osl_attr.type = TypeRGBA;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if (req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
- }
- else if (req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
- }
- }
-
- if (req.subd_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.subd_desc;
-
- if (req.subd_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if (req.subd_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else if (req.subd_type == TypeFloat2)
- osl_attr.type = TypeFloat2;
- else if (req.subd_type == TypeRGBA)
- osl_attr.type = TypeRGBA;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if (req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr;
- }
- else if (req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr;
- }
- }
- }
- }
-#else
- (void)device;
- (void)scene;
- (void)mesh_attributes;
-#endif
-}
-
-void MeshManager::update_svm_attributes(Device *,
- DeviceScene *dscene,
- Scene *scene,
- vector<AttributeRequestSet> &mesh_attributes)
-{
- /* for SVM, the attributes_map table is used to lookup the offset of an
- * attribute, based on a unique shader attribute id. */
-
- /* compute array stride */
- int attr_map_size = 0;
-
- for (size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- mesh->attr_map_offset = attr_map_size;
- attr_map_size += (mesh_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
- }
-
- if (attr_map_size == 0)
- return;
-
- /* create attribute map */
- uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
- memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint));
-
- for (size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet &attributes = mesh_attributes[i];
-
- /* set object attributes */
- int index = mesh->attr_map_offset;
-
- foreach (AttributeRequest &req, attributes.requests) {
- uint id;
-
- if (req.std == ATTR_STD_NONE)
- id = scene->shader_manager->get_attribute_id(req.name);
- else
- id = scene->shader_manager->get_attribute_id(req.std);
-
- if (mesh->num_triangles()) {
- attr_map[index].x = id;
- attr_map[index].y = req.triangle_desc.element;
- attr_map[index].z = as_uint(req.triangle_desc.offset);
-
- if (req.triangle_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if (req.triangle_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if (req.triangle_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else if (req.triangle_type == TypeRGBA)
- attr_map[index].w = NODE_ATTR_RGBA;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
-
- attr_map[index].w |= req.triangle_desc.flags << 8;
- }
-
- index++;
-
- if (mesh->num_curves()) {
- attr_map[index].x = id;
- attr_map[index].y = req.curve_desc.element;
- attr_map[index].z = as_uint(req.curve_desc.offset);
-
- if (req.curve_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if (req.curve_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if (req.curve_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
-
- attr_map[index].w |= req.curve_desc.flags << 8;
- }
-
- index++;
-
- if (mesh->subd_faces.size()) {
- attr_map[index].x = id;
- attr_map[index].y = req.subd_desc.element;
- attr_map[index].z = as_uint(req.subd_desc.offset);
-
- if (req.subd_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if (req.subd_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if (req.subd_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else if (req.triangle_type == TypeRGBA)
- attr_map[index].w = NODE_ATTR_RGBA;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
-
- attr_map[index].w |= req.subd_desc.flags << 8;
- }
-
- index++;
- }
-
- /* terminator */
- for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
- attr_map[index].x = ATTR_STD_NONE;
- attr_map[index].y = 0;
- attr_map[index].z = 0;
- attr_map[index].w = 0;
-
- index++;
- }
- }
-
- /* copy to device */
- dscene->attributes_map.copy_to_device();
-}
-
-static void update_attribute_element_size(Mesh *mesh,
- Attribute *mattr,
- AttributePrimitive prim,
- size_t *attr_float_size,
- size_t *attr_float2_size,
- size_t *attr_float3_size,
- size_t *attr_uchar4_size)
-{
- if (mattr) {
- size_t size = mattr->element_size(mesh, prim);
-
- if (mattr->element == ATTR_ELEMENT_VOXEL) {
- /* pass */
- }
- else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
- *attr_uchar4_size += size;
- }
- else if (mattr->type == TypeDesc::TypeFloat) {
- *attr_float_size += size;
- }
- else if (mattr->type == TypeFloat2) {
- *attr_float2_size += size;
- }
- else if (mattr->type == TypeDesc::TypeMatrix) {
- *attr_float3_size += size * 4;
- }
- else {
- *attr_float3_size += size;
- }
- }
-}
-
-static void update_attribute_element_offset(Mesh *mesh,
- device_vector<float> &attr_float,
- size_t &attr_float_offset,
- device_vector<float2> &attr_float2,
- size_t &attr_float2_offset,
- device_vector<float4> &attr_float3,
- size_t &attr_float3_offset,
- device_vector<uchar4> &attr_uchar4,
- size_t &attr_uchar4_offset,
- Attribute *mattr,
- AttributePrimitive prim,
- TypeDesc &type,
- AttributeDescriptor &desc)
-{
- if (mattr) {
- /* store element and type */
- desc.element = mattr->element;
- desc.flags = mattr->flags;
- type = mattr->type;
-
- /* store attribute data in arrays */
- size_t size = mattr->element_size(mesh, prim);
-
- AttributeElement &element = desc.element;
- int &offset = desc.offset;
-
- if (mattr->element == ATTR_ELEMENT_VOXEL) {
- /* store slot in offset value */
- VoxelAttribute *voxel_data = mattr->data_voxel();
- offset = voxel_data->slot;
- }
- else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
- uchar4 *data = mattr->data_uchar4();
- offset = attr_uchar4_offset;
-
- assert(attr_uchar4.size() >= offset + size);
- for (size_t k = 0; k < size; k++) {
- attr_uchar4[offset + k] = data[k];
- }
- attr_uchar4_offset += size;
- }
- else if (mattr->type == TypeDesc::TypeFloat) {
- float *data = mattr->data_float();
- offset = attr_float_offset;
-
- assert(attr_float.size() >= offset + size);
- for (size_t k = 0; k < size; k++) {
- attr_float[offset + k] = data[k];
- }
- attr_float_offset += size;
- }
- else if (mattr->type == TypeFloat2) {
- float2 *data = mattr->data_float2();
- offset = attr_float2_offset;
-
- assert(attr_float2.size() >= offset + size);
- for (size_t k = 0; k < size; k++) {
- attr_float2[offset + k] = data[k];
- }
- attr_float2_offset += size;
- }
- else if (mattr->type == TypeDesc::TypeMatrix) {
- Transform *tfm = mattr->data_transform();
- offset = attr_float3_offset;
-
- assert(attr_float3.size() >= offset + size * 3);
- for (size_t k = 0; k < size * 3; k++) {
- attr_float3[offset + k] = (&tfm->x)[k];
- }
- attr_float3_offset += size * 3;
- }
- else {
- float4 *data = mattr->data_float4();
- offset = attr_float3_offset;
-
- assert(attr_float3.size() >= offset + size);
- for (size_t k = 0; k < size; k++) {
- attr_float3[offset + k] = data[k];
- }
- attr_float3_offset += size;
- }
-
- /* mesh vertex/curve index is global, not per object, so we sneak
- * a correction for that in here */
- if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
- desc.flags & ATTR_SUBDIVIDED) {
- /* indices for subdivided attributes are retrieved
- * from patch table so no need for correction here*/
- }
- else if (element == ATTR_ELEMENT_VERTEX)
- offset -= mesh->vert_offset;
- else if (element == ATTR_ELEMENT_VERTEX_MOTION)
- offset -= mesh->vert_offset;
- else if (element == ATTR_ELEMENT_FACE) {
- if (prim == ATTR_PRIM_TRIANGLE)
- offset -= mesh->tri_offset;
- else
- offset -= mesh->face_offset;
- }
- else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
- if (prim == ATTR_PRIM_TRIANGLE)
- offset -= 3 * mesh->tri_offset;
- else
- offset -= mesh->corner_offset;
- }
- else if (element == ATTR_ELEMENT_CURVE)
- offset -= mesh->curve_offset;
- else if (element == ATTR_ELEMENT_CURVE_KEY)
- offset -= mesh->curvekey_offset;
- else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
- offset -= mesh->curvekey_offset;
- }
- else {
- /* attribute not found */
- desc.element = ATTR_ELEMENT_NONE;
- desc.offset = 0;
- }
-}
-
-void MeshManager::device_update_attributes(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress)
-{
- progress.set_status("Updating Mesh", "Computing attributes");
-
- /* gather per mesh requested attributes. as meshes may have multiple
- * shaders assigned, this merges the requested attributes that have
- * been set per shader by the shader manager */
- vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());
-
- for (size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
-
- scene->need_global_attributes(mesh_attributes[i]);
-
- foreach (Shader *shader, mesh->used_shaders) {
- mesh_attributes[i].add(shader->attributes);
- }
- }
-
- /* mesh attribute are stored in a single array per data type. here we fill
- * those arrays, and set the offset and element type to create attribute
- * maps next */
-
- /* Pre-allocate attributes to avoid arrays re-allocation which would
- * take 2x of overall attribute memory usage.
- */
- size_t attr_float_size = 0;
- size_t attr_float2_size = 0;
- size_t attr_float3_size = 0;
- size_t attr_uchar4_size = 0;
- for (size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet &attributes = mesh_attributes[i];
- foreach (AttributeRequest &req, attributes.requests) {
- Attribute *triangle_mattr = mesh->attributes.find(req);
- Attribute *curve_mattr = mesh->curve_attributes.find(req);
- Attribute *subd_mattr = mesh->subd_attributes.find(req);
-
- update_attribute_element_size(mesh,
- triangle_mattr,
- ATTR_PRIM_TRIANGLE,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- update_attribute_element_size(mesh,
- curve_mattr,
- ATTR_PRIM_CURVE,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- update_attribute_element_size(mesh,
- subd_mattr,
- ATTR_PRIM_SUBD,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- }
- }
-
- dscene->attributes_float.alloc(attr_float_size);
- dscene->attributes_float2.alloc(attr_float2_size);
- dscene->attributes_float3.alloc(attr_float3_size);
- dscene->attributes_uchar4.alloc(attr_uchar4_size);
-
- size_t attr_float_offset = 0;
- size_t attr_float2_offset = 0;
- size_t attr_float3_offset = 0;
- size_t attr_uchar4_offset = 0;
-
- /* Fill in attributes. */
- for (size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet &attributes = mesh_attributes[i];
-
- /* todo: we now store std and name attributes from requests even if
- * they actually refer to the same mesh attributes, optimize */
- foreach (AttributeRequest &req, attributes.requests) {
- Attribute *triangle_mattr = mesh->attributes.find(req);
- Attribute *curve_mattr = mesh->curve_attributes.find(req);
- Attribute *subd_mattr = mesh->subd_attributes.find(req);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float,
- attr_float_offset,
- dscene->attributes_float2,
- attr_float2_offset,
- dscene->attributes_float3,
- attr_float3_offset,
- dscene->attributes_uchar4,
- attr_uchar4_offset,
- triangle_mattr,
- ATTR_PRIM_TRIANGLE,
- req.triangle_type,
- req.triangle_desc);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float,
- attr_float_offset,
- dscene->attributes_float2,
- attr_float2_offset,
- dscene->attributes_float3,
- attr_float3_offset,
- dscene->attributes_uchar4,
- attr_uchar4_offset,
- curve_mattr,
- ATTR_PRIM_CURVE,
- req.curve_type,
- req.curve_desc);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float,
- attr_float_offset,
- dscene->attributes_float2,
- attr_float2_offset,
- dscene->attributes_float3,
- attr_float3_offset,
- dscene->attributes_uchar4,
- attr_uchar4_offset,
- subd_mattr,
- ATTR_PRIM_SUBD,
- req.subd_type,
- req.subd_desc);
-
- if (progress.get_cancel())
- return;
- }
- }
-
- /* create attribute lookup maps */
- if (scene->shader_manager->use_osl())
- update_osl_attributes(device, scene, mesh_attributes);
-
- update_svm_attributes(device, dscene, scene, mesh_attributes);
-
- if (progress.get_cancel())
- return;
-
- /* copy to device */
- progress.set_status("Updating Mesh", "Copying Attributes to device");
-
- if (dscene->attributes_float.size()) {
- dscene->attributes_float.copy_to_device();
- }
- if (dscene->attributes_float2.size()) {
- dscene->attributes_float2.copy_to_device();
- }
- if (dscene->attributes_float3.size()) {
- dscene->attributes_float3.copy_to_device();
- }
- if (dscene->attributes_uchar4.size()) {
- dscene->attributes_uchar4.copy_to_device();
- }
-
- if (progress.get_cancel())
- return;
-
- /* After mesh attributes and patch tables have been copied to device memory,
- * we need to update offsets in the objects. */
- scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
-}
-
-void MeshManager::mesh_calc_offset(Scene *scene)
-{
- size_t vert_size = 0;
- size_t tri_size = 0;
-
- size_t curve_key_size = 0;
- size_t curve_size = 0;
-
- size_t patch_size = 0;
- size_t face_size = 0;
- size_t corner_size = 0;
-
- size_t prim_size = 0;
-
- foreach (Mesh *mesh, scene->meshes) {
- mesh->vert_offset = vert_size;
- mesh->tri_offset = tri_size;
-
- mesh->curvekey_offset = curve_key_size;
- mesh->curve_offset = curve_size;
-
- mesh->patch_offset = patch_size;
- mesh->face_offset = face_size;
- mesh->corner_offset = corner_size;
-
- vert_size += mesh->verts.size();
- tri_size += mesh->num_triangles();
-
- curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->num_curves();
-
- if (mesh->subd_faces.size()) {
- Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
- patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
-
- /* patch tables are stored in same array so include them in patch_size */
- if (mesh->patch_table) {
- mesh->patch_table_offset = patch_size;
- patch_size += mesh->patch_table->total_size();
- }
- }
- face_size += mesh->subd_faces.size();
- corner_size += mesh->subd_face_corners.size();
-
- mesh->prim_offset = prim_size;
- prim_size += mesh->num_primitives();
- }
-}
-
-void MeshManager::device_update_mesh(
- Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress)
-{
- /* Count. */
- size_t vert_size = 0;
- size_t tri_size = 0;
-
- size_t curve_key_size = 0;
- size_t curve_size = 0;
-
- size_t patch_size = 0;
-
- foreach (Mesh *mesh, scene->meshes) {
- vert_size += mesh->verts.size();
- tri_size += mesh->num_triangles();
-
- curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->num_curves();
-
- if (mesh->subd_faces.size()) {
- Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
- patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
-
- /* patch tables are stored in same array so include them in patch_size */
- if (mesh->patch_table) {
- mesh->patch_table_offset = patch_size;
- patch_size += mesh->patch_table->total_size();
- }
- }
- }
-
- /* Create mapping from triangle to primitive triangle array. */
- vector<uint> tri_prim_index(tri_size);
- if (for_displacement) {
- /* For displacement kernels we do some trickery to make them believe
- * we've got all required data ready. However, that data is different
- * from final render kernels since we don't have BVH yet, so can't
- * really use same semantic of arrays.
- */
- foreach (Mesh *mesh, scene->meshes) {
- for (size_t i = 0; i < mesh->num_triangles(); ++i) {
- tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset);
- }
- }
- }
- else {
- for (size_t i = 0; i < dscene->prim_index.size(); ++i) {
- if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i];
- }
- }
- }
-
- /* Fill in all the arrays. */
- if (tri_size != 0) {
- /* normals */
- progress.set_status("Updating Mesh", "Computing normals");
-
- uint *tri_shader = dscene->tri_shader.alloc(tri_size);
- float4 *vnormal = dscene->tri_vnormal.alloc(vert_size);
- uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
- uint *tri_patch = dscene->tri_patch.alloc(tri_size);
- float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
-
- foreach (Mesh *mesh, scene->meshes) {
- mesh->pack_shaders(scene, &tri_shader[mesh->tri_offset]);
- mesh->pack_normals(&vnormal[mesh->vert_offset]);
- mesh->pack_verts(tri_prim_index,
- &tri_vindex[mesh->tri_offset],
- &tri_patch[mesh->tri_offset],
- &tri_patch_uv[mesh->vert_offset],
- mesh->vert_offset,
- mesh->tri_offset);
- if (progress.get_cancel())
- return;
- }
-
- /* vertex coordinates */
- progress.set_status("Updating Mesh", "Copying Mesh to device");
-
- dscene->tri_shader.copy_to_device();
- dscene->tri_vnormal.copy_to_device();
- dscene->tri_vindex.copy_to_device();
- dscene->tri_patch.copy_to_device();
- dscene->tri_patch_uv.copy_to_device();
- }
-
- if (curve_size != 0) {
- progress.set_status("Updating Mesh", "Copying Strands to device");
-
- float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
- float4 *curves = dscene->curves.alloc(curve_size);
-
- foreach (Mesh *mesh, scene->meshes) {
- mesh->pack_curves(scene,
- &curve_keys[mesh->curvekey_offset],
- &curves[mesh->curve_offset],
- mesh->curvekey_offset);
- if (progress.get_cancel())
- return;
- }
-
- dscene->curve_keys.copy_to_device();
- dscene->curves.copy_to_device();
- }
-
- if (patch_size != 0) {
- progress.set_status("Updating Mesh", "Copying Patches to device");
-
- uint *patch_data = dscene->patches.alloc(patch_size);
-
- foreach (Mesh *mesh, scene->meshes) {
- mesh->pack_patches(&patch_data[mesh->patch_offset],
- mesh->vert_offset,
- mesh->face_offset,
- mesh->corner_offset);
-
- if (mesh->patch_table) {
- mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset],
- mesh->patch_table_offset);
- }
-
- if (progress.get_cancel())
- return;
- }
-
- dscene->patches.copy_to_device();
- }
-
- if (for_displacement) {
- float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
- foreach (Mesh *mesh, scene->meshes) {
- for (size_t i = 0; i < mesh->num_triangles(); ++i) {
- Mesh::Triangle t = mesh->get_triangle(i);
- size_t offset = 3 * (i + mesh->tri_offset);
- prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
- prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
- prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
- }
- }
- dscene->prim_tri_verts.copy_to_device();
- }
-}
-
-void MeshManager::device_update_bvh(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress)
-{
- /* bvh build */
- progress.set_status("Updating Scene BVH", "Building");
-
- BVHParams bparams;
- bparams.top_level = true;
- bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
- device->get_bvh_layout_mask());
- bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
- bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
- scene->params.use_bvh_unaligned_nodes;
- bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
- bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
- bparams.bvh_type = scene->params.bvh_type;
- bparams.curve_flags = dscene->data.curve.curveflags;
- bparams.curve_subdivisions = dscene->data.curve.subdivisions;
-
- VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
-
-#ifdef WITH_EMBREE
- if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- if (dscene->data.bvh.scene) {
- BVHEmbree::destroy(dscene->data.bvh.scene);
- }
- }
-#endif
-
- BVH *bvh = BVH::create(bparams, scene->meshes, scene->objects);
- bvh->build(progress, &device->stats);
-
- if (progress.get_cancel()) {
-#ifdef WITH_EMBREE
- if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- if (dscene->data.bvh.scene) {
- BVHEmbree::destroy(dscene->data.bvh.scene);
- }
- }
-#endif
- delete bvh;
- return;
- }
-
- /* copy to device */
- progress.set_status("Updating Scene BVH", "Copying BVH to device");
-
- PackedBVH &pack = bvh->pack;
-
- if (pack.nodes.size()) {
- dscene->bvh_nodes.steal_data(pack.nodes);
- dscene->bvh_nodes.copy_to_device();
- }
- if (pack.leaf_nodes.size()) {
- dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
- dscene->bvh_leaf_nodes.copy_to_device();
- }
- if (pack.object_node.size()) {
- dscene->object_node.steal_data(pack.object_node);
- dscene->object_node.copy_to_device();
- }
- if (pack.prim_tri_index.size()) {
- dscene->prim_tri_index.steal_data(pack.prim_tri_index);
- dscene->prim_tri_index.copy_to_device();
- }
- if (pack.prim_tri_verts.size()) {
- dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
- dscene->prim_tri_verts.copy_to_device();
- }
- if (pack.prim_type.size()) {
- dscene->prim_type.steal_data(pack.prim_type);
- dscene->prim_type.copy_to_device();
- }
- if (pack.prim_visibility.size()) {
- dscene->prim_visibility.steal_data(pack.prim_visibility);
- dscene->prim_visibility.copy_to_device();
- }
- if (pack.prim_index.size()) {
- dscene->prim_index.steal_data(pack.prim_index);
- dscene->prim_index.copy_to_device();
- }
- if (pack.prim_object.size()) {
- dscene->prim_object.steal_data(pack.prim_object);
- dscene->prim_object.copy_to_device();
- }
- if (pack.prim_time.size()) {
- dscene->prim_time.steal_data(pack.prim_time);
- dscene->prim_time.copy_to_device();
- }
-
- dscene->data.bvh.root = pack.root_index;
- dscene->data.bvh.bvh_layout = bparams.bvh_layout;
- dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
-
- bvh->copy_to_device(progress, dscene);
-
- delete bvh;
-}
-
-void MeshManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress)
-{
- if (!need_update && !need_flags_update) {
- return;
- }
-
- progress.set_status("Updating Meshes Flags");
-
- /* Update flags. */
- bool volume_images_updated = false;
-
- foreach (Mesh *mesh, scene->meshes) {
- mesh->has_volume = false;
-
- foreach (const Shader *shader, mesh->used_shaders) {
- if (shader->has_volume) {
- mesh->has_volume = true;
- }
- if (shader->has_surface_bssrdf) {
- mesh->has_surface_bssrdf = true;
- }
- }
-
- if (need_update && mesh->has_volume) {
- /* Create volume meshes if there is voxel data. */
- if (mesh->has_voxel_attributes()) {
- if (!volume_images_updated) {
- progress.set_status("Updating Meshes Volume Bounds");
- device_update_volume_images(device, scene, progress);
- volume_images_updated = true;
- }
-
- create_volume_mesh(scene, mesh, progress);
- }
- }
- }
-
- need_flags_update = false;
-}
-
-void MeshManager::device_update_displacement_images(Device *device,
- Scene *scene,
- Progress &progress)
-{
- progress.set_status("Updating Displacement Images");
- TaskPool pool;
- ImageManager *image_manager = scene->image_manager;
- set<int> bump_images;
- foreach (Mesh *mesh, scene->meshes) {
- if (mesh->need_update) {
- foreach (Shader *shader, mesh->used_shaders) {
- if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
- foreach (ShaderNode *node, shader->graph->nodes) {
- if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
- continue;
- }
-
- ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node);
- foreach (int slot, image_node->slots) {
- if (slot != -1) {
- bump_images.insert(slot);
- }
- }
- }
- }
- }
- }
- foreach (int slot, bump_images) {
- pool.push(function_bind(
- &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
- }
- pool.wait_work();
-}
-
-void MeshManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress)
-{
- progress.set_status("Updating Volume Images");
- TaskPool pool;
- ImageManager *image_manager = scene->image_manager;
- set<int> volume_images;
-
- foreach (Mesh *mesh, scene->meshes) {
- if (!mesh->need_update) {
- continue;
- }
-
- foreach (Attribute &attr, mesh->attributes.attributes) {
- if (attr.element != ATTR_ELEMENT_VOXEL) {
- continue;
- }
-
- VoxelAttribute *voxel = attr.data_voxel();
-
- if (voxel->slot != -1) {
- volume_images.insert(voxel->slot);
- }
- }
- }
-
- foreach (int slot, volume_images) {
- pool.push(function_bind(
- &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
- }
- pool.wait_work();
-}
-
-void MeshManager::device_update(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress)
-{
- if (!need_update)
- return;
-
- VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
-
- bool true_displacement_used = false;
- size_t total_tess_needed = 0;
-
- foreach (Mesh *mesh, scene->meshes) {
- foreach (Shader *shader, mesh->used_shaders) {
- if (shader->need_update_mesh)
- mesh->need_update = true;
- }
-
- if (mesh->need_update) {
- /* Update normals. */
- mesh->add_face_normals();
- mesh->add_vertex_normals();
-
- if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
- mesh->add_undisplaced();
- }
-
- /* Test if we need tessellation. */
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
- mesh->subd_params) {
- total_tess_needed++;
- }
-
- /* Test if we need displacement. */
- if (mesh->has_true_displacement()) {
- true_displacement_used = true;
- }
-
- if (progress.get_cancel())
- return;
- }
- }
-
- /* Tessellate meshes that are using subdivision */
- if (total_tess_needed) {
- Camera *dicing_camera = scene->dicing_camera;
- dicing_camera->update(scene);
-
- size_t i = 0;
- foreach (Mesh *mesh, scene->meshes) {
- if (mesh->need_update && mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 && mesh->subd_params) {
- string msg = "Tessellating ";
- if (mesh->name == "")
- msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
- else
- msg += string_printf(
- "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed);
-
- progress.set_status("Updating Mesh", msg);
-
- mesh->subd_params->camera = dicing_camera;
- DiagSplit dsplit(*mesh->subd_params);
- mesh->tessellate(&dsplit);
-
- i++;
-
- if (progress.get_cancel())
- return;
- }
- }
- }
-
- /* Update images needed for true displacement. */
- bool old_need_object_flags_update = false;
- if (true_displacement_used) {
- VLOG(1) << "Updating images used for true displacement.";
- device_update_displacement_images(device, scene, progress);
- old_need_object_flags_update = scene->object_manager->need_flags_update;
- scene->object_manager->device_update_flags(device, dscene, scene, progress, false);
- }
-
- /* Device update. */
- device_free(device, dscene);
-
- mesh_calc_offset(scene);
- if (true_displacement_used) {
- device_update_mesh(device, dscene, scene, true, progress);
- }
- if (progress.get_cancel())
- return;
-
- device_update_attributes(device, dscene, scene, progress);
- if (progress.get_cancel())
- return;
-
- /* Update displacement. */
- bool displacement_done = false;
- size_t num_bvh = 0;
- BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
- device->get_bvh_layout_mask());
-
- foreach (Mesh *mesh, scene->meshes) {
- if (mesh->need_update) {
- if (displace(device, dscene, scene, mesh, progress)) {
- displacement_done = true;
- }
-
- if (mesh->need_build_bvh(bvh_layout)) {
- num_bvh++;
- }
- }
-
- if (progress.get_cancel())
- return;
- }
-
- /* Device re-update after displacement. */
- if (displacement_done) {
- device_free(device, dscene);
-
- device_update_attributes(device, dscene, scene, progress);
- if (progress.get_cancel())
- return;
- }
-
- TaskPool pool;
-
- size_t i = 0;
- foreach (Mesh *mesh, scene->meshes) {
- if (mesh->need_update) {
- pool.push(function_bind(
- &Mesh::compute_bvh, mesh, device, dscene, &scene->params, &progress, i, num_bvh));
- if (mesh->need_build_bvh(bvh_layout)) {
- i++;
- }
- }
- }
-
- TaskPool::Summary summary;
- pool.wait_work(&summary);
- VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report();
-
- foreach (Shader *shader, scene->shaders) {
- shader->need_update_mesh = false;
- }
-
- Scene::MotionType need_motion = scene->need_motion();
- bool motion_blur = need_motion == Scene::MOTION_BLUR;
-
- /* Update objects. */
- vector<Object *> volume_objects;
- foreach (Object *object, scene->objects) {
- object->compute_bounds(motion_blur);
- }
-
- if (progress.get_cancel())
- return;
-
- device_update_bvh(device, dscene, scene, progress);
- if (progress.get_cancel())
- return;
-
- device_update_mesh(device, dscene, scene, false, progress);
- if (progress.get_cancel())
- return;
-
- need_update = false;
-
- if (true_displacement_used) {
- /* Re-tag flags for update, so they're re-evaluated
- * for meshes with correct bounding boxes.
- *
- * This wouldn't cause wrong results, just true
- * displacement might be less optimal ot calculate.
- */
- scene->object_manager->need_flags_update = old_need_object_flags_update;
- }
-}
-
-void MeshManager::device_free(Device *device, DeviceScene *dscene)
-{
- dscene->bvh_nodes.free();
- dscene->bvh_leaf_nodes.free();
- dscene->object_node.free();
- dscene->prim_tri_verts.free();
- dscene->prim_tri_index.free();
- dscene->prim_type.free();
- dscene->prim_visibility.free();
- dscene->prim_index.free();
- dscene->prim_object.free();
- dscene->prim_time.free();
- dscene->tri_shader.free();
- dscene->tri_vnormal.free();
- dscene->tri_vindex.free();
- dscene->tri_patch.free();
- dscene->tri_patch_uv.free();
- dscene->curves.free();
- dscene->curve_keys.free();
- dscene->patches.free();
- dscene->attributes_map.free();
- dscene->attributes_float.free();
- dscene->attributes_float2.free();
- dscene->attributes_float3.free();
- dscene->attributes_uchar4.free();
-
- /* Signal for shaders like displacement not to do ray tracing. */
- dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE;
-
-#ifdef WITH_OSL
- OSLGlobals *og = (OSLGlobals *)device->osl_memory();
-
- if (og) {
- og->object_name_map.clear();
- og->attribute_map.clear();
- og->object_names.clear();
- }
-#else
- (void)device;
-#endif
-}
-
-void MeshManager::tag_update(Scene *scene)
-{
- need_update = true;
- scene->object_manager->need_update = true;
-}
-
-void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats)
-{
- foreach (Mesh *mesh, scene->meshes) {
- stats->mesh.geometry.add_entry(
- NamedSizeEntry(string(mesh->name.c_str()), mesh->get_total_size_in_bytes()));
- }
-}
-
-bool Mesh::need_attribute(Scene *scene, AttributeStandard std)
-{
- if (std == ATTR_STD_NONE)
- return false;
-
- if (scene->need_global_attribute(std))
- return true;
-
- foreach (Shader *shader, used_shaders)
- if (shader->attributes.find(std))
- return true;
-
- return false;
-}
-
-bool Mesh::need_attribute(Scene * /*scene*/, ustring name)
-{
- if (name == ustring())
- return false;
-
- foreach (Shader *shader, used_shaders)
- if (shader->attributes.find(name))
- return true;
-
- return false;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index c5be0ba60b9..5583e9c0400 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -21,6 +21,7 @@
#include "bvh/bvh_params.h"
#include "render/attribute.h"
+#include "render/geometry.h"
#include "render/shader.h"
#include "util/util_array.h"
@@ -29,7 +30,6 @@
#include "util/util_map.h"
#include "util/util_param.h"
#include "util/util_set.h"
-#include "util/util_transform.h"
#include "util/util_types.h"
#include "util/util_vector.h"
@@ -51,7 +51,7 @@ struct PackedPatchTable;
/* Mesh */
-class Mesh : public Node {
+class Mesh : public Geometry {
public:
NODE_DECLARE
@@ -91,94 +91,6 @@ class Mesh : public Node {
return triangles.size() / 3;
}
- /* Mesh Curve */
- struct Curve {
- int first_key;
- int num_keys;
-
- int num_segments() const
- {
- return num_keys - 1;
- }
-
- void bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- BoundBox &bounds) const;
- void bounds_grow(float4 keys[4], BoundBox &bounds) const;
- void bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- const Transform &aligned_space,
- BoundBox &bounds) const;
-
- void motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0,
- size_t k1,
- float4 r_keys[2]) const;
- void cardinal_motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0,
- size_t k1,
- size_t k2,
- size_t k3,
- float4 r_keys[4]) const;
-
- void keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0,
- size_t k1,
- float4 r_keys[2]) const;
- void cardinal_keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0,
- size_t k1,
- size_t k2,
- size_t k3,
- float4 r_keys[4]) const;
- };
-
- Curve get_curve(size_t i) const
- {
- int first = curve_first_key[i];
- int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] : curve_keys.size();
-
- Curve curve = {first, next_first - first};
- return curve;
- }
-
- size_t num_curves() const
- {
- return curve_first_key.size();
- }
-
- size_t num_segments() const
- {
- return curve_keys.size() - curve_first_key.size();
- }
-
- size_t num_primitives() const
- {
- return num_triangles() + num_segments();
- }
-
/* Mesh SubdFace */
struct SubdFace {
int start_corner;
@@ -212,14 +124,6 @@ class Mesh : public Node {
SubdivisionType subdivision_type;
/* Mesh Data */
- enum GeometryFlags {
- GEOMETRY_NONE = 0,
- GEOMETRY_TRIANGLES = (1 << 0),
- GEOMETRY_CURVES = (1 << 1),
- };
- int geometry_flags; /* used to distinguish meshes with no verts
- and meshed for which geometry is not created */
-
array<int> triangles;
array<float3> verts;
array<int> shader;
@@ -230,13 +134,6 @@ class Mesh : public Node {
array<float2> vert_patch_uv;
float volume_isovalue;
- bool has_volume; /* Set in the device_update_flags(). */
- bool has_surface_bssrdf; /* Set in the device_update_flags(). */
-
- array<float3> curve_keys;
- array<float> curve_radius;
- array<int> curve_first_key;
- array<int> curve_shader;
array<SubdFace> subd_faces;
array<int> subd_face_corners;
@@ -246,42 +143,18 @@ class Mesh : public Node {
SubdParams *subd_params;
- vector<Shader *> used_shaders;
- AttributeSet attributes;
- AttributeSet curve_attributes;
AttributeSet subd_attributes;
- BoundBox bounds;
- bool transform_applied;
- bool transform_negative_scaled;
- Transform transform_normal;
-
PackedPatchTable *patch_table;
- uint motion_steps;
- bool use_motion_blur;
-
- /* Update Flags */
- bool need_update;
- bool need_update_rebuild;
-
/* BVH */
- BVH *bvh;
- size_t tri_offset;
size_t vert_offset;
- size_t curve_offset;
- size_t curvekey_offset;
-
size_t patch_offset;
size_t patch_table_offset;
size_t face_offset;
size_t corner_offset;
- size_t attr_map_offset;
-
- size_t prim_offset;
-
size_t num_subd_verts;
private:
@@ -289,7 +162,7 @@ class Mesh : public Node {
unordered_multimap<int, int>
vert_stitching_map; /* stitching index -> multiple real vert indices */
friend class DiagSplit;
- friend class MeshManager;
+ friend class GeometryManager;
public:
/* Functions */
@@ -298,24 +171,24 @@ class Mesh : public Node {
void resize_mesh(int numverts, int numfaces);
void reserve_mesh(int numverts, int numfaces);
- void resize_curves(int numcurves, int numkeys);
- void reserve_curves(int numcurves, int numkeys);
void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
- void clear(bool preserve_voxel_data = false);
+ void clear(bool preserve_voxel_data);
+ void clear() override;
void add_vertex(float3 P);
void add_vertex_slow(float3 P);
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
- void add_curve_key(float3 loc, float radius);
- void add_curve(int first_key, int shader);
void add_subd_face(int *corners, int num_corners, int shader_, bool smooth_);
- void compute_bounds();
+ void copy_center_to_motion_step(const int motion_step);
+
+ void compute_bounds() override;
+ void apply_transform(const Transform &tfm, const bool apply_to_motion) override;
void add_face_normals();
void add_vertex_normals();
void add_undisplaced();
- void get_uv_tiles(ustring map, unordered_set<int> &tiles);
+ void get_uv_tiles(ustring map, unordered_set<int> &tiles) override;
void pack_shaders(Scene *scene, uint *shader);
void pack_normals(float4 *vnormal);
@@ -325,103 +198,11 @@ class Mesh : public Node {
float2 *tri_patch_uv,
size_t vert_offset,
size_t tri_offset);
- void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
- void compute_bvh(Device *device,
- DeviceScene *dscene,
- SceneParams *params,
- Progress *progress,
- int n,
- int total);
-
- bool need_attribute(Scene *scene, AttributeStandard std);
- bool need_attribute(Scene *scene, ustring name);
-
- void tag_update(Scene *scene, bool rebuild);
-
- bool has_motion_blur() const;
- bool has_true_displacement() const;
- bool has_voxel_attributes() const;
-
- /* Convert between normalized -1..1 motion time and index
- * in the VERTEX_MOTION attribute. */
- float motion_time(int step) const;
- int motion_step(float time) const;
-
- /* Check whether the mesh should have own BVH built separately. Briefly,
- * own BVH is needed for mesh, if:
- *
- * - It is instanced multiple times, so each instance object should share the
- * same BVH tree.
- * - Special ray intersection is needed, for example to limit subsurface rays
- * to only the mesh itself.
- * - The BVH layout requires the top level to only contain instances.
- */
- bool need_build_bvh(BVHLayout layout) const;
-
- /* Check if the mesh should be treated as instanced. */
- bool is_instanced() const;
-
void tessellate(DiagSplit *split);
};
-/* Mesh Manager */
-
-class MeshManager {
- public:
- bool need_update;
- bool need_flags_update;
-
- MeshManager();
- ~MeshManager();
-
- bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress);
-
- /* attributes */
- void update_osl_attributes(Device *device,
- Scene *scene,
- vector<AttributeRequestSet> &mesh_attributes);
- void update_svm_attributes(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- vector<AttributeRequestSet> &mesh_attributes);
-
- void device_update_preprocess(Device *device, Scene *scene, Progress &progress);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
-
- void device_free(Device *device, DeviceScene *dscene);
-
- void tag_update(Scene *scene);
-
- void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
-
- void collect_statistics(const Scene *scene, RenderStats *stats);
-
- protected:
- /* Calculate verts/triangles/curves offsets in global arrays. */
- void mesh_calc_offset(Scene *scene);
-
- void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
-
- void device_update_mesh(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- bool for_displacement,
- Progress &progress);
-
- void device_update_attributes(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress);
-
- void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
-
- void device_update_displacement_images(Device *device, Scene *scene, Progress &progress);
-
- void device_update_volume_images(Device *device, Scene *scene, Progress &progress);
-};
-
CCL_NAMESPACE_END
#endif /* __MESH_H__ */
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 6a6c2fbb3eb..467810f9273 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -43,7 +43,7 @@ static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
return norm / normlen;
}
-bool MeshManager::displace(
+bool GeometryManager::displace(
Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress)
{
/* verify if we have a displacement shader */
@@ -58,7 +58,7 @@ bool MeshManager::displace(
size_t object_index = OBJECT_NONE;
for (size_t i = 0; i < scene->objects.size(); i++) {
- if (scene->objects[i]->mesh == mesh) {
+ if (scene->objects[i]->geometry == mesh) {
object_index = i;
break;
}
@@ -91,7 +91,7 @@ bool MeshManager::displace(
/* set up object, primitive and barycentric coordinates */
int object = object_index;
- int prim = mesh->tri_offset + i;
+ int prim = mesh->prim_offset + i;
float u, v;
switch (j) {
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index f451b58e92a..74c6a7759a6 100644
--- a/intern/cycles/render/mesh_volume.cpp
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -362,7 +362,7 @@ struct VoxelAttributeGrid {
int channels;
};
-void MeshManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress)
+void GeometryManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress)
{
string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
progress.set_status("Updating Mesh", msg);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 00f4a7283bb..75e21e00dcf 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -333,10 +333,10 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph)
/* TODO(lukas): This is quite inefficient. A fairly simple improvement would
* be to have a cache in each mesh that is indexed by attribute.
* Additionally, building a graph-to-meshes list once could help. */
- foreach (Mesh *mesh, scene->meshes) {
- foreach (Shader *shader, mesh->used_shaders) {
+ foreach (Geometry *geom, scene->geometry) {
+ foreach (Shader *shader, geom->used_shaders) {
if (shader->graph == graph) {
- mesh->get_uv_tiles(attribute, used_tiles);
+ geom->get_uv_tiles(attribute, used_tiles);
}
}
}
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 849329a086d..4987b6089d7 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -16,6 +16,7 @@
#include "render/camera.h"
#include "device/device.h"
+#include "render/hair.h"
#include "render/light.h"
#include "render/mesh.h"
#include "render/curves.h"
@@ -87,7 +88,7 @@ NODE_DEFINE(Object)
{
NodeType *type = NodeType::add("object", create);
- SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
+ SOCKET_NODE(geometry, "Geometry", &Geometry::node_base_type);
SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
SOCKET_UINT(visibility, "Visibility", ~0);
SOCKET_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
@@ -152,7 +153,7 @@ void Object::update_motion()
void Object::compute_bounds(bool motion_blur)
{
- BoundBox mbounds = mesh->bounds;
+ BoundBox mbounds = geometry->bounds;
if (motion_blur && use_motion()) {
array<DecomposedTransform> decomp(motion.size());
@@ -172,7 +173,7 @@ void Object::compute_bounds(bool motion_blur)
}
else {
/* No motion blur case. */
- if (mesh->transform_applied) {
+ if (geometry->transform_applied) {
bounds = mbounds;
}
else {
@@ -183,89 +184,18 @@ void Object::compute_bounds(bool motion_blur)
void Object::apply_transform(bool apply_to_motion)
{
- if (!mesh || tfm == transform_identity())
+ if (!geometry || tfm == transform_identity())
return;
- /* triangles */
- if (mesh->verts.size()) {
- /* store matrix to transform later. when accessing these as attributes we
- * do not want the transform to be applied for consistency between static
- * and dynamic BVH, so we do it on packing. */
- mesh->transform_normal = transform_transposed_inverse(tfm);
-
- /* apply to mesh vertices */
- for (size_t i = 0; i < mesh->verts.size(); i++)
- mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
-
- if (apply_to_motion) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if (attr) {
- size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
-
- for (size_t i = 0; i < steps_size; i++)
- vert_steps[i] = transform_point(&tfm, vert_steps[i]);
- }
-
- Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if (attr_N) {
- Transform ntfm = mesh->transform_normal;
- size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
- float3 *normal_steps = attr_N->data_float3();
-
- for (size_t i = 0; i < steps_size; i++)
- normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
- }
- }
- }
-
- /* curves */
- if (mesh->curve_keys.size()) {
- /* compute uniform scale */
- float3 c0 = transform_get_column(&tfm, 0);
- float3 c1 = transform_get_column(&tfm, 1);
- float3 c2 = transform_get_column(&tfm, 2);
- float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
-
- /* apply transform to curve keys */
- for (size_t i = 0; i < mesh->curve_keys.size(); i++) {
- float3 co = transform_point(&tfm, mesh->curve_keys[i]);
- float radius = mesh->curve_radius[i] * scalar;
-
- /* scale for curve radius is only correct for uniform scale */
- mesh->curve_keys[i] = co;
- mesh->curve_radius[i] = radius;
- }
-
- if (apply_to_motion) {
- Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if (curve_attr) {
- /* apply transform to motion curve keys */
- size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
- float4 *key_steps = curve_attr->data_float4();
-
- for (size_t i = 0; i < steps_size; i++) {
- float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
- float radius = key_steps[i].w * scalar;
-
- /* scale for curve radius is only correct for uniform scale */
- key_steps[i] = float3_to_float4(co);
- key_steps[i].w = radius;
- }
- }
- }
- }
+ geometry->apply_transform(tfm, apply_to_motion);
/* we keep normals pointing in same direction on negative scale, notify
- * mesh about this in it (re)calculates normals */
+ * geometry about this in it (re)calculates normals */
if (transform_negative_scale(tfm))
- mesh->transform_negative_scaled = true;
+ geometry->transform_negative_scaled = true;
if (bounds.valid()) {
- mesh->compute_bounds();
+ geometry->compute_bounds();
compute_bounds(false);
}
@@ -275,11 +205,11 @@ void Object::apply_transform(bool apply_to_motion)
void Object::tag_update(Scene *scene)
{
- if (mesh) {
- if (mesh->transform_applied)
- mesh->need_update = true;
+ if (geometry) {
+ if (geometry->transform_applied)
+ geometry->need_update = true;
- foreach (Shader *shader, mesh->used_shaders) {
+ foreach (Shader *shader, geometry->used_shaders) {
if (shader->use_mis && shader->has_surface_emission)
scene->light_manager->need_update = true;
}
@@ -287,7 +217,7 @@ void Object::tag_update(Scene *scene)
scene->camera->need_flags_update = true;
scene->curve_system_manager->need_update = true;
- scene->mesh_manager->need_update = true;
+ scene->geometry_manager->need_update = true;
scene->object_manager->need_update = true;
}
@@ -353,32 +283,22 @@ ObjectManager::~ObjectManager()
{
}
-void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
+static float object_surface_area(UpdateObjectTransformState *state,
+ const Transform &tfm,
+ Geometry *geom)
{
- KernelObject &kobject = state->objects[ob->index];
- Transform *object_motion_pass = state->object_motion_pass;
-
- Mesh *mesh = ob->mesh;
- uint flag = 0;
-
- /* Compute transformations. */
- Transform tfm = ob->tfm;
- Transform itfm = transform_inverse(tfm);
+ if (geom->type != Geometry::MESH) {
+ return 0.0f;
+ }
/* Compute surface area. for uniform scale we can do avoid the many
* transform calls and share computation for instances.
*
* TODO(brecht): Correct for displacement, and move to a better place.
*/
- float uniform_scale;
+ Mesh *mesh = static_cast<Mesh *>(geom);
float surface_area = 0.0f;
- float3 color = ob->color;
- float pass_id = ob->pass_id;
- float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF);
- int particle_index = (ob->particle_system) ?
- ob->particle_index + state->particle_offset[ob->particle_system] :
- 0;
-
+ float uniform_scale;
if (transform_uniform_scale(tfm, uniform_scale)) {
map<Mesh *, float>::iterator it;
@@ -424,9 +344,31 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
}
}
+ return surface_area;
+}
+
+void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
+{
+ KernelObject &kobject = state->objects[ob->index];
+ Transform *object_motion_pass = state->object_motion_pass;
+
+ Geometry *geom = ob->geometry;
+ uint flag = 0;
+
+ /* Compute transformations. */
+ Transform tfm = ob->tfm;
+ Transform itfm = transform_inverse(tfm);
+
+ float3 color = ob->color;
+ float pass_id = ob->pass_id;
+ float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF);
+ int particle_index = (ob->particle_system) ?
+ ob->particle_index + state->particle_offset[ob->particle_system] :
+ 0;
+
kobject.tfm = tfm;
kobject.itfm = itfm;
- kobject.surface_area = surface_area;
+ kobject.surface_area = object_surface_area(state, tfm, geom);
kobject.color[0] = color.x;
kobject.color[1] = color.y;
kobject.color[2] = color.z;
@@ -435,11 +377,16 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.particle_index = particle_index;
kobject.motion_offset = 0;
- if (mesh->use_motion_blur) {
+ if (geom->use_motion_blur) {
state->have_motion = true;
}
- if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
- flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+
+ if (geom->type == Geometry::MESH) {
+ /* TODO: why only mesh? */
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+ }
}
if (state->need_motion == Scene::MOTION_PASS) {
@@ -460,7 +407,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
/* Motion transformations, is world/object space depending if mesh
* comes with deformed position in object space, or if we transform
* the shading point in world space. */
- if (!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ if (!(flag & SD_OBJECT_HAS_VERTEX_MOTION)) {
tfm_pre = tfm_pre * itfm;
tfm_post = tfm_post * itfm;
}
@@ -485,12 +432,13 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.dupli_generated[0] = ob->dupli_generated[0];
kobject.dupli_generated[1] = ob->dupli_generated[1];
kobject.dupli_generated[2] = ob->dupli_generated[2];
- kobject.numkeys = mesh->curve_keys.size();
+ kobject.numkeys = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom)->curve_keys.size() :
+ 0;
kobject.dupli_uv[0] = ob->dupli_uv[0];
kobject.dupli_uv[1] = ob->dupli_uv[1];
- int totalsteps = mesh->motion_steps;
+ int totalsteps = geom->motion_steps;
kobject.numsteps = (totalsteps - 1) / 2;
- kobject.numverts = mesh->verts.size();
+ kobject.numverts = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom)->verts.size() : 0;
kobject.patch_map_offset = 0;
kobject.attribute_map_offset = 0;
uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
@@ -505,7 +453,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
state->object_flag[ob->index] = flag;
/* Have curves. */
- if (mesh->num_curves()) {
+ if (geom->type == Geometry::HAIR) {
state->have_curves = true;
}
}
@@ -681,7 +629,7 @@ void ObjectManager::device_update_flags(
vector<Object *> volume_objects;
bool has_volume_objects = false;
foreach (Object *object, scene->objects) {
- if (object->mesh->has_volume) {
+ if (object->geometry->has_volume) {
if (bounds_valid) {
volume_objects.push_back(object);
}
@@ -690,11 +638,11 @@ void ObjectManager::device_update_flags(
}
foreach (Object *object, scene->objects) {
- if (object->mesh->has_volume) {
+ if (object->geometry->has_volume) {
object_flag[object->index] |= SD_OBJECT_HAS_VOLUME;
object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
- foreach (Attribute &attr, object->mesh->attributes.attributes) {
+ foreach (Attribute &attr, object->geometry->attributes.attributes) {
if (attr.element == ATTR_ELEMENT_VOXEL) {
object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
}
@@ -744,21 +692,24 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
bool update = false;
foreach (Object *object, scene->objects) {
- Mesh *mesh = object->mesh;
-
- if (mesh->patch_table) {
- uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() -
- mesh->patch_table->num_nodes * PATCH_NODE_SIZE) -
- mesh->patch_offset;
-
- if (kobjects[object->index].patch_map_offset != patch_map_offset) {
- kobjects[object->index].patch_map_offset = patch_map_offset;
- update = true;
+ Geometry *geom = object->geometry;
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->patch_table) {
+ uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() -
+ mesh->patch_table->num_nodes * PATCH_NODE_SIZE) -
+ mesh->patch_offset;
+
+ if (kobjects[object->index].patch_map_offset != patch_map_offset) {
+ kobjects[object->index].patch_map_offset = patch_map_offset;
+ update = true;
+ }
}
}
- if (kobjects[object->index].attribute_map_offset != mesh->attr_map_offset) {
- kobjects[object->index].attribute_map_offset = mesh->attr_map_offset;
+ if (kobjects[object->index].attribute_map_offset != geom->attr_map_offset) {
+ kobjects[object->index].attribute_map_offset = geom->attr_map_offset;
update = true;
}
}
@@ -779,10 +730,10 @@ void ObjectManager::device_free(Device *, DeviceScene *dscene)
void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
{
/* todo: normals and displacement should be done before applying transform! */
- /* todo: create objects/meshes in right order! */
+ /* todo: create objects/geometry in right order! */
- /* counter mesh users */
- map<Mesh *, int> mesh_users;
+ /* counter geometry users */
+ map<Geometry *, int> geometry_users;
Scene::MotionType need_motion = scene->need_motion();
bool motion_blur = need_motion == Scene::MOTION_BLUR;
bool apply_to_motion = need_motion != Scene::MOTION_PASS;
@@ -790,10 +741,10 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
bool have_instancing = false;
foreach (Object *object, scene->objects) {
- map<Mesh *, int>::iterator it = mesh_users.find(object->mesh);
+ map<Geometry *, int>::iterator it = geometry_users.find(object->geometry);
- if (it == mesh_users.end())
- mesh_users[object->mesh] = 1;
+ if (it == geometry_users.end())
+ geometry_users[object->geometry] = 1;
else
it->second++;
}
@@ -803,27 +754,34 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
uint *object_flag = dscene->object_flag.data();
- /* apply transforms for objects with single user meshes */
+ /* apply transforms for objects with single user geometry */
foreach (Object *object, scene->objects) {
/* Annoying feedback loop here: we can't use is_instanced() because
* it'll use uninitialized transform_applied flag.
*
- * Could be solved by moving reference counter to Mesh.
+ * Could be solved by moving reference counter to Geometry.
*/
- if ((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
- !object->mesh->has_true_displacement() &&
- object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
+ Geometry *geom = object->geometry;
+ bool apply = (geometry_users[geom] == 1) && !geom->has_surface_bssrdf &&
+ !geom->has_true_displacement();
+
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ apply = apply && mesh->subdivision_type == Mesh::SUBDIVISION_NONE;
+ }
+
+ if (apply) {
if (!(motion_blur && object->use_motion())) {
- if (!object->mesh->transform_applied) {
+ if (!geom->transform_applied) {
object->apply_transform(apply_to_motion);
- object->mesh->transform_applied = true;
+ geom->transform_applied = true;
if (progress.get_cancel())
return;
}
object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
- if (object->mesh->transform_negative_scaled)
+ if (geom->transform_negative_scaled)
object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
}
else
@@ -842,7 +800,7 @@ void ObjectManager::tag_update(Scene *scene)
{
need_update = true;
scene->curve_system_manager->need_update = true;
- scene->mesh_manager->need_update = true;
+ scene->geometry_manager->need_update = true;
scene->light_manager->need_update = true;
}
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index cbbff0d4c6d..c5d878ec938 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -32,7 +32,7 @@ CCL_NAMESPACE_BEGIN
class Device;
class DeviceScene;
-class Mesh;
+class Geometry;
class ParticleSystem;
class Progress;
class Scene;
@@ -46,7 +46,7 @@ class Object : public Node {
public:
NODE_DECLARE
- Mesh *mesh;
+ Geometry *geometry;
Transform tfm;
BoundBox bounds;
uint random_id;
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 1e75fa0f99b..24469620840 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -94,7 +94,7 @@ Scene::Scene(const SceneParams &params_, Device *device)
film = new Film();
background = new Background();
light_manager = new LightManager();
- mesh_manager = new MeshManager();
+ geometry_manager = new GeometryManager();
object_manager = new ObjectManager();
integrator = new Integrator();
image_manager = new ImageManager(device->info);
@@ -118,8 +118,8 @@ void Scene::free_memory(bool final)
{
foreach (Shader *s, shaders)
delete s;
- foreach (Mesh *m, meshes)
- delete m;
+ foreach (Geometry *g, geometry)
+ delete g;
foreach (Object *o, objects)
delete o;
foreach (Light *l, lights)
@@ -128,7 +128,7 @@ void Scene::free_memory(bool final)
delete p;
shaders.clear();
- meshes.clear();
+ geometry.clear();
objects.clear();
lights.clear();
particle_systems.clear();
@@ -140,7 +140,7 @@ void Scene::free_memory(bool final)
integrator->device_free(device, &dscene);
object_manager->device_free(device, &dscene);
- mesh_manager->device_free(device, &dscene);
+ geometry_manager->device_free(device, &dscene);
shader_manager->device_free(device, &dscene, this);
light_manager->device_free(device, &dscene);
@@ -165,7 +165,7 @@ void Scene::free_memory(bool final)
delete background;
delete integrator;
delete object_manager;
- delete mesh_manager;
+ delete geometry_manager;
delete shader_manager;
delete light_manager;
delete particle_system_manager;
@@ -211,7 +211,7 @@ void Scene::device_update(Device *device_, Progress &progress)
if (progress.get_cancel() || device->have_error())
return;
- mesh_manager->device_update_preprocess(device, this, progress);
+ geometry_manager->device_update_preprocess(device, this, progress);
if (progress.get_cancel() || device->have_error())
return;
@@ -235,7 +235,7 @@ void Scene::device_update(Device *device_, Progress &progress)
return;
progress.set_status("Updating Meshes");
- mesh_manager->device_update(device, &dscene, this, progress);
+ geometry_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error())
return;
@@ -356,8 +356,8 @@ bool Scene::need_update()
bool Scene::need_data_update()
{
return (background->need_update || image_manager->need_update || object_manager->need_update ||
- mesh_manager->need_update || light_manager->need_update || lookup_tables->need_update ||
- integrator->need_update || shader_manager->need_update ||
+ geometry_manager->need_update || light_manager->need_update ||
+ lookup_tables->need_update || integrator->need_update || shader_manager->need_update ||
particle_system_manager->need_update || curve_system_manager->need_update ||
bake_manager->need_update || film->need_update);
}
@@ -379,7 +379,7 @@ void Scene::reset()
background->tag_update(this);
integrator->tag_update(this);
object_manager->tag_update(this);
- mesh_manager->tag_update(this);
+ geometry_manager->tag_update(this);
light_manager->tag_update(this);
particle_system_manager->tag_update(this);
curve_system_manager->tag_update(this);
@@ -392,7 +392,7 @@ void Scene::device_free()
void Scene::collect_statistics(RenderStats *stats)
{
- mesh_manager->collect_statistics(this, stats);
+ geometry_manager->collect_statistics(this, stats);
image_manager->collect_statistics(stats);
}
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index f99510d2d42..ab30aaa1f43 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -44,8 +44,8 @@ class Integrator;
class Light;
class LightManager;
class LookupTables;
-class Mesh;
-class MeshManager;
+class Geometry;
+class GeometryManager;
class Object;
class ObjectManager;
class ParticleSystemManager;
@@ -213,7 +213,7 @@ class Scene {
/* data lists */
vector<Object *> objects;
- vector<Mesh *> meshes;
+ vector<Geometry *> geometry;
vector<Shader *> shaders;
vector<Light *> lights;
vector<ParticleSystem *> particle_systems;
@@ -222,7 +222,7 @@ class Scene {
ImageManager *image_manager;
LightManager *light_manager;
ShaderManager *shader_manager;
- MeshManager *mesh_manager;
+ GeometryManager *geometry_manager;
ObjectManager *object_manager;
ParticleSystemManager *particle_system_manager;
CurveSystemManager *curve_system_manager;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index c77a20787f5..dac7fbac806 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -701,23 +701,26 @@ DeviceRequestedFeatures Session::get_requested_device_features()
requested_features.use_object_motion = false;
requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
foreach (Object *object, scene->objects) {
- Mesh *mesh = object->mesh;
- if (mesh->num_curves()) {
- requested_features.use_hair = true;
- }
+ Geometry *geom = object->geometry;
if (use_motion) {
- requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
- requested_features.use_camera_motion |= mesh->use_motion_blur;
- }
-#ifdef WITH_OPENSUBDIV
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
- requested_features.use_patch_evaluation = true;
+ requested_features.use_object_motion |= object->use_motion() | geom->use_motion_blur;
+ requested_features.use_camera_motion |= geom->use_motion_blur;
}
-#endif
if (object->is_shadow_catcher) {
requested_features.use_shadow_tricks = true;
}
- requested_features.use_true_displacement |= mesh->has_true_displacement();
+ if (geom->type == Geometry::MESH) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+#ifdef WITH_OPENSUBDIV
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ requested_features.use_patch_evaluation = true;
+ }
+#endif
+ requested_features.use_true_displacement |= mesh->has_true_displacement();
+ }
+ else if (geom->type == Geometry::HAIR) {
+ requested_features.use_hair = true;
+ }
}
requested_features.use_background_light = scene->light_manager->has_background_light(scene);
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 661208c6463..60f38aa14da 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -214,7 +214,7 @@ Shader::Shader() : Node(node_type)
used = false;
need_update = true;
- need_update_mesh = true;
+ need_update_geometry = true;
need_sync_object = false;
}
@@ -288,7 +288,7 @@ void Shader::set_graph(ShaderGraph *graph_)
const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
if (strcmp(old_hash, new_hash) != 0) {
- need_update_mesh = true;
+ need_update_geometry = true;
}
}
@@ -347,14 +347,14 @@ void Shader::tag_update(Scene *scene)
}
/* compare if the attributes changed, mesh manager will check
- * need_update_mesh, update the relevant meshes and clear it. */
+ * need_update_geometry, update the relevant meshes and clear it. */
if (attributes.modified(prev_attributes)) {
- need_update_mesh = true;
- scene->mesh_manager->need_update = true;
+ need_update_geometry = true;
+ scene->geometry_manager->need_update = true;
}
if (has_volume != prev_has_volume) {
- scene->mesh_manager->need_flags_update = true;
+ scene->geometry_manager->need_flags_update = true;
scene->object_manager->need_flags_update = true;
}
}
@@ -489,8 +489,8 @@ void ShaderManager::device_update_shaders_used(Scene *scene)
if (scene->background->shader)
scene->background->shader->used = true;
- foreach (Mesh *mesh, scene->meshes)
- foreach (Shader *shader, mesh->used_shaders)
+ foreach (Geometry *geom, scene->geometry)
+ foreach (Shader *shader, geom->used_shaders)
shader->used = true;
foreach (Light *light, scene->lights)
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index f74204df355..c6f40bb7833 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -95,7 +95,7 @@ class Shader : public Node {
/* synchronization */
bool need_update;
- bool need_update_mesh;
+ bool need_update_geometry;
bool need_sync_object;
/* If the shader has only volume components, the surface is assumed to
diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt
index 98fcc8cd15e..dc7e40c0039 100644
--- a/intern/cycles/test/CMakeLists.txt
+++ b/intern/cycles/test/CMakeLists.txt
@@ -100,7 +100,11 @@ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LIN
CYCLES_TEST(render_graph_finalize "${ALL_CYCLES_LIBRARIES};bf_intern_numaapi")
CYCLES_TEST(util_aligned_malloc "cycles_util")
-CYCLES_TEST(util_path "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}")
-CYCLES_TEST(util_string "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}")
-CYCLES_TEST(util_task "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES};bf_intern_numaapi")
-CYCLES_TEST(util_time "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}")
+CYCLES_TEST(util_path "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
+CYCLES_TEST(util_string "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
+CYCLES_TEST(util_task "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES};bf_intern_numaapi")
+CYCLES_TEST(util_time "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
+set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
+CYCLES_TEST(util_avxf_avx "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
+set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+CYCLES_TEST(util_avxf_avx2 "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
diff --git a/intern/cycles/test/util_avxf_avx2_test.cpp b/intern/cycles/test/util_avxf_avx2_test.cpp
new file mode 100644
index 00000000000..9b466ddd3a0
--- /dev/null
+++ b/intern/cycles/test/util_avxf_avx2_test.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define __KERNEL_AVX2__
+#define __KERNEL_CPU__
+
+#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
+# include "util_avxf_test.h"
+#endif
diff --git a/intern/cycles/test/util_avxf_avx_test.cpp b/intern/cycles/test/util_avxf_avx_test.cpp
new file mode 100644
index 00000000000..87b519085b4
--- /dev/null
+++ b/intern/cycles/test/util_avxf_avx_test.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define __KERNEL_AVX__
+#define __KERNEL_CPU__
+
+#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
+# include "util_avxf_test.h"
+#endif \ No newline at end of file
diff --git a/intern/cycles/test/util_avxf_test.h b/intern/cycles/test/util_avxf_test.h
new file mode 100644
index 00000000000..1dd677e35e6
--- /dev/null
+++ b/intern/cycles/test/util_avxf_test.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testing/testing.h"
+#include "util/util_types.h"
+#include "util/util_system.h"
+
+CCL_NAMESPACE_BEGIN
+
+bool validate_cpu_capabilities()
+{
+
+#ifdef __KERNEL_AVX2__
+ return system_cpu_support_avx2();
+#else
+# ifdef __KERNEL_AVX__
+ return system_cpu_support_avx();
+# endif
+#endif
+}
+
+#define VALIDATECPU \
+ if (!validate_cpu_capabilities()) \
+ return;
+
+#define compare_vector_scalar(a, b) \
+ for (size_t index = 0; index < a.size; index++) \
+ EXPECT_FLOAT_EQ(a[index], b);
+
+#define compare_vector_vector(a, b) \
+ for (size_t index = 0; index < a.size; index++) \
+ EXPECT_FLOAT_EQ(a[index], b[index]);
+
+#define basic_test_vv(a, b, op) \
+ VALIDATECPU \
+ avxf c = a op b; \
+ for (size_t i = 0; i < a.size; i++) \
+ EXPECT_FLOAT_EQ(c[i], a[i] op b[i]);
+
+/* vector op float tests */
+#define basic_test_vf(a, b, op) \
+ VALIDATECPU \
+ avxf c = a op b; \
+ for (size_t i = 0; i < a.size; i++) \
+ EXPECT_FLOAT_EQ(c[i], a[i] op b);
+
+const avxf avxf_a(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f);
+const avxf avxf_b(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
+const avxf avxf_c(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f);
+const float float_b = 1.5f;
+
+TEST(util_avx, avxf_add_vv){basic_test_vv(avxf_a, avxf_b, +)} TEST(util_avx, avxf_sub_vv){
+ basic_test_vv(avxf_a, avxf_b, -)} TEST(util_avx, avxf_mul_vv){
+ basic_test_vv(avxf_a, avxf_b, *)} TEST(util_avx, avxf_div_vv){
+ basic_test_vv(avxf_a, avxf_b, /)} TEST(util_avx, avxf_add_vf){
+ basic_test_vf(avxf_a, float_b, +)} TEST(util_avx, avxf_sub_vf){
+ basic_test_vf(avxf_a, float_b, -)} TEST(util_avx, avxf_mul_vf){
+ basic_test_vf(avxf_a, float_b, *)} TEST(util_avx,
+ avxf_div_vf){basic_test_vf(avxf_a, float_b, /)}
+
+TEST(util_avx, avxf_ctor)
+{
+ VALIDATECPU
+ compare_vector_scalar(avxf(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f),
+ static_cast<float>(index));
+ compare_vector_scalar(avxf(1.0f), 1.0f);
+ compare_vector_vector(avxf(1.0f, 2.0f), avxf(1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 2.0f));
+ compare_vector_vector(avxf(1.0f, 2.0f, 3.0f, 4.0f),
+ avxf(1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f));
+ compare_vector_vector(avxf(make_float3(1.0f, 2.0f, 3.0f)),
+ avxf(0.0f, 3.0f, 2.0f, 1.0f, 0.0f, 3.0f, 2.0f, 1.0f));
+}
+
+TEST(util_avx, avxf_sqrt)
+{
+ VALIDATECPU
+ compare_vector_vector(mm256_sqrt(avxf(1.0f, 4.0f, 9.0f, 16.0f, 25.0f, 36.0f, 49.0f, 64.0f)),
+ avxf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f));
+}
+
+TEST(util_avx, avxf_min_max)
+{
+ VALIDATECPU
+ compare_vector_vector(min(avxf_a, avxf_b), avxf_a);
+ compare_vector_vector(max(avxf_a, avxf_b), avxf_b);
+}
+
+TEST(util_avx, avxf_set_sign)
+{
+ VALIDATECPU
+ avxf res = set_sign_bit<1, 0, 0, 0, 0, 0, 0, 0>(avxf_a);
+ compare_vector_vector(res, avxf(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, -0.8f));
+}
+
+TEST(util_avx, avxf_msub)
+{
+ VALIDATECPU
+ avxf res = msub(avxf_a, avxf_b, avxf_c);
+ avxf exp = avxf((avxf_a[7] * avxf_b[7]) - avxf_c[7],
+ (avxf_a[6] * avxf_b[6]) - avxf_c[6],
+ (avxf_a[5] * avxf_b[5]) - avxf_c[5],
+ (avxf_a[4] * avxf_b[4]) - avxf_c[4],
+ (avxf_a[3] * avxf_b[3]) - avxf_c[3],
+ (avxf_a[2] * avxf_b[2]) - avxf_c[2],
+ (avxf_a[1] * avxf_b[1]) - avxf_c[1],
+ (avxf_a[0] * avxf_b[0]) - avxf_c[0]);
+ compare_vector_vector(res, exp);
+}
+
+TEST(util_avx, avxf_madd)
+{
+ VALIDATECPU
+ avxf res = madd(avxf_a, avxf_b, avxf_c);
+ avxf exp = avxf((avxf_a[7] * avxf_b[7]) + avxf_c[7],
+ (avxf_a[6] * avxf_b[6]) + avxf_c[6],
+ (avxf_a[5] * avxf_b[5]) + avxf_c[5],
+ (avxf_a[4] * avxf_b[4]) + avxf_c[4],
+ (avxf_a[3] * avxf_b[3]) + avxf_c[3],
+ (avxf_a[2] * avxf_b[2]) + avxf_c[2],
+ (avxf_a[1] * avxf_b[1]) + avxf_c[1],
+ (avxf_a[0] * avxf_b[0]) + avxf_c[0]);
+ compare_vector_vector(res, exp);
+}
+
+TEST(util_avx, avxf_nmadd)
+{
+ VALIDATECPU
+ avxf res = nmadd(avxf_a, avxf_b, avxf_c);
+ avxf exp = avxf(avxf_c[7] - (avxf_a[7] * avxf_b[7]),
+ avxf_c[6] - (avxf_a[6] * avxf_b[6]),
+ avxf_c[5] - (avxf_a[5] * avxf_b[5]),
+ avxf_c[4] - (avxf_a[4] * avxf_b[4]),
+ avxf_c[3] - (avxf_a[3] * avxf_b[3]),
+ avxf_c[2] - (avxf_a[2] * avxf_b[2]),
+ avxf_c[1] - (avxf_a[1] * avxf_b[1]),
+ avxf_c[0] - (avxf_a[0] * avxf_b[0]));
+ compare_vector_vector(res, exp);
+}
+
+TEST(util_avx, avxf_compare)
+{
+ VALIDATECPU
+ avxf a(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);
+ avxf b(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f);
+ avxb res = a <= b;
+ int exp[8] = {
+ a[0] <= b[0] ? -1 : 0,
+ a[1] <= b[1] ? -1 : 0,
+ a[2] <= b[2] ? -1 : 0,
+ a[3] <= b[3] ? -1 : 0,
+ a[4] <= b[4] ? -1 : 0,
+ a[5] <= b[5] ? -1 : 0,
+ a[6] <= b[6] ? -1 : 0,
+ a[7] <= b[7] ? -1 : 0,
+ };
+ compare_vector_vector(res, exp);
+}
+
+TEST(util_avx, avxf_permute)
+{
+ VALIDATECPU
+ avxf res = permute<3, 0, 1, 7, 6, 5, 2, 4>(avxf_b);
+ compare_vector_vector(res, avxf(4.0f, 6.0f, 3.0f, 2.0f, 1.0f, 7.0f, 8.0f, 5.0f));
+}
+
+TEST(util_avx, avxf_blend)
+{
+ VALIDATECPU
+ avxf res = blend<0, 0, 1, 0, 1, 0, 1, 0>(avxf_a, avxf_b);
+ compare_vector_vector(res, avxf(0.1f, 0.2f, 3.0f, 0.4f, 5.0f, 0.6f, 7.0f, 0.8f));
+}
+
+TEST(util_avx, avxf_shuffle)
+{
+ VALIDATECPU
+ avxf res = shuffle<0, 1, 2, 3, 1, 3, 2, 0>(avxf_a);
+ compare_vector_vector(res, avxf(0.4f, 0.2f, 0.1f, 0.3f, 0.5f, 0.6f, 0.7f, 0.8f));
+}
+
+/* XXX Test Fails on AVX2, needs further investigation before it can be enabled */
+#if 0
+TEST(util_avx, avxf_cross)
+{
+ VALIDATECPU
+ avxf res = cross(avxf_b, avxf_c);
+ compare_vector_vector(res,
+ avxf(0.0f,
+ -9.5367432e-07f,
+ 0.0f,
+ 4.7683716e-07f,
+ 0.0f,
+ -3.8146973e-06f,
+ 3.8146973e-06f,
+ 3.8146973e-06f));
+}
+#endif
+
+TEST(util_avx, avxf_dot3)
+{
+ VALIDATECPU
+ float den, den2;
+ dot3(avxf_a, avxf_b, den, den2);
+ EXPECT_FLOAT_EQ(den, 14.9f);
+ EXPECT_FLOAT_EQ(den2, 2.9f);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/eigen/CMakeLists.txt b/intern/eigen/CMakeLists.txt
index 70088d080e1..f5ccb6efb67 100644
--- a/intern/eigen/CMakeLists.txt
+++ b/intern/eigen/CMakeLists.txt
@@ -43,4 +43,10 @@ set(SRC
set(LIB
)
+if(WITH_OPENMP_STATIC)
+ list(APPEND LIB
+ ${OpenMP_LIBRARIES}
+ )
+endif()
+
blender_add_lib(bf_intern_eigen "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
index e072f0823f3..02daad2111a 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -316,7 +316,7 @@ bool GHOST_ContextEGL::initContextEGLEW()
{
/* We have to manually get this function before we can call eglewInit, since
* it requires a display argument. glewInit() does the same, but we only want
- * to intialize EGLEW here. */
+ * to initialize EGLEW here. */
eglGetDisplay = (PFNEGLGETDISPLAYPROC)eglGetProcAddress("eglGetDisplay");
if (eglGetDisplay == NULL) {
return false;
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index c32689e4043..a682eccf7e2 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -115,7 +115,7 @@ class GHOST_WindowManager {
/**
* Return a vector of the windows currently managed by this
* class.
- * \return Const reference to the vector of windows managed
+ * \return Constant reference to the vector of windows managed
*/
const std::vector<GHOST_IWindow *> &getWindows() const;
diff --git a/intern/mantaflow/CMakeLists.txt b/intern/mantaflow/CMakeLists.txt
index c7b3c56c3c2..2d49f96a451 100644
--- a/intern/mantaflow/CMakeLists.txt
+++ b/intern/mantaflow/CMakeLists.txt
@@ -27,6 +27,7 @@ add_definitions(-DWITH_FLUID=1)
if(WITH_OPENVDB)
add_definitions(-DOPENVDB=1)
+ add_definitions(-DOPENVDB_STATICLIB)
endif()
set(INC
@@ -47,6 +48,35 @@ set(INC_SYS
${ZLIB_INCLUDE_DIRS}
)
+if(WITH_TBB)
+ list(APPEND INC_SYS
+ ${TBB_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ ${TBB_LIBRARIES}
+ )
+endif()
+
+if(WITH_OPENVDB)
+ list(APPEND INC_SYS
+ ${BOOST_INCLUDE_DIR}
+ ${OPENEXR_INCLUDE_DIRS}
+ ${OPENVDB_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ ${OPENVDB_LIBRARIES}
+ ${OPENEXR_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ ${BOOST_LIBRARIES}
+ )
+ if(WITH_OPENVDB_BLOSC)
+ list(APPEND LIB
+ ${BLOSC_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ )
+ endif()
+endif()
+
set(SRC
intern/manta_python_API.cpp
intern/manta_fluid_API.cpp
diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h
index 8dc2cf1805a..4ebedeb5e38 100644
--- a/intern/mantaflow/extern/manta_fluid_API.h
+++ b/intern/mantaflow/extern/manta_fluid_API.h
@@ -55,6 +55,8 @@ int manta_update_mesh_structures(struct MANTA *fluid, struct FluidModifierData *
int manta_update_particle_structures(struct MANTA *fluid,
struct FluidModifierData *mmd,
int framenr);
+int manta_update_smoke_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr);
+int manta_update_noise_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr);
int manta_bake_data(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr);
int manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr);
int manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr);
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 7f6ff9094c6..d7c8f5491a9 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -27,6 +27,10 @@
#include <iomanip>
#include <zlib.h>
+#if OPENVDB == 1
+# include "openvdb/openvdb.h"
+#endif
+
#include "MANTA_main.h"
#include "manta.h"
#include "Python.h"
@@ -568,6 +572,29 @@ void MANTA::terminateMantaflow()
mantaInitialized = false;
}
+static std::string getCacheFileEnding(char cache_format)
+{
+ if (MANTA::with_debug)
+ std::cout << "MANTA::getCacheFileEnding()" << std::endl;
+
+ switch (cache_format) {
+ case FLUID_DOMAIN_FILE_UNI:
+ return ".uni";
+ case FLUID_DOMAIN_FILE_OPENVDB:
+ return ".vdb";
+ case FLUID_DOMAIN_FILE_RAW:
+ return ".raw";
+ case FLUID_DOMAIN_FILE_BIN_OBJECT:
+ return ".bobj.gz";
+ case FLUID_DOMAIN_FILE_OBJECT:
+ return ".obj";
+ default:
+ if (MANTA::with_debug)
+ std::cout << "Error: Could not find file extension" << std::endl;
+ return ".uni";
+ }
+}
+
std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *mmd)
{
std::ostringstream ss;
@@ -811,6 +838,14 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
ss << mmd->time;
else if (varName == "END_FRAME")
ss << mmd->domain->cache_frame_end;
+ else if (varName == "CACHE_DATA_FORMAT")
+ ss << getCacheFileEnding(mmd->domain->cache_data_format);
+ else if (varName == "CACHE_MESH_FORMAT")
+ ss << getCacheFileEnding(mmd->domain->cache_mesh_format);
+ else if (varName == "CACHE_NOISE_FORMAT")
+ ss << getCacheFileEnding(mmd->domain->cache_noise_format);
+ else if (varName == "CACHE_PARTICLE_FORMAT")
+ ss << getCacheFileEnding(mmd->domain->cache_particle_format);
else if (varName == "SIMULATION_METHOD") {
if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_FLIP) {
ss << "'FLIP'";
@@ -983,29 +1018,6 @@ std::string MANTA::parseScript(const std::string &setup_string, FluidModifierDat
return res.str();
}
-static std::string getCacheFileEnding(char cache_format)
-{
- if (MANTA::with_debug)
- std::cout << "MANTA::getCacheFileEnding()" << std::endl;
-
- switch (cache_format) {
- case FLUID_DOMAIN_FILE_UNI:
- return ".uni";
- case FLUID_DOMAIN_FILE_OPENVDB:
- return ".vdb";
- case FLUID_DOMAIN_FILE_RAW:
- return ".raw";
- case FLUID_DOMAIN_FILE_BIN_OBJECT:
- return ".bobj.gz";
- case FLUID_DOMAIN_FILE_OBJECT:
- return ".obj";
- default:
- if (MANTA::with_debug)
- std::cout << "Error: Could not find file extension" << std::endl;
- return ".uni";
- }
-}
-
int MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
{
if (MANTA::with_debug)
@@ -1168,6 +1180,244 @@ int MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
return 1;
}
+int MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr)
+{
+ if (MANTA::with_debug)
+ std::cout << "MANTA::updateGridStructures()" << std::endl;
+
+ mSmokeFromFile = false;
+
+ if (!mUsingSmoke)
+ return 0;
+ if (BLI_path_is_rel(mmd->domain->cache_directory))
+ return 0;
+
+ int result = 0;
+ int expected = 0; /* Expected number of read successes for this frame. */
+
+ std::ostringstream ss;
+ char cacheDir[FILE_MAX], targetFile[FILE_MAX];
+ cacheDir[0] = '\0';
+ targetFile[0] = '\0';
+
+ std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ BLI_path_join(
+ cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr);
+
+ expected += 1;
+ ss.str("");
+ ss << "density_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mDensity, false);
+
+ expected += 1;
+ ss.str("");
+ ss << "shadow_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mShadow, false);
+
+ if (mUsingHeat) {
+ expected += 1;
+ ss.str("");
+ ss << "heat_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mHeat, false);
+ }
+
+ if (mUsingColors) {
+ expected += 3;
+ ss.str("");
+ ss << "color_r_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mColorR, false);
+
+ ss.str("");
+ ss << "color_g_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mColorG, false);
+
+ ss.str("");
+ ss << "color_b_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mColorB, false);
+ }
+
+ if (mUsingFire) {
+ expected += 3;
+ ss.str("");
+ ss << "flame_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mFlame, false);
+
+ ss.str("");
+ ss << "fuel_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mFuel, false);
+
+ ss.str("");
+ ss << "react_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDir, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mReact, false);
+ }
+
+ mSmokeFromFile = true;
+ return (result == expected) ? 1 : 0;
+}
+
+int MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr)
+{
+ if (MANTA::with_debug)
+ std::cout << "MANTA::updateNoiseStructures()" << std::endl;
+
+ mNoiseFromFile = false;
+
+ if (!mUsingSmoke || !mUsingNoise)
+ return 0;
+ if (BLI_path_is_rel(mmd->domain->cache_directory))
+ return 0;
+
+ int result = 0;
+ int expected = 0; /* Expected number of read successes for this frame. */
+
+ std::ostringstream ss;
+ char cacheDirData[FILE_MAX], cacheDirNoise[FILE_MAX], targetFile[FILE_MAX];
+ cacheDirData[0] = '\0';
+ cacheDirNoise[0] = '\0';
+ targetFile[0] = '\0';
+
+ std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format);
+ BLI_path_join(cacheDirData,
+ sizeof(cacheDirData),
+ mmd->domain->cache_directory,
+ FLUID_DOMAIN_DIR_DATA,
+ nullptr);
+ BLI_path_join(cacheDirNoise,
+ sizeof(cacheDirNoise),
+ mmd->domain->cache_directory,
+ FLUID_DOMAIN_DIR_NOISE,
+ nullptr);
+
+ expected += 1;
+ ss.str("");
+ ss << "density_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mDensityHigh, true);
+
+ expected += 1;
+ ss.str("");
+ ss << "shadow_####" << dformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirData, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mShadow, false);
+
+ if (mUsingColors) {
+ expected += 3;
+ ss.str("");
+ ss << "color_r_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mColorRHigh, true);
+
+ ss.str("");
+ ss << "color_g_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mColorGHigh, true);
+
+ ss.str("");
+ ss << "color_b_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mColorBHigh, true);
+ }
+
+ if (mUsingFire) {
+ expected += 3;
+ ss.str("");
+ ss << "flame_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mFlameHigh, true);
+
+ ss.str("");
+ ss << "fuel_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mFuelHigh, true);
+
+ ss.str("");
+ ss << "react_noise_####" << nformat;
+ BLI_join_dirfile(targetFile, sizeof(targetFile), cacheDirNoise, ss.str().c_str());
+ BLI_path_frame(targetFile, framenr, 0);
+ if (!BLI_exists(targetFile)) {
+ return 0;
+ }
+ result += updateGridFromFile(targetFile, mReactHigh, true);
+ }
+
+ mNoiseFromFile = true;
+ return (result == expected) ? 1 : 0;
+}
+
/* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */
static std::string escapeSlashes(std::string const &s)
{
@@ -1190,11 +1440,10 @@ int MANTA::writeConfiguration(FluidModifierData *mmd, int framenr)
FluidDomainSettings *mds = mmd->domain;
std::ostringstream ss;
char cacheDir[FILE_MAX], targetFile[FILE_MAX];
- ;
cacheDir[0] = '\0';
targetFile[0] = '\0';
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ std::string dformat = ".uni";
BLI_path_join(
cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_CONFIG, nullptr);
@@ -1287,7 +1536,7 @@ int MANTA::readConfiguration(FluidModifierData *mmd, int framenr)
targetFile[0] = '\0';
float dummy;
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ std::string dformat = ".uni";
BLI_path_join(
cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_CONFIG, nullptr);
@@ -1759,6 +2008,9 @@ int MANTA::bakeGuiding(FluidModifierData *mmd, int framenr)
std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ std::string resumable_cache = (final_cache) ? "False" : "True";
+
BLI_path_join(cacheDirGuiding,
sizeof(cacheDirGuiding),
mmd->domain->cache_directory,
@@ -1768,7 +2020,7 @@ int MANTA::bakeGuiding(FluidModifierData *mmd, int framenr)
ss.str("");
ss << "bake_guiding_" << mCurrentID << "('" << escapeSlashes(cacheDirGuiding) << "', " << framenr
- << ", '" << gformat << "')";
+ << ", '" << gformat << "', " << resumable_cache << ")";
pythonCommands.push_back(ss.str());
runPythonString(pythonCommands);
@@ -1932,6 +2184,7 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
bool floater = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
bool tracer = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
+ bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS;
bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
@@ -1968,6 +2221,8 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
manta_script += fluid_alloc_guiding;
if (obstacle)
manta_script += fluid_alloc_obstacle;
+ if (fractions)
+ manta_script += fluid_alloc_fractions;
if (invel)
manta_script += fluid_alloc_invel;
@@ -2533,6 +2788,191 @@ void MANTA::updateParticlesFromUni(const char *filename, bool isSecondarySys, bo
gzclose(gzf);
}
+int MANTA::updateGridFromFile(const char *filename, float *grid, bool isNoise)
+{
+ if (with_debug)
+ std::cout << "MANTA::updateGridFromFile()" << std::endl;
+
+ if (!grid) {
+ std::cout << "MANTA::updateGridFromFile(): cannot read into uninitialized grid, grid is null"
+ << std::endl;
+ return 0;
+ }
+
+ std::string fname(filename);
+ std::string::size_type idx;
+
+ idx = fname.rfind('.');
+ if (idx != std::string::npos) {
+ std::string extension = fname.substr(idx + 1);
+
+ if (extension.compare("uni") == 0)
+ return updateGridFromUni(filename, grid, isNoise);
+#if OPENVDB == 1
+ else if (extension.compare("vdb") == 0)
+ return updateGridFromVDB(filename, grid, isNoise);
+#endif
+ else if (extension.compare("raw") == 0)
+ return updateGridFromRaw(filename, grid, isNoise);
+ else
+ std::cerr << "MANTA::updateGridFromFile(): invalid file extension in file: " << filename
+ << std::endl;
+ return 0;
+ }
+ else {
+ std::cerr << "MANTA::updateGridFromFile(): unable to open file: " << filename << std::endl;
+ return 0;
+ }
+}
+
+int MANTA::updateGridFromUni(const char *filename, float *grid, bool isNoise)
+{
+ if (with_debug)
+ std::cout << "MANTA::updateGridFromUni()" << std::endl;
+
+ gzFile gzf;
+ int ibuffer[4];
+
+ gzf = (gzFile)BLI_gzopen(filename, "rb1");
+ if (!gzf) {
+ std::cout << "MANTA::updateGridFromUni(): unable to open file" << std::endl;
+ return 0;
+ }
+
+ char ID[5] = {0, 0, 0, 0, 0};
+ gzread(gzf, ID, 4);
+
+ if (!strcmp(ID, "DDF2")) {
+ std::cout << "MANTA::updateGridFromUni(): grid uni file format DDF2 not supported anymore"
+ << std::endl;
+ return 0;
+ }
+ if (!strcmp(ID, "MNT1")) {
+ std::cout << "MANTA::updateGridFromUni(): grid uni file format MNT1 not supported anymore"
+ << std::endl;
+ return 0;
+ }
+ if (!strcmp(ID, "MNT2")) {
+ std::cout << "MANTA::updateGridFromUni(): grid uni file format MNT2 not supported anymore"
+ << std::endl;
+ return 0;
+ }
+
+ // grid uni header
+ const int STR_LEN_GRID = 252;
+ int elementType, bytesPerElement; // data type info
+ char info[STR_LEN_GRID]; // mantaflow build information
+ int dimT; // optionally store forth dimension for 4d grids
+ unsigned long long timestamp; // creation time
+
+ // read grid header
+ gzread(gzf, &ibuffer, sizeof(int) * 4); // dimX, dimY, dimZ, gridType
+ gzread(gzf, &elementType, sizeof(int));
+ gzread(gzf, &bytesPerElement, sizeof(int));
+ gzread(gzf, &info, sizeof(info));
+ gzread(gzf, &dimT, sizeof(int));
+ gzread(gzf, &timestamp, sizeof(unsigned long long));
+
+ int resX = (isNoise) ? mResXNoise : mResX;
+ int resY = (isNoise) ? mResYNoise : mResY;
+ int resZ = (isNoise) ? mResZNoise : mResZ;
+
+ if (with_debug)
+ std::cout << "read " << ibuffer[3] << " grid type in file: " << filename << std::endl;
+
+ // Sanity checks
+ if (ibuffer[0] != resX || ibuffer[1] != resY || ibuffer[2] != resZ) {
+ std::cout << "grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1] << ", "
+ << ibuffer[2] << ") vs setup: (" << resX << ", " << resY << ", " << resZ << ")"
+ << std::endl;
+ return 0;
+ }
+
+ // Actual data reading
+ if (!strcmp(ID, "MNT3")) {
+ gzread(gzf, grid, sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2]);
+ }
+
+ if (with_debug)
+ std::cout << "read successfully: " << filename << std::endl;
+
+ gzclose(gzf);
+ return 1;
+}
+
+#if OPENVDB == 1
+int MANTA::updateGridFromVDB(const char *filename, float *grid, bool isNoise)
+{
+ if (with_debug)
+ std::cout << "MANTA::updateGridFromVDB()" << std::endl;
+
+ openvdb::initialize();
+ openvdb::io::File file(filename);
+ try {
+ file.open();
+ }
+ catch (const openvdb::IoError &) {
+ std::cout << "MANTA::updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename
+ << std::endl;
+ return 0;
+ }
+
+ openvdb::GridBase::Ptr baseGrid;
+ for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
+ ++nameIter) {
+ baseGrid = file.readGrid(nameIter.gridName());
+ break;
+ }
+ file.close();
+ openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid);
+ openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor();
+
+ int resX = (isNoise) ? mResXNoise : mResX;
+ int resY = (isNoise) ? mResYNoise : mResY;
+ int resZ = (isNoise) ? mResZNoise : mResZ;
+
+ size_t index = 0;
+ for (int z = 0; z < resZ; ++z) {
+ for (int y = 0; y < resY; ++y) {
+ for (int x = 0; x < resX; ++x, ++index) {
+ openvdb::Coord xyz(x, y, z);
+ float v = accessor.getValue(xyz);
+ grid[index] = v;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+int MANTA::updateGridFromRaw(const char *filename, float *grid, bool isNoise)
+{
+ if (with_debug)
+ std::cout << "MANTA::updateGridFromRaw()" << std::endl;
+
+ gzFile gzf;
+ int expectedBytes, readBytes;
+
+ gzf = (gzFile)BLI_gzopen(filename, "rb");
+ if (!gzf) {
+ std::cout << "MANTA::updateGridFromRaw(): unable to open file" << std::endl;
+ return 0;
+ }
+
+ int resX = (isNoise) ? mResXNoise : mResX;
+ int resY = (isNoise) ? mResYNoise : mResY;
+ int resZ = (isNoise) ? mResZNoise : mResZ;
+
+ expectedBytes = sizeof(float) * resX * resY * resZ;
+ readBytes = gzread(gzf, grid, expectedBytes);
+
+ assert(expectedBytes == readBytes);
+ (void)readBytes; // Unused in release.
+
+ gzclose(gzf);
+ return 1;
+}
+
void MANTA::updatePointers()
{
if (with_debug)
@@ -2660,7 +3100,9 @@ void MANTA::updatePointers()
callPythonFunction("pLifeSnd" + parts_ext, func));
}
- mFlipFromFile = true;
+ mFlipFromFile = false;
mMeshFromFile = false;
mParticlesFromFile = false;
+ mSmokeFromFile = false;
+ mNoiseFromFile = false;
}
diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h
index f8d94e2631c..105beaf6e20 100644
--- a/intern/mantaflow/intern/MANTA_main.h
+++ b/intern/mantaflow/intern/MANTA_main.h
@@ -93,6 +93,8 @@ struct MANTA {
int updateMeshStructures(FluidModifierData *mmd, int framenr);
int updateFlipStructures(FluidModifierData *mmd, int framenr);
int updateParticleStructures(FluidModifierData *mmd, int framenr);
+ int updateSmokeStructures(FluidModifierData *mmd, int framenr);
+ int updateNoiseStructures(FluidModifierData *mmd, int framenr);
void updateVariables(FluidModifierData *mmd);
// Bake cache
@@ -742,6 +744,8 @@ struct MANTA {
bool mFlipFromFile;
bool mMeshFromFile;
bool mParticlesFromFile;
+ bool mSmokeFromFile;
+ bool mNoiseFromFile;
int mResX;
int mResY;
@@ -852,8 +856,12 @@ struct MANTA {
void updateMeshFromObj(const char *filename);
void updateMeshFromUni(const char *filename);
void updateParticlesFromUni(const char *filename, bool isSecondarySys, bool isVelData);
+ int updateGridFromUni(const char *filename, float *grid, bool isNoise);
+ int updateGridFromVDB(const char *filename, float *grid, bool isNoise);
+ int updateGridFromRaw(const char *filename, float *grid, bool isNoise);
void updateMeshFromFile(const char *filename);
void updateParticlesFromFile(const char *filename, bool isSecondarySys, bool isVelData);
+ int updateGridFromFile(const char *filename, float *grid, bool isNoise);
};
#endif
diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp
index 35f2ebbaf44..82bfed7cf61 100644
--- a/intern/mantaflow/intern/manta_fluid_API.cpp
+++ b/intern/mantaflow/intern/manta_fluid_API.cpp
@@ -143,6 +143,20 @@ int manta_update_particle_structures(MANTA *fluid, FluidModifierData *mmd, int f
return fluid->updateParticleStructures(mmd, framenr);
}
+int manta_update_smoke_structures(MANTA *fluid, FluidModifierData *mmd, int framenr)
+{
+ if (!fluid || !mmd)
+ return 0;
+ return fluid->updateSmokeStructures(mmd, framenr);
+}
+
+int manta_update_noise_structures(MANTA *fluid, FluidModifierData *mmd, int framenr)
+{
+ if (!fluid || !mmd)
+ return 0;
+ return fluid->updateNoiseStructures(mmd, framenr);
+}
+
int manta_bake_data(MANTA *fluid, FluidModifierData *mmd, int framenr)
{
if (!fluid || !mmd)
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index f66f2fadcb1..477cf3ff789 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -559,12 +559,9 @@ def bake_particles_$ID$(path_data, path_particles, framenr, format_data, format_
const std::string fluid_bake_guiding =
"\n\
-def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding):\n\
+def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable):\n\
mantaMsg('Bake fluid guiding')\n\
\n\
- if framenr>1:\n\
- fluid_load_guiding_$ID$(path_guiding, framenr-1, format_guiding)\n\
- \n\
# Average out velocities from multiple guiding objects at one cell\n\
x_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
y_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
@@ -582,13 +579,13 @@ def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding):\n\
extrapolateVec3Simple(vel=guidevelC_s$ID$, phi=phiGuideIn_s$ID$, distance=4, inside=False)\n\
resampleVec3ToMac(source=guidevelC_s$ID$, target=guidevel_sg$ID$)\n\
\n\
- fluid_save_guiding_$ID$(path_guiding, framenr, format_guiding)\n\
+ fluid_save_guiding_$ID$(path_guiding, framenr, format_guiding, resumable)\n\
\n\
-def bake_guiding_$ID$(path_guiding, framenr, format_guiding):\n\
+def bake_guiding_$ID$(path_guiding, framenr, format_guiding, resumable):\n\
if not withMPBake or isWindows:\n\
- bake_guiding_process_$ID$(framenr, format_guiding, path_guiding)\n\
+ bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable)\n\
else:\n\
- fluid_cache_multiprocessing_start_$ID$(function=bake_guiding_process_$ID$, framenr=framenr, format_guiding=format_guiding, path_guiding=path_guiding)\n";
+ fluid_cache_multiprocessing_start_$ID$(function=bake_guiding_process_$ID$, framenr=framenr, format_guiding=format_guiding, path_guiding=path_guiding, resumable=resumable)\n";
//////////////////////////////////////////////////////////////////////
// IMPORT
@@ -692,12 +689,12 @@ if (GUI):\n\
gui.show()\n\
gui.pause()\n\
\n\
-cache_dir = '$CACHE_DIR$'\n\
-cache_resumable = $CACHE_RESUMABLE$\n\
-file_format_data = '.uni'\n\
-file_format_noise = '.uni'\n\
-file_format_particles = '.uni'\n\
-file_format_mesh = '.bobj.gz'\n\
+cache_resumable = $CACHE_RESUMABLE$\n\
+cache_dir = '$CACHE_DIR$'\n\
+file_format_data = '$CACHE_DATA_FORMAT$'\n\
+file_format_noise = '$CACHE_NOISE_FORMAT$'\n\
+file_format_particles = '$CACHE_PARTICLE_FORMAT$'\n\
+file_format_mesh = '$CACHE_MESH_FORMAT$'\n\
\n\
# Start and stop for simulation\n\
current_frame = $CURRENT_FRAME$\n\
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 442b09b5a8a..9a494a1cb6a 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -181,7 +181,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\
phi_s$ID$.join(phiIn_s$ID$)\n\
\n\
if using_obstacle_s$ID$:\n\
- phi_s$ID$.subtract(phiObsIn_s$ID$)\n\
+ phi_s$ID$.subtract(o=phiObsIn_s$ID$, flags=flags_s$ID$, subtractType=FlagObstacle)\n\
\n\
if using_outflow_s$ID$:\n\
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 74afb3ed35e3271b2609feaf67bea6b8bdffe7c
+Subproject 34d98762cef85b9c065f21a051d1dbe3bf2979b
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index 1eff85b6129..df8fde40f3c 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -413,7 +413,7 @@ const bTheme U_theme_default = {
.tab_inactive = RGBA(0x2b2b2bff),
.tab_back = RGBA(0x232323ff),
.tab_outline = RGBA(0x232323ff),
- .button = RGBA(0x282828ff),
+ .button = RGBA(0x424242ff),
.button_title = RGBA(0xffffffff),
.button_text = RGBA(0xe5e5e5ff),
.button_text_hi = RGBA(0xffffffff),
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject ad6928706de2fa8f44fa35a275453c716d65e77
+Subproject cbcf507f3045e867c4b2d8e0976b76e1753dc49
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 8c009a77d3d..540bc75cece 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -161,7 +161,7 @@ def object_data_add(context, obdata, operator=None, name=None):
bpy.ops.object.mode_set(mode='EDIT')
else:
layer.objects.active = obj_new
- if context.preferences.edit.use_enter_edit_mode:
+ if obdata and context.preferences.edit.use_enter_edit_mode:
bpy.ops.object.mode_set(mode='EDIT')
return obj_new
diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py
index 2e78f18b78e..de2919cc883 100644
--- a/release/scripts/modules/rna_manual_reference.py
+++ b/release/scripts/modules/rna_manual_reference.py
@@ -45,6 +45,8 @@ url_manual_mapping = (
("bpy.types.cyclesrendersettings.offscreen_dicing_scale*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-offscreen-dicing-scale"),
("bpy.types.linestylegeometrymodifier_backbonestretcher*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/backbone_stretcher.html#bpy-types-linestylegeometrymodifier-backbonestretcher"),
("bpy.types.linestylegeometrymodifier_sinusdisplacement*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/sinus_displacement.html#bpy-types-linestylegeometrymodifier-sinusdisplacement"),
+ ("bpy.types.fluiddomainsettings.use_adaptive_timesteps*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-adaptive-timesteps"),
+ ("bpy.types.fluiddomainsettings.use_dissolve_smoke_log*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-dissolve-smoke-log"),
("bpy.types.linestylegeometrymodifier_polygonalization*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/polygonization.html#bpy-types-linestylegeometrymodifier-polygonalization"),
("bpy.types.cyclesrendersettings.distance_cull_margin*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-distance-cull-margin"),
("bpy.types.materialgpencilstyle.use_fill_texture_mix*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-use-fill-texture-mix"),
@@ -52,21 +54,39 @@ url_manual_mapping = (
("bpy.types.rendersettings_simplify_gpencil_view_fill*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-view-fill"),
("bpy.types.brushgpencilsettings.use_jitter_pressure*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-use-jitter-pressure"),
("bpy.types.brushgpencilsettings.use_settings_random*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-use-settings-random"),
+ ("bpy.types.fluiddomainsettings.mesh_particle_radius*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-particle-radius"),
+ ("bpy.types.fluiddomainsettings.use_bubble_particles*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-use-bubble-particles"),
+ ("bpy.types.fluiddomainsettings.use_collision_border*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border"),
("bpy.types.linestylegeometrymodifier_simplification*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/simplification.html#bpy-types-linestylegeometrymodifier-simplification"),
("bpy.types.materialgpencilstyle.use_overlap_strokes*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-use-overlap-strokes"),
("bpy.types.toolsettings.use_gpencil_weight_data_add*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-weight-data-add"),
("bpy.types.cyclesrendersettings.camera_cull_margin*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-camera-cull-margin"),
+ ("bpy.types.fluiddomainsettings.export_manta_script*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-export-manta-script"),
+ ("bpy.types.fluiddomainsettings.use_adaptive_domain*", "physics/fluid/type/domain/gas/adaptive_domain.html#bpy-types-fluiddomainsettings-use-adaptive-domain"),
+ ("bpy.types.fluiddomainsettings.use_spray_particles*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-use-spray-particles"),
+ ("bpy.types.fluiddomainsettings.vector_display_type*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-vector-display-type"),
("bpy.types.linestylegeometrymodifier_perlinnoise1d*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/perlin_noise_1d.html#bpy-types-linestylegeometrymodifier-perlinnoise1d"),
("bpy.types.linestylegeometrymodifier_perlinnoise2d*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/perlin_noise_2d.html#bpy-types-linestylegeometrymodifier-perlinnoise2d"),
- ("bpy.types.smokedomainsettings.use_high_resolution*", "render/cycles/render_settings/simplify.html#bpy-types-smokedomainsettings-use-high-resolution"),
("bpy.types.cyclesrendersettings.use_distance_cull*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-use-distance-cull"),
+ ("bpy.types.fluiddomainsettings.mesh_concave_lower*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-concave-lower"),
+ ("bpy.types.fluiddomainsettings.mesh_concave_upper*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-concave-upper"),
+ ("bpy.types.fluiddomainsettings.use_dissolve_smoke*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-dissolve-smoke"),
+ ("bpy.types.fluiddomainsettings.use_foam_particles*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-use-foam-particles"),
+ ("bpy.types.fluiddomainsettings.viscosity_exponent*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-viscosity-exponent"),
+ ("bpy.types.fluidflowsettings.use_initial_velocity*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-initial-velocity"),
("bpy.types.linestylegeometrymodifier_guidinglines*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/guiding_lines.html#bpy-types-linestylegeometrymodifier-guidinglines"),
("bpy.types.linestylegeometrymodifier_spatialnoise*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/spatial_noise.html#bpy-types-linestylegeometrymodifier-spatialnoise"),
("bpy.types.linestylethicknessmodifier_calligraphy*", "render/freestyle/parameter_editor/line_style/modifiers/thickness/calligraphy.html#bpy-types-linestylethicknessmodifier-calligraphy"),
("bpy.types.rendersettings_simplify_gpencil_onplay*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-onplay"),
("bpy.types.toolsettings.use_gpencil_draw_additive*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-draw-additive"),
+ ("bpy.types.toolsettings.use_snap_backface_culling*", "scene_layout/object/editing/transform/control/snap.html#bpy-types-toolsettings-use-snap-backface-culling"),
("bpy.types.toolsettings.use_transform_data_origin*", "scene_layout/object/editing/transform/control/options.html#bpy-types-toolsettings-use-transform-data-origin"),
("bpy.types.cyclesrendersettings.max_subdivisions*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-max-subdivisions"),
+ ("bpy.types.fluiddomainsettings.axis_slice_method*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-axis-slice-method"),
+ ("bpy.types.fluiddomainsettings.flame_smoke_color*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flame-smoke-color"),
+ ("bpy.types.fluiddomainsettings.mesh_smoothen_neg*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-smoothen-neg"),
+ ("bpy.types.fluiddomainsettings.mesh_smoothen_pos*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-smoothen-pos"),
+ ("bpy.types.fluiddomainsettings.use_speed_vectors*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-use-speed-vectors"),
("bpy.types.linestyle*modifier_distancefromcamera*", "render/freestyle/parameter_editor/line_style/modifiers/color/distance_from_camera.html#bpy-types-linestyle-modifier-distancefromcamera"),
("bpy.types.linestyle*modifier_distancefromobject*", "render/freestyle/parameter_editor/line_style/modifiers/color/distance_from_object.html#bpy-types-linestyle-modifier-distancefromobject"),
("bpy.types.linestylegeometrymodifier_2dtransform*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/2d_transform.html#bpy-types-linestylegeometrymodifier-2dtransform"),
@@ -77,28 +97,68 @@ url_manual_mapping = (
("bpy.types.linestylegeometrymodifier_tipremover*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/tip_remover.html#bpy-types-linestylegeometrymodifier-tipremover"),
("bpy.types.rendersettings_simplify_gpencil_tint*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-tint"),
("bpy.types.toolsettings.use_gpencil_draw_onback*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-draw-onback"),
+ ("bpy.types.clothsettings.vertex_group_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-pressure"),
("bpy.types.cyclesmaterialsettings.displacement*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-displacement"),
+ ("bpy.types.fluiddomainsettings.adapt_threshold*", "physics/fluid/type/domain/gas/adaptive_domain.html#bpy-types-fluiddomainsettings-adapt-threshold"),
+ ("bpy.types.fluiddomainsettings.flame_vorticity*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flame-vorticity"),
+ ("bpy.types.fluiddomainsettings.slice_per_voxel*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-slice-per-voxel"),
+ ("bpy.types.fluiddomainsettings.surface_tension*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-surface-tension"),
+ ("bpy.types.fluidflowsettings.use_particle_size*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-particle-size"),
("bpy.types.linestylegeometrymodifier_blueprint*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/blueprint.html#bpy-types-linestylegeometrymodifier-blueprint"),
("bpy.types.materialgpencilstyle.alignment_mode*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-alignment-mode"),
("bpy.types.rendersettings.simplify_subdivision*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-subdivision"),
("bpy.ops.object.vertex_group_copy_to_selected*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy-to-selected"),
+ ("bpy.types.clothsettings.internal_compression*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-internal-compression"),
("bpy.types.cyclesrendersettings.dicing_camera*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-dicing-camera"),
("bpy.types.cyclesrendersettings.texture_limit*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-texture-limit"),
+ ("bpy.types.fluiddomainsettings.additional_res*", "physics/fluid/type/domain/gas/adaptive_domain.html#bpy-types-fluiddomainsettings-additional-res"),
+ ("bpy.types.fluiddomainsettings.dissolve_speed*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-dissolve-speed"),
+ ("bpy.types.fluiddomainsettings.effector_group*", "physics/fluid/type/domain/collections.html#bpy-types-fluiddomainsettings-effector-group"),
+ ("bpy.types.fluiddomainsettings.flame_ignition*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flame-ignition"),
+ ("bpy.types.fluiddomainsettings.flame_max_temp*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flame-max-temp"),
+ ("bpy.types.fluiddomainsettings.mesh_generator*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-generator"),
+ ("bpy.types.fluiddomainsettings.particle_scale*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-particle-scale"),
+ ("bpy.types.fluiddomainsettings.resolution_max*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-resolution-max"),
+ ("bpy.types.fluiddomainsettings.use_color_ramp*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-use-color-ramp"),
+ ("bpy.types.fluiddomainsettings.viscosity_base*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-viscosity-base"),
+ ("bpy.types.fluidflowsettings.surface_distance*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-surface-distance"),
("bpy.types.gpencilsculptguide.reference_point*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-reference-point"),
("bpy.types.linestylegeometrymodifier_2doffset*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/2d_offset.html#bpy-types-linestylegeometrymodifier-2doffset"),
("bpy.types.linestylegeometrymodifier_sampling*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/sampling.html#bpy-types-linestylegeometrymodifier-sampling"),
+ ("bpy.types.clothsettings.use_pressure_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-use-pressure-volume"),
+ ("bpy.types.clothsettings.vertex_group_intern*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-intern"),
("bpy.types.cyclesrendersettings.*dicing_rate*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-dicing-rate"),
+ ("bpy.types.fluiddomainsettings.cfl_condition*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-cfl-condition"),
+ ("bpy.types.fluiddomainsettings.show_velocity*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-show-velocity"),
+ ("bpy.types.fluiddomainsettings.timesteps_max*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-timesteps-max"),
+ ("bpy.types.fluiddomainsettings.timesteps_min*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-timesteps-min"),
+ ("bpy.types.fluidflowsettings.particle_system*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-particle-system"),
("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-stroke-style"),
("bpy.types.rendersettings.use_file_extension*", "render/output/settings.html#bpy-types-rendersettings-use-file-extension"),
("bpy.types.spaceview3d.transform_orientation*", "scene_layout/object/editing/transform/control/orientations.html#bpy-types-spaceview3d-transform-orientation"),
("bpy.ops.object.constraint_add_with_targets*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraint-add-with-targets"),
("bpy.ops.object.vertex_group_copy_to_linked*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy-to-linked"),
("bpy.types.cyclesobjectsettings.dicing_rate*", "render/cycles/object_settings/adaptive_subdiv.html#bpy-types-cyclesobjectsettings-dicing-rate"),
+ ("bpy.types.fluiddomainsettings.adapt_margin*", "physics/fluid/type/domain/gas/adaptive_domain.html#bpy-types-fluiddomainsettings-adapt-margin"),
+ ("bpy.types.fluiddomainsettings.burning_rate*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-burning-rate"),
+ ("bpy.types.fluiddomainsettings.guide_source*", "physics/fluid/type/domain/guides.html#bpy-types-fluiddomainsettings-guide-source"),
+ ("bpy.types.fluiddomainsettings.slice_method*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-slice-method"),
+ ("bpy.types.fluiddomainsettings.vector_scale*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-vector-scale"),
+ ("bpy.types.fluidflowsettings.use_plane_init*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-plane-init"),
+ ("bpy.types.fluidflowsettings.volume_density*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-volume-density"),
("bpy.types.materialgpencilstyle.show_stroke*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-show-stroke"),
("bpy.types.posebone.use_ik_rotation_control*", "animation/armatures/posing/bone_constraints/inverse_kinematics/introduction.html#bpy-types-posebone-use-ik-rotation-control"),
("bpy.ops.constraint.disable_keep_transform*", "animation/constraints/interface/common.html#bpy-ops-constraint-disable-keep-transform"),
("bpy.ops.object.vertex_group_normalize_all*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-normalize-all"),
("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-pen-jitter"),
+ ("bpy.types.fluiddomainsettings.domain_size*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-domain-size"),
+ ("bpy.types.fluiddomainsettings.domain_type*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-domain-type"),
+ ("bpy.types.fluiddomainsettings.flame_smoke*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flame-smoke"),
+ ("bpy.types.fluiddomainsettings.fluid_group*", "physics/fluid/type/domain/collections.html#bpy-types-fluiddomainsettings-fluid-group"),
+ ("bpy.types.fluiddomainsettings.slice_depth*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-slice-depth"),
+ ("bpy.types.fluiddomainsettings.sndparticle*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle"),
+ ("bpy.types.fluidflowsettings.noise_texture*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-noise-texture"),
+ ("bpy.types.fluidflowsettings.particle_size*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-particle-size"),
("bpy.types.gpencillayer.use_onion_skinning*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-onion-skinning"),
("bpy.types.gpencilsculptguide.use_snapping*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-use-snapping"),
("bpy.types.gpencilsculptsettings.lock_axis*", "grease_pencil/modes/draw/drawing_planes.html#bpy-types-gpencilsculptsettings-lock-axis"),
@@ -111,12 +171,18 @@ url_manual_mapping = (
("bpy.types.rendersettings_simplify_gpencil*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil"),
("bpy.types.sceneeevee.use_taa_reprojection*", "render/eevee/render_settings/sampling.html#bpy-types-sceneeevee-use-taa-reprojection"),
("bpy.types.sequenceeditor.use_overlay_lock*", "video_editing/preview/properties.html#bpy-types-sequenceeditor-use-overlay-lock"),
+ ("bpy.types.spaceuveditor.show_pixel_coords*", "editors/uv/display_panel.html#bpy-types-spaceuveditor-show-pixel-coords"),
("bpy.types.toolsettings.gpencil_selectmode*", "grease_pencil/selecting.html#bpy-types-toolsettings-gpencil-selectmode"),
("bpy.ops.gpencil.active_frames_delete_all*", "grease_pencil/animation/tools.html#bpy-ops-gpencil-active-frames-delete-all"),
("bpy.ops.gpencil.stroke_merge_by_distance*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-merge-by-distance"),
("bpy.ops.object.anim_transforms_to_deltas*", "scene_layout/object/editing/transform/clear_apply.html#bpy-ops-object-anim-transforms-to-deltas"),
("bpy.types.brushgpencilsettings.uv_random*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-uv-random"),
+ ("bpy.types.clothsettings.internal_tension*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-internal-tension"),
("bpy.types.compositornodeplanetrackdeform*", "compositing/types/distort/plane_track_deform.html#bpy-types-compositornodeplanetrackdeform"),
+ ("bpy.types.fluiddomainsettings.coba_field*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-coba-field"),
+ ("bpy.types.fluiddomainsettings.mesh_scale*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-scale"),
+ ("bpy.types.fluiddomainsettings.slice_axis*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-slice-axis"),
+ ("bpy.types.fluiddomainsettings.time_scale*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-time-scale"),
("bpy.types.linestyle*modifier_alongstroke*", "render/freestyle/parameter_editor/line_style/modifiers/color/along_stroke.html#bpy-types-linestyle-modifier-alongstroke"),
("bpy.types.linestyle*modifier_creaseangle*", "render/freestyle/parameter_editor/line_style/modifiers/color/crease_angle.html#bpy-types-linestyle-modifier-creaseangle"),
("bpy.types.linestylecolormodifier_tangent*", "render/freestyle/parameter_editor/line_style/modifiers/color/tangent.html#bpy-types-linestylecolormodifier-tangent"),
@@ -126,18 +192,25 @@ url_manual_mapping = (
("bpy.types.shadernodesubsurfacescattering*", "render/shader_nodes/shader/sss.html#bpy-types-shadernodesubsurfacescattering"),
("bpy.ops.object.vertex_group_limit_total*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-limit-total"),
("bpy.ops.object.vertex_group_remove_from*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-remove-from"),
+ ("bpy.types.clothsettings.internal_spring*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-internal-spring"),
+ ("bpy.types.clothsettings.pressure_factor*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-pressure-factor"),
("bpy.types.compositornodecolorcorrection*", "compositing/types/color/color_correction.html#bpy-types-compositornodecolorcorrection"),
("bpy.types.compositornodemoviedistortion*", "compositing/types/distort/movie_distortion.html#bpy-types-compositornodemoviedistortion"),
("bpy.types.ffmpegsettings.audio_channels*", "scene_layout/scene/properties.html#bpy-types-ffmpegsettings-audio-channels"),
+ ("bpy.types.fluiddomainsettings.use_guide*", "physics/fluid/type/domain/guides.html#bpy-types-fluiddomainsettings-use-guide"),
+ ("bpy.types.fluiddomainsettings.vorticity*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-vorticity"),
+ ("bpy.types.fluidflowsettings.flow_source*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-flow-source"),
+ ("bpy.types.fluidflowsettings.use_texture*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-texture"),
("bpy.types.fmodifierenvelopecontrolpoint*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierenvelopecontrolpoint"),
("bpy.types.material.use_sss_translucency*", "render/eevee/materials/settings.html#bpy-types-material-use-sss-translucency"),
("bpy.types.sceneeevee.taa_render_samples*", "render/eevee/render_settings/sampling.html#bpy-types-sceneeevee-taa-render-samples"),
- ("bpy.types.spaceuveditor.pixel_snap_mode*", "modeling/meshes/editing/uv/layout.html#bpy-types-spaceuveditor-pixel-snap-mode"),
- ("bpy.types.spaceuveditor.use_live_unwrap*", "modeling/meshes/editing/uv/layout.html#bpy-types-spaceuveditor-use-live-unwrap"),
+ ("bpy.types.spaceuveditor.pixel_snap_mode*", "modeling/meshes/editing/uv/editing.html#bpy-types-spaceuveditor-pixel-snap-mode"),
+ ("bpy.types.spaceuveditor.use_live_unwrap*", "modeling/meshes/editing/uv/editing.html#bpy-types-spaceuveditor-use-live-unwrap"),
("bpy.types.vertexweightproximitymodifier*", "modeling/modifiers/modify/weight_proximity.html#bpy-types-vertexweightproximitymodifier"),
("bpy.types.compositornodebrightcontrast*", "compositing/types/color/bright_contrast.html#bpy-types-compositornodebrightcontrast"),
("bpy.types.compositornodedoubleedgemask*", "compositing/types/matte/double_edge_mask.html#bpy-types-compositornodedoubleedgemask"),
("bpy.types.ffmpegsettings.audio_mixrate*", "scene_layout/scene/properties.html#bpy-types-ffmpegsettings-audio-mixrate"),
+ ("bpy.types.fluiddomainsettings.use_mesh*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-use-mesh"),
("bpy.types.material.preview_render_type*", "render/materials/preview.html#bpy-types-material-preview-render-type"),
("bpy.types.materialgpencilstyle.pattern*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-pattern"),
("bpy.types.materialgpencilstyle.texture*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-texture"),
@@ -152,10 +225,13 @@ url_manual_mapping = (
("bpy.ops.object.gpencil_modifier_apply*", "grease_pencil/modifiers/introduction.html#bpy-ops-object-gpencil-modifier-apply"),
("bpy.ops.object.vertex_group_normalize*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-normalize"),
("bpy.ops.object.visual_transform_apply*", "scene_layout/object/editing/transform/clear_apply.html#bpy-ops-object-visual-transform-apply"),
- ("bpy.types.brush.texture_overlay_alpha*", "sculpt_paint/brush/display.html#bpy-types-brush-texture-overlay-alpha"),
+ ("bpy.types.brush.texture_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-texture-overlay-alpha"),
("bpy.types.brushgpencilsettings.random*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-random"),
+ ("bpy.types.clothsettings.target_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-target-volume"),
("bpy.types.compositornodebilateralblur*", "compositing/types/filter/bilateral_blur.html#bpy-types-compositornodebilateralblur"),
("bpy.types.compositornodedistancematte*", "compositing/types/matte/distance_key.html#bpy-types-compositornodedistancematte"),
+ ("bpy.types.fluiddomainsettings.display*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-display"),
+ ("bpy.types.fluiddomainsettings.gravity*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-gravity"),
("bpy.types.imagepaint.screen_grab_size*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-screen-grab-size"),
("bpy.types.linestyle*modifier_material*", "render/freestyle/parameter_editor/line_style/modifiers/color/material.html#bpy-types-linestyle-modifier-material"),
("bpy.types.particlesettingstextureslot*", "physics/particles/texture_influence.html#bpy-types-particlesettingstextureslot"),
@@ -168,12 +244,14 @@ url_manual_mapping = (
("bpy.ops.object.duplicate_move_linked*", "scene_layout/object/editing/duplication.html#bpy-ops-object-duplicate-move-linked"),
("bpy.ops.object.vertex_group_quantize*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-quantize"),
("bpy.ops.view3d.localview_remove_from*", "editors/3dview/navigate/views.html#bpy-ops-view3d-localview-remove-from"),
- ("bpy.types.brush.cursor_overlay_alpha*", "sculpt_paint/brush/display.html#bpy-types-brush-cursor-overlay-alpha"),
+ ("bpy.types.brush.cursor_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-cursor-overlay-alpha"),
("bpy.types.brush.topology_rake_factor*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-brush-topology-rake-factor"),
+ ("bpy.types.clothsettings.use_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-use-pressure"),
("bpy.types.compositornodechannelmatte*", "compositing/types/matte/channel_key.html#bpy-types-compositornodechannelmatte"),
("bpy.types.compositornodecolorbalance*", "compositing/types/color/color_balance.html#bpy-types-compositornodecolorbalance"),
("bpy.types.compositornodekeyingscreen*", "compositing/types/matte/keying_screen.html#bpy-types-compositornodekeyingscreen"),
("bpy.types.dynamicpaintcanvassettings*", "physics/dynamic_paint/canvas.html#bpy-types-dynamicpaintcanvassettings"),
+ ("bpy.types.fluidflowsettings.velocity*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-velocity"),
("bpy.types.fmodifierfunctiongenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierfunctiongenerator"),
("bpy.types.gpencillayer.use_solo_mode*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-solo-mode"),
("bpy.types.greasepencil.use_multiedit*", "grease_pencil/multiframe.html#bpy-types-greasepencil-use-multiedit"),
@@ -192,12 +270,17 @@ url_manual_mapping = (
("bpy.ops.object.duplicates_make_real*", "scene_layout/object/editing/transform/clear_apply.html#bpy-ops-object-duplicates-make-real"),
("bpy.ops.object.transforms_to_deltas*", "scene_layout/object/editing/transform/clear_apply.html#bpy-ops-object-transforms-to-deltas"),
("bpy.ops.sequencer.view_ghost_border*", "video_editing/preview/properties.html#bpy-ops-sequencer-view-ghost-border"),
- ("bpy.types.brush.use_primary_overlay*", "sculpt_paint/brush/display.html#bpy-types-brush-use-primary-overlay"),
+ ("bpy.types.brush.use_primary_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-primary-overlay"),
("bpy.types.compositornodechromamatte*", "compositing/types/matte/chroma_key.html#bpy-types-compositornodechromamatte"),
("bpy.types.compositornodedilateerode*", "compositing/types/filter/dilate_erode.html#bpy-types-compositornodedilateerode"),
("bpy.types.compositornodeellipsemask*", "compositing/types/matte/ellipse_mask.html#bpy-types-compositornodeellipsemask"),
("bpy.types.compositornodesplitviewer*", "compositing/types/output/split_viewer.html#bpy-types-compositornodesplitviewer"),
+ ("bpy.types.curve.use_uv_as_generated*", "modeling/meshes/editing/uv/uv_texture_spaces.html#bpy-types-curve-use-uv-as-generated"),
("bpy.types.dynamicpaintbrushsettings*", "physics/dynamic_paint/brush.html#bpy-types-dynamicpaintbrushsettings"),
+ ("bpy.types.fluiddomainsettings.alpha*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-alpha"),
+ ("bpy.types.fluiddomainsettings.cache*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-cache"),
+ ("bpy.types.fluiddomainsettings.noise*", "physics/fluid/type/domain/gas/noise.html#bpy-types-fluiddomainsettings-noise"),
+ ("bpy.types.fluidflowsettings.texture*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-texture"),
("bpy.types.materialgpencilstyle.flip*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-flip"),
("bpy.types.materialgpencilstyle.mode*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-mode"),
("bpy.types.rendersettings.use_border*", "render/output/settings.html#bpy-types-rendersettings-use-border"),
@@ -206,7 +289,7 @@ url_manual_mapping = (
("bpy.types.shadernodebsdftranslucent*", "render/shader_nodes/shader/translucent.html#bpy-types-shadernodebsdftranslucent"),
("bpy.types.shadernodebsdftransparent*", "render/shader_nodes/shader/transparent.html#bpy-types-shadernodebsdftransparent"),
("bpy.types.shadernodevectortransform*", "render/shader_nodes/vector/transform.html#bpy-types-shadernodevectortransform"),
- ("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/editing/uv/layout.html#bpy-types-spaceuveditor-lock-bounds"),
+ ("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/editing/uv/editing.html#bpy-types-spaceuveditor-lock-bounds"),
("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"),
("bpy.ops.mesh.quads_convert_to_tris*", "modeling/meshes/editing/faces.html#bpy-ops-mesh-quads-convert-to-tris"),
("bpy.ops.node.read_fullsamplelayers*", "interface/controls/nodes/editing.html#bpy-ops-node-read-fullsamplelayers"),
@@ -221,7 +304,7 @@ url_manual_mapping = (
("bpy.ops.sequencer.export_subtitles*", "video_editing/preview/introduction.html#bpy-ops-sequencer-export-subtitles"),
("bpy.ops.transform.edge_bevelweight*", "modeling/meshes/editing/edges.html#bpy-ops-transform-edge-bevelweight"),
("bpy.ops.wm.previews_batch_generate*", "files/blend/previews.html#bpy-ops-wm-previews-batch-generate"),
- ("bpy.types.brush.use_cursor_overlay*", "sculpt_paint/brush/display.html#bpy-types-brush-use-cursor-overlay"),
+ ("bpy.types.brush.use_cursor_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-cursor-overlay"),
("bpy.types.compositornodebokehimage*", "compositing/types/input/bokeh_image.html#bpy-types-compositornodebokehimage"),
("bpy.types.compositornodecolormatte*", "compositing/types/matte/color_key.html#bpy-types-compositornodecolormatte"),
("bpy.types.compositornodecolorspill*", "compositing/types/matte/color_spill.html#bpy-types-compositornodecolorspill"),
@@ -231,6 +314,8 @@ url_manual_mapping = (
("bpy.types.copytransformsconstraint*", "animation/constraints/transform/copy_transforms.html#bpy-types-copytransformsconstraint"),
("bpy.types.correctivesmoothmodifier*", "modeling/modifiers/deform/corrective_smooth.html#bpy-types-correctivesmoothmodifier"),
("bpy.types.cyclesvisibilitysettings*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesvisibilitysettings"),
+ ("bpy.types.fluiddomainsettings.beta*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-beta"),
+ ("bpy.types.fluidmodifier.fluid_type*", "physics/fluid/type/index.html#bpy-types-fluidmodifier-fluid-type"),
("bpy.types.imagepaint.interpolation*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-interpolation"),
("bpy.types.linestyle*modifier_noise*", "render/freestyle/parameter_editor/line_style/modifiers/color/noise.html#bpy-types-linestyle-modifier-noise"),
("bpy.types.maintainvolumeconstraint*", "animation/constraints/transform/maintain_volume.html#bpy-types-maintainvolumeconstraint"),
@@ -244,9 +329,8 @@ url_manual_mapping = (
("bpy.types.subdividegpencilmodifier*", "grease_pencil/modifiers/generate/subdivide.html#bpy-types-subdividegpencilmodifier"),
("bpy.types.thicknessgpencilmodifier*", "grease_pencil/modifiers/deform/thickness.html#bpy-types-thicknessgpencilmodifier"),
("bpy.types.transformcacheconstraint*", "animation/constraints/transform/transform_cache.html#bpy-types-transformcacheconstraint"),
- ("bpy.types.userpreferencesfilepaths*", "editors/preferences/file_paths.html#bpy-types-userpreferencesfilepaths"),
("bpy.types.vertexweighteditmodifier*", "modeling/modifiers/modify/weight_edit.html#bpy-types-vertexweighteditmodifier"),
- ("bpy.ops.curve.match_texture_space*", "editors/uv/generated_uvs.html#bpy-ops-curve-match-texture-space"),
+ ("bpy.ops.curve.match_texture_space*", "modeling/meshes/editing/uv/uv_texture_spaces.html#bpy-ops-curve-match-texture-space"),
("bpy.ops.font.text_paste_from_file*", "modeling/texts/selecting_editing.html#bpy-ops-font-text-paste-from-file"),
("bpy.ops.gpencil.frame_clean_loose*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-frame-clean-loose"),
("bpy.ops.object.vertex_group_clean*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-clean"),
@@ -265,7 +349,6 @@ url_manual_mapping = (
("bpy.types.compositornodestabilize*", "compositing/types/distort/stabilize_2d.html#bpy-types-compositornodestabilize"),
("bpy.types.compositornodetransform*", "compositing/types/distort/transform.html#bpy-types-compositornodetransform"),
("bpy.types.compositornodetranslate*", "compositing/types/distort/translate.html#bpy-types-compositornodetranslate"),
- ("bpy.types.fluidsimulationmodifier*", "physics/fluid/index.html#bpy-types-fluidsimulationmodifier"),
("bpy.types.freestylemodulesettings*", "render/freestyle/python.html#bpy-types-freestylemodulesettings"),
("bpy.types.gpencillayer.blend_mode*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-blend-mode"),
("bpy.types.gpencillayer.mask_layer*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-mask-layer"),
@@ -275,25 +358,29 @@ url_manual_mapping = (
("bpy.types.limitdistanceconstraint*", "animation/constraints/transform/limit_distance.html#bpy-types-limitdistanceconstraint"),
("bpy.types.limitlocationconstraint*", "animation/constraints/transform/limit_location.html#bpy-types-limitlocationconstraint"),
("bpy.types.limitrotationconstraint*", "animation/constraints/transform/limit_rotation.html#bpy-types-limitrotationconstraint"),
+ ("bpy.types.multiplygpencilmodifier*", "grease_pencil/modifiers/generate/multiple_strokes.html#bpy-types-multiplygpencilmodifier"),
("bpy.types.rendersettings.filepath*", "render/output/settings.html#bpy-types-rendersettings-filepath"),
("bpy.types.sceneeevee.use_overscan*", "render/eevee/render_settings/film.html#bpy-types-sceneeevee-use-overscan"),
("bpy.types.shadernodeeeveespecular*", "render/shader_nodes/shader/specular_bsdf.html#bpy-types-shadernodeeeveespecular"),
("bpy.types.shadernodehuesaturation*", "render/shader_nodes/color/hue_saturation.html#bpy-types-shadernodehuesaturation"),
+ ("bpy.types.shadernodetexwhitenoise*", "render/shader_nodes/textures/white_noise.html#bpy-types-shadernodetexwhitenoise"),
("bpy.types.shadernodevolumescatter*", "render/shader_nodes/shader/volume_scatter.html#bpy-types-shadernodevolumescatter"),
("bpy.types.simplifygpencilmodifier*", "grease_pencil/modifiers/generate/simplify.html#bpy-types-simplifygpencilmodifier"),
("bpy.types.spacegrapheditor.cursor*", "editors/graph_editor/introduction.html#bpy-types-spacegrapheditor-cursor"),
("bpy.types.vertexweightmixmodifier*", "modeling/modifiers/modify/weight_mix.html#bpy-types-vertexweightmixmodifier"),
("bpy.ops.gpencil.frame_clean_fill*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-frame-clean-fill"),
("bpy.ops.gpencil.stroke_subdivide*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-subdivide"),
+ ("bpy.ops.graph.interpolation_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-interpolation-type"),
("bpy.ops.object.constraints_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-clear"),
+ ("bpy.ops.object.quadriflow_remesh*", "modeling/meshes/editing/retopology.html#bpy-ops-object-quadriflow-remesh"),
("bpy.ops.object.vertex_group_copy*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy"),
("bpy.ops.object.vertex_group_lock*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-lock"),
("bpy.ops.object.vertex_group_move*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-move"),
("bpy.ops.object.vertex_group_sort*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-sort"),
- ("bpy.ops.uv.average_islands_scale*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-average-islands-scale"),
+ ("bpy.ops.uv.average_islands_scale*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-average-islands-scale"),
("bpy.ops.view3d.edit_mesh_extrude*", "modeling/meshes/editing/duplicating/extrude.html#bpy-ops-view3d-edit-mesh-extrude"),
("bpy.types.brightcontrastmodifier*", "video_editing/sequencer/properties/modifiers.html#bpy-types-brightcontrastmodifier"),
- ("bpy.types.brush.cursor_color_add*", "sculpt_paint/brush/display.html#bpy-types-brush-cursor-color-add"),
+ ("bpy.types.brush.cursor_color_add*", "sculpt_paint/brush/cursor.html#bpy-types-brush-cursor-color-add"),
("bpy.types.camerasolverconstraint*", "animation/constraints/motion_tracking/camera_solver.html#bpy-types-camerasolverconstraint"),
("bpy.types.clothcollisionsettings*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings"),
("bpy.types.compositornodecurvergb*", "compositing/types/color/rgb_curves.html#bpy-types-compositornodecurvergb"),
@@ -341,10 +428,12 @@ url_manual_mapping = (
("bpy.ops.transform.shrink_fatten*", "modeling/meshes/editing/transform/shrink-fatten.html#bpy-ops-transform-shrink-fatten"),
("bpy.ops.wm.dependency_relations*", "advanced/operators.html#bpy-ops-wm-dependency-relations"),
("bpy.ops.wm.previews_batch_clear*", "files/blend/previews.html#bpy-ops-wm-previews-batch-clear"),
- ("bpy.types.brush.use_custom_icon*", "sculpt_paint/brush/display.html#bpy-types-brush-use-custom-icon"),
+ ("bpy.types.brush.use_custom_icon*", "sculpt_paint/brush/brush.html#bpy-types-brush-use-custom-icon"),
+ ("bpy.types.brushtextureslot.mask*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-mask"),
("bpy.types.camerabackgroundimage*", "render/cameras.html#bpy-types-camerabackgroundimage"),
("bpy.types.compositornodeboxmask*", "compositing/types/matte/box_mask.html#bpy-types-compositornodeboxmask"),
("bpy.types.compositornodedefocus*", "compositing/types/filter/defocus.html#bpy-types-compositornodedefocus"),
+ ("bpy.types.compositornodedenoise*", "compositing/types/filter/denoise.html#bpy-types-compositornodedenoise"),
("bpy.types.compositornodeinpaint*", "compositing/types/filter/inpaint.html#bpy-types-compositornodeinpaint"),
("bpy.types.compositornodergbtobw*", "compositing/types/converter/rgb_to_bw.html#bpy-types-compositornodergbtobw"),
("bpy.types.compositornoderlayers*", "compositing/types/input/render_layers.html#bpy-types-compositornoderlayers"),
@@ -353,12 +442,12 @@ url_manual_mapping = (
("bpy.types.compositornodevecblur*", "compositing/types/filter/vector_blur.html#bpy-types-compositornodevecblur"),
("bpy.types.dampedtrackconstraint*", "animation/constraints/tracking/damped_track.html#bpy-types-dampedtrackconstraint"),
("bpy.types.distortednoisetexture*", "render/materials/legacy_textures/types/distorted_noise.html#bpy-types-distortednoisetexture"),
+ ("bpy.types.fluideffectorsettings*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings"),
("bpy.types.followtrackconstraint*", "animation/constraints/motion_tracking/follow_track.html#bpy-types-followtrackconstraint"),
("bpy.types.gpencilsculptsettings*", "grease_pencil/properties/index.html#bpy-types-gpencilsculptsettings"),
("bpy.types.lockedtrackconstraint*", "animation/constraints/tracking/locked_track.html#bpy-types-lockedtrackconstraint"),
("bpy.types.material.blend_method*", "render/eevee/materials/settings.html#bpy-types-material-blend-method"),
("bpy.types.mirrorgpencilmodifier*", "grease_pencil/modifiers/generate/mirror.html#bpy-types-mirrorgpencilmodifier"),
- ("bpy.types.obstaclefluidsettings*", "physics/fluid/types/obstacle.html#bpy-types-obstaclefluidsettings"),
("bpy.types.offsetgpencilmodifier*", "grease_pencil/modifiers/deform/offset.html#bpy-types-offsetgpencilmodifier"),
("bpy.types.particlefluidsettings*", "physics/particles/emitter/physics/fluid.html#bpy-types-particlefluidsettings"),
("bpy.types.sceneeevee.volumetric*", "render/eevee/render_settings/volumetrics.html#bpy-types-sceneeevee-volumetric"),
@@ -369,16 +458,17 @@ url_manual_mapping = (
("bpy.types.shadernodetexgradient*", "render/shader_nodes/textures/gradient.html#bpy-types-shadernodetexgradient"),
("bpy.types.shadernodetexmusgrave*", "render/shader_nodes/textures/musgrave.html#bpy-types-shadernodetexmusgrave"),
("bpy.types.shadernodevectorcurve*", "render/shader_nodes/vector/curves.html#bpy-types-shadernodevectorcurve"),
+ ("bpy.types.shadernodevertexcolor*", "render/shader_nodes/input/vertex_color.html#bpy-types-shadernodevertexcolor"),
("bpy.types.smoothgpencilmodifier*", "grease_pencil/modifiers/deform/smooth.html#bpy-types-smoothgpencilmodifier"),
("bpy.types.spline.use_endpoint_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-use-endpoint-u"),
- ("bpy.types.userpreferencessystem*", "editors/preferences/system.html#bpy-types-userpreferencessystem"),
("bpy.ops.curve.switch_direction*", "modeling/curves/editing/segments.html#bpy-ops-curve-switch-direction"),
("bpy.ops.gpencil.duplicate_move*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-duplicate-move"),
("bpy.ops.gpencil.stroke_arrange*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-arrange"),
("bpy.ops.mesh.bridge-edge-loops*", "modeling/meshes/editing/edges.html#bpy-ops-mesh-bridge-edge-loops"),
("bpy.ops.object.paths_calculate*", "animation/motion_paths.html#bpy-ops-object-paths-calculate"),
("bpy.ops.object.transform_apply*", "scene_layout/object/editing/transform/clear_apply.html#bpy-ops-object-transform-apply"),
- ("bpy.ops.outliner.lib_operation*", "files/linked_libraries.html#bpy-ops-outliner-lib-operation"),
+ ("bpy.ops.outliner.lib_operation*", "files/linked_libraries/introduction.html#bpy-ops-outliner-lib-operation"),
+ ("bpy.ops.outliner.orphans_purge*", "editors/outliner.html#bpy-ops-outliner-orphans-purge"),
("bpy.ops.screen.region_quadview*", "editors/3dview/navigate/views.html#bpy-ops-screen-region-quadview"),
("bpy.ops.uv.follow_active_quads*", "modeling/meshes/editing/uv/unwrapping/mapping_types.html#bpy-ops-uv-follow-active-quads"),
("bpy.types.arraygpencilmodifier*", "grease_pencil/modifiers/generate/array.html#bpy-types-arraygpencilmodifier"),
@@ -396,7 +486,6 @@ url_manual_mapping = (
("bpy.types.compositornoderotate*", "compositing/types/distort/rotate.html#bpy-types-compositornoderotate"),
("bpy.types.compositornodeviewer*", "compositing/types/output/viewer.html#bpy-types-compositornodeviewer"),
("bpy.types.constraint.influence*", "animation/constraints/interface/common.html#bpy-types-constraint-influence"),
- ("bpy.types.controlfluidsettings*", "physics/fluid/types/control.html#bpy-types-controlfluidsettings"),
("bpy.types.datatransfermodifier*", "modeling/modifiers/modify/data_transfer.html#bpy-types-datatransfermodifier"),
("bpy.types.dynamicpaintmodifier*", "physics/dynamic_paint/index.html#bpy-types-dynamicpaintmodifier"),
("bpy.types.ffmpegsettings.audio*", "render/output/file_formats.html#bpy-types-ffmpegsettings-audio"),
@@ -407,7 +496,7 @@ url_manual_mapping = (
("bpy.types.limitscaleconstraint*", "animation/constraints/transform/limit_scale.html#bpy-types-limitscaleconstraint"),
("bpy.types.materialgpencilstyle*", "grease_pencil/materials/index.html#bpy-types-materialgpencilstyle"),
("bpy.types.mesh.use_auto_smooth*", "modeling/meshes/structure.html#bpy-types-mesh-use-auto-smooth"),
- ("bpy.types.outflowfluidsettings*", "physics/fluid/types/flow.html#bpy-types-outflowfluidsettings"),
+ ("bpy.types.preferencesfilepaths*", "editors/preferences/file_paths.html#bpy-types-preferencesfilepaths"),
("bpy.types.scene.background_set*", "scene_layout/scene/properties.html#bpy-types-scene-background-set"),
("bpy.types.shadernodebackground*", "render/shader_nodes/shader/background.html#bpy-types-shadernodebackground"),
("bpy.types.shadernodebsdfglossy*", "render/shader_nodes/shader/glossy.html#bpy-types-shadernodebsdfglossy"),
@@ -417,22 +506,22 @@ url_manual_mapping = (
("bpy.types.shadernodetexchecker*", "render/shader_nodes/textures/checker.html#bpy-types-shadernodetexchecker"),
("bpy.types.shadernodetexvoronoi*", "render/shader_nodes/textures/voronoi.html#bpy-types-shadernodetexvoronoi"),
("bpy.types.shadernodevectormath*", "render/shader_nodes/converter/vector_math.html#bpy-types-shadernodevectormath"),
+ ("bpy.types.shadernodevolumeinfo*", "render/shader_nodes/input/volume_info.html#bpy-types-shadernodevolumeinfo"),
("bpy.types.shadernodewavelength*", "render/shader_nodes/converter/wavelength.html#bpy-types-shadernodewavelength"),
("bpy.types.shrinkwrapconstraint*", "animation/constraints/relationship/shrinkwrap.html#bpy-types-shrinkwrapconstraint"),
("bpy.types.simpledeformmodifier*", "modeling/modifiers/deform/simple_deform.html#bpy-types-simpledeformmodifier"),
("bpy.types.spacedopesheeteditor*", "editors/dope_sheet/index.html#bpy-types-spacedopesheeteditor"),
- ("bpy.types.spaceuserpreferences*", "editors/preferences/index.html#bpy-types-spaceuserpreferences"),
("bpy.types.speedcontrolsequence*", "video_editing/sequencer/strips/effects/speed_control.html#bpy-types-speedcontrolsequence"),
("bpy.types.texturenodecurvetime*", "editors/texture_node/types/input/time.html#bpy-types-texturenodecurvetime"),
("bpy.types.transformorientation*", "scene_layout/object/editing/transform/control/orientations.html#bpy-types-transformorientation"),
- ("bpy.types.unifiedpaintsettings*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-unifiedpaintsettings"),
- ("bpy.types.userpreferencesinput*", "editors/preferences/input.html#bpy-types-userpreferencesinput"),
+ ("bpy.types.unifiedpaintsettings*", "sculpt_paint/brush/brush.html#bpy-types-unifiedpaintsettings"),
("bpy.types.whitebalancemodifier*", "video_editing/sequencer/properties/modifiers.html#bpy-types-whitebalancemodifier"),
("bpy.ops.curve.handle_type_set*", "modeling/curves/editing/control_points.html#bpy-ops-curve-handle-type-set"),
("bpy.ops.curve.spline_type_set*", "modeling/curves/editing/curve.html#bpy-ops-curve-spline-type-set"),
("bpy.ops.gpencil.move_to_layer*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-move-to-layer"),
("bpy.ops.gpencil.stroke_sample*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-sample"),
("bpy.ops.gpencil.stroke_smooth*", "grease_pencil/modes/edit/point_menu.html#bpy-ops-gpencil-stroke-smooth"),
+ ("bpy.ops.graph.keyframe_insert*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-keyframe-insert"),
("bpy.ops.mesh.smoothen_normals*", "modeling/meshes/editing/normals.html#bpy-ops-mesh-smoothen-normals"),
("bpy.ops.object.duplicate_move*", "scene_layout/object/editing/duplication.html#bpy-ops-object-duplicate-move"),
("bpy.ops.object.hook_add_selob*", "modeling/meshes/editing/vertices.html#bpy-ops-object-hook-add-selob"),
@@ -444,7 +533,7 @@ url_manual_mapping = (
("bpy.ops.surface.primitive*add*", "modeling/surfaces/primitives.html#bpy-ops-surface-primitive-add"),
("bpy.ops.transform.edge_crease*", "modeling/meshes/editing/edges.html#bpy-ops-transform-edge-crease"),
("bpy.ops.uv.seams_from_islands*", "modeling/meshes/editing/uv/unwrapping/seams.html#bpy-ops-uv-seams-from-islands"),
- ("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/display.html#bpy-types-brush-icon-filepath"),
+ ("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/brush.html#bpy-types-brush-icon-filepath"),
("bpy.types.brush.smooth_stroke*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brush-smooth-stroke"),
("bpy.types.camera.display_size*", "render/cameras.html#bpy-types-camera-display-size"),
("bpy.types.compositornodedblur*", "compositing/types/filter/directional_blur.html#bpy-types-compositornodedblur"),
@@ -457,13 +546,12 @@ url_manual_mapping = (
("bpy.types.compositornodevalue*", "compositing/types/input/value.html#bpy-types-compositornodevalue"),
("bpy.types.copyscaleconstraint*", "animation/constraints/transform/copy_scale.html#bpy-types-copyscaleconstraint"),
("bpy.types.cyclesworldsettings*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings"),
- ("bpy.types.domainfluidsettings*", "physics/fluid/types/domain.html#bpy-types-domainfluidsettings"),
+ ("bpy.types.fluiddomainsettings*", "physics/fluid/type/domain/index.html#bpy-types-fluiddomainsettings"),
("bpy.types.hookgpencilmodifier*", "grease_pencil/modifiers/deform/hook.html#bpy-types-hookgpencilmodifier"),
("bpy.types.imageformatsettings*", "files/media/image_formats.html#bpy-types-imageformatsettings"),
- ("bpy.types.inflowfluidsettings*", "physics/fluid/types/flow.html#bpy-types-inflowfluidsettings"),
("bpy.types.kinematicconstraint*", "animation/constraints/tracking/ik_solver.html#bpy-types-kinematicconstraint"),
("bpy.types.mesh.use_paint_mask*", "sculpt_paint/brush/introduction.html#bpy-types-mesh-use-paint-mask"),
- ("bpy.types.movietrackingcamera*", "movie_clip/tracking/clip/properties/camera_data.html#bpy-types-movietrackingcamera"),
+ ("bpy.types.movietrackingcamera*", "movie_clip/tracking/clip/properties/track/camera.html#bpy-types-movietrackingcamera"),
("bpy.types.noisepencilmodifier*", "grease_pencil/modifiers/deform/noise.html#bpy-types-noisepencilmodifier"),
("bpy.types.object.display_type*", "scene_layout/object/properties/display.html#bpy-types-object-display-type"),
("bpy.types.particledupliweight*", "physics/particles/emitter/vertex_groups.html#bpy-types-particledupliweight"),
@@ -477,7 +565,6 @@ url_manual_mapping = (
("bpy.types.shadernodemixshader*", "render/shader_nodes/shader/mix.html#bpy-types-shadernodemixshader"),
("bpy.types.shadernodenormalmap*", "render/shader_nodes/vector/normal_map.html#bpy-types-shadernodenormalmap"),
("bpy.types.shadernodewireframe*", "render/shader_nodes/input/wireframe.html#bpy-types-shadernodewireframe"),
- ("bpy.types.smokedomainsettings*", "physics/smoke/types/domain.html#bpy-types-smokedomainsettings"),
("bpy.types.spacesequenceeditor*", "video_editing/index.html#bpy-types-spacesequenceeditor"),
("bpy.types.spline.resolution_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-resolution-u"),
("bpy.types.spline.use_bezier_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-use-bezier-u"),
@@ -489,8 +576,6 @@ url_manual_mapping = (
("bpy.types.tintgpencilmodifier*", "grease_pencil/modifiers/color/tint.html#bpy-types-tintgpencilmodifier"),
("bpy.types.transformconstraint*", "animation/constraints/transform/transformation.html#bpy-types-transformconstraint"),
("bpy.types.triangulatemodifier*", "modeling/modifiers/generate/triangulate.html#bpy-types-triangulatemodifier"),
- ("bpy.types.userpreferencesedit*", "editors/preferences/editing.html#bpy-types-userpreferencesedit"),
- ("bpy.types.userpreferencesview*", "editors/preferences/interface.html#bpy-types-userpreferencesview"),
("bpy.types.windowmanager.addon*", "editors/preferences/addons.html#bpy-types-windowmanager-addon"),
("bpy.ops.anim.keyframe_delete*", "animation/keyframes/editing.html#bpy-ops-anim-keyframe-delete"),
("bpy.ops.anim.keyframe_insert*", "animation/keyframes/editing.html#bpy-ops-anim-keyframe-insert"),
@@ -500,6 +585,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.extrude_move*", "grease_pencil/modes/edit/point_menu.html#bpy-ops-gpencil-extrude-move"),
("bpy.ops.gpencil.stroke_merge*", "grease_pencil/modes/edit/point_menu.html#bpy-ops-gpencil-stroke-merge"),
("bpy.ops.gpencil.stroke_split*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-split"),
+ ("bpy.ops.graph.duplicate_move*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-duplicate-move"),
("bpy.ops.mesh.average_normals*", "modeling/meshes/editing/normals.html#bpy-ops-mesh-average-normals"),
("bpy.ops.mesh.vertices_smooth*", "modeling/meshes/editing/transform/smooth.html#bpy-ops-mesh-vertices-smooth"),
("bpy.ops.node.read_viewlayers*", "interface/controls/nodes/editing.html#bpy-ops-node-read-viewlayers"),
@@ -526,7 +612,6 @@ url_manual_mapping = (
("bpy.types.curve.resolution_u*", "modeling/curves/properties/shape.html#bpy-types-curve-resolution-u"),
("bpy.types.curve.resolution_v*", "modeling/surfaces/properties/shape.html#bpy-types-curve-resolution-v"),
("bpy.types.curvepaintsettings*", "modeling/curves/editing/other.html#bpy-types-curvepaintsettings"),
- ("bpy.types.fluidfluidsettings*", "physics/fluid/types/fluid_object.html#bpy-types-fluidfluidsettings"),
("bpy.types.fmodifiergenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiergenerator"),
("bpy.types.freestylelinestyle*", "render/freestyle/parameter_editor/line_style/index.html#bpy-types-freestylelinestyle"),
("bpy.types.gammacrosssequence*", "video_editing/sequencer/strips/transitions/cross.html#bpy-types-gammacrosssequence"),
@@ -534,7 +619,7 @@ url_manual_mapping = (
("bpy.types.huecorrectmodifier*", "video_editing/sequencer/properties/modifiers.html#bpy-types-huecorrectmodifier"),
("bpy.types.imagepaint.stencil*", "sculpt_paint/texture_paint/tool_settings/mask.html#bpy-types-imagepaint-stencil"),
("bpy.types.meshdeformmodifier*", "modeling/modifiers/deform/mesh_deform.html#bpy-types-meshdeformmodifier"),
- ("bpy.types.movietrackingtrack*", "movie_clip/tracking/clip/properties/introduction.html#bpy-types-movietrackingtrack"),
+ ("bpy.types.movietrackingtrack*", "movie_clip/tracking/clip/properties/track/index.html#bpy-types-movietrackingtrack"),
("bpy.types.nodeoutputfileslot*", "compositing/types/output/file.html#bpy-types-nodeoutputfileslot"),
("bpy.types.normaleditmodifier*", "modeling/modifiers/modify/normal_edit.html#bpy-types-normaleditmodifier"),
("bpy.types.object.show_bounds*", "scene_layout/object/properties/display.html#bpy-types-object-show-bounds"),
@@ -568,12 +653,13 @@ url_manual_mapping = (
("bpy.ops.mesh.extrude_region*", "modeling/meshes/editing/duplicating/extrude.html#bpy-ops-mesh-extrude-region"),
("bpy.ops.object.parent_clear*", "scene_layout/object/properties/relations/parents.html#bpy-ops-object-parent-clear"),
("bpy.ops.object.shade_smooth*", "modeling/meshes/editing/normals.html#bpy-ops-object-shade-smooth"),
+ ("bpy.ops.object.voxel_remesh*", "modeling/meshes/editing/retopology.html#bpy-ops-object-voxel-remesh"),
("bpy.ops.transform.push_pull*", "modeling/meshes/editing/transform/push_pull.html#bpy-ops-transform-push-pull"),
("bpy.ops.transform.trackball*", "scene_layout/object/editing/transform/basics.html#bpy-ops-transform-trackball"),
("bpy.ops.transform.transform*", "scene_layout/object/editing/transform/control/orientations.html#bpy-ops-transform-transform"),
("bpy.ops.transform.translate*", "scene_layout/object/editing/transform/basics.html#bpy-ops-transform-translate"),
("bpy.ops.uv.cylinder_project*", "modeling/meshes/editing/uv/unwrapping/mapping_types.html#bpy-ops-uv-cylinder-project"),
- ("bpy.ops.uv.minimize_stretch*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-minimize-stretch"),
+ ("bpy.ops.uv.minimize_stretch*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-minimize-stretch"),
("bpy.types.alphaoversequence*", "video_editing/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-alphaoversequence"),
("bpy.types.armatureeditbones*", "animation/armatures/bones/editing/index.html#bpy-types-armatureeditbones"),
("bpy.types.cameradofsettings*", "render/cameras.html#bpy-types-cameradofsettings"),
@@ -584,17 +670,21 @@ url_manual_mapping = (
("bpy.types.compositornodergb*", "compositing/types/input/rgb.html#bpy-types-compositornodergb"),
("bpy.types.compositornodesep*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodesep"),
("bpy.types.edgesplitmodifier*", "modeling/modifiers/generate/edge_split.html#bpy-types-edgesplitmodifier"),
+ ("bpy.types.fluidflowsettings*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings"),
("bpy.types.fmodifierenvelope*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierenvelope"),
("bpy.types.freestylesettings*", "render/freestyle/view_layer.html#bpy-types-freestylesettings"),
("bpy.types.gpencillayer.hide*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-hide"),
("bpy.types.gpencillayer.lock*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-lock"),
("bpy.types.imagepaint.dither*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-dither"),
- ("bpy.types.mesh.texture_mesh*", "editors/uv/generated_uvs.html#bpy-types-mesh-texture-mesh"),
+ ("bpy.types.mesh.texture_mesh*", "modeling/meshes/editing/uv/uv_texture_spaces.html#bpy-types-mesh-texture-mesh"),
("bpy.types.mesh.use_mirror_x*", "modeling/meshes/editing/mesh_options.html#bpy-types-mesh-use-mirror-x"),
+ ("bpy.types.mesh.use_mirror_y*", "modeling/meshes/editing/mesh_options.html#bpy-types-mesh-use-mirror-y"),
+ ("bpy.types.mesh.use_mirror_z*", "modeling/meshes/editing/mesh_options.html#bpy-types-mesh-use-mirror-z"),
("bpy.types.meshcachemodifier*", "modeling/modifiers/modify/mesh_cache.html#bpy-types-meshcachemodifier"),
("bpy.types.movieclipsequence*", "video_editing/sequencer/strips/clip_mask.html#bpy-types-movieclipsequence"),
("bpy.types.object.dimensions*", "scene_layout/object/properties/transforms.html#bpy-types-object-dimensions"),
("bpy.types.object.track_axis*", "scene_layout/object/properties/relations/extras.html#bpy-types-object-track-axis"),
+ ("bpy.types.preferencessystem*", "editors/preferences/system.html#bpy-types-preferencessystem"),
("bpy.types.scene.active_clip*", "scene_layout/scene/properties.html#bpy-types-scene-active-clip"),
("bpy.types.sceneeevee.shadow*", "render/eevee/render_settings/shadows.html#bpy-types-sceneeevee-shadow"),
("bpy.types.shadernodecombine*", "render/shader_nodes/converter/combine_separate.html#bpy-types-shadernodecombine"),
@@ -604,8 +694,6 @@ url_manual_mapping = (
("bpy.types.shadernodergbtobw*", "render/shader_nodes/converter/rgb_to_bw.html#bpy-types-shadernodergbtobw"),
("bpy.types.shadernodetangent*", "render/shader_nodes/input/tangent.html#bpy-types-shadernodetangent"),
("bpy.types.shadernodetexwave*", "render/shader_nodes/textures/wave.html#bpy-types-shadernodetexwave"),
- ("bpy.types.smokecollsettings*", "physics/smoke/types/collision.html#bpy-types-smokecollsettings"),
- ("bpy.types.smokeflowsettings*", "physics/smoke/types/flow_object.html#bpy-types-smokeflowsettings"),
("bpy.types.spline.use_smooth*", "modeling/curves/properties/active_spline.html#bpy-types-spline-use-smooth"),
("bpy.types.texturenodebricks*", "editors/texture_node/types/patterns/bricks.html#bpy-types-texturenodebricks"),
("bpy.types.texturenodemixrgb*", "editors/texture_node/types/color/mix_rgb.html#bpy-types-texturenodemixrgb"),
@@ -617,6 +705,7 @@ url_manual_mapping = (
("bpy.types.worldmistsettings*", "render/cycles/world_settings.html#bpy-types-worldmistsettings"),
("bpy.ops.curve.extrude_move*", "modeling/curves/editing/control_points.html#bpy-ops-curve-extrude-move"),
("bpy.ops.curve.make_segment*", "modeling/curves/editing/control_points.html#bpy-ops-curve-make-segment"),
+ ("bpy.ops.graph.euler_filter*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-euler-filter"),
("bpy.ops.mesh.loopcut_slide*", "modeling/meshes/editing/subdividing/loop.html#bpy-ops-mesh-loopcut-slide"),
("bpy.ops.mesh.merge_normals*", "modeling/meshes/editing/normals.html#bpy-ops-mesh-merge-normals"),
("bpy.ops.mesh.normals_tools*", "modeling/meshes/editing/normals.html#bpy-ops-mesh-normals-tools"),
@@ -645,9 +734,10 @@ url_manual_mapping = (
("bpy.types.multiresmodifier*", "modeling/modifiers/generate/multiresolution.html#bpy-types-multiresmodifier"),
("bpy.types.object.use_extra*", "scene_layout/object/properties/relations/extras.html#bpy-types-object-use-extra"),
("bpy.types.overdropsequence*", "video_editing/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-overdropsequence"),
- ("bpy.types.paint.show_brush*", "sculpt_paint/brush/display.html#bpy-types-paint-show-brush"),
+ ("bpy.types.paint.show_brush*", "sculpt_paint/brush/cursor.html#bpy-types-paint-show-brush"),
("bpy.types.paint.use_cavity*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-paint-use-cavity"),
("bpy.types.particlesettings*", "physics/particles/index.html#bpy-types-particlesettings"),
+ ("bpy.types.preferencesinput*", "editors/preferences/input.html#bpy-types-preferencesinput"),
("bpy.types.sceneeevee.bloom*", "render/eevee/render_settings/bloom.html#bpy-types-sceneeevee-bloom"),
("bpy.types.scenerenderlayer*", "render/layers/layers.html#bpy-types-scenerenderlayer"),
("bpy.types.sequencemodifier*", "video_editing/sequencer/properties/modifiers.html#bpy-types-sequencemodifier"),
@@ -663,26 +753,28 @@ url_manual_mapping = (
("bpy.types.softbodysettings*", "physics/soft_body/settings.html#bpy-types-softbodysettings"),
("bpy.types.solidifymodifier*", "modeling/modifiers/generate/solidify.html#bpy-types-solidifymodifier"),
("bpy.types.spacegrapheditor*", "editors/graph_editor/index.html#bpy-types-spacegrapheditor"),
+ ("bpy.types.spacepreferences*", "editors/preferences/index.html#bpy-types-spacepreferences"),
("bpy.types.spaceview3d.lock*", "editors/3dview/properties/sidebar.html#bpy-types-spaceview3d-lock"),
- ("bpy.types.sphfluidsettings*", "physics/fluid/index.html#bpy-types-sphfluidsettings"),
("bpy.types.subtractsequence*", "video_editing/sequencer/strips/effects/subtract.html#bpy-types-subtractsequence"),
("bpy.types.texturenodegroup*", "editors/texture_node/types/groups.html#bpy-types-texturenodegroup"),
("bpy.types.texturenodeimage*", "editors/texture_node/types/input/image.html#bpy-types-texturenodeimage"),
("bpy.ops.curve.smooth_tilt*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth-tilt"),
("bpy.ops.gpencil.reproject*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-reproject"),
+ ("bpy.ops.graph.easing_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-easing-type"),
+ ("bpy.ops.graph.handle_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-handle-type"),
("bpy.ops.mesh.flip_normals*", "modeling/meshes/editing/normals.html#bpy-ops-mesh-flip-normals"),
("bpy.ops.object.lightprobe*", "render/eevee/lightprobes/index.html#bpy-ops-object-lightprobe"),
("bpy.ops.object.make_links*", "scene_layout/object/editing/duplication.html#bpy-ops-object-make-links"),
- ("bpy.ops.object.make_local*", "files/linked_libraries.html#bpy-ops-object-make-local"),
+ ("bpy.ops.object.make_local*", "files/linked_libraries/introduction.html#bpy-ops-object-make-local"),
("bpy.ops.object.origin_set*", "scene_layout/object/origin.html#bpy-ops-object-origin-set"),
("bpy.ops.object.parent_set*", "scene_layout/object/properties/relations/parents.html#bpy-ops-object-parent-set"),
- ("bpy.ops.object.proxy_make*", "files/linked_libraries.html#bpy-ops-object-proxy-make"),
+ ("bpy.ops.object.proxy_make*", "files/linked_libraries/library_proxies.html#bpy-ops-object-proxy-make"),
("bpy.ops.object.select_all*", "scene_layout/object/selecting.html#bpy-ops-object-select-all"),
("bpy.ops.object.shade_flat*", "modeling/meshes/editing/normals.html#bpy-ops-object-shade-flat"),
("bpy.ops.preferences.addon*", "editors/preferences/addons.html#bpy-ops-preferences-addon"),
("bpy.ops.scene.light_cache*", "render/eevee/render_settings/indirect_lighting.html#bpy-ops-scene-light-cache"),
("bpy.ops.screen.area_dupli*", "interface/window_system/areas.html#bpy-ops-screen-area-dupli"),
- ("bpy.ops.uv.remove_doubles*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-remove-doubles"),
+ ("bpy.ops.uv.remove_doubles*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-remove-doubles"),
("bpy.ops.uv.sphere_project*", "modeling/meshes/editing/uv/unwrapping/mapping_types.html#bpy-ops-uv-sphere-project"),
("bpy.ops.wm.previews_clear*", "files/blend/previews.html#bpy-ops-wm-previews-clear"),
("bpy.types.booleanmodifier*", "modeling/modifiers/generate/booleans.html#bpy-types-booleanmodifier"),
@@ -690,7 +782,6 @@ url_manual_mapping = (
("bpy.types.explodemodifier*", "modeling/modifiers/simulate/explode.html#bpy-types-explodemodifier"),
("bpy.types.fcurvemodifiers*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fcurvemodifiers"),
("bpy.types.floorconstraint*", "animation/constraints/relationship/floor.html#bpy-types-floorconstraint"),
- ("bpy.types.fluidmeshvertex*", "physics/fluid/index.html#bpy-types-fluidmeshvertex"),
("bpy.types.fmodifiercycles*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiercycles"),
("bpy.types.fmodifierlimits*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierlimits"),
("bpy.types.imagepaint.mode*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-mode"),
@@ -700,6 +791,8 @@ url_manual_mapping = (
("bpy.types.object.rotation*", "scene_layout/object/properties/transforms.html#bpy-types-object-rotation"),
("bpy.types.particlehairkey*", "physics/particles/emitter/physics/keyed.html#bpy-types-particlehairkey"),
("bpy.types.pivotconstraint*", "animation/constraints/relationship/pivot.html#bpy-types-pivotconstraint"),
+ ("bpy.types.preferencesedit*", "editors/preferences/editing.html#bpy-types-preferencesedit"),
+ ("bpy.types.preferencesview*", "editors/preferences/interface.html#bpy-types-preferencesview"),
("bpy.types.rigidbodyobject*", "physics/rigid_body/index.html#bpy-types-rigidbodyobject"),
("bpy.types.sceneeevee.gtao*", "render/eevee/render_settings/ambient_occlusion.html#bpy-types-sceneeevee-gtao"),
("bpy.types.shadernodebevel*", "render/shader_nodes/input/bevel.html#bpy-types-shadernodebevel"),
@@ -713,12 +806,12 @@ url_manual_mapping = (
("bpy.types.spacetexteditor*", "editors/text_editor.html#bpy-types-spacetexteditor"),
("bpy.types.subsurfmodifier*", "modeling/modifiers/generate/subdivision_surface.html#bpy-types-subsurfmodifier"),
("bpy.types.texturenodemath*", "editors/texture_node/types/converter/math.html#bpy-types-texturenodemath"),
- ("bpy.types.userpreferences*", "editors/preferences/index.html#bpy-types-userpreferences"),
("bpy.ops.curve.select_row*", "modeling/surfaces/selecting.html#bpy-ops-curve-select-row"),
("bpy.ops.curve.tilt_clear*", "modeling/curves/editing/control_points.html#bpy-ops-curve-tilt-clear"),
("bpy.ops.curve.vertex_add*", "modeling/curves/editing/other.html#bpy-ops-curve-vertex-add"),
("bpy.ops.gpencil.dissolve*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-dissolve"),
- ("bpy.ops.graph.frame_jump*", "editors/graph_editor/fcurves/properties.html#bpy-ops-graph-frame-jump"),
+ ("bpy.ops.graph.frame_jump*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-frame-jump"),
+ ("bpy.ops.graph.sound_bake*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-sound-bake"),
("bpy.ops.mesh.edge_rotate*", "modeling/meshes/editing/edges.html#bpy-ops-mesh-edge-rotate"),
("bpy.ops.object.hide_view*", "scene_layout/object/editing/introduction.html#bpy-ops-object-hide-view"),
("bpy.ops.object.track_set*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-track-set"),
@@ -763,7 +856,7 @@ url_manual_mapping = (
("bpy.ops.rigidbody.world*", "physics/rigid_body/world.html#bpy-ops-rigidbody-world"),
("bpy.ops.transform.shear*", "modeling/meshes/editing/transform/shear.html#bpy-ops-transform-shear"),
("bpy.ops.uv.cube_project*", "modeling/meshes/editing/uv/unwrapping/mapping_types.html#bpy-ops-uv-cube-project"),
- ("bpy.ops.uv.pack_islands*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-pack-islands"),
+ ("bpy.ops.uv.pack_islands*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-pack-islands"),
("bpy.ops.wm.app_template*", "advanced/app_templates.html#bpy-ops-wm-app-template"),
("bpy.ops.wm.batch_rename*", "files/blend/rename.html#bpy-ops-wm-batch-rename"),
("bpy.ops.wm.redraw_timer*", "advanced/operators.html#bpy-ops-wm-redraw-timer"),
@@ -780,7 +873,6 @@ url_manual_mapping = (
("bpy.types.crosssequence*", "video_editing/sequencer/strips/transitions/cross.html#bpy-types-crosssequence"),
("bpy.types.curvemodifier*", "modeling/modifiers/deform/curve.html#bpy-types-curvemodifier"),
("bpy.types.fieldsettings*", "physics/forces/force_fields/index.html#bpy-types-fieldsettings"),
- ("bpy.types.fluidsettings*", "physics/fluid/index.html#bpy-types-fluidsettings"),
("bpy.types.imagesequence*", "video_editing/sequencer/strips/movie_image.html#bpy-types-imagesequence"),
("bpy.types.marbletexture*", "render/materials/legacy_textures/types/marble.html#bpy-types-marbletexture"),
("bpy.types.modifier.show*", "modeling/modifiers/introduction.html#bpy-types-modifier-show"),
@@ -797,7 +889,6 @@ url_manual_mapping = (
("bpy.types.shaderfxlight*", "grease_pencil/visual_effects/light.html#bpy-types-shaderfxlight"),
("bpy.types.shaderfxswirl*", "grease_pencil/visual_effects/swirl.html#bpy-types-shaderfxswirl"),
("bpy.types.shadernodergb*", "render/shader_nodes/input/rgb.html#bpy-types-shadernodergb"),
- ("bpy.types.smokemodifier*", "physics/smoke/index.html#bpy-types-smokemodifier"),
("bpy.types.soundsequence*", "video_editing/sequencer/strips/sound.html#bpy-types-soundsequence"),
("bpy.types.spaceoutliner*", "editors/outliner.html#bpy-types-spaceoutliner"),
("bpy.types.spacetimeline*", "editors/timeline.html#bpy-types-spacetimeline"),
@@ -808,6 +899,7 @@ url_manual_mapping = (
("bpy.ops.curve.separate*", "modeling/curves/editing/curve.html#bpy-ops-curve-separate"),
("bpy.ops.gpencil.delete*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-delete"),
("bpy.ops.gpencil.select*", "grease_pencil/selecting.html#bpy-ops-gpencil-select"),
+ ("bpy.ops.graph.decimate*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-decimate"),
("bpy.ops.mesh.mark_seam*", "modeling/meshes/editing/edges.html#bpy-ops-mesh-mark-seam"),
("bpy.ops.mesh.subdivide*", "modeling/meshes/editing/subdividing/subdivide.html#bpy-ops-mesh-subdivide"),
("bpy.ops.object.convert*", "scene_layout/object/editing/introduction.html#bpy-ops-object-convert"),
@@ -846,6 +938,7 @@ url_manual_mapping = (
("bpy.types.view3dcursor*", "editors/3dview/3d_cursor.html#bpy-types-view3dcursor"),
("bpy.types.warpmodifier*", "modeling/modifiers/deform/warp.html#bpy-types-warpmodifier"),
("bpy.types.wavemodifier*", "modeling/modifiers/deform/wave.html#bpy-types-wavemodifier"),
+ ("bpy.types.weldmodifier*", "modeling/modifiers/generate/weld.html#bpy-types-weldmodifier"),
("bpy.types.wipesequence*", "video_editing/sequencer/strips/transitions/wipe.html#bpy-types-wipesequence"),
("bpy.ops.gpencil.paste*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-paste"),
("bpy.ops.image.project*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-ops-image-project"),
@@ -859,12 +952,14 @@ url_manual_mapping = (
("bpy.types.addsequence*", "video_editing/sequencer/strips/effects/add.html#bpy-types-addsequence"),
("bpy.types.camera.show*", "render/cameras.html#bpy-types-camera-show"),
("bpy.types.consoleline*", "editors/python_console.html#bpy-types-consoleline"),
+ ("bpy.types.mesh.remesh*", "modeling/meshes/editing/retopology.html#bpy-types-mesh-remesh"),
("bpy.types.meshstatvis*", "modeling/meshes/mesh_analysis.html#bpy-types-meshstatvis"),
("bpy.types.nodesetting*", "interface/controls/nodes/parts.html#bpy-types-nodesetting"),
("bpy.types.object.lock*", "scene_layout/object/properties/transforms.html#bpy-types-object-lock"),
("bpy.types.object.show*", "scene_layout/object/properties/display.html#bpy-types-object-show"),
("bpy.types.particlekey*", "physics/particles/emitter/physics/keyed.html#bpy-types-particlekey"),
("bpy.types.posebone.ik*", "animation/armatures/posing/bone_constraints/inverse_kinematics/introduction.html#bpy-types-posebone-ik"),
+ ("bpy.types.preferences*", "editors/preferences/index.html#bpy-types-preferences"),
("bpy.types.renderlayer*", "render/layers/layers.html#bpy-types-renderlayer"),
("bpy.types.shaderfxrim*", "grease_pencil/visual_effects/rim.html#bpy-types-shaderfxrim"),
("bpy.types.spaceview3d*", "editors/3dview/index.html#bpy-types-spaceview3d"),
@@ -875,7 +970,12 @@ url_manual_mapping = (
("bpy.ops.curve.delete*", "modeling/curves/editing/curve.html#bpy-ops-curve-delete"),
("bpy.ops.curve.reveal*", "modeling/curves/editing/curve.html#bpy-ops-curve-reveal"),
("bpy.ops.curve.smooth*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth"),
+ ("bpy.ops.fluid.preset*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-ops-fluid-preset"),
("bpy.ops.gpencil.copy*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-copy"),
+ ("bpy.ops.graph.delete*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-delete"),
+ ("bpy.ops.graph.mirror*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-mirror"),
+ ("bpy.ops.graph.sample*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-sample"),
+ ("bpy.ops.graph.smooth*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-smooth"),
("bpy.ops.object.align*", "scene_layout/object/editing/transform/tools.html#bpy-ops-object-align"),
("bpy.ops.object.empty*", "modeling/empties.html#bpy-ops-object-empty"),
("bpy.ops.object.quick*", "physics/introduction.html#bpy-ops-object-quick"),
@@ -889,17 +989,20 @@ url_manual_mapping = (
("bpy.types.imagepaint*", "sculpt_paint/texture_paint/index.html#bpy-types-imagepaint"),
("bpy.types.lightprobe*", "render/eevee/lightprobes/index.html#bpy-types-lightprobe"),
("bpy.types.nodesocket*", "interface/controls/nodes/parts.html#bpy-types-nodesocket"),
+ ("bpy.types.paint.tile*", "sculpt_paint/texture_paint/tool_settings/tiling.html#bpy-types-paint-tile"),
("bpy.types.pointcache*", "physics/baking.html#bpy-types-pointcache"),
("bpy.types.pointlight*", "render/lights/light_object.html#bpy-types-pointlight"),
("bpy.types.renderview*", "render/output/multiview/index.html#bpy-types-renderview"),
("bpy.types.sceneeevee*", "render/eevee/index.html#bpy-types-sceneeevee"),
("bpy.types.vectorfont*", "modeling/texts/index.html#bpy-types-vectorfont"),
("bpy.ops.curve.split*", "modeling/curves/editing/curve.html#bpy-ops-curve-split"),
+ ("bpy.ops.graph.clean*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-clean"),
+ ("bpy.ops.graph.paste*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-paste"),
("bpy.ops.mesh.bisect*", "modeling/meshes/editing/subdividing/bisect.html#bpy-ops-mesh-bisect"),
("bpy.ops.object.join*", "scene_layout/object/editing/introduction.html#bpy-ops-object-join"),
("bpy.ops.object.text*", "modeling/texts/index.html#bpy-ops-object-text"),
("bpy.ops.view3d.snap*", "scene_layout/object/editing/transform/control/snap.html#bpy-ops-view3d-snap"),
- ("bpy.types.*texspace*", "editors/uv/generated_uvs.html#bpy-types-texspace"),
+ ("bpy.types.*texspace*", "modeling/meshes/editing/uv/uv_texture_spaces.html#bpy-types-texspace"),
("bpy.types.arealight*", "render/lights/light_object.html#bpy-types-arealight"),
("bpy.types.blenddata*", "files/data_blocks.html#bpy-types-blenddata"),
("bpy.types.colorramp*", "interface/controls/templates/color_ramp.html#bpy-types-colorramp"),
@@ -911,6 +1014,7 @@ url_manual_mapping = (
("bpy.types.nodegroup*", "interface/controls/nodes/groups.html#bpy-types-nodegroup"),
("bpy.types.spotlight*", "render/lights/light_object.html#bpy-types-spotlight"),
("bpy.types.textcurve*", "modeling/texts/index.html#bpy-types-textcurve"),
+ ("bpy.types.udimtiles*", "modeling/meshes/editing/uv/workflows/udims.html#bpy-types-udimtiles"),
("bpy.types.uipiemenu*", "interface/controls/buttons/menus.html#bpy-types-uipiemenu"),
("bpy.types.uipopover*", "interface/controls/buttons/menus.html#bpy-types-uipopover"),
("bpy.ops.collection*", "scene_layout/collections/collections.html#bpy-ops-collection"),
@@ -918,6 +1022,10 @@ url_manual_mapping = (
("bpy.ops.curve.draw*", "modeling/curves/editing/other.html#bpy-ops-curve-draw"),
("bpy.ops.curve.hide*", "modeling/curves/editing/curve.html#bpy-ops-curve-hide"),
("bpy.ops.curve.spin*", "modeling/surfaces/editing/surface.html#bpy-ops-curve-spin"),
+ ("bpy.ops.graph.bake*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-bake"),
+ ("bpy.ops.graph.copy*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-copy"),
+ ("bpy.ops.graph.snap*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-snap"),
+ ("bpy.ops.image.tile*", "modeling/meshes/editing/uv/workflows/udims.html#bpy-ops-image-tile"),
("bpy.ops.mesh.knife*", "modeling/meshes/editing/subdividing/knife.html#bpy-ops-mesh-knife"),
("bpy.ops.mesh.noise*", "modeling/meshes/editing/transform/noise.html#bpy-ops-mesh-noise"),
("bpy.ops.mesh.screw*", "modeling/meshes/editing/duplicating/screw.html#bpy-ops-mesh-screw"),
@@ -944,11 +1052,11 @@ url_manual_mapping = (
("bpy.ops.sequencer*", "video_editing/index.html#bpy-ops-sequencer"),
("bpy.ops.transform*", "scene_layout/object/editing/transform/index.html#bpy-ops-transform"),
("bpy.ops.uv.select*", "editors/uv/selecting.html#bpy-ops-uv-select"),
- ("bpy.ops.uv.stitch*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-stitch"),
+ ("bpy.ops.uv.stitch*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-stitch"),
("bpy.ops.uv.unwrap*", "modeling/meshes/editing/uv/unwrapping/mapping_types.html#bpy-ops-uv-unwrap"),
("bpy.types.animviz*", "animation/motion_paths.html#bpy-types-animviz"),
("bpy.types.lattice*", "animation/lattice.html#bpy-types-lattice"),
- ("bpy.types.library*", "files/linked_libraries.html#bpy-types-library"),
+ ("bpy.types.library*", "files/linked_libraries/index.html#bpy-types-library"),
("bpy.types.speaker*", "render/output/audio/speaker.html#bpy-types-speaker"),
("bpy.types.textbox*", "modeling/texts/layout.html#bpy-types-textbox"),
("bpy.types.texture*", "render/materials/legacy_textures/index.html#bpy-types-texture"),
@@ -956,7 +1064,7 @@ url_manual_mapping = (
("bpy.ops.nla.bake*", "animation/actions.html#bpy-ops-nla-bake"),
("bpy.ops.outliner*", "editors/outliner.html#bpy-ops-outliner"),
("bpy.ops.particle*", "physics/particles/index.html#bpy-ops-particle"),
- ("bpy.ops.uv.align*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-align"),
+ ("bpy.ops.uv.align*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-align"),
("bpy.ops.uv.reset*", "modeling/meshes/editing/uv/unwrapping/mapping_types.html#bpy-ops-uv-reset"),
("bpy.ops.wm.addon*", "editors/preferences/addons.html#bpy-ops-wm-addon"),
("bpy.types.action*", "animation/actions.html#bpy-types-action"),
@@ -981,7 +1089,7 @@ url_manual_mapping = (
("bpy.ops.ptcache*", "physics/baking.html#bpy-ops-ptcache"),
("bpy.ops.surface*", "modeling/surfaces/index.html#bpy-ops-surface"),
("bpy.ops.texture*", "render/materials/legacy_textures/index.html#bpy-ops-texture"),
- ("bpy.ops.uv.weld*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-weld"),
+ ("bpy.ops.uv.weld*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-weld"),
("bpy.ops.wm.tool*", "interface/tool_system.html#bpy-ops-wm-tool"),
("bpy.types.addon*", "editors/preferences/addons.html#bpy-types-addon"),
("bpy.types.brush*", "sculpt_paint/brush/brush.html#bpy-types-brush"),
@@ -1005,7 +1113,7 @@ url_manual_mapping = (
("bpy.ops.render*", "render/index.html#bpy-ops-render"),
("bpy.ops.script*", "advanced/scripting/index.html#bpy-ops-script"),
("bpy.ops.sculpt*", "sculpt_paint/sculpting/index.html#bpy-ops-sculpt"),
- ("bpy.ops.uv.pin*", "modeling/meshes/editing/uv/layout.html#bpy-ops-uv-pin"),
+ ("bpy.ops.uv.pin*", "modeling/meshes/editing/uv/editing.html#bpy-ops-uv-pin"),
("bpy.ops.view3d*", "editors/3dview/index.html#bpy-ops-view3d"),
("bpy.types.area*", "interface/window_system/areas.html#bpy-types-area"),
("bpy.types.boid*", "physics/particles/emitter/physics/boids.html#bpy-types-boid"),
@@ -1018,7 +1126,6 @@ url_manual_mapping = (
("bpy.ops.brush*", "sculpt_paint/brush/brush.html#bpy-ops-brush"),
("bpy.ops.cloth*", "physics/cloth/index.html#bpy-ops-cloth"),
("bpy.ops.curve*", "modeling/curves/index.html#bpy-ops-curve"),
- ("bpy.ops.fluid*", "physics/fluid/index.html#bpy-ops-fluid"),
("bpy.ops.graph*", "editors/graph_editor/index.html#bpy-ops-graph"),
("bpy.ops.image*", "files/media/image_formats.html#bpy-ops-image"),
("bpy.ops.mball*", "modeling/metas/index.html#bpy-ops-mball"),
diff --git a/release/scripts/presets/keyconfig/blender.py b/release/scripts/presets/keyconfig/blender.py
index 11cd76335f1..73be645d037 100644
--- a/release/scripts/presets/keyconfig/blender.py
+++ b/release/scripts/presets/keyconfig/blender.py
@@ -108,6 +108,38 @@ class Prefs(bpy.types.KeyConfigPreferences):
update=update_fn,
)
+ v3d_mmb_action: EnumProperty(
+ name="MMB Action",
+ items=(
+ ('ORBIT', "Orbit",
+ "Orbit",
+ 0),
+ ('PAN', "Pan",
+ "Set the view axis where each mouse direction always maps to the same axis",
+ 1),
+ ),
+ description=(
+ "The action when Middle-Mouse dragging in the viewport. Shift-Middle-Mouse is used for the other action"
+ ),
+ update=update_fn,
+ )
+
+ v3d_alt_mmb_drag_action: EnumProperty(
+ name="Alt-MMB Drag Action",
+ items=(
+ ('RELATIVE', "Relative",
+ "Set the view axis where each mouse direction maps to an axis relative to the current orientation",
+ 0),
+ ('ABSOLUTE', "Absolute",
+ "Set the view axis where each mouse direction always maps to the same axis",
+ 1),
+ ),
+ description=(
+ "Action when Alt-MMB dragging in the 3D viewport"
+ ),
+ update=update_fn,
+ )
+
# Developer note, this is an experemental option.
use_pie_click_drag: BoolProperty(
name="Pie Menu on Drag",
@@ -149,10 +181,14 @@ class Prefs(bpy.types.KeyConfigPreferences):
col = split.column()
col.prop(self, "use_v3d_tab_menu")
col.prop(self, "use_pie_click_drag")
+ col.prop(self, "use_v3d_shade_ex_pie")
col = split.column()
col.label(text="Tilde Action:")
col.row().prop(self, "v3d_tilde_action", expand=True)
- col.prop(self, "use_v3d_shade_ex_pie")
+ col.label(text="Middle Mouse Action:")
+ col.row().prop(self, "v3d_mmb_action", expand=True)
+ col.label(text="Alt Middle Mouse Drag Action:")
+ col.row().prop(self, "v3d_alt_mmb_drag_action", expand=True)
blender_default = bpy.utils.execfile(os.path.join(DIRNAME, "keymap_data", "blender_default.py"))
@@ -176,6 +212,8 @@ def load():
),
spacebar_action=kc_prefs.spacebar_action,
v3d_tilde_action=kc_prefs.v3d_tilde_action,
+ use_v3d_mmb_pan=(kc_prefs.v3d_mmb_action == 'PAN'),
+ v3d_alt_mmb_drag_action=kc_prefs.v3d_alt_mmb_drag_action,
use_select_all_toggle=kc_prefs.use_select_all_toggle,
use_v3d_tab_menu=kc_prefs.use_v3d_tab_menu,
use_v3d_shade_ex_pie=kc_prefs.use_v3d_shade_ex_pie,
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 629bc24abb3..3f5b7917f9c 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -50,9 +50,13 @@ class Params:
"use_v3d_tab_menu",
# Use extended pie menu for shading.
"use_v3d_shade_ex_pie",
+ # Swap orbit/pan keys (for 2D workflows).
+ "use_v3d_mmb_pan",
# Experimental option.
"use_pie_click_drag",
"v3d_tilde_action",
+ # Alt-MMB axis switching 'RELATIVE' or 'ABSOLUTE' axis switching.
+ "v3d_alt_mmb_drag_action",
)
def __init__(
@@ -68,8 +72,10 @@ class Params:
use_gizmo_drag=True,
use_v3d_tab_menu=False,
use_v3d_shade_ex_pie=False,
+ use_v3d_mmb_pan=False,
use_pie_click_drag=False,
v3d_tilde_action='VIEW',
+ v3d_alt_mmb_drag_action='RELATIVE',
):
from sys import platform
self.apple = (platform == 'darwin')
@@ -116,7 +122,9 @@ class Params:
self.use_select_all_toggle = use_select_all_toggle
self.use_v3d_tab_menu = use_v3d_tab_menu
self.use_v3d_shade_ex_pie = use_v3d_shade_ex_pie
+ self.use_v3d_mmb_pan = use_v3d_mmb_pan
self.v3d_tilde_action = v3d_tilde_action
+ self.v3d_alt_mmb_drag_action = v3d_alt_mmb_drag_action
self.use_pie_click_drag = use_pie_click_drag
if not use_pie_click_drag:
@@ -945,8 +953,13 @@ def km_view3d(params):
("view3d.localview", {"type": 'MOUSESMARTZOOM', "value": 'ANY'}, None),
("view3d.localview_remove_from", {"type": 'M', "value": 'PRESS'}, None),
# Navigation.
- ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
- ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ *((
+ ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ) if params.use_v3d_mmb_pan else (
+ ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ )),
("view3d.zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None),
("view3d.dolly", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("view3d.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS', "ctrl": True},
@@ -1043,14 +1056,25 @@ def km_view3d(params):
{"properties": [("type", 'LEFT'), ("align_active", True)]}),
("view3d.view_axis", {"type": 'NUMPAD_7', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("type", 'BOTTOM'), ("align_active", True)]}),
- ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'NORTH', "alt": True},
- {"properties": [("type", 'TOP'), ("relative", True)]}),
- ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'SOUTH', "alt": True},
- {"properties": [("type", 'BOTTOM'), ("relative", True)]}),
- ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'EAST', "alt": True},
- {"properties": [("type", 'RIGHT'), ("relative", True)]}),
- ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'WEST', "alt": True},
- {"properties": [("type", 'LEFT'), ("relative", True)]}),
+ *((
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'NORTH', "alt": True},
+ {"properties": [("type", 'TOP'), ("relative", True)]}),
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'SOUTH', "alt": True},
+ {"properties": [("type", 'BOTTOM'), ("relative", True)]}),
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'EAST', "alt": True},
+ {"properties": [("type", 'RIGHT'), ("relative", True)]}),
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'WEST', "alt": True},
+ {"properties": [("type", 'LEFT'), ("relative", True)]}),
+ ) if params.v3d_alt_mmb_drag_action == 'RELATIVE' else (
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'NORTH', "alt": True},
+ {"properties": [("type", 'TOP')]}),
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'SOUTH', "alt": True},
+ {"properties": [("type", 'BOTTOM')]}),
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'EAST', "alt": True},
+ {"properties": [("type", 'RIGHT')]}),
+ ("view3d.view_axis", {"type": 'EVT_TWEAK_M', "value": 'WEST', "alt": True},
+ {"properties": [("type", 'LEFT')]}),
+ )),
("view3d.view_center_pick", {"type": 'MIDDLEMOUSE', "value": 'CLICK', "alt": True}, None),
("view3d.ndof_orbit_zoom", {"type": 'NDOF_MOTION', "value": 'ANY'}, None),
("view3d.ndof_orbit", {"type": 'NDOF_MOTION', "value": 'ANY', "ctrl": True}, None),
@@ -1232,8 +1256,9 @@ def km_mask_editing(params):
# click select keymap it's fine to have the context menu instead.
items.extend([
("mask.select", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
- {"properties": [("extend", False), ("deselect", False), ("toggle", False),
- ("deselect_all", not params.legacy)]}),
+ {"properties": [
+ ("extend", False), ("deselect", False), ("toggle", False),
+ ("deselect_all", not params.legacy)]}),
("transform.translate", {"type": 'EVT_TWEAK_R', "value": 'ANY'}, None),
])
@@ -1406,8 +1431,9 @@ def km_graph_editor(params):
("wm.context_toggle", {"type": 'H', "value": 'PRESS', "ctrl": True},
{"properties": [("data_path", 'space_data.show_handles')]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS'},
- {"properties": [("extend", False), ("deselect_all", not params.legacy),
- ("column", False), ("curves", False)]}),
+ {"properties": [
+ ("extend", False), ("deselect_all", not params.legacy),
+ ("column", False), ("curves", False)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "alt": True},
{"properties": [("extend", False), ("column", True), ("curves", False)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
@@ -1948,8 +1974,9 @@ def km_dopesheet(params):
items.extend([
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS'},
- {"properties": [("extend", False), ("deselect_all", not params.legacy),
- ("column", False), ("channel", False)]}),
+ {"properties": [
+ ("extend", False), ("deselect_all", not params.legacy),
+ ("column", False), ("channel", False)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "alt": True},
{"properties": [("extend", False), ("column", True), ("channel", False)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
@@ -2425,8 +2452,9 @@ def km_sequencer(params):
)
),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS'},
- {"properties": [("extend", False), ("deselect_all", True),
- ("linked_handle", False), ("left_right", 'NONE'), ("linked_time", False)]}),
+ {"properties": [
+ ("extend", False), ("deselect_all", True),
+ ("linked_handle", False), ("left_right", 'NONE'), ("linked_time", False)]}),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True), ("linked_handle", False), ("left_right", 'NONE'), ("linked_time", False)]}),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS', "alt": True},
@@ -2453,6 +2481,14 @@ def km_sequencer(params):
("sequencer.select_box", {"type": params.select_tweak, "value": 'ANY', "ctrl": True},
{"properties": [("tweak", True), ("mode", 'SUB')]}),
("sequencer.select_box", {"type": 'B', "value": 'PRESS'}, None),
+ ("sequencer.select_box", {"type": 'B', "value": 'PRESS', "alt": True},
+ {"properties": [("handles", True)]}),
+ ("sequencer.select_box", {"type": params.select_tweak, "value": 'ANY', "alt": True},
+ {"properties": [("handles", True), ("tweak", True), ("mode", 'SET')]}),
+ ("sequencer.select_box", {"type": params.select_tweak, "value": 'ANY', "shift": True, "alt": True},
+ {"properties": [("handles", True), ("tweak", True), ("mode", 'ADD')]}),
+ ("sequencer.select_box", {"type": params.select_tweak, "value": 'ANY', "ctrl": True, "alt": True},
+ {"properties": [("handles", True), ("tweak", True), ("mode", 'SUB')]}),
("sequencer.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
op_menu("SEQUENCER_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
op_menu("SEQUENCER_MT_change", {"type": 'C', "value": 'PRESS'}),
@@ -6087,7 +6123,7 @@ def km_sequencer_editor_tool_select_box(params):
)
-def km_sequencer_editor_tool_cut(params):
+def km_sequencer_editor_tool_cut(_params):
return (
"Sequencer Tool: Cut",
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index c50b9414667..aca358870c8 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -268,18 +268,43 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
col = layout.column()
col.prop(bone, "hide", text="Hide")
+
+
+class BONE_PT_display_custom_shape(BoneButtonsPanel, Panel):
+ bl_label = "Custom Shape"
+ bl_parent_id = "BONE_PT_display"
+
+ @classmethod
+ def poll(cls, context):
+ return context.bone
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ bone = context.bone
+ pchan = None
+
+ if ob and bone:
+ pchan = ob.pose.bones[bone.name]
+ elif bone is None:
+ bone = context.edit_bone
+
+ if bone and pchan:
+ col = layout.column()
+ col.prop(pchan, "custom_shape")
+
sub = col.column()
sub.active = bool(pchan and pchan.custom_shape)
+ sub.separator()
+ sub.prop(pchan, "custom_shape_scale", text="Scale")
+ sub.prop_search(pchan, "custom_shape_transform",
+ ob.pose, "bones", text="Override Transform")
+ sub.prop(pchan, "use_custom_shape_bone_size")
+ sub.separator()
sub.prop(bone, "show_wire", text="Wireframe")
- if pchan:
- col = layout.column()
- col.prop(pchan, "custom_shape")
- if pchan.custom_shape:
- col.prop(pchan, "use_custom_shape_bone_size", text="Bone Size")
- col.prop(pchan, "custom_shape_scale", text="Scale")
- col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones")
-
class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
bl_label = "Inverse Kinematics"
@@ -431,6 +456,7 @@ classes = (
BONE_PT_inverse_kinematics,
BONE_PT_deform,
BONE_PT_display,
+ BONE_PT_display_custom_shape,
BONE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 28c9895f53b..7c2077a178c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -162,9 +162,6 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
if md.fluid_type == 'DOMAIN':
domain = md.domain_settings
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = not self.check_domain_has_unbaked_guide(domain)
-
is_baking_any = domain.is_cache_baking_any
has_baked_data = domain.has_cache_baked_data
@@ -176,7 +173,9 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
flow.enabled = not is_baking_any and not has_baked_data
col = flow.column()
+ col.enabled = not domain.has_cache_baked_guide
col.prop(domain, "resolution_max", text="Resolution Divisions")
+ col = flow.column()
col.prop(domain, "time_scale", text="Time Scale")
col.prop(domain, "cfl_condition", text="CFL Number")
@@ -201,7 +200,17 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+
+ # Deactivate bake operator if guides are enabled but not baked yet.
+ note_flag = True
+ if self.check_domain_has_unbaked_guide(domain) and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Guides: Bake Guides or disable them.")
+
split = layout.split()
+ split.enabled = note_flag
bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end)
if domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete:
@@ -354,10 +363,13 @@ class PHYSICS_PT_smoke_dissolve(PhysicButtonsPanel, Panel):
return (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
- md = context.fluid
- domain = md.domain_settings
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
- self.layout.prop(domain, "use_dissolve_smoke", text="")
+ is_baking_any = domain.is_cache_baking_any
+
+ self.layout.enabled = not is_baking_any
+ self.layout.prop(md, "use_dissolve_smoke", text="")
def draw(self, context):
layout = self.layout
@@ -433,6 +445,11 @@ class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
def draw_header(self, context):
md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+
+ is_baking_any = domain.is_cache_baking_any
+
+ self.layout.enabled = not is_baking_any
self.layout.prop(md, "use_flip_particles", text="")
def draw(self, context):
@@ -445,32 +462,27 @@ class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
is_baking_any = domain.is_cache_baking_any
has_baked_data = domain.has_cache_baked_data
+ layout.enabled = not is_baking_any and not has_baked_data
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
- col0 = col.column()
- col0.enabled = not is_baking_any and not has_baked_data
- col0.prop(domain, "simulation_method", expand=False)
- col0.prop(domain, "flip_ratio", text="FLIP Ratio")
- col0.prop(domain, "particle_radius", text="Particle Radius")
-
- col1 = flow.column(align=True)
- col1.enabled = not is_baking_any and not has_baked_data
- col1.prop(domain, "particle_max", text="Particles Maximum")
- col1.prop(domain, "particle_min", text="Minimum")
-
- col1 = flow.column()
- col1.enabled = not is_baking_any and not has_baked_data
- col1.prop(domain, "particle_number", text="Particle Sampling")
- col1.prop(domain, "particle_band_width", text="Narrow Band Width")
- col1.prop(domain, "particle_randomness", text="Particle Randomness")
-
- col2 = flow.column()
- col2.enabled = not is_baking_any and not has_baked_data
- col2.prop(domain, "use_fractions", text="Fractional Obstacles")
- col3 = col2.column()
- col3.enabled = domain.use_fractions and col2.enabled
- col3.prop(domain, "fractions_threshold", text="Obstacle-Fluid Threshold")
+ col.prop(domain, "simulation_method", expand=False)
+ col.prop(domain, "flip_ratio", text="FLIP Ratio")
+ col.prop(domain, "particle_radius", text="Particle Radius")
+
+ col = flow.column()
+ col.prop(domain, "particle_max", text="Particles Maximum")
+ col.prop(domain, "particle_min", text="Minimum")
+
+ col = flow.column()
+ col.prop(domain, "particle_number", text="Particle Sampling")
+ col.prop(domain, "particle_band_width", text="Narrow Band Width")
+ col.prop(domain, "particle_randomness", text="Particle Randomness")
+
+ col = flow.column()
+ col.prop(domain, "use_fractions", text="Fractional Obstacles")
+ col.active = domain.use_fractions
+ col.prop(domain, "fractions_threshold", text="Obstacle-Fluid Threshold")
class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel):
@@ -618,6 +630,12 @@ class PHYSICS_PT_adaptive_domain(PhysicButtonsPanel, Panel):
if not PhysicButtonsPanel.poll_gas_domain(context):
return False
+ md = context.fluid
+ domain = md.domain_settings
+ # Effector guides require a fixed domain size
+ if domain.use_guide and domain.guide_source == 'EFFECTOR':
+ return False
+
return (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
@@ -678,9 +696,7 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
layout.use_property_split = True
domain = context.fluid.domain_settings
-
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = domain.use_noise and not self.check_domain_has_unbaked_guide(domain)
+ layout.enabled = domain.use_noise
is_baking_any = domain.is_cache_baking_any
has_baked_noise = domain.has_cache_baked_noise
@@ -701,8 +717,16 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+ # Deactivate bake operator if data has not been baked yet.
+ note_flag = True
+ if domain.use_noise and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Data: Bake Data first.")
+
split = layout.split()
- split.enabled = domain.has_cache_baked_data
+ split.enabled = domain.has_cache_baked_data and note_flag
bake_incomplete = (domain.cache_frame_pause_noise < domain.cache_frame_end)
if domain.has_cache_baked_noise and not domain.is_cache_baking_noise and bake_incomplete:
@@ -744,9 +768,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
layout.use_property_split = True
domain = context.fluid.domain_settings
-
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = domain.use_mesh and not self.check_domain_has_unbaked_guide(domain)
+ layout.enabled = domain.use_mesh
is_baking_any = domain.is_cache_baking_any
has_baked_mesh = domain.has_cache_baked_mesh
@@ -780,8 +802,16 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+ # Deactivate bake operator if data has not been baked yet.
+ note_flag = True
+ if domain.use_mesh and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Data: Bake Data first.")
+
split = layout.split()
- split.enabled = domain.has_cache_baked_data
+ split.enabled = domain.has_cache_baked_data and note_flag
bake_incomplete = (domain.cache_frame_pause_mesh < domain.cache_frame_end)
if domain.has_cache_baked_mesh and not domain.is_cache_baking_mesh and bake_incomplete:
@@ -817,9 +847,6 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = not self.check_domain_has_unbaked_guide(domain)
-
is_baking_any = domain.is_cache_baking_any
has_baked_particles = domain.has_cache_baked_particles
using_particles = domain.use_spray_particles or domain.use_foam_particles or domain.use_bubble_particles
@@ -887,8 +914,17 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
if domain.cache_type == 'MODULAR':
col.separator()
+ # Deactivate bake operator if data has not been baked yet.
+ note_flag = True
+ if using_particles and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
+ note = layout.split()
+ note_flag = False
+ note.enabled = note_flag
+ note.label(icon='INFO', text="Unbaked Data: Bake Data first.")
+
split = layout.split()
split.enabled = (
+ note_flag and
domain.has_cache_baked_data and
(domain.use_spray_particles or
domain.use_bubble_particles or
@@ -931,9 +967,6 @@ class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
- # Deactivate UI if guides are enabled but not baked yet.
- layout.active = not self.check_domain_has_unbaked_guide(domain)
-
is_baking_any = domain.is_cache_baking_any
has_baked_any = domain.has_cache_baked_any
has_baked_data = domain.has_cache_baked_data
@@ -1018,7 +1051,8 @@ class PHYSICS_PT_guide(PhysicButtonsPanel, Panel):
col = split.column()
col.operator("fluid.free_guides", text="Free")
elif not domain.has_cache_baked_guide and domain.is_cache_baking_guide:
- split.operator("fluid.pause_bake", text="Pause Guides")
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking Guides - ESC to pause")
elif not domain.has_cache_baked_guide and not domain.is_cache_baking_guide:
split.operator("fluid.bake_guides", text="Bake Guides")
else:
@@ -1072,7 +1106,10 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
is_baking_any = domain.is_cache_baking_any
- has_baked_any = domain.has_cache_baked_any
+ has_baked_data = domain.has_cache_baked_data
+ has_baked_noise = domain.has_cache_baked_noise
+ has_baked_mesh = domain.has_cache_baked_mesh
+ has_baked_particles = domain.has_cache_baked_particles
col = layout.column()
col.prop(domain, "cache_directory", text="")
@@ -1096,18 +1133,24 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
col.separator()
col = flow.column()
- col.enabled = not is_baking_any and not has_baked_any
+ col.enabled = not is_baking_any and not has_baked_data
col.prop(domain, "cache_data_format", text="Data File Format")
if md.domain_settings.domain_type in {'GAS'}:
if domain.use_noise:
+ col = flow.column()
+ col.enabled = not is_baking_any and not has_baked_noise
col.prop(domain, "cache_noise_format", text="Noise File Format")
if md.domain_settings.domain_type in {'LIQUID'}:
# File format for all particle systemes (FLIP and secondary)
+ col = flow.column()
+ col.enabled = not is_baking_any and not has_baked_particles
col.prop(domain, "cache_particle_format", text="Particle File Format")
if domain.use_mesh:
+ col = flow.column()
+ col.enabled = not is_baking_any and not has_baked_mesh
col.prop(domain, "cache_mesh_format", text="Mesh File Format")
if domain.cache_type == 'FINAL':
@@ -1132,7 +1175,8 @@ class PHYSICS_PT_export(PhysicButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- if not PhysicButtonsPanel.poll_fluid_domain(context):
+ # Only show the advanced panel to advanced users who know Mantaflow's birthday :)
+ if not PhysicButtonsPanel.poll_fluid_domain(context) or bpy.app.debug_value != 3001:
return False
return (context.engine in cls.COMPAT_ENGINES)
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index c1ad196b555..13b8dced08c 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -144,11 +144,7 @@ class _defs_view3d_generic:
class _defs_annotate:
def draw_settings_common(context, layout, tool):
- if type(context.gpencil_data_owner) is bpy.types.Object:
- gpd = context.scene.grease_pencil
- else:
- gpd = context.gpencil_data
-
+ gpd = context.annotation_data
if gpd is not None:
if gpd.layers.active_note is not None:
text = gpd.layers.active_note
@@ -158,7 +154,7 @@ class _defs_annotate:
else:
text = ""
- gpl = context.active_gpencil_layer
+ gpl = context.active_annotation_layer
if gpl is not None:
layout.label(text="Annotation:")
sub = layout.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 6ca6cb7b544..537a4a4761a 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2713,6 +2713,7 @@ class VIEW3D_MT_make_single_user(Menu):
def draw(self, _context):
layout = self.layout
+ layout.operator_context = 'EXEC_DEFAULT'
props = layout.operator("object.make_single_user", text="Object")
props.object = True
diff --git a/source/blender/alembic/intern/abc_mball.cc b/source/blender/alembic/intern/abc_mball.cc
index db4b9d82ebf..6fc7d8c24c8 100644
--- a/source/blender/alembic/intern/abc_mball.cc
+++ b/source/blender/alembic/intern/abc_mball.cc
@@ -31,7 +31,7 @@ extern "C" {
#include "BKE_curve.h"
#include "BKE_displist.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index f7a18b0325e..991fa02e4be 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -40,7 +40,7 @@ extern "C" {
#include "BKE_animsys.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index b05246371fa..f6f266c808e 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -31,7 +31,7 @@ extern "C" {
#include "BKE_constraint.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 5519cbef53c..0cab0303fcc 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -47,7 +47,7 @@ extern "C" {
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index fd7fa632999..2911002b9e9 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -20,6 +20,10 @@
#ifndef __BKE_DEFORM_H__
#define __BKE_DEFORM_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/** \file
* \ingroup bke
* \brief support for deformation groups and hooks.
@@ -102,7 +106,7 @@ void defvert_normalize_subset(struct MDeformVert *dvert,
void defvert_normalize_lock_single(struct MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
- const int def_nr_lock);
+ const uint def_nr_lock);
void defvert_normalize_lock_map(struct MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
@@ -142,4 +146,8 @@ void BKE_defvert_extract_vgroup_to_polyweights(struct MDeformVert *dvert,
void BKE_defvert_weight_to_rgb(float r_rgb[3], const float weight);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BKE_DEFORM_H__ */
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 405b052f477..d389b557503 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -87,7 +87,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt);
void fcurve_free_driver(struct FCurve *fcu);
struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
-void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
+void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars);
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]);
@@ -280,7 +280,7 @@ struct FCurve *rna_get_fcurve_context_ui(struct bContext *C,
struct PointerRNA *ptr,
struct PropertyRNA *prop,
int rnaindex,
- struct AnimData **r_adt,
+ struct AnimData **r_animdata,
struct bAction **r_action,
bool *r_driven,
bool *r_special);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 65c3725d994..93840db49c9 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -77,6 +77,7 @@ typedef struct Global {
* * 799: Enable some mysterious new depsgraph behavior (05/2015).
* * 1112: Disable new Cloth internal springs handling (09/2014).
* * 1234: Disable new dyntopo code fixing skinny faces generation (04/2015).
+ * * 3001: Enable additional Fluid modifier (Mantaflow) options (02/2020).
* * 16384 and above: Reserved for python (add-ons) usage.
*/
short debug_value;
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
new file mode 100644
index 00000000000..7d00e98f239
--- /dev/null
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -0,0 +1,263 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+#ifndef __BKE_LIB_ID_H__
+#define __BKE_LIB_ID_H__
+
+/** \file
+ * \ingroup bke
+ *
+ * API to manage data-blocks inside of Blender's Main data-base, or as independant runtime-only
+ * data.
+ *
+ * \note `BKE_lib_` files are for operations over data-blocks themselves, although they might
+ * alter Main as well (when creating/renaming/deleting an ID e.g.).
+ *
+ * \section Function Names
+ *
+ * \warning Descriptions below is ideal goal, current status of naming does not yet fully follow it
+ * (this is WIP).
+ *
+ * - `BKE_lib_id_` should be used for rather high-level operations, that involve Main database and
+ * relations with other IDs, and can be considered as 'safe' (as in, in themselves, they leave
+ * affected IDs/Main in a consistent status).
+ * - `BKE_lib_libblock_` should be used for lower level operations, that perform some parts of
+ * `BKE_lib_id_` ones, but will generally not ensure caller that affected data is in a consistent
+ * state by their own execution alone.
+ * - `BKE_lib_main_` should be used for operations performed over all IDs of a given Main
+ * data-base.
+ *
+ * \note External code should typically not use `BKE_lib_libblock_` functions, except in some
+ * specific cases requiring advanced (and potentially dangerous) handling.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_compiler_attrs.h"
+
+struct GHash;
+struct ID;
+struct Library;
+struct ListBase;
+struct Main;
+struct PointerRNA;
+struct PropertyRNA;
+struct bContext;
+
+size_t BKE_libblock_get_alloc_info(short type, const char **name);
+void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT;
+void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag)
+ ATTR_WARN_UNUSED_RESULT;
+void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
+
+void *BKE_id_new(struct Main *bmain, const short type, const char *name);
+void *BKE_id_new_nomain(const short type, const char *name);
+
+/**
+ * New ID creation/copying options.
+ */
+enum {
+ /* *** Generic options (should be handled by all ID types copying, ID creation, etc.). *** */
+ /** Create datablock outside of any main database -
+ * similar to 'localize' functions of materials etc. */
+ LIB_ID_CREATE_NO_MAIN = 1 << 0,
+ /** Do not affect user refcount of datablocks used by new one
+ * (which also gets zero usercount then).
+ * Implies LIB_ID_CREATE_NO_MAIN. */
+ LIB_ID_CREATE_NO_USER_REFCOUNT = 1 << 1,
+ /** Assume given 'newid' already points to allocated memory for whole datablock
+ * (ID + data) - USE WITH CAUTION!
+ * Implies LIB_ID_CREATE_NO_MAIN. */
+ LIB_ID_CREATE_NO_ALLOCATE = 1 << 2,
+
+ /** Do not tag new ID for update in depsgraph. */
+ LIB_ID_CREATE_NO_DEG_TAG = 1 << 8,
+
+ /* *** Specific options to some ID types or usages. *** */
+ /* *** May be ignored by unrelated ID copying functions. *** */
+ /** Object only, needed by make_local code. */
+ LIB_ID_COPY_NO_PROXY_CLEAR = 1 << 16,
+ /** Do not copy preview data, when supported. */
+ LIB_ID_COPY_NO_PREVIEW = 1 << 17,
+ /** Copy runtime data caches. */
+ LIB_ID_COPY_CACHES = 1 << 18,
+ /** Don't copy id->adt, used by ID datablock localization routines. */
+ LIB_ID_COPY_NO_ANIMDATA = 1 << 19,
+ /** Mesh: Reference CD data layers instead of doing real copy - USE WITH CAUTION! */
+ LIB_ID_COPY_CD_REFERENCE = 1 << 20,
+
+ /* *** XXX Hackish/not-so-nice specific behaviors needed for some corner cases. *** */
+ /* *** Ideally we should not have those, but we need them for now... *** */
+ /** EXCEPTION! Deep-copy actions used by animdata of copied ID. */
+ LIB_ID_COPY_ACTIONS = 1 << 24,
+ /** Keep the library pointer when copying datablock outside of bmain. */
+ LIB_ID_COPY_KEEP_LIB = 1 << 25,
+ /** EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */
+ LIB_ID_COPY_SHAPEKEY = 1 << 26,
+
+ /* *** Helper 'defines' gathering most common flag sets. *** */
+ /** Shapekeys are not real ID's, more like local data to geometry IDs... */
+ LIB_ID_COPY_DEFAULT = LIB_ID_COPY_SHAPEKEY,
+ /** Generate a local copy, outside of bmain, to work on (used by COW e.g.). */
+ LIB_ID_COPY_LOCALIZE = LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_CACHES,
+};
+
+void BKE_libblock_copy_ex(struct Main *bmain,
+ const struct ID *id,
+ struct ID **r_newid,
+ const int orig_flag);
+void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+/* Special version. sued by datablock localization. */
+void *BKE_libblock_copy_for_localize(const struct ID *id);
+
+void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
+void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL();
+
+struct ID *BKE_libblock_find_name(struct Main *bmain,
+ const short type,
+ const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+/* lib_remap.c (keep here since they're general functions) */
+/**
+ * New freeing logic options.
+ */
+enum {
+ /* *** Generic options (should be handled by all ID types freeing). *** */
+ /** Do not try to remove freed ID from given Main (passed Main may be NULL). */
+ LIB_ID_FREE_NO_MAIN = 1 << 0,
+ /**
+ * Do not affect user refcount of datablocks used by freed one.
+ * Implies LIB_ID_FREE_NO_MAIN.
+ */
+ LIB_ID_FREE_NO_USER_REFCOUNT = 1 << 1,
+ /**
+ * Assume freed ID datablock memory is managed elsewhere, do not free it
+ * (still calls relevant ID type's freeing function though) - USE WITH CAUTION!
+ * Implies LIB_ID_FREE_NO_MAIN.
+ */
+ LIB_ID_FREE_NOT_ALLOCATED = 1 << 2,
+
+ /** Do not tag freed ID for update in depsgraph. */
+ LIB_ID_FREE_NO_DEG_TAG = 1 << 8,
+ /** Do not attempt to remove freed ID from UI data/notifiers/... */
+ LIB_ID_FREE_NO_UI_USER = 1 << 9,
+};
+
+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();
+
+void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag);
+void BKE_id_free(struct Main *bmain, void *idv);
+
+void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
+
+void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
+void BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL();
+
+void BKE_libblock_management_main_add(struct Main *bmain, void *idv);
+void BKE_libblock_management_main_remove(struct Main *bmain, void *idv);
+
+void BKE_libblock_management_usercounts_set(struct Main *bmain, void *idv);
+void BKE_libblock_management_usercounts_clear(struct Main *bmain, void *idv);
+
+void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
+void id_lib_extern(struct ID *id);
+void id_lib_indirect_weak_link(struct ID *id);
+void id_us_ensure_real(struct ID *id);
+void id_us_clear_real(struct ID *id);
+void id_us_plus_no_lib(struct ID *id);
+void id_us_plus(struct ID *id);
+void id_us_min(struct ID *id);
+void id_fake_user_set(struct ID *id);
+void id_fake_user_clear(struct ID *id);
+void BKE_id_clear_newpoin(struct ID *id);
+
+void BKE_id_make_local_generic(struct Main *bmain,
+ struct ID *id,
+ const bool id_in_mainlist,
+ const bool lib_local);
+bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
+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);
+bool BKE_id_copy(struct Main *bmain, const struct ID *id, struct ID **newid);
+bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
+void BKE_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
+void id_sort_by_name(struct ListBase *lb, struct ID *id, struct ID *id_sorting_hint);
+void BKE_id_expand_local(struct Main *bmain, struct ID *id);
+void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id);
+
+bool BKE_id_new_name_validate(struct ListBase *lb, struct ID *id, const char *name)
+ ATTR_NONNULL(1, 2);
+void id_clear_lib_data(struct Main *bmain, struct ID *id);
+void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_mainlist);
+
+/* Affect whole Main database. */
+void BKE_main_id_tag_idcode(struct Main *mainvar,
+ const short type,
+ const int tag,
+ const bool value);
+void BKE_main_id_tag_listbase(struct ListBase *lb, const int tag, const bool value);
+void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value);
+
+void BKE_main_id_flag_listbase(struct ListBase *lb, const int flag, const bool value);
+void BKE_main_id_flag_all(struct Main *bmain, const int flag, const bool value);
+
+void BKE_main_id_clear_newpoins(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. */
+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. */
+void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id);
+void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const struct ID *id);
+
+char *BKE_id_to_unique_string_key(const struct ID *id);
+
+void BKE_library_make_local(struct Main *bmain,
+ const struct Library *lib,
+ struct GHash *old_to_new_ids,
+ const bool untagged_only,
+ const bool set_fake);
+
+void BKE_id_tag_set_atomic(struct ID *id, int tag);
+void BKE_id_tag_clear_atomic(struct ID *id, int tag);
+
+bool BKE_id_is_in_global_main(struct ID *id);
+
+void BKE_id_ordered_list(struct ListBase *ordered_lb, const struct ListBase *lb);
+void BKE_id_reorder(const struct ListBase *lb, struct ID *id, struct ID *relative, bool after);
+
+#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->tag & LIB_TAG_DOIT))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_LIB_ID_H__ */
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
new file mode 100644
index 00000000000..29b19af7abf
--- /dev/null
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -0,0 +1,114 @@
+/*
+ * 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) 2016 by Blender Foundation.
+ * All rights reserved.
+ */
+
+#ifndef __BKE_LIB_OVERRIDE_H__
+#define __BKE_LIB_OVERRIDE_H__
+
+/** \file
+ * \ingroup bke
+ *
+ * API to manage data-blocks inside of Blender's Main data-base, or as independant runtime-only
+ * data.
+ *
+ * \note `BKE_lib_` files are for operations over data-blocks themselves, although they might
+ * alter Main as well (when creating/renaming/deleting an ID e.g.).
+ *
+ * \section Function Names
+ *
+ * \warning Descriptions below is ideal goal, current status of naming does not yet fully follow it
+ * (this is WIP).
+ *
+ * - `BKE_lib_override_library_` should be used for function affecting a single ID.
+ * - `BKE_lib_override_library_main_` should be used for function affecting the whole collection
+ * of IDs in a given Main data-base.
+ */
+
+struct ID;
+struct IDOverrideLibrary;
+struct IDOverrideLibraryProperty;
+struct IDOverrideLibraryPropertyOperation;
+struct Main;
+
+void BKE_lib_override_library_enable(const bool do_enable);
+bool BKE_lib_override_library_is_enabled(void);
+
+struct IDOverrideLibrary *BKE_lib_override_library_init(struct ID *local_id,
+ struct ID *reference_id);
+void BKE_lib_override_library_copy(struct ID *dst_id, const struct ID *src_id);
+void BKE_lib_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user);
+void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user);
+
+struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
+ struct ID *reference_id,
+ const bool do_tagged_remap);
+bool BKE_lib_override_library_create_from_tag(struct Main *bmain);
+
+struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find(
+ struct IDOverrideLibrary *override, const char *rna_path);
+struct IDOverrideLibraryProperty *BKE_lib_override_library_property_get(
+ struct IDOverrideLibrary *override, const char *rna_path, bool *r_created);
+void BKE_lib_override_library_property_delete(struct IDOverrideLibrary *override,
+ struct IDOverrideLibraryProperty *override_property);
+
+struct IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_find(
+ struct IDOverrideLibraryProperty *override_property,
+ const char *subitem_refname,
+ const char *subitem_locname,
+ const int subitem_refindex,
+ const int subitem_locindex,
+ const bool strict,
+ bool *r_strict);
+struct IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_get(
+ struct IDOverrideLibraryProperty *override_property,
+ const short operation,
+ const char *subitem_refname,
+ const char *subitem_locname,
+ const int subitem_refindex,
+ const int subitem_locindex,
+ const bool strict,
+ bool *r_strict,
+ bool *r_created);
+void BKE_lib_override_library_property_operation_delete(
+ struct IDOverrideLibraryProperty *override_property,
+ struct IDOverrideLibraryPropertyOperation *override_property_operation);
+
+bool BKE_lib_override_library_status_check_local(struct Main *bmain, struct ID *local);
+bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct ID *local);
+
+bool BKE_lib_override_library_operations_create(struct Main *bmain,
+ struct ID *local,
+ const bool force_auto);
+void BKE_lib_override_library_main_operations_create(struct Main *bmain, const bool force_auto);
+
+void BKE_lib_override_library_update(struct Main *bmain, struct ID *local);
+void BKE_lib_override_library_main_update(struct Main *bmain);
+
+/* Storage (.blend file writing) part. */
+
+/* For now, we just use a temp main list. */
+typedef struct Main OverrideLibraryStorage;
+
+OverrideLibraryStorage *BKE_lib_override_library_operations_store_initialize(void);
+struct ID *BKE_lib_override_library_operations_store_start(
+ struct Main *bmain, OverrideLibraryStorage *override_storage, struct ID *local);
+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);
+
+#endif /* __BKE_LIB_OVERRIDE_H__ */
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_lib_query.h
index b959b55b1d6..36aa69bf795 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_lib_query.h
@@ -16,11 +16,23 @@
* The Original Code is Copyright (C) 2014 by Blender Foundation.
* All rights reserved.
*/
-#ifndef __BKE_LIBRARY_QUERY_H__
-#define __BKE_LIBRARY_QUERY_H__
+#ifndef __BKE_LIB_QUERY_H__
+#define __BKE_LIB_QUERY_H__
/** \file
* \ingroup bke
+ *
+ * API to perform operations over all ID pointers used by a given data-block.
+ *
+ * \note `BKE_lib_` files are for operations over data-blocks themselves, although they might
+ * alter Main as well (when creating/renaming/deleting an ID e.g.).
+ *
+ * \section Function Names
+ *
+ * \warning Descriptions below is ideal goal, current status of naming does not yet fully follow it
+ * (this is WIP).
+ *
+ * - `BKE_lib_query_` should be used for functions in that file.
*/
struct ID;
@@ -109,4 +121,4 @@ void BKE_library_ID_test_usages(struct Main *bmain,
void BKE_library_unused_linked_data_set_tag(struct Main *bmain, const bool do_init_tag);
void BKE_library_indirectly_used_data_tag_clear(struct Main *bmain);
-#endif /* __BKE_LIBRARY_QUERY_H__ */
+#endif /* __BKE_LIB_QUERY_H__ */
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index 784e1a570c5..6105662c5d3 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -13,12 +13,26 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BKE_LIBRARY_REMAP_H__
-#define __BKE_LIBRARY_REMAP_H__
+#ifndef __BKE_LIB_REMAP_H__
+#define __BKE_LIB_REMAP_H__
/** \file
* \ingroup bke
+ *
+ * API to perform remapping from one data-block pointer to another.
+ *
+ * \note `BKE_lib_` files are for operations over data-blocks themselves, although they might
+ * alter Main as well (when creating/renaming/deleting an ID e.g.).
+ *
+ * \section Function Names
+ *
+ * \warning Descriptions below is ideal goal, current status of naming does not yet fully follow it
+ * (this is WIP).
+ *
+ * - `BKE_lib_remap_libblock_` should be used for functions performing remapping.
+ * - `BKE_lib_remap_callback_` should be used for functions managing remapping callbacks.
*/
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -27,7 +41,7 @@ extern "C" {
struct wmWindowManager;
-/* BKE_libblock_free, delete are declared in BKE_library.h for convenience. */
+/* BKE_libblock_free, delete are declared in BKE_lib_id.h for convenience. */
/* Also IDRemap->flag. */
enum {
@@ -102,4 +116,4 @@ void BKE_library_callback_remap_editor_id_reference_set(
}
#endif
-#endif /* __BKE_LIBRARY_REMAP_H__ */
+#endif /* __BKE_LIB_REMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index c41cd50eba5..1324e4ebf90 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -21,237 +21,22 @@
/** \file
* \ingroup bke
+ *
+ * API to manage `Library` data-blocks.
*/
+
#ifdef __cplusplus
extern "C" {
#endif
#include "BLI_compiler_attrs.h"
-/**
- * Naming: BKE_id_ vs BKE_libblock_
- *
- * WARNING: description below is ideal goal, current status of naming does not yet
- * fully follow it (this is WIP).
- *
- * - BKE_id_ should be used for rather high-level operations, that involve Main database and
- * relations with other IDs, and can be considered as 'safe'
- * (as in, in themselves, they leave affected IDs/Main in a consistent status).
- *
- * - BKE_libblock_ should be used for lower level operations,
- * that perform some parts of BKE_id_ ones, but will generally not ensure caller that affected
- * data is in a consistent state by their own execution alone.
- *
- * Consequently, external code should not typically use BKE_libblock_ functions,
- * except in some specific cases requiring advanced (and potentially dangerous) handling.
- */
-
-struct GHash;
-struct ID;
struct Library;
-struct ListBase;
struct Main;
-struct PointerRNA;
-struct PropertyRNA;
-struct bContext;
-
-size_t BKE_libblock_get_alloc_info(short type, const char **name);
-void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT;
-void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag)
- ATTR_WARN_UNUSED_RESULT;
-void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
-
-void *BKE_id_new(struct Main *bmain, const short type, const char *name);
-void *BKE_id_new_nomain(const short type, const char *name);
-
-/**
- * New ID creation/copying options.
- */
-enum {
- /* *** Generic options (should be handled by all ID types copying, ID creation, etc.). *** */
- /** Create datablock outside of any main database -
- * similar to 'localize' functions of materials etc. */
- LIB_ID_CREATE_NO_MAIN = 1 << 0,
- /** Do not affect user refcount of datablocks used by new one
- * (which also gets zero usercount then).
- * Implies LIB_ID_CREATE_NO_MAIN. */
- LIB_ID_CREATE_NO_USER_REFCOUNT = 1 << 1,
- /** Assume given 'newid' already points to allocated memory for whole datablock
- * (ID + data) - USE WITH CAUTION!
- * Implies LIB_ID_CREATE_NO_MAIN. */
- LIB_ID_CREATE_NO_ALLOCATE = 1 << 2,
-
- /** Do not tag new ID for update in depsgraph. */
- LIB_ID_CREATE_NO_DEG_TAG = 1 << 8,
-
- /* *** Specific options to some ID types or usages. *** */
- /* *** May be ignored by unrelated ID copying functions. *** */
- /** Object only, needed by make_local code. */
- LIB_ID_COPY_NO_PROXY_CLEAR = 1 << 16,
- /** Do not copy preview data, when supported. */
- LIB_ID_COPY_NO_PREVIEW = 1 << 17,
- /** Copy runtime data caches. */
- LIB_ID_COPY_CACHES = 1 << 18,
- /** Don't copy id->adt, used by ID datablock localization routines. */
- LIB_ID_COPY_NO_ANIMDATA = 1 << 19,
- /** Mesh: Reference CD data layers instead of doing real copy - USE WITH CAUTION! */
- LIB_ID_COPY_CD_REFERENCE = 1 << 20,
-
- /* *** XXX Hackish/not-so-nice specific behaviors needed for some corner cases. *** */
- /* *** Ideally we should not have those, but we need them for now... *** */
- /** EXCEPTION! Deep-copy actions used by animdata of copied ID. */
- LIB_ID_COPY_ACTIONS = 1 << 24,
- /** Keep the library pointer when copying datablock outside of bmain. */
- LIB_ID_COPY_KEEP_LIB = 1 << 25,
- /** EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */
- LIB_ID_COPY_SHAPEKEY = 1 << 26,
-
- /* *** Helper 'defines' gathering most common flag sets. *** */
- /** Shapekeys are not real ID's, more like local data to geometry IDs... */
- LIB_ID_COPY_DEFAULT = LIB_ID_COPY_SHAPEKEY,
- /** Generate a local copy, outside of bmain, to work on (used by COW e.g.). */
- LIB_ID_COPY_LOCALIZE = LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT |
- LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_CACHES,
-};
-
-void BKE_libblock_copy_ex(struct Main *bmain,
- const struct ID *id,
- struct ID **r_newid,
- const int orig_flag);
-void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT
- ATTR_NONNULL();
-/* Special version. sued by datablock localization. */
-void *BKE_libblock_copy_for_localize(const struct ID *id);
-
-void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
-void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL();
-
-struct ID *BKE_libblock_find_name(struct Main *bmain,
- const short type,
- const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-/* library_remap.c (keep here since they're general functions) */
-/**
- * New freeing logic options.
- */
-enum {
- /* *** Generic options (should be handled by all ID types freeing). *** */
- /** Do not try to remove freed ID from given Main (passed Main may be NULL). */
- LIB_ID_FREE_NO_MAIN = 1 << 0,
- /**
- * Do not affect user refcount of datablocks used by freed one.
- * Implies LIB_ID_FREE_NO_MAIN.
- */
- LIB_ID_FREE_NO_USER_REFCOUNT = 1 << 1,
- /**
- * Assume freed ID datablock memory is managed elsewhere, do not free it
- * (still calls relevant ID type's freeing function though) - USE WITH CAUTION!
- * Implies LIB_ID_FREE_NO_MAIN.
- */
- LIB_ID_FREE_NOT_ALLOCATED = 1 << 2,
-
- /** Do not tag freed ID for update in depsgraph. */
- LIB_ID_FREE_NO_DEG_TAG = 1 << 8,
- /** Do not attempt to remove freed ID from UI data/notifiers/... */
- LIB_ID_FREE_NO_UI_USER = 1 << 9,
-};
-
-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();
-
-void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag);
-void BKE_id_free(struct Main *bmain, void *idv);
-
-void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
-
-void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
-void BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL();
-
-void BKE_libblock_management_main_add(struct Main *bmain, void *idv);
-void BKE_libblock_management_main_remove(struct Main *bmain, void *idv);
-
-void BKE_libblock_management_usercounts_set(struct Main *bmain, void *idv);
-void BKE_libblock_management_usercounts_clear(struct Main *bmain, void *idv);
-
-void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
-void id_lib_extern(struct ID *id);
-void id_lib_indirect_weak_link(struct ID *id);
-void BKE_library_filepath_set(struct Main *bmain, struct Library *lib, const char *filepath);
-void id_us_ensure_real(struct ID *id);
-void id_us_clear_real(struct ID *id);
-void id_us_plus_no_lib(struct ID *id);
-void id_us_plus(struct ID *id);
-void id_us_min(struct ID *id);
-void id_fake_user_set(struct ID *id);
-void id_fake_user_clear(struct ID *id);
-void BKE_id_clear_newpoin(struct ID *id);
-
-void BKE_id_make_local_generic(struct Main *bmain,
- struct ID *id,
- const bool id_in_mainlist,
- const bool lib_local);
-bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
-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);
-bool BKE_id_copy(struct Main *bmain, const struct ID *id, struct ID **newid);
-bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
-void BKE_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
-void id_sort_by_name(struct ListBase *lb, struct ID *id, struct ID *id_sorting_hint);
-void BKE_id_expand_local(struct Main *bmain, struct ID *id);
-void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id);
-
-bool BKE_id_new_name_validate(struct ListBase *lb, struct ID *id, const char *name)
- ATTR_NONNULL(1, 2);
-void id_clear_lib_data(struct Main *bmain, struct ID *id);
-void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_mainlist);
-
-/* Affect whole Main database. */
-void BKE_main_id_tag_idcode(struct Main *mainvar,
- const short type,
- const int tag,
- const bool value);
-void BKE_main_id_tag_listbase(struct ListBase *lb, const int tag, const bool value);
-void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value);
-
-void BKE_main_id_flag_listbase(struct ListBase *lb, const int flag, const bool value);
-void BKE_main_id_flag_all(struct Main *bmain, const int flag, const bool value);
-
-void BKE_main_id_clear_newpoins(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. */
-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. */
-void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id);
-void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const struct ID *id);
-
-char *BKE_id_to_unique_string_key(const struct ID *id);
void BKE_library_free(struct Library *lib);
-void BKE_library_make_local(struct Main *bmain,
- const struct Library *lib,
- struct GHash *old_to_new_ids,
- const bool untagged_only,
- const bool set_fake);
-
-void BKE_id_tag_set_atomic(struct ID *id, int tag);
-void BKE_id_tag_clear_atomic(struct ID *id, int tag);
-
-bool BKE_id_is_in_global_main(struct ID *id);
-
-void BKE_id_ordered_list(struct ListBase *ordered_lb, const struct ListBase *lb);
-void BKE_id_reorder(const struct ListBase *lb, struct ID *id, struct ID *relative, bool after);
-
-#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->tag & LIB_TAG_DOIT))
+void BKE_library_filepath_set(struct Main *bmain, struct Library *lib, const char *filepath);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h
deleted file mode 100644
index 5cffabd333f..00000000000
--- a/source/blender/blenkernel/BKE_library_override.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2016 by Blender Foundation.
- * All rights reserved.
- */
-
-#ifndef __BKE_LIBRARY_OVERRIDE_H__
-#define __BKE_LIBRARY_OVERRIDE_H__
-
-/** \file
- * \ingroup bke
- */
-
-struct ID;
-struct IDOverrideLibrary;
-struct IDOverrideLibraryProperty;
-struct IDOverrideLibraryPropertyOperation;
-struct Main;
-
-void BKE_override_library_enable(const bool do_enable);
-bool BKE_override_library_is_enabled(void);
-
-struct IDOverrideLibrary *BKE_override_library_init(struct ID *local_id, struct ID *reference_id);
-void BKE_override_library_copy(struct ID *dst_id, const struct ID *src_id);
-void BKE_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user);
-void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user);
-
-struct ID *BKE_override_library_create_from_id(struct Main *bmain,
- struct ID *reference_id,
- const bool do_tagged_remap);
-bool BKE_override_library_create_from_tag(struct Main *bmain);
-
-struct IDOverrideLibraryProperty *BKE_override_library_property_find(
- struct IDOverrideLibrary *override, const char *rna_path);
-struct IDOverrideLibraryProperty *BKE_override_library_property_get(
- struct IDOverrideLibrary *override, const char *rna_path, bool *r_created);
-void BKE_override_library_property_delete(struct IDOverrideLibrary *override,
- struct IDOverrideLibraryProperty *override_property);
-
-struct IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_find(
- struct IDOverrideLibraryProperty *override_property,
- const char *subitem_refname,
- const char *subitem_locname,
- const int subitem_refindex,
- const int subitem_locindex,
- const bool strict,
- bool *r_strict);
-struct IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_get(
- struct IDOverrideLibraryProperty *override_property,
- const short operation,
- const char *subitem_refname,
- const char *subitem_locname,
- const int subitem_refindex,
- const int subitem_locindex,
- const bool strict,
- bool *r_strict,
- bool *r_created);
-void BKE_override_library_property_operation_delete(
- struct IDOverrideLibraryProperty *override_property,
- struct IDOverrideLibraryPropertyOperation *override_property_operation);
-
-bool BKE_override_library_status_check_local(struct Main *bmain, struct ID *local);
-bool BKE_override_library_status_check_reference(struct Main *bmain, struct ID *local);
-
-bool BKE_override_library_operations_create(struct Main *bmain,
- struct ID *local,
- const bool force_auto);
-void BKE_main_override_library_operations_create(struct Main *bmain, const bool force_auto);
-
-void BKE_override_library_update(struct Main *bmain, struct ID *local);
-void BKE_main_override_library_update(struct Main *bmain);
-
-/* Storage (.blend file writing) part. */
-
-/* For now, we just use a temp main list. */
-typedef struct Main OverrideLibraryStorage;
-
-OverrideLibraryStorage *BKE_override_library_operations_store_initialize(void);
-struct ID *BKE_override_library_operations_store_start(struct Main *bmain,
- OverrideLibraryStorage *override_storage,
- struct ID *local);
-void BKE_override_library_operations_store_end(OverrideLibraryStorage *override_storage,
- struct ID *local);
-void BKE_override_library_operations_store_finalize(OverrideLibraryStorage *override_storage);
-
-#endif /* __BKE_LIBRARY_OVERRIDE_H__ */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index c48a9cad443..66cbe6d838f 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -22,13 +22,20 @@
/** \file
* \ingroup bke
* \section aboutmain Main struct
- * Main is the root of the 'database' of a Blender context. All data
- * is stuffed into lists, and all these lists are knotted to here. A
- * Blender file is not much more but a binary dump of these
- * lists. This list of lists is not serialized itself.
+ * Main is the root of the 'data-base' of a Blender context. All data is put into lists, and all
+ * these lists are stored here.
*
- * Oops... this should be a _types.h file.
+ * \note A Blender file is not much more than a binary dump of these lists. This list of lists is
+ * not serialized itself.
+ *
+ * \note `BKE_main` files are for operations over the Main database itself, or generating extra
+ * temp data to help working with it. Those should typically not affect the data-blocks themselves.
+ *
+ * \section Function Names
+ *
+ * - `BKE_main_` should be used for functions in that file.
*/
+
#include "DNA_listBase.h"
#include "BLI_compiler_attrs.h"
@@ -59,7 +66,7 @@ typedef struct MainIDRelationsEntry {
/* WARNING! for user_to_used,
* that pointer is really an ID** one, but for used_to_user, it’s only an ID* one! */
struct ID **id_pointer;
- int usage_flag; /* Using IDWALK_ enums, in BKE_library_query.h */
+ int usage_flag; /* Using IDWALK_ enums, in BKE_lib_query.h */
} MainIDRelationsEntry;
typedef struct MainIDRelations {
diff --git a/source/blender/blenkernel/BKE_library_idmap.h b/source/blender/blenkernel/BKE_main_idmap.h
index 0285699dea3..b411d34be47 100644
--- a/source/blender/blenkernel/BKE_library_idmap.h
+++ b/source/blender/blenkernel/BKE_main_idmap.h
@@ -13,11 +13,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BKE_LIBRARY_IDMAP_H__
-#define __BKE_LIBRARY_IDMAP_H__
+#ifndef __BKE_MAIN_IDMAP_H__
+#define __BKE_MAIN_IDMAP_H__
/** \file
* \ingroup bke
+ *
+ * API to generate and use a mapping from [ID type & name] to [id pointer], within a given Main
+ * data-base.
+ *
+ * \note `BKE_main` files are for operations over the Main database itself, or generating extra
+ * temp data to help working with it. Those should typically not affect the data-blocks themselves.
+ *
+ * \section Function Names
+ *
+ * - `BKE_main_idmap_` Should be used for functions in that file.
*/
#include "BLI_compiler_attrs.h"
@@ -42,4 +52,4 @@ struct ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_typemap,
const struct ID *id) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2);
-#endif /* __BKE_LIBRARY_IDMAP_H__ */
+#endif /* __BKE_MAIN_IDMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 570541eb990..d6934e8a7da 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -91,9 +91,7 @@ struct Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(
float (*vertexCos)[3],
const struct Mesh *me_settings);
-int poly_find_loop_from_vert(const struct MPoly *poly,
- const struct MLoop *loopstart,
- unsigned vert);
+int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert);
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const struct MLoop *mloop,
unsigned int vert,
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 1e549849989..2ff6f1f3652 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -20,14 +20,14 @@
* \ingroup bke
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "DNA_modifier_types.h" /* needed for all enum typdefs */
#include "BLI_compiler_attrs.h"
#include "BKE_customdata.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BMEditMesh;
struct CustomData_MeshMasks;
struct DepsNodeHandle;
@@ -161,7 +161,7 @@ typedef struct ModifierTypeInfo {
/* Copy instance data for this modifier type. Should copy all user
* level settings to the target modifier.
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void (*copyData)(const struct ModifierData *md, struct ModifierData *target, const int flag);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b599e1e1b2c..1c479c92ef5 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -387,7 +387,8 @@ struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntre
void ntreeUserIncrefID(struct bNodeTree *ntree);
void ntreeUserDecrefID(struct bNodeTree *ntree);
-struct bNodeTree *ntreeFromID(const struct ID *id);
+struct bNodeTree **BKE_ntree_ptr_from_id(struct ID *id);
+struct bNodeTree *ntreeFromID(struct ID *id);
struct ID *BKE_node_tree_find_owner_ID(struct Main *bmain, struct bNodeTree *ntree);
void ntreeMakeLocal(struct Main *bmain,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index db35fbde2c8..28e564f0fe2 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -194,10 +194,7 @@ bool paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, in
bool paint_is_bmesh_face_hidden(struct BMFace *f);
/* paint masks */
-float paint_grid_paint_mask(const struct GridPaintMask *gpm,
- unsigned level,
- unsigned x,
- unsigned y);
+float paint_grid_paint_mask(const struct GridPaintMask *gpm, uint level, uint x, uint y);
/* stroke related */
bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups,
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index bc312c7bb2b..2618bea74e6 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -211,9 +211,6 @@ struct SeqEffectHandle {
double BKE_sequencer_rendersize_to_scale_factor(int size);
struct ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int chanshown);
-struct ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context,
- float cfra,
- int chanshown);
struct ImBuf *BKE_sequencer_give_ibuf_direct(const SeqRenderData *context,
float cfra,
struct Sequence *seq);
@@ -221,9 +218,6 @@ struct ImBuf *BKE_sequencer_give_ibuf_seqbase(const SeqRenderData *context,
float cfra,
int chan_shown,
struct ListBase *seqbasep);
-void BKE_sequencer_give_ibuf_prefetch_request(const SeqRenderData *context,
- float cfra,
- int chan_shown);
/* **********************************************************************
* sequencer.c
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index c64d684de5a..11eb98054d5 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -56,9 +56,7 @@ struct MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(
struct MovieTracking *tracking);
/* matrices for constraints and drawing */
-void BKE_tracking_get_camera_object_matrix(struct Scene *scene,
- struct Object *ob,
- float mat[4][4]);
+void BKE_tracking_get_camera_object_matrix(struct Object *camera_object, float mat[4][4]);
void BKE_tracking_get_projection_matrix(struct MovieTracking *tracking,
struct MovieTrackingObject *object,
int framenr,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 0aa4f0fe677..f536b8d94fc 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -135,15 +135,17 @@ set(SRC
intern/lattice.c
intern/layer.c
intern/layer_utils.c
+ intern/lib_id.c
+ intern/lib_id_delete.c
+ intern/lib_override.c
+ intern/lib_query.c
+ intern/lib_remap.c
intern/library.c
- intern/library_idmap.c
- intern/library_override.c
- intern/library_query.c
- intern/library_remap.c
intern/light.c
intern/lightprobe.c
intern/linestyle.c
intern/main.c
+ intern/main_idmap.c
intern/mask.c
intern/mask_evaluate.c
intern/mask_rasterize.c
@@ -298,15 +300,16 @@ set(SRC
BKE_keyconfig.h
BKE_lattice.h
BKE_layer.h
+ BKE_lib_id.h
+ BKE_lib_override.h
+ BKE_lib_query.h
+ BKE_lib_remap.h
BKE_library.h
- BKE_library_idmap.h
- BKE_library_override.h
- BKE_library_query.h
- BKE_library_remap.h
BKE_light.h
BKE_lightprobe.h
BKE_linestyle.h
BKE_main.h
+ BKE_main_idmap.h
BKE_mask.h
BKE_material.h
BKE_mball.h
@@ -370,6 +373,7 @@ set(SRC
intern/CCGSubSurf_inline.h
intern/CCGSubSurf_intern.h
intern/data_transfer_intern.h
+ intern/lib_intern.h
intern/multires_inline.h
intern/pbvh_intern.h
intern/subdiv_converter.h
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index f9e7627a8dd..c04079bed22 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -48,7 +48,7 @@
#include "BKE_editmesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index b474e3f5ec5..97b6a7b2f40 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -50,7 +50,7 @@
#include "BKE_deform.h"
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -123,7 +123,7 @@ void BKE_action_free(bAction *act)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_action_copy_data(Main *UNUSED(bmain),
bAction *act_dst,
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index be6622e5d42..2f4d58a1992 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -55,7 +55,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_nla.h"
@@ -307,7 +307,7 @@ bool BKE_animdata_id_is_animated(const struct ID *id)
/**
* 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_library.h
+ * 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)
@@ -351,7 +351,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
/**
* \param flag: Control ID pointers management,
- * see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_library.h
+ * 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)
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index e4da10797ff..d4498017ffd 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -58,7 +58,7 @@
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -194,7 +194,7 @@ static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_armature_copy_data(Main *UNUSED(bmain),
bArmature *arm_dst,
@@ -1562,8 +1562,8 @@ static void armature_vert_task(void *__restrict userdata,
int deformed = 0;
unsigned int j;
for (j = dvert->totweight; j != 0; j--, dw++) {
- const int index = dw->def_nr;
- if (index >= 0 && index < data->defbase_tot && (pchan = data->defnrToPC[index])) {
+ const uint index = dw->def_nr;
+ if (index < data->defbase_tot && (pchan = data->defnrToPC[index])) {
float weight = dw->weight;
Bone *bone = pchan->bone;
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index 32c6f74dc2d..f78eefa0a27 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -41,7 +41,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_scene.h"
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 62173393256..d1188bdb220 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -50,7 +50,7 @@
#include "BKE_ipo.h"
#include "BKE_keyconfig.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 90b26f8c288..3743a340a53 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -66,6 +66,7 @@
#include "BLI_utildefines.h"
#include "BKE_font.h"
+#include "BKE_lib_id.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 4f98290874e..230fe831184 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -33,9 +33,9 @@
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_paint.h"
@@ -704,7 +704,7 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mo
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_brush_copy_data(Main *UNUSED(bmain),
Brush *brush_dst,
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 3b0f4d9c2aa..cfef2a7e8e7 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -39,7 +39,7 @@
#include "BKE_animsys.h"
#include "BKE_cachefile.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
@@ -192,7 +192,7 @@ void BKE_cachefile_free(CacheFile *cache_file)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_cachefile_copy_data(Main *UNUSED(bmain),
CacheFile *cache_file_dst,
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index f70c5bb99d6..77a7c9581ac 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -42,7 +42,7 @@
#include "BKE_camera.h"
#include "BKE_object.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -79,7 +79,7 @@ void *BKE_camera_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_camera_copy_data(Main *UNUSED(bmain),
Camera *cam_dst,
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index c1c3cc62f11..ba0f019e700 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -32,8 +32,8 @@
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_rigidbody.h"
@@ -196,7 +196,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_collection_copy_data(Main *bmain,
Collection *collection_dst,
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a17a09297c5..76acaf5c91c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -65,7 +65,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh_runtime.h"
#include "BKE_movieclip.h"
#include "BKE_object.h"
@@ -4557,9 +4557,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
MovieTracking *tracking;
MovieTrackingTrack *track;
MovieTrackingObject *tracking_object;
-
- Object *camob_eval = DEG_get_evaluated_object(depsgraph,
- data->camera ? data->camera : scene->camera);
+ Object *camob = data->camera ? data->camera : scene->camera;
float ctime = DEG_get_ctime(depsgraph);
float framenr;
@@ -4568,7 +4566,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
clip = scene->clip;
}
- if (!clip || !data->track[0] || !camob_eval) {
+ if (!clip || !data->track[0] || !camob) {
return;
}
@@ -4602,7 +4600,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
float imat[4][4];
- copy_m4_m4(mat, camob_eval->obmat);
+ copy_m4_m4(mat, camob->obmat);
BKE_tracking_camera_get_reconstructed_interpolate(
tracking, tracking_object, framenr, imat);
@@ -4613,7 +4611,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
}
else {
- BKE_tracking_get_camera_object_matrix(cob->scene, camob_eval, mat);
+ BKE_tracking_get_camera_object_matrix(camob, mat);
mul_m4_m4m4(cob->matrix, obmat, mat);
translate_m4(
@@ -4626,7 +4624,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp);
float len, d;
- BKE_object_where_is_calc_mat4(camob_eval, mat);
+ BKE_object_where_is_calc_mat4(camob, mat);
/* camera axis */
vec[0] = 0.0f;
@@ -4694,7 +4692,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
}
BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, camob_eval);
+ BKE_camera_params_from_object(&params, camob);
if (params.is_ortho) {
vec[0] = params.ortho_scale * (pos[0] - 0.5f + params.shiftx);
@@ -4708,9 +4706,9 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
vec[0] *= aspect;
}
- mul_v3_m4v3(disp, camob_eval->obmat, vec);
+ mul_v3_m4v3(disp, camob->obmat, vec);
- copy_m4_m4(rmat, camob_eval->obmat);
+ copy_m4_m4(rmat, camob->obmat);
zero_v3(rmat[3]);
mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
@@ -4730,10 +4728,10 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
vec[0] *= aspect;
}
- mul_v3_m4v3(disp, camob_eval->obmat, vec);
+ mul_v3_m4v3(disp, camob->obmat, vec);
/* apply camera rotation so Z-axis would be co-linear */
- copy_m4_m4(rmat, camob_eval->obmat);
+ copy_m4_m4(rmat, camob->obmat);
zero_v3(rmat[3]);
mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
@@ -4751,7 +4749,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
invert_m4_m4(imat, depth_ob->obmat);
- mul_v3_m4v3(ray_start, imat, camob_eval->obmat[3]);
+ mul_v3_m4v3(ray_start, imat, camob->obmat[3]);
mul_v3_m4v3(ray_end, imat, cob->matrix[3]);
sub_v3_v3v3(ray_nor, ray_end, ray_start);
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 85b58da61de..e0abe836bf8 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -39,7 +39,7 @@
#include "BKE_multires.h"
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "DEG_depsgraph_query.h"
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 8246c3d9ff4..fab212f0944 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -49,7 +49,7 @@
#include "BKE_displist.h"
#include "BKE_font.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_material.h"
@@ -189,7 +189,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 79dcdd15bf7..41ff9594cff 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -255,10 +255,9 @@ void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
unsigned int i;
for (i = dvert->totweight; i != 0; i--, dw++) {
if (dw->def_nr < map_len) {
- dw->def_nr = map[dw->def_nr];
+ BLI_assert(map[dw->def_nr] >= 0);
- /* just in case */
- BLI_assert(dw->def_nr >= 0);
+ dw->def_nr = map[dw->def_nr];
}
}
}
@@ -337,7 +336,7 @@ void defvert_normalize(MDeformVert *dvert)
void defvert_normalize_lock_single(MDeformVert *dvert,
const bool *vgroup_subset,
const int vgroup_tot,
- const int def_nr_lock)
+ const uint def_nr_lock)
{
if (dvert->totweight == 0) {
/* nothing */
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 46f6a604eaa..fc310ee720a 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -43,7 +43,7 @@
#include "BKE_displist.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_object.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mball.h"
#include "BKE_mball_tessellate.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index a70e5b67a15..48c5aff721d 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -58,7 +58,7 @@
#include "BKE_dynamicpaint.h"
#include "BKE_effect.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 9b67a4fb925..4c076256d9f 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -31,7 +31,7 @@
#include "BKE_editmesh.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
#include "BKE_object.h"
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 833b8409f7d..251c6421d66 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -204,29 +204,31 @@ FCurve *id_data_find_fcurve(
RNA_pointer_create(id, type, data, &ptr);
prop = RNA_struct_find_property(&ptr, prop_name);
+ if (prop == NULL) {
+ return NULL;
+ }
- if (prop) {
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- if (path) {
- /* animation takes priority over drivers */
- if ((adt->action) && (adt->action->curves.first)) {
- fcu = list_find_fcurve(&adt->action->curves, path, index);
- }
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+ if (path == NULL) {
+ return NULL;
+ }
- /* if not animated, check if driven */
- if ((fcu == NULL) && (adt->drivers.first)) {
- fcu = list_find_fcurve(&adt->drivers, path, index);
- if (fcu && r_driven) {
- *r_driven = true;
- }
- fcu = NULL;
- }
+ /* animation takes priority over drivers */
+ if (adt->action && adt->action->curves.first) {
+ fcu = list_find_fcurve(&adt->action->curves, path, index);
+ }
- MEM_freeN(path);
+ /* if not animated, check if driven */
+ if (fcu == NULL && adt->drivers.first) {
+ fcu = list_find_fcurve(&adt->drivers, path, index);
+ if (fcu && r_driven) {
+ *r_driven = true;
}
+ fcu = NULL;
}
+ MEM_freeN(path);
+
return fcu;
}
@@ -309,26 +311,28 @@ int list_find_data_fcurves(ListBase *dst,
/* search each F-Curve one by one */
for (fcu = src->first; fcu; fcu = fcu->next) {
/* check if quoted string matches the path */
- if ((fcu->rna_path) && strstr(fcu->rna_path, dataPrefix)) {
- char *quotedName = BLI_str_quoted_substrN(fcu->rna_path, dataPrefix);
+ if (fcu->rna_path == NULL || !strstr(fcu->rna_path, dataPrefix)) {
+ continue;
+ }
- if (quotedName) {
- /* check if the quoted name matches the required name */
- if (STREQ(quotedName, dataName)) {
- LinkData *ld = MEM_callocN(sizeof(LinkData), __func__);
+ char *quotedName = BLI_str_quoted_substrN(fcu->rna_path, dataPrefix);
+ if (quotedName == NULL) {
+ continue;
+ }
- ld->data = fcu;
- BLI_addtail(dst, ld);
+ /* check if the quoted name matches the required name */
+ if (STREQ(quotedName, dataName)) {
+ LinkData *ld = MEM_callocN(sizeof(LinkData), __func__);
- matches++;
- }
+ ld->data = fcu;
+ BLI_addtail(dst, ld);
- /* always free the quoted string, since it needs freeing */
- MEM_freeN(quotedName);
- }
+ matches++;
}
- }
+ /* always free the quoted string, since it needs freeing */
+ MEM_freeN(quotedName);
+ }
/* return the number of matches */
return matches;
}
@@ -397,53 +401,58 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
/* Standard F-Curve - Animation (Action) or Drivers */
while (adt && step--) {
- if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
- /* XXX this function call can become a performance bottleneck */
- if (step) {
- path = RNA_path_from_ID_to_property(&tptr, prop);
- }
+ if ((adt->action == NULL || adt->action->curves.first == NULL) &&
+ (adt->drivers.first == NULL)) {
+ continue;
+ }
- // XXX: the logic here is duplicated with a function up above
- if (path) {
- /* animation takes priority over drivers */
- if (adt->action && adt->action->curves.first) {
- fcu = list_find_fcurve(&adt->action->curves, path, rnaindex);
+ /* XXX this function call can become a performance bottleneck */
+ if (step) {
+ path = RNA_path_from_ID_to_property(&tptr, prop);
+ }
+ if (path == NULL) {
+ continue;
+ }
- if (fcu && r_action) {
- *r_action = adt->action;
- }
- }
+ // XXX: the logic here is duplicated with a function up above
+ /* animation takes priority over drivers */
+ if (adt->action && adt->action->curves.first) {
+ fcu = list_find_fcurve(&adt->action->curves, path, rnaindex);
- /* if not animated, check if driven */
- if (!fcu && (adt->drivers.first)) {
- fcu = list_find_fcurve(&adt->drivers, path, rnaindex);
+ if (fcu && r_action) {
+ *r_action = adt->action;
+ }
+ }
- if (fcu) {
- if (r_animdata) {
- *r_animdata = adt;
- }
- *r_driven = true;
- }
- }
+ /* if not animated, check if driven */
+ if (!fcu && (adt->drivers.first)) {
+ fcu = list_find_fcurve(&adt->drivers, path, rnaindex);
- if (fcu && r_action) {
- if (r_animdata) {
- *r_animdata = adt;
- }
- *r_action = adt->action;
- break;
- }
- else if (step) {
- char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path);
- if (tpath && tpath != path) {
- MEM_freeN(path);
- path = tpath;
- adt = BKE_animdata_from_id(tptr.owner_id);
- }
- else {
- adt = NULL;
- }
+ if (fcu) {
+ if (r_animdata) {
+ *r_animdata = adt;
}
+ *r_driven = true;
+ }
+ }
+
+ if (fcu && r_action) {
+ if (r_animdata) {
+ *r_animdata = adt;
+ }
+ *r_action = adt->action;
+ break;
+ }
+
+ if (step) {
+ char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path);
+ if (tpath && tpath != path) {
+ MEM_freeN(path);
+ path = tpath;
+ adt = BKE_animdata_from_id(tptr.owner_id);
+ }
+ else {
+ adt = NULL;
}
}
}
@@ -476,29 +485,28 @@ static int binarysearch_bezt_index_ex(
CLOG_WARN(&LOG, "encountered invalid array");
return 0;
}
- else {
- /* check whether to add before/after/on */
- float framenum;
- /* 'First' Keyframe (when only one keyframe, this case is used) */
- framenum = array[0].vec[1][0];
- if (IS_EQT(frame, framenum, threshold)) {
- *r_replace = true;
- return 0;
- }
- else if (frame < framenum) {
- return 0;
- }
+ /* check whether to add before/after/on */
+ float framenum;
- /* 'Last' Keyframe */
- framenum = array[(arraylen - 1)].vec[1][0];
- if (IS_EQT(frame, framenum, threshold)) {
- *r_replace = true;
- return (arraylen - 1);
- }
- else if (frame > framenum) {
- return arraylen;
- }
+ /* 'First' Keyframe (when only one keyframe, this case is used) */
+ framenum = array[0].vec[1][0];
+ if (IS_EQT(frame, framenum, threshold)) {
+ *r_replace = true;
+ return 0;
+ }
+ if (frame < framenum) {
+ return 0;
+ }
+
+ /* 'Last' Keyframe */
+ framenum = array[(arraylen - 1)].vec[1][0];
+ if (IS_EQT(frame, framenum, threshold)) {
+ *r_replace = true;
+ return (arraylen - 1);
+ }
+ if (frame > framenum) {
+ return arraylen;
}
/* most of the time, this loop is just to find where to put it
@@ -1171,41 +1179,42 @@ void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_ha
*/
void sort_time_fcurve(FCurve *fcu)
{
+ if (fcu->bezt == NULL) {
+ return;
+ }
/* keep adjusting order of beztriples until nothing moves (bubble-sort) */
- if (fcu->bezt) {
- BezTriple *bezt;
- uint a;
-
- bool ok = true;
- while (ok) {
- ok = 0;
- /* currently, will only be needed when there are beztriples */
-
- /* loop over ALL points to adjust position in array and recalculate handles */
- for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
- /* check if thee's a next beztriple which we could try to swap with current */
- if (a < (fcu->totvert - 1)) {
- /* swap if one is after the other (and indicate that order has changed) */
- if (bezt->vec[1][0] > (bezt + 1)->vec[1][0]) {
- SWAP(BezTriple, *bezt, *(bezt + 1));
- ok = 1;
- }
+ BezTriple *bezt;
+ uint a;
+
+ bool ok = true;
+ while (ok) {
+ ok = 0;
+ /* currently, will only be needed when there are beztriples */
+
+ /* loop over ALL points to adjust position in array and recalculate handles */
+ for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
+ /* check if thee's a next beztriple which we could try to swap with current */
+ if (a < (fcu->totvert - 1)) {
+ /* swap if one is after the other (and indicate that order has changed) */
+ if (bezt->vec[1][0] > (bezt + 1)->vec[1][0]) {
+ SWAP(BezTriple, *bezt, *(bezt + 1));
+ ok = 1;
}
}
}
+ }
- for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
- /* if either one of both of the points exceeds crosses over the keyframe time... */
- if ((bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0])) {
- /* swap handles if they have switched sides for some reason */
- swap_v2_v2(bezt->vec[0], bezt->vec[2]);
- }
- else {
- /* clamp handles */
- CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);
- CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]);
- }
+ for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
+ /* if either one of both of the points exceeds crosses over the keyframe time... */
+ if ((bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0])) {
+ /* swap handles if they have switched sides for some reason */
+ swap_v2_v2(bezt->vec[0], bezt->vec[2]);
+ }
+ else {
+ /* clamp handles */
+ CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);
+ CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]);
}
}
}
@@ -1311,60 +1320,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
RNA_id_pointer_create(id, &id_ptr);
/* get property to read from, and get value as appropriate */
- if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
- if (RNA_property_array_check(prop)) {
- /* array */
- if ((index >= 0) && (index < RNA_property_array_length(&ptr, prop))) {
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- value = (float)RNA_property_boolean_get_index(&ptr, prop, index);
- break;
- case PROP_INT:
- value = (float)RNA_property_int_get_index(&ptr, prop, index);
- break;
- case PROP_FLOAT:
- value = RNA_property_float_get_index(&ptr, prop, index);
- break;
- default:
- break;
- }
- }
- else {
- /* out of bounds */
- if (G.debug & G_DEBUG) {
- CLOG_ERROR(&LOG,
- "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
- id->name,
- dtar->rna_path,
- index);
- }
-
- driver->flag |= DRIVER_FLAG_INVALID;
- dtar->flag |= DTAR_FLAG_INVALID;
- return 0.0f;
- }
- }
- else {
- /* not an array */
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- value = (float)RNA_property_boolean_get(&ptr, prop);
- break;
- case PROP_INT:
- value = (float)RNA_property_int_get(&ptr, prop);
- break;
- case PROP_FLOAT:
- value = RNA_property_float_get(&ptr, prop);
- break;
- case PROP_ENUM:
- value = (float)RNA_property_enum_get(&ptr, prop);
- break;
- default:
- break;
- }
- }
- }
- else {
+ if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
/* path couldn't be resolved */
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG,
@@ -1378,6 +1334,57 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return 0.0f;
}
+ if (RNA_property_array_check(prop)) {
+ /* array */
+ if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) {
+ /* out of bounds */
+ if (G.debug & G_DEBUG) {
+ CLOG_ERROR(&LOG,
+ "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
+ id->name,
+ dtar->rna_path,
+ index);
+ }
+
+ driver->flag |= DRIVER_FLAG_INVALID;
+ dtar->flag |= DTAR_FLAG_INVALID;
+ return 0.0f;
+ }
+
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ value = (float)RNA_property_boolean_get_index(&ptr, prop, index);
+ break;
+ case PROP_INT:
+ value = (float)RNA_property_int_get_index(&ptr, prop, index);
+ break;
+ case PROP_FLOAT:
+ value = RNA_property_float_get_index(&ptr, prop, index);
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ /* not an array */
+ switch (RNA_property_type(prop)) {
+ case PROP_BOOLEAN:
+ value = (float)RNA_property_boolean_get(&ptr, prop);
+ break;
+ case PROP_INT:
+ value = (float)RNA_property_int_get(&ptr, prop);
+ break;
+ case PROP_FLOAT:
+ value = RNA_property_float_get(&ptr, prop);
+ break;
+ case PROP_ENUM:
+ value = (float)RNA_property_enum_get(&ptr, prop);
+ break;
+ default:
+ break;
+ }
+ }
+
/* if we're still here, we should be ok... */
dtar->flag &= ~DTAR_FLAG_INVALID;
return value;
@@ -2347,6 +2354,98 @@ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
return dvar->curval;
}
+static void evaluate_driver_sum(ChannelDriver *driver)
+{
+ DriverVar *dvar;
+
+ /* check how many variables there are first (i.e. just one?) */
+ if (BLI_listbase_is_single(&driver->variables)) {
+ /* just one target, so just use that */
+ dvar = driver->variables.first;
+ driver->curval = driver_get_variable_value(driver, dvar);
+ return;
+ }
+
+ /* more than one target, so average the values of the targets */
+ float value = 0.0f;
+ int tot = 0;
+
+ /* loop through targets, adding (hopefully we don't get any overflow!) */
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ value += driver_get_variable_value(driver, dvar);
+ tot++;
+ }
+
+ /* perform operations on the total if appropriate */
+ if (driver->type == DRIVER_TYPE_AVERAGE) {
+ driver->curval = tot ? (value / (float)tot) : 0.0f;
+ }
+ else {
+ driver->curval = value;
+ }
+}
+
+static void evaluate_driver_min_max(ChannelDriver *driver)
+{
+ DriverVar *dvar;
+ float value = 0.0f;
+
+ /* loop through the variables, getting the values and comparing them to existing ones */
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ /* get value */
+ float tmp_val = driver_get_variable_value(driver, dvar);
+
+ /* store this value if appropriate */
+ if (dvar->prev) {
+ /* check if greater/smaller than the baseline */
+ if (driver->type == DRIVER_TYPE_MAX) {
+ /* max? */
+ if (tmp_val > value) {
+ value = tmp_val;
+ }
+ }
+ else {
+ /* min? */
+ if (tmp_val < value) {
+ value = tmp_val;
+ }
+ }
+ }
+ else {
+ /* first item - make this the baseline for comparisons */
+ value = tmp_val;
+ }
+ }
+
+ /* store value in driver */
+ driver->curval = value;
+}
+
+static void evaluate_driver_python(PathResolvedRNA *anim_rna,
+ ChannelDriver *driver,
+ ChannelDriver *driver_orig,
+ const float evaltime)
+{
+ /* check for empty or invalid expression */
+ if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) {
+ driver->curval = 0.0f;
+ }
+ else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) {
+#ifdef WITH_PYTHON
+ /* this evaluates the expression using Python, and returns its result:
+ * - on errors it reports, then returns 0.0f
+ */
+ BLI_mutex_lock(&python_driver_lock);
+
+ driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime);
+
+ BLI_mutex_unlock(&python_driver_lock);
+#else /* WITH_PYTHON*/
+ UNUSED_VARS(anim_rna, evaltime);
+#endif /* WITH_PYTHON*/
+ }
+}
+
/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime"
* - "evaltime" is the frame at which F-Curve is being evaluated
* - has to return a float value
@@ -2357,8 +2456,6 @@ float evaluate_driver(PathResolvedRNA *anim_rna,
ChannelDriver *driver_orig,
const float evaltime)
{
- DriverVar *dvar;
-
/* check if driver can be evaluated */
if (driver_orig->flag & DRIVER_FLAG_INVALID) {
return 0.0f;
@@ -2367,99 +2464,21 @@ float evaluate_driver(PathResolvedRNA *anim_rna,
switch (driver->type) {
case DRIVER_TYPE_AVERAGE: /* average values of driver targets */
case DRIVER_TYPE_SUM: /* sum values of driver targets */
- {
- /* check how many variables there are first (i.e. just one?) */
- if (BLI_listbase_is_single(&driver->variables)) {
- /* just one target, so just use that */
- dvar = driver->variables.first;
- driver->curval = driver_get_variable_value(driver, dvar);
- }
- else {
- /* more than one target, so average the values of the targets */
- float value = 0.0f;
- int tot = 0;
-
- /* loop through targets, adding (hopefully we don't get any overflow!) */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- value += driver_get_variable_value(driver, dvar);
- tot++;
- }
-
- /* perform operations on the total if appropriate */
- if (driver->type == DRIVER_TYPE_AVERAGE) {
- driver->curval = tot ? (value / (float)tot) : 0.0f;
- }
- else {
- driver->curval = value;
- }
- }
+ evaluate_driver_sum(driver);
break;
- }
case DRIVER_TYPE_MIN: /* smallest value */
case DRIVER_TYPE_MAX: /* largest value */
- {
- float value = 0.0f;
-
- /* loop through the variables, getting the values and comparing them to existing ones */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* get value */
- float tmp_val = driver_get_variable_value(driver, dvar);
-
- /* store this value if appropriate */
- if (dvar->prev) {
- /* check if greater/smaller than the baseline */
- if (driver->type == DRIVER_TYPE_MAX) {
- /* max? */
- if (tmp_val > value) {
- value = tmp_val;
- }
- }
- else {
- /* min? */
- if (tmp_val < value) {
- value = tmp_val;
- }
- }
- }
- else {
- /* first item - make this the baseline for comparisons */
- value = tmp_val;
- }
- }
-
- /* store value in driver */
- driver->curval = value;
+ evaluate_driver_min_max(driver);
break;
- }
case DRIVER_TYPE_PYTHON: /* expression */
- {
- /* check for empty or invalid expression */
- if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) {
- driver->curval = 0.0f;
- }
- else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) {
-#ifdef WITH_PYTHON
- /* this evaluates the expression using Python, and returns its result:
- * - on errors it reports, then returns 0.0f
- */
- BLI_mutex_lock(&python_driver_lock);
-
- driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime);
-
- BLI_mutex_unlock(&python_driver_lock);
-#else /* WITH_PYTHON*/
- UNUSED_VARS(anim_rna, evaltime);
-#endif /* WITH_PYTHON*/
- }
+ evaluate_driver_python(anim_rna, driver, driver_orig, evaltime);
break;
- }
- default: {
+ default:
/* special 'hack' - just use stored value
* This is currently used as the mechanism which allows animated settings to be able
* to be changed via the UI.
*/
break;
- }
}
/* return value for driver */
@@ -2539,11 +2558,10 @@ static int findzero(float x, float q0, float q1, float q2, float q3, float *o)
if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
return 1;
}
- else {
- return 0;
- }
+ return 0;
}
- else if (d == 0.0) {
+
+ if (d == 0.0) {
t = sqrt3d(-q);
o[0] = (float)(2 * t - a);
@@ -2555,87 +2573,78 @@ static int findzero(float x, float q0, float q1, float q2, float q3, float *o)
if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
return nr + 1;
}
- else {
- return nr;
- }
+ return nr;
}
- else {
- phi = acos(-q / sqrt(-(p * p * p)));
- t = sqrt(-p);
- p = cos(phi / 3);
- q = sqrt(3 - 3 * p * p);
- o[0] = (float)(2 * t * p - a);
- if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
- nr++;
- }
- o[nr] = (float)(-t * (p + q) - a);
+ phi = acos(-q / sqrt(-(p * p * p)));
+ t = sqrt(-p);
+ p = cos(phi / 3);
+ q = sqrt(3 - 3 * p * p);
+ o[0] = (float)(2 * t * p - a);
- if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
- nr++;
- }
- o[nr] = (float)(-t * (p - q) - a);
+ if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
+ nr++;
+ }
+ o[nr] = (float)(-t * (p + q) - a);
- if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
- return nr + 1;
- }
- else {
- return nr;
- }
+ if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
+ nr++;
}
+ o[nr] = (float)(-t * (p - q) - a);
+
+ if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
+ return nr + 1;
+ }
+ return nr;
}
- else {
- a = c2;
- b = c1;
- c = c0;
+ a = c2;
+ b = c1;
+ c = c0;
- if (a != 0.0) {
- /* discriminant */
- p = b * b - 4 * a * c;
+ if (a != 0.0) {
+ /* discriminant */
+ p = b * b - 4 * a * c;
- if (p > 0) {
- p = sqrt(p);
- o[0] = (float)((-b - p) / (2 * a));
+ if (p > 0) {
+ p = sqrt(p);
+ o[0] = (float)((-b - p) / (2 * a));
- if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
- nr++;
- }
- o[nr] = (float)((-b + p) / (2 * a));
-
- if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
- return nr + 1;
- }
- else {
- return nr;
- }
+ if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
+ nr++;
}
- else if (p == 0) {
- o[0] = (float)(-b / (2 * a));
- if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
- return 1;
- }
- else {
- return 0;
- }
+ o[nr] = (float)((-b + p) / (2 * a));
+
+ if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) {
+ return nr + 1;
}
+ return nr;
}
- else if (b != 0.0) {
- o[0] = (float)(-c / b);
+ if (p == 0) {
+ o[0] = (float)(-b / (2 * a));
if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
return 1;
}
- else {
- return 0;
- }
}
- else if (c == 0.0) {
- o[0] = 0.0;
+
+ return 0;
+ }
+
+ if (b != 0.0) {
+ o[0] = (float)(-c / b);
+
+ if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) {
return 1;
}
-
return 0;
}
+
+ if (c == 0.0) {
+ o[0] = 0.0;
+ return 1;
+ }
+
+ return 0;
}
static void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
@@ -3244,19 +3253,18 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
/* only calculate + set curval (overriding the existing value) if curve has
* any data which warrants this...
*/
- if (!BKE_fcurve_is_empty(fcu)) {
- /* calculate and set curval (evaluates driver too if necessary) */
- float curval;
- if (fcu->driver) {
- curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime);
- }
- else {
- curval = evaluate_fcurve(fcu, evaltime);
- }
- fcu->curval = curval; /* debug display only, not thread safe! */
- return curval;
+ if (BKE_fcurve_is_empty(fcu)) {
+ return 0.0f;
+ }
+
+ /* calculate and set curval (evaluates driver too if necessary) */
+ float curval;
+ if (fcu->driver) {
+ curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime);
}
else {
- return 0.0f;
+ curval = evaluate_fcurve(fcu, evaltime);
}
+ fcu->curval = curval; /* debug display only, not thread safe! */
+ return curval;
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index f35aebbae16..d38541c8bbe 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -38,7 +38,7 @@
#include "BKE_effect.h"
#include "BKE_fluid.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
@@ -632,7 +632,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
/* Distance between two opposing vertices in a unit cube.
* I.e. the unit cube diagonal or sqrt(3).
- * This value is our nearest neighbour search distance. */
+ * This value is our nearest neighbor search distance. */
const float surface_distance = 1.732;
for (int x = mds->res_min[0]; x < mds->res_max[0]; x++) {
@@ -2219,7 +2219,7 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
}
/* Set emission value for smoke inflow.
- * Ensure that emission value is "maximised". */
+ * Ensure that emission value is "maximized". */
if (emission_in) {
emission_in[index] = MAX2(emission_value, emission_in[index]);
}
@@ -3239,7 +3239,6 @@ static void manta_guiding(
FluidDomainSettings *mds = mmd->domain;
float fps = scene->r.frs_sec / scene->r.frs_sec_base;
float dt = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
- ;
BLI_mutex_lock(&object_update_lock);
@@ -3325,15 +3324,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
BKE_fluid_modifier_reset_ex(mmd, false);
}
- BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
-
- /* ensure that time parameters are initialized correctly before every step */
- float fps = scene->r.frs_sec / scene->r.frs_sec_base;
- mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
- mds->dt = mds->frame_length;
- mds->time_per_frame = 0;
- mds->time_total = (scene_framenr - 1) * mds->frame_length;
-
/* Guiding parent res pointer needs initialization */
guide_parent = mds->guide_parent;
if (guide_parent) {
@@ -3343,6 +3333,15 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
}
}
+ BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
+
+ /* ensure that time parameters are initialized correctly before every step */
+ float fps = scene->r.frs_sec / scene->r.frs_sec_base;
+ mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
+ mds->dt = mds->frame_length;
+ mds->time_per_frame = 0;
+ mds->time_total = (scene_framenr - 1) * mds->frame_length;
+
objs = BKE_collision_objects_create(
depsgraph, ob, mds->fluid_group, &numobj, eModifierType_Fluid);
update_flowsflags(mds, objs, numobj);
@@ -3403,7 +3402,8 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
resume_guide = (!is_startframe) && (mds->cache_frame_pause_guide == scene_framenr);
bool read_cache, bake_cache;
- read_cache = false, bake_cache = baking_data || baking_noise || baking_mesh || baking_particles;
+ read_cache = false;
+ bake_cache = baking_data || baking_noise || baking_mesh || baking_particles || baking_guide;
bool with_gdomain;
with_gdomain = (mds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
@@ -3419,14 +3419,14 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
switch (mode) {
case FLUID_DOMAIN_CACHE_FINAL:
/* Just load the data that has already been baked */
- if (!baking_data && !baking_noise && !baking_mesh && !baking_particles) {
+ if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
read_cache = true;
bake_cache = false;
}
break;
case FLUID_DOMAIN_CACHE_MODULAR:
/* Just load the data that has already been baked */
- if (!baking_data && !baking_noise && !baking_mesh && !baking_particles) {
+ if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
read_cache = true;
bake_cache = false;
break;
@@ -3505,10 +3505,14 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
manta_needs_realloc(mds->fluid, mmd)) {
BKE_fluid_reallocate_fluid(mds, mds->res, 1);
}
- has_noise = manta_read_noise(mds->fluid, mmd, noise_frame);
+ if (!baking_data && !baking_noise && !mode_replay) {
+ has_data = manta_update_noise_structures(mds->fluid, mmd, noise_frame);
+ }
+ else {
+ has_noise = manta_read_noise(mds->fluid, mmd, noise_frame);
+ }
- /* In case of using the adaptive domain, copy all data that was read to a new fluid object.
- */
+ /* When using the adaptive domain, copy all data that was read to a new fluid object. */
if (with_adaptive && baking_noise) {
/* Adaptive domain needs to know about current state, so save it, then copy. */
copy_v3_v3_int(o_res, mds->res);
@@ -3521,7 +3525,13 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift);
}
}
- has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ if (!baking_data && !baking_noise && !mode_replay) {
+ /* TODO (sebbas): Confirm if this read call is really needed or not. */
+ has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame);
+ }
+ else {
+ has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ }
}
/* Read data cache only */
else {
@@ -3532,7 +3542,12 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
BKE_fluid_reallocate_fluid(mds, mds->res, 1);
}
/* Read data cache */
- has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) {
+ has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame);
+ }
+ else {
+ has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ }
}
if (with_liquid) {
if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) {
@@ -4433,9 +4448,15 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
mmd->domain->cache_flag = 0;
mmd->domain->cache_type = FLUID_DOMAIN_CACHE_MODULAR;
mmd->domain->cache_mesh_format = FLUID_DOMAIN_FILE_BIN_OBJECT;
+#ifdef WITH_OPENVDB
mmd->domain->cache_data_format = FLUID_DOMAIN_FILE_OPENVDB;
mmd->domain->cache_particle_format = FLUID_DOMAIN_FILE_OPENVDB;
mmd->domain->cache_noise_format = FLUID_DOMAIN_FILE_OPENVDB;
+#else
+ mmd->domain->cache_data_format = FLUID_DOMAIN_FILE_UNI;
+ mmd->domain->cache_particle_format = FLUID_DOMAIN_FILE_UNI;
+ mmd->domain->cache_noise_format = FLUID_DOMAIN_FILE_UNI;
+#endif
modifier_path_init(mmd->domain->cache_directory,
sizeof(mmd->domain->cache_directory),
FLUID_DOMAIN_DIR_DEFAULT);
@@ -4540,7 +4561,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
mmd->effector->flags = 0;
/* guide options */
- mmd->effector->guide_mode = FLUID_EFFECTOR_GUIDE_MAX;
+ mmd->effector->guide_mode = FLUID_EFFECTOR_GUIDE_OVERRIDE;
mmd->effector->vel_multi = 1.0f;
}
}
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 47b6fbfb4f8..3d840c6232c 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -47,7 +47,7 @@
#include "DNA_object_types.h"
#include "BKE_packedFile.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_main.h"
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 19c5012dc54..aa3b4f1ef5e 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -31,7 +31,7 @@
#include "BLI_string_utils.h"
#include "BKE_freestyle.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_linestyle.h"
// function declarations
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index db137d26005..e3d6e73e8c9 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -55,7 +55,7 @@
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_icons.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
@@ -647,7 +647,7 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
{
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 181cb2d38a9..ebb927a7d60 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -39,8 +39,8 @@
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_gpencil.h"
#include "BKE_lattice.h"
#include "BKE_material.h"
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index e3b27236616..e5b710b3619 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -32,7 +32,7 @@
#include "BLI_math.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "CLG_log.h"
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index be354b04157..ebe90072f63 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -71,7 +71,7 @@
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -417,7 +417,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index adf5d55efaa..f84d0681dad 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -63,7 +63,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_sequencer.h"
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 6e8677b5422..6bc494ae3ee 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -48,7 +48,7 @@
#include "BKE_deform.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
@@ -158,7 +158,7 @@ Key *BKE_key_add(Main *bmain, ID *id) /* common function */
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_key_copy_data(Main *UNUSED(bmain),
Key *key_dst,
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 243c63a8f03..ebfffc8279d 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -50,7 +50,7 @@
#include "BKE_displist.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -274,7 +274,7 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_lattice_copy_data(Main *bmain, Lattice *lt_dst, const Lattice *lt_src, const int flag)
{
@@ -783,7 +783,7 @@ void curve_deform_verts(Object *cuOb,
if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = invert_vgroup? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) :
+ const float weight = invert_vgroup ? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) :
defvert_find_weight(dvert_iter, defgrp_index);
if (weight > 0.0f) {
@@ -800,7 +800,7 @@ void curve_deform_verts(Object *cuOb,
INIT_MINMAX(cd.dmin, cd.dmax);
for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = invert_vgroup? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) :
+ const float weight = invert_vgroup ? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) :
defvert_find_weight(dvert_iter, defgrp_index);
if (weight > 0.0f) {
mul_m4_v3(cd.curvespace, vert_coords[a]);
@@ -809,7 +809,7 @@ void curve_deform_verts(Object *cuOb,
}
for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = invert_vgroup? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) :
+ const float weight = invert_vgroup ? 1.0f - defvert_find_weight(dvert_iter, defgrp_index) :
defvert_find_weight(dvert_iter, defgrp_index);
if (weight > 0.0f) {
@@ -899,8 +899,9 @@ static void lattice_deform_vert_task(void *__restrict userdata,
const LatticeDeformUserdata *data = userdata;
if (data->dvert != NULL) {
- const float weight = data->invert_vgroup? 1.0f - defvert_find_weight(data->dvert + index, data->defgrp_index) :
- defvert_find_weight(data->dvert + index, data->defgrp_index);
+ const float weight = data->invert_vgroup ?
+ 1.0f - defvert_find_weight(data->dvert + index, data->defgrp_index) :
+ defvert_find_weight(data->dvert + index, data->defgrp_index);
if (weight > 0.0f) {
calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 34c1c5ecab4..f9f15918d67 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -32,7 +32,7 @@
#include "BKE_freestyle.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_object.h"
@@ -388,7 +388,7 @@ 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_library.h's LIB_ID_COPY_... flags for more).
+ * \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),
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
new file mode 100644
index 00000000000..18faf00d60f
--- /dev/null
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -0,0 +1,2606 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Contains management of ID's and libraries
+ * allocate and free of all library data
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+
+#include "CLG_log.h"
+
+#include "MEM_guardedalloc.h"
+
+/* all types are needed here, in order to do memory operations */
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_cachefile_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_collection_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_light_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_speaker_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_text_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+#include "DNA_workspace_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_action.h"
+#include "BKE_animsys.h"
+#include "BKE_armature.h"
+#include "BKE_bpath.h"
+#include "BKE_brush.h"
+#include "BKE_camera.h"
+#include "BKE_cachefile.h"
+#include "BKE_collection.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_idcode.h"
+#include "BKE_idprop.h"
+#include "BKE_image.h"
+#include "BKE_key.h"
+#include "BKE_light.h"
+#include "BKE_lattice.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_linestyle.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_mask.h"
+#include "BKE_movieclip.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_lightprobe.h"
+#include "BKE_rigidbody.h"
+#include "BKE_sound.h"
+#include "BKE_speaker.h"
+#include "BKE_scene.h"
+#include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_world.h"
+
+#include "DEG_depsgraph.h"
+
+#include "RNA_access.h"
+
+#include "atomic_ops.h"
+
+//#define DEBUG_TIME
+
+#ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+#endif
+
+static CLG_LogRef LOG = {.identifier = "bke.lib_id"};
+
+/* GS reads the memory pointed at in a specific ordering.
+ * only use this definition, makes little and big endian systems
+ * work fine, in conjunction with MAKE_ID */
+
+/* ************* general ************************ */
+
+/* this has to be called from each make_local_* func, we could call
+ * from id_make_local() but then the make local functions would not be self
+ * contained.
+ * also note that the id _must_ have a library - campbell */
+void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
+{
+ const char *bpath_user_data[2] = {BKE_main_blendfile_path(bmain), lib->filepath};
+
+ BKE_bpath_traverse_id(bmain,
+ id,
+ BKE_bpath_relocate_visitor,
+ BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
+ (void *)bpath_user_data);
+}
+
+void id_lib_extern(ID *id)
+{
+ if (id && ID_IS_LINKED(id)) {
+ BLI_assert(BKE_idcode_is_linkable(GS(id->name)));
+ if (id->tag & LIB_TAG_INDIRECT) {
+ id->tag &= ~LIB_TAG_INDIRECT;
+ id->flag &= ~LIB_INDIRECT_WEAK_LINK;
+ id->tag |= LIB_TAG_EXTERN;
+ id->lib->parent = NULL;
+ }
+ }
+}
+
+void id_lib_indirect_weak_link(ID *id)
+{
+ if (id && ID_IS_LINKED(id)) {
+ BLI_assert(BKE_idcode_is_linkable(GS(id->name)));
+ if (id->tag & LIB_TAG_INDIRECT) {
+ id->flag |= LIB_INDIRECT_WEAK_LINK;
+ }
+ }
+}
+
+/**
+ * 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) {
+ const int limit = ID_FAKE_USERS(id);
+ id->tag |= LIB_TAG_EXTRAUSER;
+ if (id->us <= limit) {
+ if (id->us < limit || ((id->us == limit) && (id->tag & LIB_TAG_EXTRAUSER_SET))) {
+ CLOG_ERROR(&LOG,
+ "ID user count error: %s (from '%s')",
+ id->name,
+ id->lib ? id->lib->filepath : "[Main]");
+ BLI_assert(0);
+ }
+ id->us = limit + 1;
+ id->tag |= LIB_TAG_EXTRAUSER_SET;
+ }
+ }
+}
+
+void id_us_clear_real(ID *id)
+{
+ if (id && (id->tag & LIB_TAG_EXTRAUSER)) {
+ if (id->tag & LIB_TAG_EXTRAUSER_SET) {
+ id->us--;
+ BLI_assert(id->us >= ID_FAKE_USERS(id));
+ }
+ id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET);
+ }
+}
+
+/**
+ * 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) {
+ if ((id->tag & LIB_TAG_EXTRAUSER) && (id->tag & LIB_TAG_EXTRAUSER_SET)) {
+ BLI_assert(id->us >= 1);
+ /* No need to increase count, just tag extra user as no more set.
+ * Avoids annoying & inconsistent +1 in user count. */
+ id->tag &= ~LIB_TAG_EXTRAUSER_SET;
+ }
+ else {
+ BLI_assert(id->us >= 0);
+ id->us++;
+ }
+ }
+}
+
+void id_us_plus(ID *id)
+{
+ if (id) {
+ id_us_plus_no_lib(id);
+ id_lib_extern(id);
+ }
+}
+
+/* decrements the user count for *id. */
+void id_us_min(ID *id)
+{
+ if (id) {
+ const int limit = ID_FAKE_USERS(id);
+
+ if (id->us <= limit) {
+ CLOG_ERROR(&LOG,
+ "ID user decrement error: %s (from '%s'): %d <= %d",
+ id->name,
+ id->lib ? id->lib->filepath : "[Main]",
+ id->us,
+ limit);
+ BLI_assert(0);
+ id->us = limit;
+ }
+ else {
+ id->us--;
+ }
+
+ if ((id->us == limit) && (id->tag & LIB_TAG_EXTRAUSER)) {
+ /* We need an extra user here, but never actually incremented user count for it so far,
+ * do it now. */
+ id_us_ensure_real(id);
+ }
+ }
+}
+
+void id_fake_user_set(ID *id)
+{
+ if (id && !(id->flag & LIB_FAKEUSER)) {
+ id->flag |= LIB_FAKEUSER;
+ id_us_plus(id);
+ }
+}
+
+void id_fake_user_clear(ID *id)
+{
+ if (id && (id->flag & LIB_FAKEUSER)) {
+ id->flag &= ~LIB_FAKEUSER;
+ id_us_min(id);
+ }
+}
+
+void BKE_id_clear_newpoin(ID *id)
+{
+ if (id->newid) {
+ id->newid->tag &= ~LIB_TAG_NEW;
+ }
+ id->newid = NULL;
+}
+
+static int id_expand_local_callback(void *UNUSED(user_data),
+ struct ID *id_self,
+ struct ID **id_pointer,
+ int cb_flag)
+{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
+ /* Can happen that we get un-linkable ID here, e.g. with shape-key referring to itself
+ * (through drivers)...
+ * Just skip it, shape key can only be either indirectly linked, or fully local, period.
+ * And let's curse one more time that stupid useless shapekey ID type! */
+ if (*id_pointer && *id_pointer != id_self && BKE_idcode_is_linkable(GS((*id_pointer)->name))) {
+ id_lib_extern(*id_pointer);
+ }
+
+ 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_id_expand_local(Main *bmain, ID *id)
+{
+ BKE_library_foreach_ID_link(bmain, id, id_expand_local_callback, NULL, IDWALK_READONLY);
+}
+
+/**
+ * Ensure new (copied) ID is fully made local.
+ */
+void BKE_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id)
+{
+ if (ID_IS_LINKED(old_id)) {
+ BKE_id_expand_local(bmain, new_id);
+ BKE_id_lib_local_paths(bmain, old_id->lib, new_id);
+ }
+}
+
+/**
+ * Generic 'make local' function, works for most of data-block types...
+ */
+void BKE_id_make_local_generic(Main *bmain,
+ ID *id,
+ const bool id_in_mainlist,
+ const bool lib_local)
+{
+ bool is_local = false, is_lib = false;
+
+ /* - only lib users: do nothing (unless force_local is set)
+ * - only local users: set flag
+ * - mixed: make copy
+ * In case we make a whole lib's content local,
+ * we always want to localize, and we skip remapping (done later).
+ */
+
+ if (!ID_IS_LINKED(id)) {
+ return;
+ }
+
+ BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
+
+ if (lib_local || is_local) {
+ if (!is_lib) {
+ id_clear_lib_data_ex(bmain, id, id_in_mainlist);
+ BKE_id_expand_local(bmain, id);
+ }
+ else {
+ ID *id_new;
+
+ /* Should not fail in expected use cases,
+ * but a few ID types cannot be copied (LIB, WM, SCR...). */
+ if (BKE_id_copy(bmain, id, &id_new)) {
+ id_new->us = 0;
+
+ /* setting newid is mandatory for complex make_lib_local logic... */
+ ID_NEW_SET(id, id_new);
+ Key *key = BKE_key_from_id(id), *key_new = BKE_key_from_id(id);
+ if (key && key_new) {
+ ID_NEW_SET(key, key_new);
+ }
+ bNodeTree *ntree = ntreeFromID(id), *ntree_new = ntreeFromID(id_new);
+ if (ntree && ntree_new) {
+ ID_NEW_SET(ntree, ntree_new);
+ }
+
+ if (!lib_local) {
+ BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * 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 lib_local: Special flag used when making a whole library's content local,
+ * it needs specific handling.
+ *
+ * \return true if the block can be made local.
+ */
+bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
+{
+ /* We don't care whether ID is directly or indirectly linked
+ * in case we are making a whole lib local... */
+ if (!lib_local && (id->tag & LIB_TAG_INDIRECT)) {
+ return false;
+ }
+
+ switch ((ID_Type)GS(id->name)) {
+ case ID_SCE:
+ if (!test) {
+ BKE_scene_make_local(bmain, (Scene *)id, lib_local);
+ }
+ return true;
+ case ID_OB:
+ if (!test) {
+ BKE_object_make_local(bmain, (Object *)id, lib_local);
+ }
+ return true;
+ case ID_ME:
+ if (!test) {
+ BKE_mesh_make_local(bmain, (Mesh *)id, lib_local);
+ }
+ return true;
+ case ID_CU:
+ if (!test) {
+ BKE_curve_make_local(bmain, (Curve *)id, lib_local);
+ }
+ return true;
+ case ID_MB:
+ if (!test) {
+ BKE_mball_make_local(bmain, (MetaBall *)id, lib_local);
+ }
+ return true;
+ case ID_MA:
+ if (!test) {
+ BKE_material_make_local(bmain, (Material *)id, lib_local);
+ }
+ return true;
+ case ID_TE:
+ if (!test) {
+ BKE_texture_make_local(bmain, (Tex *)id, lib_local);
+ }
+ return true;
+ case ID_IM:
+ if (!test) {
+ BKE_image_make_local(bmain, (Image *)id, lib_local);
+ }
+ return true;
+ case ID_LT:
+ if (!test) {
+ BKE_lattice_make_local(bmain, (Lattice *)id, lib_local);
+ }
+ return true;
+ case ID_LA:
+ if (!test) {
+ BKE_light_make_local(bmain, (Light *)id, lib_local);
+ }
+ return true;
+ case ID_CA:
+ if (!test) {
+ BKE_camera_make_local(bmain, (Camera *)id, lib_local);
+ }
+ return true;
+ case ID_SPK:
+ if (!test) {
+ BKE_speaker_make_local(bmain, (Speaker *)id, lib_local);
+ }
+ return true;
+ case ID_LP:
+ if (!test) {
+ BKE_lightprobe_make_local(bmain, (LightProbe *)id, lib_local);
+ }
+ return true;
+ case ID_WO:
+ if (!test) {
+ BKE_world_make_local(bmain, (World *)id, lib_local);
+ }
+ return true;
+ case ID_VF:
+ if (!test) {
+ BKE_vfont_make_local(bmain, (VFont *)id, lib_local);
+ }
+ return true;
+ case ID_TXT:
+ if (!test) {
+ BKE_text_make_local(bmain, (Text *)id, lib_local);
+ }
+ return true;
+ case ID_SO:
+ if (!test) {
+ BKE_sound_make_local(bmain, (bSound *)id, lib_local);
+ }
+ return true;
+ case ID_GR:
+ if (!test) {
+ BKE_collection_make_local(bmain, (Collection *)id, lib_local);
+ }
+ return true;
+ case ID_AR:
+ if (!test) {
+ BKE_armature_make_local(bmain, (bArmature *)id, lib_local);
+ }
+ return true;
+ case ID_AC:
+ if (!test) {
+ BKE_action_make_local(bmain, (bAction *)id, lib_local);
+ }
+ return true;
+ case ID_NT:
+ if (!test) {
+ ntreeMakeLocal(bmain, (bNodeTree *)id, true, lib_local);
+ }
+ return true;
+ case ID_BR:
+ if (!test) {
+ BKE_brush_make_local(bmain, (Brush *)id, lib_local);
+ }
+ return true;
+ case ID_PA:
+ if (!test) {
+ BKE_particlesettings_make_local(bmain, (ParticleSettings *)id, lib_local);
+ }
+ return true;
+ case ID_GD:
+ if (!test) {
+ BKE_gpencil_make_local(bmain, (bGPdata *)id, lib_local);
+ }
+ return true;
+ case ID_MC:
+ if (!test) {
+ BKE_movieclip_make_local(bmain, (MovieClip *)id, lib_local);
+ }
+ return true;
+ case ID_MSK:
+ if (!test) {
+ BKE_mask_make_local(bmain, (Mask *)id, lib_local);
+ }
+ return true;
+ case ID_LS:
+ if (!test) {
+ BKE_linestyle_make_local(bmain, (FreestyleLineStyle *)id, lib_local);
+ }
+ return true;
+ case ID_PAL:
+ if (!test) {
+ BKE_palette_make_local(bmain, (Palette *)id, lib_local);
+ }
+ return true;
+ case ID_PC:
+ if (!test) {
+ BKE_paint_curve_make_local(bmain, (PaintCurve *)id, lib_local);
+ }
+ return true;
+ case ID_CF:
+ if (!test) {
+ BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local);
+ }
+ return true;
+ case ID_WS:
+ case ID_SCR:
+ /* A bit special: can be appended but not linked. Return false
+ * since supporting make-local doesn't make much sense. */
+ return false;
+ case ID_LI:
+ case ID_KE:
+ case ID_WM:
+ return false; /* can't be linked */
+ case ID_IP:
+ return false; /* deprecated */
+ }
+
+ return false;
+}
+
+struct IDCopyLibManagementData {
+ const ID *id_src;
+ ID *id_dst;
+ int flag;
+};
+
+/* Increases usercount as required, and remap self ID pointers. */
+static int id_copy_libmanagement_cb(void *user_data,
+ ID *UNUSED(id_self),
+ ID **id_pointer,
+ int cb_flag)
+{
+ struct IDCopyLibManagementData *data = user_data;
+ ID *id = *id_pointer;
+
+ /* Remap self-references to new copied ID. */
+ if (id == data->id_src) {
+ /* We cannot use id_self here, it is not *always* id_dst (thanks to $£!+@#&/? nodetrees). */
+ id = *id_pointer = data->id_dst;
+ }
+
+ /* Increase used IDs refcount if needed and required. */
+ if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) {
+ id_us_plus(id);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+bool BKE_id_copy_is_allowed(const ID *id)
+{
+#define LIB_ID_TYPES_NOCOPY \
+ ID_LI, ID_SCR, ID_WM, ID_WS, /* Not supported */ \
+ ID_IP /* Deprecated */
+
+ return !ELEM(GS(id->name), LIB_ID_TYPES_NOCOPY);
+
+#undef LIB_ID_TYPES_NOCOPY
+}
+
+/**
+ * Generic entry point for copying a data-block (new API).
+ *
+ * \note Copy is only affecting given data-block
+ * (no ID used by copied one will be affected, besides usercount).
+ * There is only one exception, if #LIB_ID_COPY_ACTIONS is defined,
+ * actions used by animdata will be duplicated.
+ *
+ * \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.
+ * \param flag: Set of copy options, see DNA_ID.h enum for details
+ * (leave to zero for default, full copy).
+ * \return False when copying that ID type is not supported, true otherwise.
+ */
+bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
+{
+ BLI_assert(r_newid != NULL);
+ /* Make sure destination pointer is all good. */
+ if ((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0) {
+ *r_newid = NULL;
+ }
+ else {
+ if (*r_newid != NULL) {
+ /* Allow some garbage non-initialized memory to go in, and clean it up here. */
+ const size_t size = BKE_libblock_get_alloc_info(GS(id->name), NULL);
+ memset(*r_newid, 0, size);
+ }
+ }
+
+ /* Early output is source is NULL. */
+ if (id == NULL) {
+ return false;
+ }
+ if (!BKE_id_copy_is_allowed(id)) {
+ return false;
+ }
+
+ BKE_libblock_copy_ex(bmain, id, r_newid, flag);
+
+ switch ((ID_Type)GS(id->name)) {
+ case ID_SCE:
+ BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag);
+ break;
+ case ID_OB:
+ BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag);
+ break;
+ case ID_ME:
+ BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag);
+ break;
+ case ID_CU:
+ BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag);
+ break;
+ case ID_MB:
+ BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag);
+ break;
+ case ID_MA:
+ BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag);
+ break;
+ case ID_TE:
+ BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag);
+ break;
+ case ID_IM:
+ BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag);
+ break;
+ case ID_LT:
+ BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag);
+ break;
+ case ID_LA:
+ BKE_light_copy_data(bmain, (Light *)*r_newid, (Light *)id, flag);
+ break;
+ case ID_SPK:
+ BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag);
+ break;
+ case ID_LP:
+ BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag);
+ break;
+ case ID_CA:
+ BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag);
+ break;
+ case ID_KE:
+ BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag);
+ break;
+ case ID_WO:
+ BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag);
+ break;
+ case ID_TXT:
+ BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag);
+ break;
+ case ID_GR:
+ BKE_collection_copy_data(bmain, (Collection *)*r_newid, (Collection *)id, flag);
+ break;
+ case ID_AR:
+ BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag);
+ break;
+ case ID_AC:
+ BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag);
+ break;
+ case ID_NT:
+ BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag);
+ break;
+ case ID_BR:
+ BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag);
+ break;
+ case ID_PA:
+ BKE_particlesettings_copy_data(
+ bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag);
+ break;
+ case ID_GD:
+ BKE_gpencil_copy_data((bGPdata *)*r_newid, (bGPdata *)id, flag);
+ break;
+ case ID_MC:
+ BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag);
+ break;
+ case ID_MSK:
+ BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag);
+ break;
+ case ID_LS:
+ BKE_linestyle_copy_data(
+ bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag);
+ break;
+ case ID_PAL:
+ BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag);
+ break;
+ case ID_PC:
+ BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag);
+ break;
+ case ID_CF:
+ BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag);
+ break;
+ case ID_SO:
+ BKE_sound_copy_data(bmain, (bSound *)*r_newid, (bSound *)id, flag);
+ break;
+ case ID_VF:
+ BKE_vfont_copy_data(bmain, (VFont *)*r_newid, (VFont *)id, flag);
+ break;
+ case ID_LI:
+ case ID_SCR:
+ case ID_WM:
+ case ID_WS:
+ case ID_IP:
+ BLI_assert(0); /* Should have been rejected at start of function! */
+ break;
+ }
+
+ /* Update ID refcount, remap pointers to self in new ID. */
+ struct IDCopyLibManagementData data = {
+ .id_src = id,
+ .id_dst = *r_newid,
+ .flag = flag,
+ };
+ BKE_library_foreach_ID_link(bmain, *r_newid, id_copy_libmanagement_cb, &data, IDWALK_NOP);
+
+ /* Do not make new copy local in case we are copying outside of main...
+ * XXX TODO: is this behavior OK, or should we need own flag to control that? */
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ BLI_assert((flag & LIB_ID_COPY_KEEP_LIB) == 0);
+ BKE_id_copy_ensure_local(bmain, id, *r_newid);
+ }
+ else {
+ (*r_newid)->lib = id->lib;
+ }
+
+ return true;
+}
+
+/**
+ * Invokes the appropriate copy method for the block and returns the result in
+ * newid, unless test. Returns true if the block can be copied.
+ */
+bool BKE_id_copy(Main *bmain, const ID *id, ID **newid)
+{
+ return BKE_id_copy_ex(bmain, id, newid, LIB_ID_COPY_DEFAULT);
+}
+
+/**
+ * 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).
+ */
+void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
+{
+ BLI_assert(GS(id_a->name) == GS(id_b->name));
+
+ const ID id_a_back = *id_a;
+ const ID id_b_back = *id_b;
+
+#define CASE_SWAP(_gs, _type) \
+ case _gs: \
+ SWAP(_type, *(_type *)id_a, *(_type *)id_b); \
+ break
+
+ switch ((ID_Type)GS(id_a->name)) {
+ CASE_SWAP(ID_SCE, Scene);
+ CASE_SWAP(ID_LI, Library);
+ CASE_SWAP(ID_OB, Object);
+ CASE_SWAP(ID_ME, Mesh);
+ CASE_SWAP(ID_CU, Curve);
+ CASE_SWAP(ID_MB, MetaBall);
+ CASE_SWAP(ID_MA, Material);
+ CASE_SWAP(ID_TE, Tex);
+ CASE_SWAP(ID_IM, Image);
+ CASE_SWAP(ID_LT, Lattice);
+ CASE_SWAP(ID_LA, Light);
+ CASE_SWAP(ID_LP, LightProbe);
+ CASE_SWAP(ID_CA, Camera);
+ CASE_SWAP(ID_KE, Key);
+ CASE_SWAP(ID_WO, World);
+ CASE_SWAP(ID_SCR, bScreen);
+ CASE_SWAP(ID_VF, VFont);
+ CASE_SWAP(ID_TXT, Text);
+ CASE_SWAP(ID_SPK, Speaker);
+ CASE_SWAP(ID_SO, bSound);
+ CASE_SWAP(ID_GR, Collection);
+ CASE_SWAP(ID_AR, bArmature);
+ CASE_SWAP(ID_AC, bAction);
+ CASE_SWAP(ID_NT, bNodeTree);
+ CASE_SWAP(ID_BR, Brush);
+ CASE_SWAP(ID_PA, ParticleSettings);
+ CASE_SWAP(ID_WM, wmWindowManager);
+ CASE_SWAP(ID_WS, WorkSpace);
+ CASE_SWAP(ID_GD, bGPdata);
+ CASE_SWAP(ID_MC, MovieClip);
+ CASE_SWAP(ID_MSK, Mask);
+ CASE_SWAP(ID_LS, FreestyleLineStyle);
+ CASE_SWAP(ID_PAL, Palette);
+ CASE_SWAP(ID_PC, PaintCurve);
+ CASE_SWAP(ID_CF, CacheFile);
+ case ID_IP:
+ break; /* Deprecated. */
+ }
+
+#undef CASE_SWAP
+
+ /* Restore original ID's internal data. */
+ *id_a = id_a_back;
+ *id_b = id_b_back;
+
+ /* Exception: IDProperties. */
+ id_a->properties = id_b_back.properties;
+ id_b->properties = id_a_back.properties;
+
+ /* Swap will have broken internal references to itself, restore them. */
+ BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, ID_REMAP_SKIP_NEVER_NULL_USAGE);
+ BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, ID_REMAP_SKIP_NEVER_NULL_USAGE);
+}
+
+/** Does *not* set ID->newid pointer. */
+bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
+{
+ ID *newid = NULL;
+ PointerRNA idptr;
+
+ if (id) {
+ /* If property isn't editable,
+ * we're going to have an extra block hanging around until we save. */
+ if (RNA_property_editable(ptr, prop)) {
+ Main *bmain = CTX_data_main(C);
+ /* copy animation actions too */
+ if (BKE_id_copy_ex(bmain, id, &newid, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS) && newid) {
+ /* us is 1 by convention with new IDs, but RNA_property_pointer_set
+ * will also increment it, decrement it here. */
+ id_us_min(newid);
+
+ /* assign copy */
+ RNA_id_pointer_create(newid, &idptr);
+ RNA_property_pointer_set(ptr, prop, idptr, NULL);
+ RNA_property_update(C, ptr, prop);
+
+ /* tag grease pencil data-block and disable onion */
+ if (GS(id->name) == ID_GD) {
+ DEG_id_tag_update(id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(newid, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ bGPdata *gpd = (bGPdata *)newid;
+ gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS;
+ }
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int libblock_management_us_plus(void *UNUSED(user_data),
+ ID *UNUSED(id_self),
+ ID **id_pointer,
+ int cb_flag)
+{
+ if (cb_flag & IDWALK_CB_USER) {
+ id_us_plus(*id_pointer);
+ }
+ if (cb_flag & IDWALK_CB_USER_ONE) {
+ id_us_ensure_real(*id_pointer);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+static int libblock_management_us_min(void *UNUSED(user_data),
+ ID *UNUSED(id_self),
+ ID **id_pointer,
+ int cb_flag)
+{
+ if (cb_flag & IDWALK_CB_USER) {
+ id_us_min(*id_pointer);
+ }
+ /* We can do nothing in IDWALK_CB_USER_ONE case! */
+
+ 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;
+
+ BLI_assert(bmain != NULL);
+ if ((id->tag & LIB_TAG_NO_MAIN) == 0) {
+ return;
+ }
+
+ if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
+ /* We cannot add non-allocated ID to Main! */
+ return;
+ }
+
+ /* We cannot allow non-userrefcounting IDs in Main database! */
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
+ BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP);
+ }
+
+ ListBase *lb = which_libbase(bmain, GS(id->name));
+ BKE_main_lock(bmain);
+ BLI_addtail(lb, id);
+ BKE_id_new_name_validate(lb, id, NULL);
+ /* alphabetic insertion: is in new_id */
+ id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
+ bmain->is_memfile_undo_written = false;
+ BKE_main_unlock(bmain);
+}
+
+/** 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;
+
+ BLI_assert(bmain != NULL);
+ if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
+ return;
+ }
+
+ /* For now, allow userrefcounting IDs to get out of Main - can be handy in some cases... */
+
+ ListBase *lb = which_libbase(bmain, GS(id->name));
+ BKE_main_lock(bmain);
+ BLI_remlink(lb, id);
+ id->tag |= LIB_TAG_NO_MAIN;
+ bmain->is_memfile_undo_written = false;
+ BKE_main_unlock(bmain);
+}
+
+void BKE_libblock_management_usercounts_set(Main *bmain, void *idv)
+{
+ ID *id = idv;
+
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) == 0) {
+ return;
+ }
+
+ BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP);
+ id->tag &= ~LIB_TAG_NO_USER_REFCOUNT;
+}
+
+void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv)
+{
+ ID *id = idv;
+
+ /* We do not allow IDs in Main database to not be userrefcounting. */
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0 || (id->tag & LIB_TAG_NO_MAIN) != 0) {
+ return;
+ }
+
+ BKE_library_foreach_ID_link(bmain, id, libblock_management_us_min, NULL, IDWALK_NOP);
+ 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;
+ if (value) {
+ for (id = lb->first; id; id = id->next) {
+ id->tag |= tag;
+ }
+ }
+ else {
+ const int ntag = ~tag;
+ for (id = lb->first; id; id = id->next) {
+ id->tag &= ntag;
+ }
+ }
+}
+
+/**
+ * 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,
+ const bool value)
+{
+ ListBase *lb = which_libbase(mainvar, type);
+
+ 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[MAX_LIBARRAY];
+ int a;
+
+ a = set_listbasepointers(mainvar, lbarray);
+ while (a--) {
+ BKE_main_id_tag_listbase(lbarray[a], tag, 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;
+ if (value) {
+ for (id = lb->first; id; id = id->next) {
+ id->tag |= flag;
+ }
+ }
+ else {
+ const int nflag = ~flag;
+ for (id = lb->first; id; id = id->next) {
+ id->tag &= nflag;
+ }
+ }
+}
+
+/**
+ * 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[MAX_LIBARRAY];
+ int a;
+ a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ BKE_main_id_flag_listbase(lbarray[a], flag, value);
+ }
+}
+
+void BKE_main_id_repair_duplicate_names_listbase(ListBase *lb)
+{
+ int lb_len = 0;
+ for (ID *id = lb->first; id; id = id->next) {
+ if (id->lib == NULL) {
+ lb_len += 1;
+ }
+ }
+ if (lb_len <= 1) {
+ return;
+ }
+
+ /* Fill an array because renaming sorts. */
+ ID **id_array = MEM_mallocN(sizeof(*id_array) * lb_len, __func__);
+ GSet *gset = BLI_gset_str_new_ex(__func__, lb_len);
+ int i = 0;
+ for (ID *id = lb->first; id; id = id->next) {
+ if (id->lib == NULL) {
+ id_array[i] = id;
+ i++;
+ }
+ }
+ for (i = 0; i < lb_len; i++) {
+ if (!BLI_gset_add(gset, id_array[i]->name + 2)) {
+ BKE_id_new_name_validate(lb, id_array[i], NULL);
+ }
+ }
+ BLI_gset_free(gset, NULL);
+ MEM_freeN(id_array);
+}
+
+void BKE_main_lib_objects_recalc_all(Main *bmain)
+{
+ Object *ob;
+
+ /* flag for full recalc */
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ID_IS_LINKED(ob)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ }
+ }
+
+ DEG_id_type_tag(bmain, ID_OB);
+}
+
+/* *********** ALLOC AND FREE *****************
+ *
+ * BKE_libblock_free(ListBase *lb, ID *id )
+ * provide a list-basis and data-block, but only ID is read
+ *
+ * void *BKE_libblock_alloc(ListBase *lb, type, name)
+ * inserts in list and returns a new ID
+ *
+ * **************************** */
+
+/**
+ * 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)
+{
+#define CASE_RETURN(id_code, type) \
+ case id_code: \
+ do { \
+ if (name != NULL) { \
+ *name = #type; \
+ } \
+ return sizeof(type); \
+ } while (0)
+
+ switch ((ID_Type)type) {
+ CASE_RETURN(ID_SCE, Scene);
+ CASE_RETURN(ID_LI, Library);
+ CASE_RETURN(ID_OB, Object);
+ CASE_RETURN(ID_ME, Mesh);
+ CASE_RETURN(ID_CU, Curve);
+ CASE_RETURN(ID_MB, MetaBall);
+ CASE_RETURN(ID_MA, Material);
+ CASE_RETURN(ID_TE, Tex);
+ CASE_RETURN(ID_IM, Image);
+ CASE_RETURN(ID_LT, Lattice);
+ CASE_RETURN(ID_LA, Light);
+ CASE_RETURN(ID_CA, Camera);
+ CASE_RETURN(ID_IP, Ipo);
+ CASE_RETURN(ID_KE, Key);
+ CASE_RETURN(ID_WO, World);
+ CASE_RETURN(ID_SCR, bScreen);
+ CASE_RETURN(ID_VF, VFont);
+ CASE_RETURN(ID_TXT, Text);
+ CASE_RETURN(ID_SPK, Speaker);
+ CASE_RETURN(ID_LP, LightProbe);
+ CASE_RETURN(ID_SO, bSound);
+ CASE_RETURN(ID_GR, Collection);
+ CASE_RETURN(ID_AR, bArmature);
+ CASE_RETURN(ID_AC, bAction);
+ CASE_RETURN(ID_NT, bNodeTree);
+ CASE_RETURN(ID_BR, Brush);
+ CASE_RETURN(ID_PA, ParticleSettings);
+ CASE_RETURN(ID_WM, wmWindowManager);
+ CASE_RETURN(ID_GD, bGPdata);
+ CASE_RETURN(ID_MC, MovieClip);
+ CASE_RETURN(ID_MSK, Mask);
+ CASE_RETURN(ID_LS, FreestyleLineStyle);
+ CASE_RETURN(ID_PAL, Palette);
+ CASE_RETURN(ID_PC, PaintCurve);
+ CASE_RETURN(ID_CF, CacheFile);
+ CASE_RETURN(ID_WS, WorkSpace);
+ }
+ return 0;
+#undef CASE_RETURN
+}
+
+/**
+ * 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;
+ size_t size = BKE_libblock_get_alloc_info(type, &name);
+ if (size != 0) {
+ return MEM_callocN(size, name);
+ }
+ BLI_assert(!"Request to allocate unknown data 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);
+
+ ID *id = BKE_libblock_alloc_notest(type);
+
+ if (id) {
+ if ((flag & LIB_ID_CREATE_NO_MAIN) != 0) {
+ id->tag |= LIB_TAG_NO_MAIN;
+ }
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) {
+ id->tag |= LIB_TAG_NO_USER_REFCOUNT;
+ }
+
+ id->icon_id = 0;
+ *((short *)id->name) = type;
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id->us = 1;
+ }
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ ListBase *lb = which_libbase(bmain, type);
+
+ BKE_main_lock(bmain);
+ BLI_addtail(lb, id);
+ BKE_id_new_name_validate(lb, id, name);
+ bmain->is_memfile_undo_written = false;
+ /* alphabetic insertion: is in new_id */
+ BKE_main_unlock(bmain);
+
+ /* TODO to be removed from here! */
+ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
+ DEG_id_type_tag(bmain, type);
+ }
+ }
+ else {
+ BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
+ }
+ }
+
+ 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)
+{
+ /* Note that only ID types that are not valid when filled of zero should have a callback here. */
+ switch ((ID_Type)GS(id->name)) {
+ case ID_SCE:
+ BKE_scene_init((Scene *)id);
+ break;
+ case ID_LI:
+ /* Nothing to do. */
+ break;
+ case ID_OB: {
+ Object *ob = (Object *)id;
+ BKE_object_init(ob, OB_EMPTY);
+ break;
+ }
+ case ID_ME:
+ BKE_mesh_init((Mesh *)id);
+ break;
+ case ID_CU:
+ BKE_curve_init((Curve *)id, 0);
+ break;
+ case ID_MB:
+ BKE_mball_init((MetaBall *)id);
+ break;
+ case ID_MA:
+ BKE_material_init((Material *)id);
+ break;
+ case ID_TE:
+ BKE_texture_default((Tex *)id);
+ break;
+ case ID_IM:
+ BKE_image_init((Image *)id);
+ break;
+ case ID_LT:
+ BKE_lattice_init((Lattice *)id);
+ break;
+ case ID_LA:
+ BKE_light_init((Light *)id);
+ break;
+ case ID_SPK:
+ BKE_speaker_init((Speaker *)id);
+ break;
+ case ID_LP:
+ BKE_lightprobe_init((LightProbe *)id);
+ break;
+ case ID_CA:
+ BKE_camera_init((Camera *)id);
+ break;
+ case ID_WO:
+ BKE_world_init((World *)id);
+ break;
+ case ID_SCR:
+ /* Nothing to do. */
+ break;
+ case ID_VF:
+ BKE_vfont_init((VFont *)id);
+ break;
+ case ID_TXT:
+ BKE_text_init((Text *)id);
+ break;
+ case ID_SO:
+ /* Another fuzzy case, think NULLified content is OK here... */
+ break;
+ case ID_GR:
+ /* Nothing to do. */
+ break;
+ case ID_AR:
+ /* Nothing to do. */
+ break;
+ case ID_AC:
+ /* Nothing to do. */
+ break;
+ case ID_NT:
+ ntreeInitDefault((bNodeTree *)id);
+ break;
+ case ID_BR:
+ BKE_brush_init((Brush *)id);
+ break;
+ case ID_PA:
+ /* Nothing to do. */
+ break;
+ case ID_PC:
+ /* Nothing to do. */
+ break;
+ case ID_GD:
+ /* Nothing to do. */
+ break;
+ case ID_MSK:
+ /* Nothing to do. */
+ break;
+ case ID_LS:
+ BKE_linestyle_init((FreestyleLineStyle *)id);
+ break;
+ case ID_CF:
+ BKE_cachefile_init((CacheFile *)id);
+ break;
+ case ID_KE:
+ /* Shapekeys are a complex topic too - they depend on their 'user' data type...
+ * They are not linkable, though, so it should never reach here anyway. */
+ BLI_assert(0);
+ break;
+ case ID_WM:
+ /* We should never reach this. */
+ BLI_assert(0);
+ break;
+ case ID_IP:
+ /* Should not be needed - animation from lib pre-2.5 is broken anyway. */
+ BLI_assert(0);
+ break;
+ case ID_PAL:
+ BKE_palette_init((Palette *)id);
+ break;
+ default:
+ BLI_assert(0); /* Should never reach this point... */
+ }
+}
+
+/**
+ * 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);
+
+ if (name == NULL) {
+ name = DATA_(BKE_idcode_to_name(type));
+ }
+
+ ID *id = BKE_libblock_alloc(bmain, type, name, 0);
+ BKE_libblock_init_empty(id);
+
+ 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) {
+ name = DATA_(BKE_idcode_to_name(type));
+ }
+
+ ID *id = BKE_libblock_alloc(NULL,
+ type,
+ name,
+ LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG);
+ BKE_libblock_init_empty(id);
+
+ return id;
+}
+
+void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int orig_flag)
+{
+ ID *new_id = *r_newid;
+ int flag = orig_flag;
+
+ const bool is_private_id_data = (id->flag & LIB_PRIVATE_DATA) != 0;
+
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
+ if (!is_private_id_data) {
+ /* When we are handling private ID data, we might still want to manage usercounts, even though
+ * that ID data-block is actually outside of Main... */
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 ||
+ (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
+ }
+ /* Never implicitly copy shapekeys when generating temp data outside of Main database. */
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_COPY_SHAPEKEY) == 0);
+
+ /* 'Private ID' data handling. */
+ if ((bmain != NULL) && is_private_id_data) {
+ flag |= LIB_ID_CREATE_NO_MAIN;
+ }
+
+ /* The id->flag bits to copy over. */
+ const int copy_idflag_mask = LIB_PRIVATE_DATA;
+
+ if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
+ /* r_newid already contains pointer to allocated memory. */
+ /* TODO do we want to memset(0) whole mem before filling it? */
+ BLI_strncpy(new_id->name, id->name, sizeof(new_id->name));
+ new_id->us = 0;
+ new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT;
+ /* TODO Do we want/need to copy more from ID struct itself? */
+ }
+ else {
+ new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag);
+ }
+ BLI_assert(new_id != NULL);
+
+ const size_t id_len = BKE_libblock_get_alloc_info(GS(new_id->name), NULL);
+ const size_t id_offset = sizeof(ID);
+ if ((int)id_len - (int)id_offset > 0) { /* signed to allow neg result */ /* XXX ????? */
+ const char *cp = (const char *)id;
+ char *cpn = (char *)new_id;
+
+ memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset);
+ }
+
+ new_id->flag = (new_id->flag & ~copy_idflag_mask) | (id->flag & copy_idflag_mask);
+
+ /* We do not want any handling of usercount in code duplicating the data here, we do that all
+ * at once in id_copy_libmanagement_cb() at the end. */
+ const int copy_data_flag = orig_flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+
+ if (id->properties) {
+ new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag);
+ }
+
+ /* XXX Again... We need a way to control what we copy in a much more refined way.
+ * We cannot always copy this, some internal copying will die on it! */
+ /* For now, upper level code will have to do that itself when required. */
+#if 0
+ if (id->override != NULL) {
+ BKE_override_copy(new_id, id);
+ }
+#endif
+
+ if (id_can_have_animdata(new_id)) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)new_id;
+
+ /* the duplicate should get a copy of the animdata */
+ if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) {
+ /* Note that even though horrors like root nodetrees are not in bmain, the actions they use
+ * in their anim data *are* in bmain... super-mega-hooray. */
+ BLI_assert((copy_data_flag & LIB_ID_COPY_ACTIONS) == 0 ||
+ (copy_data_flag & LIB_ID_CREATE_NO_MAIN) == 0);
+ iat->adt = BKE_animdata_copy(bmain, iat->adt, copy_data_flag);
+ }
+ else {
+ iat->adt = NULL;
+ }
+ }
+
+ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ DEG_id_type_tag(bmain, GS(new_id->name));
+ }
+
+ *r_newid = new_id;
+}
+
+/* used everywhere in blenkernel */
+void *BKE_libblock_copy(Main *bmain, const ID *id)
+{
+ ID *idn;
+
+ BKE_libblock_copy_ex(bmain, id, &idn, 0);
+
+ return idn;
+}
+
+/* XXX TODO: get rid of this useless wrapper at some point... */
+void *BKE_libblock_copy_for_localize(const ID *id)
+{
+ ID *idn;
+ BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
+ return idn;
+}
+
+/* ***************** ID ************************ */
+ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *name)
+{
+ ListBase *lb = which_libbase(bmain, type);
+ BLI_assert(lb != NULL);
+ return BLI_findstring(lb, name, offsetof(ID, name) + 2);
+}
+
+/**
+ * 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
+
+ ID *idtest;
+
+ /* insert alphabetically */
+ if (lb->first == lb->last) {
+ return;
+ }
+
+ BLI_remlink(lb, id);
+
+ /* Check if we can actually insert id before or after id_sorting_hint, if given. */
+ if (id_sorting_hint != NULL && id_sorting_hint != id) {
+ BLI_assert(BLI_findindex(lb, id_sorting_hint) >= 0);
+
+ ID *id_sorting_hint_next = id_sorting_hint->next;
+ if (BLI_strcasecmp(id_sorting_hint->name, id->name) < 0 &&
+ (id_sorting_hint_next == NULL ||
+ BLI_strcasecmp(id_sorting_hint_next->name, id->name) > 0)) {
+ BLI_insertlinkafter(lb, id_sorting_hint, id);
+ return;
+ }
+
+ ID *id_sorting_hint_prev = id_sorting_hint->prev;
+ if (BLI_strcasecmp(id_sorting_hint->name, id->name) > 0 &&
+ (id_sorting_hint_prev == NULL ||
+ BLI_strcasecmp(id_sorting_hint_prev->name, id->name) < 0)) {
+ BLI_insertlinkbefore(lb, id_sorting_hint, id);
+ return;
+ }
+ }
+
+ void *item_array[ID_SORT_STEP_SIZE];
+ int item_array_index;
+
+ /* Step one: We go backward over a whole chunk of items at once, until we find a limit item
+ * that is lower than, or equal (should never happen!) to the one we want to insert. */
+ /* Note: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at
+ * once using the same base name), newly inserted items will generally be towards the end
+ * (higher extension numbers). */
+ for (idtest = lb->last, item_array_index = ID_SORT_STEP_SIZE - 1; idtest != NULL;
+ idtest = idtest->prev, item_array_index--) {
+ item_array[item_array_index] = idtest;
+ if (item_array_index == 0) {
+ if ((idtest->lib == NULL && id->lib != NULL) ||
+ BLI_strcasecmp(idtest->name, id->name) <= 0) {
+ break;
+ }
+ item_array_index = ID_SORT_STEP_SIZE;
+ }
+ }
+
+ /* Step two: we go forward in the selected chunk of items and check all of them, as we know
+ * that our target is in there. */
+
+ /* If we reached start of the list, current item_array_index is off-by-one.
+ * Otherwise, we already know that it points to an item lower-or-equal-than the one we want to
+ * insert, no need to redo the check for that one.
+ * So we can increment that index in any case. */
+ for (item_array_index++; item_array_index < ID_SORT_STEP_SIZE; item_array_index++) {
+ idtest = item_array[item_array_index];
+ if ((idtest->lib != NULL && id->lib == NULL) || BLI_strcasecmp(idtest->name, id->name) > 0) {
+ BLI_insertlinkbefore(lb, idtest, id);
+ break;
+ }
+ }
+ if (item_array_index == ID_SORT_STEP_SIZE) {
+ if (idtest == NULL) {
+ /* If idtest is NULL here, it means that in the first loop, the last comparison was
+ * performed exactly on the first item of the list, and that it also failed. In other
+ * words, all items in the list are greater than inserted one, so we can put it at the
+ * start of the list. */
+ /* Note that BLI_insertlinkafter() would have same behavior in that case, but better be
+ * explicit here. */
+ BLI_addhead(lb, id);
+ }
+ else {
+ BLI_insertlinkafter(lb, idtest, id);
+ }
+ }
+
+#undef ID_SORT_STEP_SIZE
+}
+
+/* Note: this code assumes and ensures that the suffix number can never go beyond 1 billion. */
+#define MAX_NUMBER 1000000000
+/* We do not want to get "name.000", so minimal number is 1. */
+#define MIN_NUMBER 1
+/* The maximum value up to which we search for the actual smallest unused number. Beyond that
+ * value, we will only use the first biggest unused number, without trying to 'fill the gaps'
+ * in-between already used numbers... */
+#define MAX_NUMBERS_IN_USE 1024
+
+/**
+ * Helper building final ID name from given base_name and number.
+ *
+ * If everything goes well and we do generate a valid final ID name in given name, we return true.
+ * In case the final name would overflow the allowed ID name length, or given number is bigger than
+ * maximum allowed value, we truncate further the base_name (and given name, which is assumed to
+ * have the same 'base_name' part), and return false.
+ */
+static bool id_name_final_build(char *name, char *base_name, size_t base_name_len, int number)
+{
+ char number_str[11]; /* Dot + nine digits + NULL terminator. */
+ size_t number_str_len = BLI_snprintf_rlen(number_str, ARRAY_SIZE(number_str), ".%.3d", number);
+
+ /* If the number would lead to an overflow of the maximum ID name length, we need to truncate
+ * the base name part and do all the number checks again. */
+ if (base_name_len + number_str_len >= MAX_ID_NAME - 2 || number >= MAX_NUMBER) {
+ if (base_name_len + number_str_len >= MAX_ID_NAME - 2) {
+ base_name_len = MAX_ID_NAME - 2 - number_str_len - 1;
+ }
+ else {
+ base_name_len--;
+ }
+ base_name[base_name_len] = '\0';
+
+ /* Code above may have generated invalid utf-8 string, due to raw truncation.
+ * Ensure we get a valid one now. */
+ base_name_len -= (size_t)BLI_utf8_invalid_strip(base_name, base_name_len);
+
+ /* Also truncate orig name, and start the whole check again. */
+ name[base_name_len] = '\0';
+ return false;
+ }
+
+ /* We have our final number, we can put it in name and exit the function. */
+ BLI_strncpy(name + base_name_len, number_str, number_str_len + 1);
+ return true;
+}
+
+/**
+ * Check to see if an ID name is already used, and find a new one if so.
+ * Return true if a new name was created (returned in name).
+ *
+ * Normally the ID that's being checked is already in the ListBase, so ID *id points at the new
+ * entry. The Python Library module needs to know what the name of a data-block will be before it
+ * is appended, in this case ID *id is NULL.
+ */
+static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_hint)
+{
+ BLI_assert(strlen(name) < MAX_ID_NAME - 2);
+
+ *r_id_sorting_hint = NULL;
+
+ ID *id_test = lb->first;
+ bool is_name_changed = false;
+
+ if (id_test == NULL) {
+ return is_name_changed;
+ }
+
+ const short id_type = (short)GS(id_test->name);
+
+ /* Static storage of previous handled ID/name info, used to perform a quicker test and optimize
+ * creation of huge number of IDs using the same given base name. */
+ static char prev_orig_base_name[MAX_ID_NAME - 2] = {0};
+ static char prev_final_base_name[MAX_ID_NAME - 2] = {0};
+ static short prev_id_type = ID_LINK_PLACEHOLDER; /* Should never exist in actual ID list. */
+ static int prev_number = MIN_NUMBER - 1;
+
+ /* Initial test to check whether we can 'shortcut' the more complex loop of the main code below.
+ * Note that we do not do that for low numbers, as that would prevent using actual smallest
+ * available number in some cases, and benefits of this special case handling mostly show up with
+ * high numbers anyway. */
+ if (id_type == prev_id_type && prev_number >= MAX_NUMBERS_IN_USE &&
+ prev_number < MAX_NUMBER - 1 && name[0] == prev_final_base_name[0]) {
+
+ /* Get the name and number parts ("name.number"). */
+ char base_name[MAX_ID_NAME - 2];
+ int number = MIN_NUMBER;
+ size_t base_name_len = BLI_split_name_num(base_name, &number, name, '.');
+ size_t prev_final_base_name_len = strlen(prev_final_base_name);
+ size_t prev_orig_base_name_len = strlen(prev_orig_base_name);
+
+ if (base_name_len == prev_orig_base_name_len &&
+ STREQLEN(base_name, prev_orig_base_name, prev_orig_base_name_len)) {
+ /* Once we have ensured given base_name and original previous one are the same, we can check
+ * that previously used number is actually used, and that next one is free. */
+ /* Note that from now on, we only used previous final base name, as it might have been
+ * truncated from original one due to number suffix length. */
+ char final_name[MAX_ID_NAME - 2];
+ char prev_final_name[MAX_ID_NAME - 2];
+ BLI_strncpy(final_name, prev_final_base_name, prev_final_base_name_len + 1);
+ BLI_strncpy(prev_final_name, prev_final_base_name, prev_final_base_name_len + 1);
+
+ if (id_name_final_build(final_name, base_name, prev_final_base_name_len, prev_number + 1) &&
+ id_name_final_build(prev_final_name, base_name, prev_final_base_name_len, prev_number)) {
+ /* We successfully built valid final names of previous and current iterations,
+ * now we have to ensure that previous final name is indeed used in current ID list,
+ * and that current one is not. */
+ bool is_valid = false;
+ for (id_test = lb->first; id_test; id_test = id_test->next) {
+ if (id != id_test && !ID_IS_LINKED(id_test)) {
+ if (id_test->name[2] == final_name[0] && STREQ(final_name, id_test->name + 2)) {
+ /* We expect final_name to not be already used, so this is a failure. */
+ is_valid = false;
+ break;
+ }
+ /* Previous final name should only be found once in the list, so if it was found
+ * already, no need to do a string comparison again. */
+ if (!is_valid && id_test->name[2] == prev_final_name[0] &&
+ STREQ(prev_final_name, id_test->name + 2)) {
+ is_valid = true;
+ *r_id_sorting_hint = id_test;
+ }
+ }
+ }
+
+ if (is_valid) {
+ /* Only the number changed, prev_orig_base_name, prev_final_base_name and prev_id_type
+ * remain the same. */
+ prev_number++;
+
+ strcpy(name, final_name);
+ return true;
+ }
+ }
+ }
+ }
+
+ /* To speed up finding smallest unused number within [0 .. MAX_NUMBERS_IN_USE - 1].
+ * We do not bother beyond that point. */
+ ID *ids_in_use[MAX_NUMBERS_IN_USE] = {NULL};
+
+ bool is_first_run = true;
+ while (true) {
+ /* Get the name and number parts ("name.number"). */
+ char base_name[MAX_ID_NAME - 2];
+ int number = MIN_NUMBER;
+ size_t base_name_len = BLI_split_name_num(base_name, &number, name, '.');
+
+ /* Store previous original given base name now, as we might alter it later in code below. */
+ if (is_first_run) {
+ strcpy(prev_orig_base_name, base_name);
+ is_first_run = false;
+ }
+
+ /* In case we get an insane initial number suffix in given name. */
+ /* Note: BLI_split_name_num() cannot return negative numbers, so we do not have to check for
+ * that here. */
+ if (number >= MAX_NUMBER || number < MIN_NUMBER) {
+ number = MIN_NUMBER;
+ }
+
+ bool is_orig_name_used = false;
+ for (id_test = lb->first; id_test; id_test = id_test->next) {
+ char base_name_test[MAX_ID_NAME - 2];
+ int number_test;
+ if ((id != id_test) && !ID_IS_LINKED(id_test) && (name[0] == id_test->name[2]) &&
+ (id_test->name[base_name_len + 2] == '.' || id_test->name[base_name_len + 2] == '\0') &&
+ STREQLEN(name, id_test->name + 2, base_name_len) &&
+ (BLI_split_name_num(base_name_test, &number_test, id_test->name + 2, '.') ==
+ base_name_len)) {
+ /* If we did not yet encounter exact same name as the given one, check the remaining parts
+ * of the strings. */
+ if (!is_orig_name_used) {
+ is_orig_name_used = STREQ(name + base_name_len, id_test->name + 2 + base_name_len);
+ }
+ /* Mark number of current id_test name as used, if possible. */
+ if (number_test < MAX_NUMBERS_IN_USE) {
+ ids_in_use[number_test] = id_test;
+ }
+ /* Keep track of first largest unused number. */
+ if (number <= number_test) {
+ *r_id_sorting_hint = id_test;
+ number = number_test + 1;
+ }
+ }
+ }
+
+ /* If there is no double, we are done.
+ * Note however that name might have been changed (truncated) in a previous iteration already.
+ */
+ if (!is_orig_name_used) {
+ /* Don't bother updating prev_ static variables here, this case is not supposed to happen
+ * that often, and is not straight-forward here, so just ignore and reset them to default. */
+ prev_id_type = ID_LINK_PLACEHOLDER;
+ prev_final_base_name[0] = '\0';
+ prev_number = MIN_NUMBER - 1;
+
+ /* Value set previously is meaningless in that case. */
+ *r_id_sorting_hint = NULL;
+
+ return is_name_changed;
+ }
+
+ /* Decide which value of number to use, either the smallest unused one if possible, or default
+ * to the first largest unused one we got from previous loop. */
+ for (int i = MIN_NUMBER; i < MAX_NUMBERS_IN_USE; i++) {
+ if (ids_in_use[i] == NULL) {
+ number = i;
+ if (i > 0) {
+ *r_id_sorting_hint = ids_in_use[i - 1];
+ }
+ break;
+ }
+ }
+ /* At this point, number is either the lowest unused number within
+ * [MIN_NUMBER .. MAX_NUMBERS_IN_USE - 1], or 1 greater than the largest used number if all
+ * those low ones are taken.
+ * We can't be bothered to look for the lowest unused number beyond
+ * (MAX_NUMBERS_IN_USE - 1).
+ */
+ /* We know for wure that name will be changed. */
+ is_name_changed = true;
+
+ /* If id_name_final_build helper returns false, it had to truncate further given name, hence we
+ * have to go over the whole check again. */
+ if (!id_name_final_build(name, base_name, base_name_len, number)) {
+ /* We have to clear our list of small used numbers before we do the whole check again. */
+ memset(ids_in_use, 0, sizeof(ids_in_use));
+
+ continue;
+ }
+
+ /* Update prev_ static variables, in case next call is for the same type of IDs and with the
+ * same initial base name, we can skip a lot of above process. */
+ prev_id_type = id_type;
+ strcpy(prev_final_base_name, base_name);
+ prev_number = number;
+
+ return is_name_changed;
+ }
+
+#undef MAX_NUMBERS_IN_USE
+}
+
+#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).
+ *
+ * \return true if a new name had to be created.
+ */
+bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname)
+{
+ bool result;
+ char name[MAX_ID_NAME - 2];
+
+ /* if library, don't rename */
+ if (ID_IS_LINKED(id)) {
+ return false;
+ }
+
+ /* if no name given, use name of current ID
+ * else make a copy (tname args can be const) */
+ if (tname == NULL) {
+ tname = id->name + 2;
+ }
+
+ BLI_strncpy(name, tname, sizeof(name));
+
+ if (name[0] == '\0') {
+ /* Disallow empty names. */
+ BLI_strncpy(name, DATA_(BKE_idcode_to_name(GS(id->name))), sizeof(name));
+ }
+ else {
+ /* disallow non utf8 chars,
+ * the interface checks for this but new ID's based on file names don't */
+ BLI_utf8_invalid_strip(name, strlen(name));
+ }
+
+ ID *id_sorting_hint = NULL;
+ result = check_for_dupid(lb, id, name, &id_sorting_hint);
+ strcpy(id->name + 2, name);
+
+ /* This was in 2.43 and previous releases
+ * however all data in blender should be sorted, not just duplicate names
+ * sorting should not hurt, but noting just in case it alters the way other
+ * functions work, so sort every time. */
+#if 0
+ if (result) {
+ id_sort_by_name(lb, id, id_sorting_hint);
+ }
+#endif
+
+ id_sort_by_name(lb, id, id_sorting_hint);
+
+ return result;
+}
+
+/**
+ * Pull an ID out of a library (make it local). Only call this for IDs that
+ * don't have other library users.
+ */
+void id_clear_lib_data_ex(Main *bmain, ID *id, const bool id_in_mainlist)
+{
+ bNodeTree *ntree = NULL;
+ Key *key = NULL;
+
+ BKE_id_lib_local_paths(bmain, id->lib, id);
+
+ id_fake_user_clear(id);
+
+ id->lib = NULL;
+ id->tag &= ~(LIB_TAG_INDIRECT | LIB_TAG_EXTERN);
+ id->flag &= ~LIB_INDIRECT_WEAK_LINK;
+ if (id_in_mainlist) {
+ if (BKE_id_new_name_validate(which_libbase(bmain, GS(id->name)), id, NULL)) {
+ bmain->is_memfile_undo_written = false;
+ }
+ }
+
+ /* Internal bNodeTree blocks inside data-blocks also stores id->lib,
+ * make sure this stays in sync. */
+ if ((ntree = ntreeFromID(id))) {
+ id_clear_lib_data_ex(bmain, &ntree->id, false); /* Datablocks' nodetree is never in Main. */
+ }
+
+ /* Same goes for shapekeys. */
+ if ((key = BKE_key_from_id(id))) {
+ id_clear_lib_data_ex(bmain, &key->id, id_in_mainlist); /* sigh, why are keys in Main? */
+ }
+}
+
+void id_clear_lib_data(Main *bmain, ID *id)
+{
+ id_clear_lib_data_ex(bmain, id, true);
+}
+
+/* next to indirect usage in read/writefile also in editobject.c scene.c */
+void BKE_main_id_clear_newpoins(Main *bmain)
+{
+ ID *id;
+
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ id->newid = NULL;
+ id->tag &= ~LIB_TAG_NEW;
+ }
+ FOREACH_MAIN_ID_END;
+}
+
+static int id_refcount_recompute_callback(void *user_data,
+ struct ID *UNUSED(id_self),
+ struct ID **id_pointer,
+ int cb_flag)
+{
+ const bool do_linked_only = (bool)POINTER_AS_INT(user_data);
+
+ if (*id_pointer == NULL) {
+ return IDWALK_RET_NOP;
+ }
+ if (do_linked_only && !ID_IS_LINKED(*id_pointer)) {
+ return IDWALK_RET_NOP;
+ }
+
+ if (cb_flag & IDWALK_CB_USER) {
+ /* Do not touch to direct/indirect linked status here... */
+ id_us_plus_no_lib(*id_pointer);
+ }
+ if (cb_flag & IDWALK_CB_USER_ONE) {
+ id_us_ensure_real(*id_pointer);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+void BKE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only)
+{
+ ID *id;
+
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (!ID_IS_LINKED(id) && do_linked_only) {
+ continue;
+ }
+ id->us = ID_FAKE_USERS(id);
+ /* Note that we keep EXTRAUSER tag here, since some UI users may define it too... */
+ if (id->tag & LIB_TAG_EXTRAUSER) {
+ id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET);
+ id_us_ensure_real(id);
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ /* Go over whole Main database to re-generate proper usercounts... */
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ BKE_library_foreach_ID_link(bmain,
+ id,
+ id_refcount_recompute_callback,
+ POINTER_FROM_INT((int)do_linked_only),
+ IDWALK_READONLY);
+ }
+ FOREACH_MAIN_ID_END;
+}
+
+static void library_make_local_copying_check(ID *id,
+ GSet *loop_tags,
+ MainIDRelations *id_relations,
+ GSet *done_ids)
+{
+ if (BLI_gset_haskey(done_ids, id)) {
+ return; /* Already checked, nothing else to do. */
+ }
+
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
+ BLI_gset_insert(loop_tags, id);
+ for (; entry != NULL; entry = entry->next) {
+
+ /* Used_to_user stores ID pointer, not pointer to ID pointer. */
+ ID *par_id = (ID *)entry->id_pointer;
+
+ /* Our oh-so-beloved 'from' pointers... */
+ if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
+ /* We totally disregard Object->proxy_from 'usage' here,
+ * this one would only generate fake positives. */
+ if (GS(par_id->name) == ID_OB) {
+ BLI_assert(((Object *)par_id)->proxy_from == (Object *)id);
+ continue;
+ }
+
+ /* Shapekeys are considered 'private' to their owner ID here, and never tagged
+ * (since they cannot be linked), * so we have to switch effective parent to their owner.
+ */
+ if (GS(par_id->name) == ID_KE) {
+ par_id = ((Key *)par_id)->from;
+ }
+ }
+
+ if (par_id->lib == NULL) {
+ /* Local user, early out to avoid some gset querying... */
+ continue;
+ }
+ if (!BLI_gset_haskey(done_ids, par_id)) {
+ if (BLI_gset_haskey(loop_tags, par_id)) {
+ /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
+ * Note that this is the situation that can lead to archipelagoes of linked data-blocks
+ * (since all of them have non-local users, they would all be duplicated,
+ * leading to a loop of unused linked data-blocks that cannot be freed since they all use
+ * each other...). */
+ continue;
+ }
+ /* Else, recursively check that user ID. */
+ library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids);
+ }
+
+ if (par_id->tag & LIB_TAG_DOIT) {
+ /* This user will be fully local in future, so far so good,
+ * nothing to do here but check next user. */
+ }
+ else {
+ /* This user won't be fully local in future, so current ID won't be either.
+ * And we are done checking it. */
+ id->tag &= ~LIB_TAG_DOIT;
+ break;
+ }
+ }
+ BLI_gset_add(done_ids, 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...
+ */
+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[MAX_LIBARRAY];
+
+ LinkNode *todo_ids = NULL;
+ LinkNode *copied_ids = NULL;
+ MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__);
+
+ GSet *done_ids = BLI_gset_ptr_new(__func__);
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(make_local);
+#endif
+
+ BKE_main_relations_create(bmain);
+
+#ifdef DEBUG_TIME
+ printf("Pre-compute current ID relations: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ /* Step 1: Detect data-blocks to make local. */
+ for (int a = set_listbasepointers(bmain, lbarray); a--;) {
+ ID *id = lbarray[a]->first;
+
+ /* Do not explicitly make local non-linkable IDs (shapekeys, in fact),
+ * they are assumed to be handled by real data-blocks responsible of them. */
+ const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name)));
+
+ for (; id; id = id->next) {
+ ID *ntree = (ID *)ntreeFromID(id);
+
+ id->tag &= ~LIB_TAG_DOIT;
+ if (ntree != NULL) {
+ ntree->tag &= ~LIB_TAG_DOIT;
+ }
+
+ if (id->lib == NULL) {
+ id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
+ id->flag &= ~LIB_INDIRECT_WEAK_LINK;
+ }
+ /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data
+ * you don't want to be made local, used for appending data,
+ * so any libdata already linked wont become local (very nasty
+ * to discover all your links are lost after appending).
+ * Also, never ever make proxified objects local, would not make any sense. */
+ /* Some more notes:
+ * - Shapekeys are never tagged here (since they are not linkable).
+ * - Nodetrees used in materials etc. have to be tagged manually,
+ * since they do not exist in Main (!).
+ * This is ok-ish on 'make local' side of things
+ * (since those are handled by their 'owner' IDs),
+ * but complicates slightly the pre-processing of relations between IDs at step 2... */
+ else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) &&
+ ELEM(lib, NULL, id->lib) &&
+ !(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) &&
+ ((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING))) {
+ BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
+ id->tag |= LIB_TAG_DOIT;
+
+ /* Tag those nasty non-ID nodetrees,
+ * but do not add them to todo list, making them local is handled by 'owner' ID.
+ * This is needed for library_make_local_copying_check() to work OK at step 2. */
+ if (ntree != NULL) {
+ ntree->tag |= LIB_TAG_DOIT;
+ }
+ }
+ else {
+ /* Linked ID that we won't be making local (needed info for step 2, see below). */
+ BLI_gset_add(done_ids, id);
+ }
+ }
+ }
+
+#ifdef DEBUG_TIME
+ printf("Step 1: Detect data-blocks to make local: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ /* Step 2: Check which data-blocks we can directly make local
+ * (because they are only used by already, or future, local data),
+ * others will need to be duplicated. */
+ GSet *loop_tags = BLI_gset_ptr_new(__func__);
+ for (LinkNode *it = todo_ids; it; it = it->next) {
+ library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids);
+ BLI_assert(BLI_gset_len(loop_tags) == 0);
+ }
+ BLI_gset_free(loop_tags, NULL);
+ BLI_gset_free(done_ids, NULL);
+
+ /* Next step will most likely add new IDs, better to get rid of this mapping now. */
+ BKE_main_relations_free(bmain);
+
+#ifdef DEBUG_TIME
+ printf("Step 2: Check which data-blocks we can directly make local: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ /* Step 3: Make IDs local, either directly (quick and simple), or using generic process,
+ * which involves more complex checks and might instead
+ * create a local copy of original linked ID. */
+ for (LinkNode *it = todo_ids, *it_next; it; it = it_next) {
+ it_next = it->next;
+ ID *id = it->link;
+
+ if (id->tag & LIB_TAG_DOIT) {
+ /* We know all users of this object are local or will be made fully local, even if
+ * currently there are some indirect usages. So instead of making a copy that we'll likely
+ * get rid of later, directly make that data block local.
+ * Saves a tremendous amount of time with complex scenes... */
+ id_clear_lib_data_ex(bmain, id, true);
+ BKE_id_expand_local(bmain, id);
+ id->tag &= ~LIB_TAG_DOIT;
+
+ if (GS(id->name) == ID_OB) {
+ BKE_rigidbody_ensure_local_object(bmain, (Object *)id);
+ }
+ }
+ else {
+ /* In this specific case, we do want to make ID local even if it has no local usage yet...
+ */
+ if (GS(id->name) == ID_OB) {
+ /* Special case for objects because we don't want proxy pointers to be
+ * cleared yet. This will happen down the road in this function.
+ */
+ BKE_object_make_local_ex(bmain, (Object *)id, true, false);
+ }
+ else {
+ id_make_local(bmain, id, false, true);
+ }
+
+ if (id->newid) {
+ if (GS(id->newid->name) == ID_OB) {
+ BKE_rigidbody_ensure_local_object(bmain, (Object *)id->newid);
+ }
+
+ /* Reuse already allocated LinkNode (transferring it from todo_ids to copied_ids). */
+ BLI_linklist_prepend_nlink(&copied_ids, id, it);
+ }
+ }
+
+ if (set_fake) {
+ if (!ELEM(GS(id->name), ID_OB, ID_GR)) {
+ /* do not set fake user on objects, groups (instancing) */
+ id_fake_user_set(id);
+ }
+ }
+ }
+
+#ifdef DEBUG_TIME
+ printf("Step 3: Make IDs local: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ /* At this point, we are done with directly made local IDs.
+ * Now we have to handle duplicated ones, since their
+ * remaining linked original counterpart may not be needed anymore... */
+ todo_ids = NULL;
+
+ /* Step 4: We have to remap local usages of old (linked) ID to new (local)
+ * ID in a separated loop,
+ * as lbarray ordering is not enough to ensure us we did catch all dependencies
+ * (e.g. if making local a parent object before its child...). See T48907. */
+ /* TODO This is now the biggest step by far (in term of processing time).
+ * We may be able to gain here by using again main->relations mapping, but...
+ * this implies BKE_libblock_remap & co to be able to update main->relations on the fly.
+ * Have to think about it a bit more, and see whether new code is OK first, anyway. */
+ for (LinkNode *it = copied_ids; it; it = it->next) {
+ ID *id = it->link;
+
+ BLI_assert(id->newid != NULL);
+ BLI_assert(id->lib != NULL);
+
+ BKE_libblock_remap(bmain, id, id->newid, ID_REMAP_SKIP_INDIRECT_USAGE);
+ if (old_to_new_ids) {
+ BLI_ghash_insert(old_to_new_ids, id, id->newid);
+ }
+
+ /* Special hack for groups... Thing is, since we can't instantiate them here, we need to
+ * ensure they remain 'alive' (only instantiation is a real group 'user'... *sigh* See
+ * T49722. */
+ if (GS(id->name) == ID_GR && (id->tag & LIB_TAG_INDIRECT) != 0) {
+ id_us_ensure_real(id->newid);
+ }
+ }
+
+#ifdef DEBUG_TIME
+ printf("Step 4: Remap local usages of old (linked) ID to new (local) ID: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ /* Step 5: proxy 'remapping' hack. */
+ for (LinkNode *it = copied_ids; it; it = it->next) {
+ ID *id = it->link;
+
+ /* 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 (ob->proxy->id.lib == NULL) {
+ CLOG_WARN(&LOG,
+ "proxy object %s will loose 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 loose 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 BKE_object_make_local_ex() (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;
+ }
+ }
+ }
+
+#ifdef DEBUG_TIME
+ printf("Step 5: Proxy 'remapping' hack: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ /* This is probably more of a hack than something we should do here, but...
+ * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels
+ * of armatures in complete invalid state (more precisely, the bone pointers of the
+ * pose-channels - very crappy cross-data-blocks relationship), se we tag it to be fully
+ * recomputed, but this does not seems to be enough in some cases, and evaluation code ends up
+ * trying to evaluate a not-yet-updated armature object's deformations.
+ * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL &&
+ ob->pose->flag & POSE_RECALC) {
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
+ }
+ }
+
+#ifdef DEBUG_TIME
+ printf("Hack: Forcefully rebuild armature object poses: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+ BKE_main_id_clear_newpoins(bmain);
+ BLI_memarena_free(linklist_mem);
+
+#ifdef DEBUG_TIME
+ printf("Cleanup and finish: Done.\n");
+ TIMEIT_END(make_local);
+#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;
+ ID *idtest;
+
+ lb = which_libbase(bmain, GS(name));
+ if (lb == NULL) {
+ return;
+ }
+
+ /* search for id */
+ idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2);
+ if (idtest != NULL) {
+ /* BKE_id_new_name_validate also takes care of sorting. */
+ BKE_id_new_name_validate(lb, idtest, NULL);
+ bmain->is_memfile_undo_written = false;
+ }
+}
+
+/**
+ * Sets the name of a block to name, suitably adjusted for uniqueness.
+ */
+void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
+{
+ ListBase *lb = which_libbase(bmain, GS(id->name));
+ if (BKE_id_new_name_validate(lb, id, name)) {
+ bmain->is_memfile_undo_written = false;
+ }
+}
+
+/**
+ * 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.
+ */
+void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id)
+{
+ strcpy(name, id->name + 2);
+
+ if (id->lib != NULL) {
+ const size_t idname_len = strlen(id->name + 2);
+ const size_t libname_len = strlen(id->lib->id.name + 2);
+
+ name[idname_len] = ' ';
+ name[idname_len + 1] = '[';
+ strcpy(name + idname_len + 2, id->lib->id.name + 2);
+ name[idname_len + 2 + libname_len] = ']';
+ name[idname_len + 2 + libname_len + 1] = '\0';
+ }
+}
+
+/**
+ * Generate full name of the data-block (without ID code, but with library if any),
+ * with a 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.
+ */
+void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const ID *id)
+{
+ name[0] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
+ name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
+ name[2] = ' ';
+
+ BKE_id_full_name_get(name + 3, id);
+}
+
+/**
+ * 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->lib == NULL) {
+ return BLI_strdup(id->name);
+ }
+ else {
+ /* Prefix with an ascii character in the range of 32..96 (visible)
+ * this ensures we can't have a library ID pair that collide.
+ * Where 'LIfooOBbarOBbaz' could be ('LIfoo, OBbarOBbaz') or ('LIfooOBbar', 'OBbaz'). */
+ const char ascii_len = strlen(id->lib->id.name + 2) + 32;
+ return BLI_sprintfN("%c%s%s", ascii_len, id->lib->id.name, id->name);
+ }
+}
+
+void BKE_id_tag_set_atomic(ID *id, int tag)
+{
+ atomic_fetch_and_or_int32(&id->tag, tag);
+}
+
+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...
+ */
+ return (id == NULL || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1);
+}
+
+/************************* Datablock order in UI **************************/
+
+static int *id_order_get(ID *id)
+{
+ /* Only for workspace tabs currently. */
+ switch (GS(id->name)) {
+ case ID_WS:
+ return &((WorkSpace *)id)->order;
+ default:
+ return NULL;
+ }
+}
+
+static int id_order_compare(const void *a, const void *b)
+{
+ ID *id_a = ((LinkData *)a)->data;
+ ID *id_b = ((LinkData *)b)->data;
+
+ int *order_a = id_order_get(id_a);
+ int *order_b = id_order_get(id_b);
+
+ if (order_a && order_b) {
+ if (*order_a < *order_b) {
+ return -1;
+ }
+ else if (*order_a > *order_b) {
+ return 1;
+ }
+ }
+
+ 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);
+
+ for (ID *id = lb->first; id; id = id->next) {
+ BLI_addtail(ordered_lb, BLI_genericNodeN(id));
+ }
+
+ BLI_listbase_sort(ordered_lb, id_order_compare);
+
+ int num = 0;
+ for (LinkData *link = ordered_lb->first; link; link = link->next) {
+ int *order = id_order_get(link->data);
+ if (order) {
+ *order = num++;
+ }
+ }
+}
+
+/**
+ * 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);
+ int relative_order;
+
+ if (relative) {
+ relative_order = *id_order_get(relative);
+ }
+ else {
+ relative_order = (after) ? BLI_listbase_count(lb) : 0;
+ }
+
+ if (after) {
+ /* Insert after. */
+ for (ID *other = lb->first; other; other = other->next) {
+ int *order = id_order_get(other);
+ if (*order > relative_order) {
+ (*order)++;
+ }
+ }
+
+ *id_order = relative_order + 1;
+ }
+ else {
+ /* Insert before. */
+ for (ID *other = lb->first; other; other = other->next) {
+ int *order = id_order_get(other);
+ if (*order < relative_order) {
+ (*order)--;
+ }
+ }
+
+ *id_order = relative_order - 1;
+ }
+}
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
new file mode 100644
index 00000000000..f2fa6946d4b
--- /dev/null
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -0,0 +1,538 @@
+/*
+ * 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
+ *
+ * Contains management of ID's for freeing & deletion.
+ */
+
+#include "MEM_guardedalloc.h"
+
+/* all types are needed here, in order to do memory operations */
+#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_cachefile_types.h"
+#include "DNA_collection_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_light_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_speaker_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_text_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
+#include "DNA_world_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_brush.h"
+#include "BKE_camera.h"
+#include "BKE_cachefile.h"
+#include "BKE_collection.h"
+#include "BKE_curve.h"
+#include "BKE_font.h"
+#include "BKE_gpencil.h"
+#include "BKE_idprop.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_light.h"
+#include "BKE_lattice.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_remap.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+#include "BKE_mask.h"
+#include "BKE_mball.h"
+#include "BKE_movieclip.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_lightprobe.h"
+#include "BKE_speaker.h"
+#include "BKE_sound.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_workspace.h"
+#include "BKE_world.h"
+
+#include "lib_intern.h"
+
+#include "DEG_depsgraph.h"
+
+#ifdef WITH_PYTHON
+# include "BPY_extern.h"
+#endif
+
+/* Not used currently. */
+// static CLG_LogRef LOG = {.identifier = "bke.lib_id_delete"};
+
+void BKE_libblock_free_data(ID *id, const bool do_id_user)
+{
+ if (id->properties) {
+ IDP_FreePropertyContent_ex(id->properties, do_id_user);
+ MEM_freeN(id->properties);
+ }
+
+ if (id->override_library) {
+ BKE_lib_override_library_free(&id->override_library, do_id_user);
+ }
+
+ /* XXX TODO remove animdata handling from each type's freeing func,
+ * and do it here, like for copy! */
+}
+
+void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
+{
+ const short type = GS(id->name);
+ switch (type) {
+ case ID_SCE:
+ BKE_scene_free_ex((Scene *)id, false);
+ break;
+ case ID_LI:
+ BKE_library_free((Library *)id);
+ break;
+ case ID_OB:
+ BKE_object_free((Object *)id);
+ break;
+ case ID_ME:
+ BKE_mesh_free((Mesh *)id);
+ break;
+ case ID_CU:
+ BKE_curve_free((Curve *)id);
+ break;
+ case ID_MB:
+ BKE_mball_free((MetaBall *)id);
+ break;
+ case ID_MA:
+ BKE_material_free((Material *)id);
+ break;
+ case ID_TE:
+ BKE_texture_free((Tex *)id);
+ break;
+ case ID_IM:
+ BKE_image_free((Image *)id);
+ break;
+ case ID_LT:
+ BKE_lattice_free((Lattice *)id);
+ break;
+ case ID_LA:
+ BKE_light_free((Light *)id);
+ break;
+ case ID_CA:
+ BKE_camera_free((Camera *)id);
+ break;
+ case ID_IP: /* Deprecated. */
+ BKE_ipo_free((Ipo *)id);
+ break;
+ case ID_KE:
+ BKE_key_free((Key *)id);
+ break;
+ case ID_WO:
+ BKE_world_free((World *)id);
+ break;
+ case ID_SCR:
+ BKE_screen_free((bScreen *)id);
+ break;
+ case ID_VF:
+ BKE_vfont_free((VFont *)id);
+ break;
+ case ID_TXT:
+ BKE_text_free((Text *)id);
+ break;
+ case ID_SPK:
+ BKE_speaker_free((Speaker *)id);
+ break;
+ case ID_LP:
+ BKE_lightprobe_free((LightProbe *)id);
+ break;
+ case ID_SO:
+ BKE_sound_free((bSound *)id);
+ break;
+ case ID_GR:
+ BKE_collection_free((Collection *)id);
+ break;
+ case ID_AR:
+ BKE_armature_free((bArmature *)id);
+ break;
+ case ID_AC:
+ BKE_action_free((bAction *)id);
+ break;
+ case ID_NT:
+ ntreeFreeTree((bNodeTree *)id);
+ break;
+ case ID_BR:
+ BKE_brush_free((Brush *)id);
+ break;
+ case ID_PA:
+ BKE_particlesettings_free((ParticleSettings *)id);
+ break;
+ case ID_WM:
+ if (free_windowmanager_cb) {
+ free_windowmanager_cb(NULL, (wmWindowManager *)id);
+ }
+ break;
+ case ID_GD:
+ BKE_gpencil_free((bGPdata *)id, true);
+ break;
+ case ID_MC:
+ BKE_movieclip_free((MovieClip *)id);
+ break;
+ case ID_MSK:
+ BKE_mask_free((Mask *)id);
+ break;
+ case ID_LS:
+ BKE_linestyle_free((FreestyleLineStyle *)id);
+ break;
+ case ID_PAL:
+ BKE_palette_free((Palette *)id);
+ break;
+ case ID_PC:
+ BKE_paint_curve_free((PaintCurve *)id);
+ break;
+ case ID_CF:
+ BKE_cachefile_free((CacheFile *)id);
+ break;
+ case ID_WS:
+ BKE_workspace_free((WorkSpace *)id);
+ break;
+ }
+}
+
+/**
+ * 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;
+
+ if (use_flag_from_idtag) {
+ if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
+ flag |= LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_UI_USER | LIB_ID_FREE_NO_DEG_TAG;
+ }
+ else {
+ flag &= ~LIB_ID_FREE_NO_MAIN;
+ }
+
+ if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
+ flag |= LIB_ID_FREE_NO_USER_REFCOUNT;
+ }
+ else {
+ flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT;
+ }
+
+ if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
+ flag |= LIB_ID_FREE_NOT_ALLOCATED;
+ }
+ else {
+ flag &= ~LIB_ID_FREE_NOT_ALLOCATED;
+ }
+ }
+
+ BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL);
+ BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0);
+ BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
+
+ const short type = GS(id->name);
+
+ if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) {
+ DEG_id_type_tag(bmain, type);
+ }
+
+#ifdef WITH_PYTHON
+# ifdef WITH_PYTHON_SAFETY
+ BPY_id_release(id);
+# endif
+ if (id->py_instance) {
+ BPY_DECREF_RNA_INVALIDATE(id->py_instance);
+ }
+#endif
+
+ if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) {
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0);
+ }
+
+ BKE_libblock_free_datablock(id, flag);
+
+ /* avoid notifying on removed data */
+ if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
+ BKE_main_lock(bmain);
+ }
+
+ if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) {
+ if (free_notifier_reference_cb) {
+ free_notifier_reference_cb(id);
+ }
+
+ if (remap_editor_id_reference_cb) {
+ remap_editor_id_reference_cb(id, NULL);
+ }
+ }
+
+ if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
+ ListBase *lb = which_libbase(bmain, type);
+ BLI_remlink(lb, id);
+ }
+
+ BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
+
+ if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
+ BKE_main_unlock(bmain);
+ }
+
+ if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) {
+ MEM_freeN(id);
+ }
+}
+
+/**
+ * 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;
+
+ id_us_min(id);
+
+ /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding collections
+ * when deleting an object. Since only 'user_one' usage of objects is collections,
+ * and only 'real user' usage of objects is scenes, removing that 'user_one' tag when there
+ * is no more real (scene) users of an object ensures it gets fully unlinked.
+ * But only for local objects, not linked ones!
+ * Otherwise, there is no real way to get rid of an object anymore -
+ * better handling of this is TODO.
+ */
+ if ((GS(id->name) == ID_OB) && (id->us == 1) && (id->lib == NULL)) {
+ id_us_clear_real(id);
+ }
+
+ if (id->us == 0) {
+ BKE_libblock_unlink(bmain, id, false, false);
+
+ BKE_id_free(bmain, id);
+ }
+}
+
+static void id_delete(Main *bmain, const bool do_tagged_deletion)
+{
+ const int tag = LIB_TAG_DOIT;
+ ListBase *lbarray[MAX_LIBARRAY];
+ Link dummy_link = {0};
+ int base_count, i;
+
+ /* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database,
+ * and has already properly unlinked its other IDs usages.
+ * UI users are always cleared in BKE_libblock_remap_locked() call, so we can always skip it. */
+ const int free_flag = LIB_ID_FREE_NO_UI_USER |
+ (do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT :
+ 0);
+ ListBase tagged_deleted_ids = {NULL};
+
+ base_count = set_listbasepointers(bmain, lbarray);
+
+ BKE_main_lock(bmain);
+ if (do_tagged_deletion) {
+ /* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
+ * This means that we won't have to loop over all deleted IDs to remove usages
+ * of other deleted IDs.
+ * This gives tremendous speed-up when deleting a large amount of IDs from a Main
+ * containing thousands of those.
+ * This also means that we have to be very careful here, as we by-pass many 'common'
+ * processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
+ bool keep_looping = true;
+ while (keep_looping) {
+ ID *id, *id_next;
+ ID *last_remapped_id = tagged_deleted_ids.last;
+ keep_looping = false;
+
+ /* First tag and remove from Main all datablocks directly from target lib.
+ * Note that we go forward here, since we want to check dependencies before users
+ * (e.g. meshes before objects). Avoids to have to loop twice. */
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+
+ for (id = lb->first; id; id = id_next) {
+ id_next = id->next;
+ /* Note: in case we delete a library, we also delete all its datablocks! */
+ if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
+ BLI_remlink(lb, id);
+ BLI_addtail(&tagged_deleted_ids, id);
+ /* Do not tag as no_main now, we want to unlink it first (lower-level ID management
+ * code has some specific handling of 'nom main'
+ * IDs that would be a problem in that case). */
+ id->tag |= tag;
+ keep_looping = true;
+ }
+ }
+ }
+ if (last_remapped_id == NULL) {
+ dummy_link.next = tagged_deleted_ids.first;
+ last_remapped_id = (ID *)(&dummy_link);
+ }
+ for (id = last_remapped_id->next; id; id = id->next) {
+ /* Will tag 'never NULL' users of this ID too.
+ * Note that we cannot use BKE_libblock_unlink() here,
+ * since it would ignore indirect (and proxy!)
+ * links, this can lead to nasty crashing here in second, actual deleting loop.
+ * Also, this will also flag users of deleted data that cannot be unlinked
+ * (object using deleted obdata, etc.), so that they also get deleted. */
+ BKE_libblock_remap_locked(
+ bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE);
+ /* Since we removed ID from Main,
+ * we also need to unlink its own other IDs usages ourself. */
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0);
+ /* Now we can safely mark that ID as not being in Main database anymore. */
+ id->tag |= LIB_TAG_NO_MAIN;
+ /* This is needed because we may not have remapped usages
+ * of that ID by other deleted ones. */
+ // id->us = 0; /* Is it actually? */
+ }
+ }
+ }
+ else {
+ /* First tag all datablocks directly from target lib.
+ * Note that we go forward here, since we want to check dependencies before users
+ * (e.g. meshes before objects).
+ * Avoids to have to loop twice. */
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id, *id_next;
+
+ for (id = lb->first; id; id = id_next) {
+ id_next = id->next;
+ /* Note: in case we delete a library, we also delete all its datablocks! */
+ if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
+ id->tag |= tag;
+
+ /* Will tag 'never NULL' users of this ID too.
+ * Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect
+ * (and proxy!) links, this can lead to nasty crashing here in second,
+ * actual deleting loop.
+ * Also, this will also flag users of deleted data that cannot be unlinked
+ * (object using deleted obdata, etc.), so that they also get deleted. */
+ BKE_libblock_remap_locked(
+ bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE);
+ }
+ }
+ }
+ }
+ BKE_main_unlock(bmain);
+
+ /* In usual reversed order, such that all usage of a given ID, even 'never NULL' ones,
+ * have been already cleared when we reach it
+ * (e.g. Objects being processed before meshes, they'll have already released their 'reference'
+ * over meshes when we come to freeing obdata). */
+ for (i = do_tagged_deletion ? 1 : base_count; i--;) {
+ ListBase *lb = lbarray[i];
+ ID *id, *id_next;
+
+ for (id = do_tagged_deletion ? tagged_deleted_ids.first : lb->first; id; id = id_next) {
+ id_next = id->next;
+ if (id->tag & tag) {
+ if (id->us != 0) {
+#ifdef DEBUG_PRINT
+ printf("%s: deleting %s (%d)\n", __func__, id->name, id->us);
+#endif
+ BLI_assert(id->us == 0);
+ }
+ BKE_id_free_ex(bmain, id, free_flag, !do_tagged_deletion);
+ }
+ }
+ }
+
+ bmain->is_memfile_undo_written = false;
+}
+
+/**
+ * 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);
+ ((ID *)idv)->tag |= LIB_TAG_DOIT;
+
+ 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.
+ */
+void BKE_id_multi_tagged_delete(Main *bmain)
+{
+ id_delete(bmain, true);
+}
diff --git a/source/blender/blenlib/BLI_temporary_allocator_cxx.h b/source/blender/blenkernel/intern/lib_intern.h
index 06159f68059..bd5e4a8dfe2 100644
--- a/source/blender/blenlib/BLI_temporary_allocator_cxx.h
+++ b/source/blender/blenkernel/intern/lib_intern.h
@@ -12,27 +12,22 @@
* 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) 2018 by Blender Foundation.
+ * All rights reserved.
*/
-#ifndef __BLI_TEMPORARY_ALLOCATOR_CXX_H__
-#define __BLI_TEMPORARY_ALLOCATOR_CXX_H__
-
/** \file
- * \ingroup bli
+ * \ingroup bke
*/
-#include "BLI_temporary_allocator.h"
-
-namespace BLI {
+#ifndef __LIB_INTERN_H__
+#define __LIB_INTERN_H__
-template<typename T> class MutableArrayRef;
+extern BKE_library_free_window_manager_cb free_windowmanager_cb;
-template<typename T> MutableArrayRef<T> temporary_allocate_array(uint size)
-{
- void *ptr = BLI_temporary_allocate(sizeof(T) * size);
- return MutableArrayRef<T>((T *)ptr, size);
-}
+extern BKE_library_free_notifier_reference_cb free_notifier_reference_cb;
-}; // namespace BLI
+extern BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb;
-#endif /* __BLI_TEMPORARY_ALLOCATOR_CXX_H__ */
+#endif /* __LIB_INTERN_H__ */
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/lib_override.c
index a8cc37973f2..af861b5b0e9 100644
--- a/source/blender/blenkernel/intern/library_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -32,9 +32,9 @@
#include "DEG_depsgraph.h"
#include "BKE_armature.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BLI_utildefines.h"
@@ -45,35 +45,33 @@
#include "RNA_access.h"
#include "RNA_types.h"
-#include "PIL_time.h"
-#include "PIL_time_utildefines.h"
-
#define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */
-static void bke_override_property_copy(IDOverrideLibraryProperty *op_dst,
- IDOverrideLibraryProperty *op_src);
-static void bke_override_property_operation_copy(IDOverrideLibraryPropertyOperation *opop_dst,
- IDOverrideLibraryPropertyOperation *opop_src);
+static void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst,
+ IDOverrideLibraryProperty *op_src);
+static void lib_override_library_property_operation_copy(
+ IDOverrideLibraryPropertyOperation *opop_dst, IDOverrideLibraryPropertyOperation *opop_src);
-static void bke_override_property_clear(IDOverrideLibraryProperty *op);
-static void bke_override_property_operation_clear(IDOverrideLibraryPropertyOperation *opop);
+static void lib_override_library_property_clear(IDOverrideLibraryProperty *op);
+static void lib_override_library_property_operation_clear(
+ IDOverrideLibraryPropertyOperation *opop);
/* Temp, for until library override is ready and tested enough to go 'public',
* we hide it by default in UI and such. */
-static bool _override_library_enabled = true;
+static bool _lib_override_library_enabled = true;
-void BKE_override_library_enable(const bool do_enable)
+void BKE_lib_override_library_enable(const bool do_enable)
{
- _override_library_enabled = do_enable;
+ _lib_override_library_enabled = do_enable;
}
-bool BKE_override_library_is_enabled()
+bool BKE_lib_override_library_is_enabled()
{
- return _override_library_enabled;
+ return _lib_override_library_enabled;
}
/** Initialize empty overriding of \a reference_id by \a local_id. */
-IDOverrideLibrary *BKE_override_library_init(ID *local_id, ID *reference_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.
* Else, reference *must* be linked data. */
@@ -89,7 +87,7 @@ IDOverrideLibrary *BKE_override_library_init(ID *local_id, ID *reference_id)
if (ancestor_id != NULL && ancestor_id->override_library != NULL) {
/* Original ID has a template, use it! */
- BKE_override_library_copy(local_id, ancestor_id);
+ BKE_lib_override_library_copy(local_id, ancestor_id);
if (local_id->override_library->reference != reference_id) {
id_us_min(local_id->override_library->reference);
local_id->override_library->reference = reference_id;
@@ -108,24 +106,24 @@ IDOverrideLibrary *BKE_override_library_init(ID *local_id, ID *reference_id)
}
/** Deep copy of a whole override from \a src_id to \a dst_id. */
-void BKE_override_library_copy(ID *dst_id, const ID *src_id)
+void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id)
{
BLI_assert(src_id->override_library != NULL);
if (dst_id->override_library != NULL) {
if (src_id->override_library == NULL) {
- BKE_override_library_free(&dst_id->override_library, true);
+ BKE_lib_override_library_free(&dst_id->override_library, true);
return;
}
else {
- BKE_override_library_clear(dst_id->override_library, true);
+ BKE_lib_override_library_clear(dst_id->override_library, true);
}
}
else if (src_id->override_library == NULL) {
return;
}
else {
- BKE_override_library_init(dst_id, NULL);
+ BKE_lib_override_library_init(dst_id, NULL);
}
/* Source is already overriding data, we copy it but reuse its reference for dest ID.
@@ -140,14 +138,14 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id)
*op_src = src_id->override_library->properties.first;
op_dst;
op_dst = op_dst->next, op_src = op_src->next) {
- bke_override_property_copy(op_dst, op_src);
+ lib_override_library_property_copy(op_dst, op_src);
}
dst_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK;
}
/** Clear any overriding data from given \a override. */
-void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_user)
+void BKE_lib_override_library_clear(IDOverrideLibrary *override, const bool do_id_user)
{
BLI_assert(override != NULL);
@@ -156,7 +154,7 @@ void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_us
}
for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) {
- bke_override_property_clear(op);
+ lib_override_library_property_clear(op);
}
BLI_freelistN(&override->properties);
@@ -167,7 +165,7 @@ void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_us
}
/** Free given \a override. */
-void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user)
+void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user)
{
BLI_assert(*override != NULL);
@@ -176,12 +174,12 @@ void BKE_override_library_free(struct IDOverrideLibrary **override, const bool d
(*override)->runtime = NULL;
}
- BKE_override_library_clear(*override, do_id_user);
+ BKE_lib_override_library_clear(*override, do_id_user);
MEM_freeN(*override);
*override = NULL;
}
-static ID *override_library_create_from(Main *bmain, ID *reference_id)
+static ID *lib_override_library_create_from(Main *bmain, ID *reference_id)
{
ID *local_id;
@@ -190,19 +188,21 @@ static ID *override_library_create_from(Main *bmain, ID *reference_id)
}
id_us_min(local_id);
- BKE_override_library_init(local_id, reference_id);
+ BKE_lib_override_library_init(local_id, reference_id);
local_id->override_library->flag |= OVERRIDE_LIBRARY_AUTO;
return local_id;
}
/** Create an overridden local copy of linked reference. */
-ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id, const bool do_tagged_remap)
+ID *BKE_lib_override_library_create_from_id(Main *bmain,
+ ID *reference_id,
+ const bool do_tagged_remap)
{
BLI_assert(reference_id != NULL);
BLI_assert(reference_id->lib != NULL);
- ID *local_id = override_library_create_from(bmain, reference_id);
+ ID *local_id = lib_override_library_create_from(bmain, reference_id);
if (do_tagged_remap) {
ID *other_id;
@@ -236,7 +236,7 @@ ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id, const boo
*
* \return \a true on success, \a false otherwise.
*/
-bool BKE_override_library_create_from_tag(Main *bmain)
+bool BKE_lib_override_library_create_from_tag(Main *bmain)
{
ID *reference_id;
bool ret = true;
@@ -257,7 +257,7 @@ bool BKE_override_library_create_from_tag(Main *bmain)
/* Override the IDs. */
for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) {
reference_id = todo_id_iter->data;
- if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) {
+ if ((reference_id->newid = lib_override_library_create_from(bmain, reference_id)) == NULL) {
ret = false;
}
else {
@@ -315,8 +315,8 @@ BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure(
/**
* Find override property from given RNA path, if it exists.
*/
-IDOverrideLibraryProperty *BKE_override_library_property_find(IDOverrideLibrary *override,
- const char *rna_path)
+IDOverrideLibraryProperty *BKE_lib_override_library_property_find(IDOverrideLibrary *override,
+ const char *rna_path)
{
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure(override);
return BLI_ghash_lookup(override_runtime, rna_path);
@@ -325,11 +325,11 @@ IDOverrideLibraryProperty *BKE_override_library_property_find(IDOverrideLibrary
/**
* Find override property from given RNA path, or create it if it does not exist.
*/
-IDOverrideLibraryProperty *BKE_override_library_property_get(IDOverrideLibrary *override,
- const char *rna_path,
- bool *r_created)
+IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibrary *override,
+ const char *rna_path,
+ bool *r_created)
{
- IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path);
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(override, rna_path);
if (op == NULL) {
op = MEM_callocN(sizeof(IDOverrideLibraryProperty), __func__);
@@ -351,8 +351,8 @@ IDOverrideLibraryProperty *BKE_override_library_property_get(IDOverrideLibrary *
return op;
}
-void bke_override_property_copy(IDOverrideLibraryProperty *op_dst,
- IDOverrideLibraryProperty *op_src)
+void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst,
+ IDOverrideLibraryProperty *op_src)
{
op_dst->rna_path = BLI_strdup(op_src->rna_path);
BLI_duplicatelist(&op_dst->operations, &op_src->operations);
@@ -361,18 +361,18 @@ void bke_override_property_copy(IDOverrideLibraryProperty *op_dst,
*opop_src = op_src->operations.first;
opop_dst;
opop_dst = opop_dst->next, opop_src = opop_src->next) {
- bke_override_property_operation_copy(opop_dst, opop_src);
+ lib_override_library_property_operation_copy(opop_dst, opop_src);
}
}
-void bke_override_property_clear(IDOverrideLibraryProperty *op)
+void lib_override_library_property_clear(IDOverrideLibraryProperty *op)
{
BLI_assert(op->rna_path != NULL);
MEM_freeN(op->rna_path);
for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
- bke_override_property_operation_clear(opop);
+ lib_override_library_property_operation_clear(opop);
}
BLI_freelistN(&op->operations);
}
@@ -380,10 +380,10 @@ void bke_override_property_clear(IDOverrideLibraryProperty *op)
/**
* Remove and free given \a override_property from given ID \a override.
*/
-void BKE_override_library_property_delete(IDOverrideLibrary *override,
- IDOverrideLibraryProperty *override_property)
+void BKE_lib_override_library_property_delete(IDOverrideLibrary *override,
+ IDOverrideLibraryProperty *override_property)
{
- bke_override_property_clear(override_property);
+ lib_override_library_property_clear(override_property);
if (override->runtime != NULL) {
BLI_ghash_remove(override->runtime, override_property->rna_path, NULL, NULL);
}
@@ -393,7 +393,7 @@ void BKE_override_library_property_delete(IDOverrideLibrary *override,
/**
* Find override property operation from given sub-item(s), if it exists.
*/
-IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_find(
+IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_find(
IDOverrideLibraryProperty *override_property,
const char *subitem_refname,
const char *subitem_locname,
@@ -481,7 +481,7 @@ IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_find
/**
* Find override property operation from given sub-item(s), or create it if it does not exist.
*/
-IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_get(
+IDOverrideLibraryPropertyOperation *BKE_lib_override_library_property_operation_get(
IDOverrideLibraryProperty *override_property,
const short operation,
const char *subitem_refname,
@@ -492,7 +492,7 @@ IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_get(
bool *r_strict,
bool *r_created)
{
- IDOverrideLibraryPropertyOperation *opop = BKE_override_library_property_operation_find(
+ IDOverrideLibraryPropertyOperation *opop = BKE_lib_override_library_property_operation_find(
override_property,
subitem_refname,
subitem_locname,
@@ -526,8 +526,8 @@ IDOverrideLibraryPropertyOperation *BKE_override_library_property_operation_get(
return opop;
}
-void bke_override_property_operation_copy(IDOverrideLibraryPropertyOperation *opop_dst,
- IDOverrideLibraryPropertyOperation *opop_src)
+void lib_override_library_property_operation_copy(IDOverrideLibraryPropertyOperation *opop_dst,
+ IDOverrideLibraryPropertyOperation *opop_src)
{
if (opop_src->subitem_reference_name) {
opop_dst->subitem_reference_name = BLI_strdup(opop_src->subitem_reference_name);
@@ -537,7 +537,7 @@ void bke_override_property_operation_copy(IDOverrideLibraryPropertyOperation *op
}
}
-void bke_override_property_operation_clear(IDOverrideLibraryPropertyOperation *opop)
+void lib_override_library_property_operation_clear(IDOverrideLibraryPropertyOperation *opop)
{
if (opop->subitem_reference_name) {
MEM_freeN(opop->subitem_reference_name);
@@ -550,11 +550,11 @@ void bke_override_property_operation_clear(IDOverrideLibraryPropertyOperation *o
/**
* Remove and free given \a override_property_operation from given ID \a override_property.
*/
-void BKE_override_library_property_operation_delete(
+void BKE_lib_override_library_property_operation_delete(
IDOverrideLibraryProperty *override_property,
IDOverrideLibraryPropertyOperation *override_property_operation)
{
- bke_override_property_operation_clear(override_property_operation);
+ lib_override_library_property_operation_clear(override_property_operation);
BLI_freelinkN(&override_property->operations, override_property_operation);
}
@@ -568,7 +568,7 @@ void BKE_override_library_property_operation_delete(
* #IDOverrideProperty (of #IDOverridePropertyOperation) has to be added.
*
* \return true if status is OK, false otherwise. */
-bool BKE_override_library_status_check_local(Main *bmain, ID *local)
+bool BKE_lib_override_library_status_check_local(Main *bmain, ID *local)
{
BLI_assert(local->override_library != NULL);
@@ -623,7 +623,7 @@ bool BKE_override_library_status_check_local(Main *bmain, ID *local)
* needs to be updated against it.
*
* \return true if status is OK, false otherwise. */
-bool BKE_override_library_status_check_reference(Main *bmain, ID *local)
+bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
{
BLI_assert(local->override_library != NULL);
@@ -637,7 +637,7 @@ bool BKE_override_library_status_check_reference(Main *bmain, ID *local)
BLI_assert(GS(local->name) == GS(reference->name));
if (reference->override_library && (reference->tag & LIB_TAG_OVERRIDE_LIBRARY_REFOK) == 0) {
- if (!BKE_override_library_status_check_reference(bmain, reference)) {
+ if (!BKE_lib_override_library_status_check_reference(bmain, reference)) {
/* If reference is also override of another data-block, and its status is not OK,
* then this override is not OK either.
* Note that this should only happen when reloading libraries... */
@@ -688,7 +688,7 @@ bool BKE_override_library_status_check_reference(Main *bmain, ID *local)
* Generating diff values and applying overrides are much cheaper.
*
* \return true if new overriding op was created, or some local data was reset. */
-bool BKE_override_library_operations_create(Main *bmain, ID *local, const bool force_auto)
+bool BKE_lib_override_library_operations_create(Main *bmain, ID *local, const bool force_auto)
{
BLI_assert(local->override_library != NULL);
const bool is_template = (local->override_library->reference == NULL);
@@ -744,14 +744,14 @@ bool BKE_override_library_operations_create(Main *bmain, ID *local, const bool f
}
/** Check all overrides from given \a bmain and create/update overriding operations as needed. */
-void BKE_main_override_library_operations_create(Main *bmain, const bool force_auto)
+void BKE_lib_override_library_main_operations_create(Main *bmain, const bool force_auto)
{
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if ((ID_IS_OVERRIDE_LIBRARY(id) && force_auto) ||
(ID_IS_OVERRIDE_LIBRARY_AUTO(id) && (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) {
- BKE_override_library_operations_create(bmain, id, force_auto);
+ BKE_lib_override_library_operations_create(bmain, id, force_auto);
id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
}
}
@@ -759,7 +759,7 @@ void BKE_main_override_library_operations_create(Main *bmain, const bool force_a
}
/** Update given override from its reference (re-applying overridden properties). */
-void BKE_override_library_update(Main *bmain, ID *local)
+void BKE_lib_override_library_update(Main *bmain, ID *local)
{
if (local->override_library == NULL || local->override_library->reference == NULL) {
return;
@@ -775,7 +775,7 @@ void BKE_override_library_update(Main *bmain, ID *local)
/* Recursively do 'ancestors' overrides first, if any. */
if (local->override_library->reference->override_library &&
(local->override_library->reference->tag & LIB_TAG_OVERRIDE_LIBRARY_REFOK) == 0) {
- BKE_override_library_update(bmain, local->override_library->reference);
+ BKE_lib_override_library_update(bmain, local->override_library->reference);
}
/* We want to avoid having to remap here, however creating up-to-date override is much simpler
@@ -837,13 +837,13 @@ void BKE_override_library_update(Main *bmain, ID *local)
}
/** Update all overrides from given \a bmain. */
-void BKE_main_override_library_update(Main *bmain)
+void BKE_lib_override_library_main_update(Main *bmain)
{
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (id->override_library != NULL && id->lib == NULL) {
- BKE_override_library_update(bmain, id);
+ BKE_lib_override_library_update(bmain, id);
}
}
FOREACH_MAIN_ID_END;
@@ -867,7 +867,7 @@ void BKE_main_override_library_update(Main *bmain)
*/
/** Initialize an override storage. */
-OverrideLibraryStorage *BKE_override_library_operations_store_initialize(void)
+OverrideLibraryStorage *BKE_lib_override_library_operations_store_initialize(void)
{
return BKE_main_new();
}
@@ -877,9 +877,9 @@ OverrideLibraryStorage *BKE_override_library_operations_store_initialize(void)
*
* 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_override_library_operations_store_start(Main *bmain,
- OverrideLibraryStorage *override_storage,
- ID *local)
+ID *BKE_lib_override_library_operations_store_start(Main *bmain,
+ OverrideLibraryStorage *override_storage,
+ ID *local)
{
BLI_assert(local->override_library != NULL);
BLI_assert(override_storage != NULL);
@@ -891,7 +891,7 @@ ID *BKE_override_library_operations_store_start(Main *bmain,
}
/* Forcefully ensure we know about all needed override operations. */
- BKE_override_library_operations_create(bmain, local, false);
+ BKE_lib_override_library_operations_create(bmain, local, false);
ID *storage_id;
#ifdef DEBUG_OVERRIDE_TIMEIT
@@ -929,8 +929,8 @@ ID *BKE_override_library_operations_store_start(Main *bmain,
}
/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */
-void BKE_override_library_operations_store_end(OverrideLibraryStorage *UNUSED(override_storage),
- ID *local)
+void BKE_lib_override_library_operations_store_end(
+ OverrideLibraryStorage *UNUSED(override_storage), ID *local)
{
BLI_assert(local->override_library != NULL);
@@ -939,7 +939,7 @@ void BKE_override_library_operations_store_end(OverrideLibraryStorage *UNUSED(ov
local->override_library->storage = NULL;
}
-void BKE_override_library_operations_store_finalize(OverrideLibraryStorage *override_storage)
+void BKE_lib_override_library_operations_store_finalize(OverrideLibraryStorage *override_storage)
{
/* We cannot just call BKE_main_free(override_storage), not until we have option to make 'ghost'
* copies of IDs without increasing usercount of used data-blocks. */
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/lib_query.c
index 5fd852ff089..cf4c96a70e9 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -23,8 +23,6 @@
#include <stdlib.h>
-#include "MEM_guardedalloc.h"
-
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
@@ -38,7 +36,6 @@
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
@@ -67,8 +64,8 @@
#include "BKE_fcurve.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
@@ -76,7 +73,6 @@
#include "BKE_rigidbody.h"
#include "BKE_sequencer.h"
#include "BKE_shader_fx.h"
-#include "BKE_tracking.h"
#include "BKE_workspace.h"
#define FOREACH_FINALIZE _finalize
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index 72b94e7b356..9b6d62a87aa 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/lib_remap.c
@@ -17,123 +17,52 @@
/** \file
* \ingroup bke
*
- * Contains management of ID's and libraries remap, unlink and free logic.
+ * Contains management of ID's for remapping.
*/
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <assert.h>
-
#include "CLG_log.h"
-#include "MEM_guardedalloc.h"
-
-/* all types are needed here, in order to do memory operations */
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_key_types.h"
-#include "DNA_light_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_linestyle_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_lightprobe_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_speaker_types.h"
-#include "DNA_sound_types.h"
-#include "DNA_text_types.h"
-#include "DNA_vfont_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_workspace_types.h"
-#include "DNA_world_types.h"
-
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BKE_action.h"
-#include "BKE_animsys.h"
+#include "DNA_object_types.h"
+
#include "BKE_armature.h"
-#include "BKE_brush.h"
-#include "BKE_camera.h"
-#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_curve.h"
-#include "BKE_fcurve.h"
-#include "BKE_font.h"
-#include "BKE_gpencil.h"
-#include "BKE_idprop.h"
-#include "BKE_image.h"
-#include "BKE_ipo.h"
-#include "BKE_key.h"
-#include "BKE_light.h"
-#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
-#include "BKE_linestyle.h"
-#include "BKE_mesh.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_material.h"
#include "BKE_main.h"
-#include "BKE_mask.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
-#include "BKE_movieclip.h"
#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_lightprobe.h"
-#include "BKE_speaker.h"
-#include "BKE_sound.h"
-#include "BKE_screen.h"
-#include "BKE_scene.h"
-#include "BKE_text.h"
-#include "BKE_texture.h"
-#include "BKE_workspace.h"
-#include "BKE_world.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#ifdef WITH_PYTHON
-# include "BPY_extern.h"
-#endif
+#include "lib_intern.h" /* own include */
-static CLG_LogRef LOG = {"bke.library_remap"};
+static CLG_LogRef LOG = {.identifier = "bke.lib_remap"};
-static BKE_library_free_window_manager_cb free_windowmanager_cb = NULL;
+BKE_library_free_window_manager_cb free_windowmanager_cb = NULL;
void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func)
{
free_windowmanager_cb = func;
}
-static BKE_library_free_notifier_reference_cb free_notifier_reference_cb = NULL;
+BKE_library_free_notifier_reference_cb free_notifier_reference_cb = NULL;
void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func)
{
free_notifier_reference_cb = func;
}
-static BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb = NULL;
+BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb = NULL;
void BKE_library_callback_remap_editor_id_reference_set(
BKE_library_remap_editor_id_reference_cb func)
@@ -159,7 +88,7 @@ typedef struct IDRemap {
int skipped_refcounted;
} IDRemap;
-/* IDRemap->flag enums defined in BKE_library.h */
+/* IDRemap->flag enums defined in BKE_lib.h */
/* IDRemap->status */
enum {
@@ -752,433 +681,3 @@ void BKE_libblock_relink_to_newid(ID *id)
BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
}
-
-void BKE_libblock_free_data(ID *id, const bool do_id_user)
-{
- if (id->properties) {
- IDP_FreePropertyContent_ex(id->properties, do_id_user);
- MEM_freeN(id->properties);
- }
-
- if (id->override_library) {
- BKE_override_library_free(&id->override_library, do_id_user);
- }
-
- /* XXX TODO remove animdata handling from each type's freeing func,
- * and do it here, like for copy! */
-}
-
-void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
-{
- const short type = GS(id->name);
- switch (type) {
- case ID_SCE:
- BKE_scene_free_ex((Scene *)id, false);
- break;
- case ID_LI:
- BKE_library_free((Library *)id);
- break;
- case ID_OB:
- BKE_object_free((Object *)id);
- break;
- case ID_ME:
- BKE_mesh_free((Mesh *)id);
- break;
- case ID_CU:
- BKE_curve_free((Curve *)id);
- break;
- case ID_MB:
- BKE_mball_free((MetaBall *)id);
- break;
- case ID_MA:
- BKE_material_free((Material *)id);
- break;
- case ID_TE:
- BKE_texture_free((Tex *)id);
- break;
- case ID_IM:
- BKE_image_free((Image *)id);
- break;
- case ID_LT:
- BKE_lattice_free((Lattice *)id);
- break;
- case ID_LA:
- BKE_light_free((Light *)id);
- break;
- case ID_CA:
- BKE_camera_free((Camera *)id);
- break;
- case ID_IP: /* Deprecated. */
- BKE_ipo_free((Ipo *)id);
- break;
- case ID_KE:
- BKE_key_free((Key *)id);
- break;
- case ID_WO:
- BKE_world_free((World *)id);
- break;
- case ID_SCR:
- BKE_screen_free((bScreen *)id);
- break;
- case ID_VF:
- BKE_vfont_free((VFont *)id);
- break;
- case ID_TXT:
- BKE_text_free((Text *)id);
- break;
- case ID_SPK:
- BKE_speaker_free((Speaker *)id);
- break;
- case ID_LP:
- BKE_lightprobe_free((LightProbe *)id);
- break;
- case ID_SO:
- BKE_sound_free((bSound *)id);
- break;
- case ID_GR:
- BKE_collection_free((Collection *)id);
- break;
- case ID_AR:
- BKE_armature_free((bArmature *)id);
- break;
- case ID_AC:
- BKE_action_free((bAction *)id);
- break;
- case ID_NT:
- ntreeFreeTree((bNodeTree *)id);
- break;
- case ID_BR:
- BKE_brush_free((Brush *)id);
- break;
- case ID_PA:
- BKE_particlesettings_free((ParticleSettings *)id);
- break;
- case ID_WM:
- if (free_windowmanager_cb) {
- free_windowmanager_cb(NULL, (wmWindowManager *)id);
- }
- break;
- case ID_GD:
- BKE_gpencil_free((bGPdata *)id, true);
- break;
- case ID_MC:
- BKE_movieclip_free((MovieClip *)id);
- break;
- case ID_MSK:
- BKE_mask_free((Mask *)id);
- break;
- case ID_LS:
- BKE_linestyle_free((FreestyleLineStyle *)id);
- break;
- case ID_PAL:
- BKE_palette_free((Palette *)id);
- break;
- case ID_PC:
- BKE_paint_curve_free((PaintCurve *)id);
- break;
- case ID_CF:
- BKE_cachefile_free((CacheFile *)id);
- break;
- case ID_WS:
- BKE_workspace_free((WorkSpace *)id);
- break;
- }
-}
-
-/**
- * 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;
-
- if (use_flag_from_idtag) {
- if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
- flag |= LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_UI_USER | LIB_ID_FREE_NO_DEG_TAG;
- }
- else {
- flag &= ~LIB_ID_FREE_NO_MAIN;
- }
-
- if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
- flag |= LIB_ID_FREE_NO_USER_REFCOUNT;
- }
- else {
- flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT;
- }
-
- if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
- flag |= LIB_ID_FREE_NOT_ALLOCATED;
- }
- else {
- flag &= ~LIB_ID_FREE_NOT_ALLOCATED;
- }
- }
-
- BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL);
- BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0);
- BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
-
- const short type = GS(id->name);
-
- if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) {
- DEG_id_type_tag(bmain, type);
- }
-
-#ifdef WITH_PYTHON
-# ifdef WITH_PYTHON_SAFETY
- BPY_id_release(id);
-# endif
- if (id->py_instance) {
- BPY_DECREF_RNA_INVALIDATE(id->py_instance);
- }
-#endif
-
- if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) {
- BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0);
- }
-
- BKE_libblock_free_datablock(id, flag);
-
- /* avoid notifying on removed data */
- if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
- BKE_main_lock(bmain);
- }
-
- if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) {
- if (free_notifier_reference_cb) {
- free_notifier_reference_cb(id);
- }
-
- if (remap_editor_id_reference_cb) {
- remap_editor_id_reference_cb(id, NULL);
- }
- }
-
- if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
- ListBase *lb = which_libbase(bmain, type);
- BLI_remlink(lb, id);
- }
-
- BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
-
- if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
- BKE_main_unlock(bmain);
- }
-
- if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) {
- MEM_freeN(id);
- }
-}
-
-/**
- * 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;
-
- id_us_min(id);
-
- /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding collections
- * when deleting an object. Since only 'user_one' usage of objects is collections,
- * and only 'real user' usage of objects is scenes, removing that 'user_one' tag when there
- * is no more real (scene) users of an object ensures it gets fully unlinked.
- * But only for local objects, not linked ones!
- * Otherwise, there is no real way to get rid of an object anymore -
- * better handling of this is TODO.
- */
- if ((GS(id->name) == ID_OB) && (id->us == 1) && (id->lib == NULL)) {
- id_us_clear_real(id);
- }
-
- if (id->us == 0) {
- BKE_libblock_unlink(bmain, id, false, false);
-
- BKE_id_free(bmain, id);
- }
-}
-
-static void id_delete(Main *bmain, const bool do_tagged_deletion)
-{
- const int tag = LIB_TAG_DOIT;
- ListBase *lbarray[MAX_LIBARRAY];
- Link dummy_link = {0};
- int base_count, i;
-
- /* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database,
- * and has already properly unlinked its other IDs usages.
- * UI users are always cleared in BKE_libblock_remap_locked() call, so we can always skip it. */
- const int free_flag = LIB_ID_FREE_NO_UI_USER |
- (do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT :
- 0);
- ListBase tagged_deleted_ids = {NULL};
-
- base_count = set_listbasepointers(bmain, lbarray);
-
- BKE_main_lock(bmain);
- if (do_tagged_deletion) {
- /* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
- * This means that we won't have to loop over all deleted IDs to remove usages
- * of other deleted IDs.
- * This gives tremendous speed-up when deleting a large amount of IDs from a Main
- * containing thousands of those.
- * This also means that we have to be very careful here, as we by-pass many 'common'
- * processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
- bool keep_looping = true;
- while (keep_looping) {
- ID *id, *id_next;
- ID *last_remapped_id = tagged_deleted_ids.last;
- keep_looping = false;
-
- /* First tag and remove from Main all datablocks directly from target lib.
- * Note that we go forward here, since we want to check dependencies before users
- * (e.g. meshes before objects). Avoids to have to loop twice. */
- for (i = 0; i < base_count; i++) {
- ListBase *lb = lbarray[i];
-
- for (id = lb->first; id; id = id_next) {
- id_next = id->next;
- /* Note: in case we delete a library, we also delete all its datablocks! */
- if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
- BLI_remlink(lb, id);
- BLI_addtail(&tagged_deleted_ids, id);
- /* Do not tag as no_main now, we want to unlink it first (lower-level ID management
- * code has some specific handling of 'nom main'
- * IDs that would be a problem in that case). */
- id->tag |= tag;
- keep_looping = true;
- }
- }
- }
- if (last_remapped_id == NULL) {
- dummy_link.next = tagged_deleted_ids.first;
- last_remapped_id = (ID *)(&dummy_link);
- }
- for (id = last_remapped_id->next; id; id = id->next) {
- /* Will tag 'never NULL' users of this ID too.
- * Note that we cannot use BKE_libblock_unlink() here,
- * since it would ignore indirect (and proxy!)
- * links, this can lead to nasty crashing here in second, actual deleting loop.
- * Also, this will also flag users of deleted data that cannot be unlinked
- * (object using deleted obdata, etc.), so that they also get deleted. */
- BKE_libblock_remap_locked(
- bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE);
- /* Since we removed ID from Main,
- * we also need to unlink its own other IDs usages ourself. */
- BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0);
- /* Now we can safely mark that ID as not being in Main database anymore. */
- id->tag |= LIB_TAG_NO_MAIN;
- /* This is needed because we may not have remapped usages
- * of that ID by other deleted ones. */
- // id->us = 0; /* Is it actually? */
- }
- }
- }
- else {
- /* First tag all datablocks directly from target lib.
- * Note that we go forward here, since we want to check dependencies before users
- * (e.g. meshes before objects).
- * Avoids to have to loop twice. */
- for (i = 0; i < base_count; i++) {
- ListBase *lb = lbarray[i];
- ID *id, *id_next;
-
- for (id = lb->first; id; id = id_next) {
- id_next = id->next;
- /* Note: in case we delete a library, we also delete all its datablocks! */
- if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
- id->tag |= tag;
-
- /* Will tag 'never NULL' users of this ID too.
- * Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect
- * (and proxy!) links, this can lead to nasty crashing here in second,
- * actual deleting loop.
- * Also, this will also flag users of deleted data that cannot be unlinked
- * (object using deleted obdata, etc.), so that they also get deleted. */
- BKE_libblock_remap_locked(
- bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE);
- }
- }
- }
- }
- BKE_main_unlock(bmain);
-
- /* In usual reversed order, such that all usage of a given ID, even 'never NULL' ones,
- * have been already cleared when we reach it
- * (e.g. Objects being processed before meshes, they'll have already released their 'reference'
- * over meshes when we come to freeing obdata). */
- for (i = do_tagged_deletion ? 1 : base_count; i--;) {
- ListBase *lb = lbarray[i];
- ID *id, *id_next;
-
- for (id = do_tagged_deletion ? tagged_deleted_ids.first : lb->first; id; id = id_next) {
- id_next = id->next;
- if (id->tag & tag) {
- if (id->us != 0) {
-#ifdef DEBUG_PRINT
- printf("%s: deleting %s (%d)\n", __func__, id->name, id->us);
-#endif
- BLI_assert(id->us == 0);
- }
- BKE_id_free_ex(bmain, id, free_flag, !do_tagged_deletion);
- }
- }
- }
-
- bmain->is_memfile_undo_written = false;
-}
-
-/**
- * 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);
- ((ID *)idv)->tag |= LIB_TAG_DOIT;
-
- 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.
- */
-void BKE_id_multi_tagged_delete(Main *bmain)
-{
- id_delete(bmain, true);
-}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index e051dc946cb..376d5aacbf5 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -20,1517 +20,27 @@
/** \file
* \ingroup bke
*
- * Contains management of ID's and libraries
- * allocate and free of all library data
+ * Contains code specific to the `Library` ID type.
*/
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <assert.h>
-
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
/* all types are needed here, in order to do memory operations */
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_key_types.h"
-#include "DNA_light_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_linestyle_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_lightprobe_types.h"
-#include "DNA_rigidbody_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_speaker_types.h"
-#include "DNA_sound_types.h"
-#include "DNA_text_types.h"
-#include "DNA_vfont_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_world_types.h"
-#include "DNA_workspace_types.h"
+#include "DNA_ID.h"
#include "BLI_utildefines.h"
-#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
-#include "BLI_linklist.h"
-#include "BLI_memarena.h"
-#include "BLI_string_utils.h"
-
-#include "BLT_translation.h"
-#include "BKE_action.h"
-#include "BKE_animsys.h"
-#include "BKE_armature.h"
-#include "BKE_bpath.h"
-#include "BKE_brush.h"
-#include "BKE_camera.h"
-#include "BKE_cachefile.h"
-#include "BKE_collection.h"
-#include "BKE_context.h"
-#include "BKE_curve.h"
-#include "BKE_font.h"
-#include "BKE_global.h"
-#include "BKE_gpencil.h"
-#include "BKE_idcode.h"
-#include "BKE_idprop.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_light.h"
-#include "BKE_lattice.h"
+#include "BKE_lib_id.h"
#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
-#include "BKE_linestyle.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
-#include "BKE_material.h"
#include "BKE_main.h"
-#include "BKE_mball.h"
-#include "BKE_mask.h"
-#include "BKE_movieclip.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_packedFile.h"
-#include "BKE_lightprobe.h"
-#include "BKE_rigidbody.h"
-#include "BKE_sound.h"
-#include "BKE_speaker.h"
-#include "BKE_scene.h"
-#include "BKE_text.h"
-#include "BKE_texture.h"
-#include "BKE_world.h"
-
-#include "DEG_depsgraph.h"
-
-#include "RNA_access.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
-#include "atomic_ops.h"
-
-//#define DEBUG_TIME
-
-#ifdef DEBUG_TIME
-# include "PIL_time_utildefines.h"
-#endif
-
-static CLG_LogRef LOG = {"bke.library"};
-
-/* GS reads the memory pointed at in a specific ordering.
- * only use this definition, makes little and big endian systems
- * work fine, in conjunction with MAKE_ID */
-
-/* ************* general ************************ */
-
-/* this has to be called from each make_local_* func, we could call
- * from id_make_local() but then the make local functions would not be self
- * contained.
- * also note that the id _must_ have a library - campbell */
-void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
-{
- const char *bpath_user_data[2] = {BKE_main_blendfile_path(bmain), lib->filepath};
-
- BKE_bpath_traverse_id(bmain,
- id,
- BKE_bpath_relocate_visitor,
- BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
- (void *)bpath_user_data);
-}
-
-void id_lib_extern(ID *id)
-{
- if (id && ID_IS_LINKED(id)) {
- BLI_assert(BKE_idcode_is_linkable(GS(id->name)));
- if (id->tag & LIB_TAG_INDIRECT) {
- id->tag &= ~LIB_TAG_INDIRECT;
- id->flag &= ~LIB_INDIRECT_WEAK_LINK;
- id->tag |= LIB_TAG_EXTERN;
- id->lib->parent = NULL;
- }
- }
-}
-
-void id_lib_indirect_weak_link(ID *id)
-{
- if (id && ID_IS_LINKED(id)) {
- BLI_assert(BKE_idcode_is_linkable(GS(id->name)));
- if (id->tag & LIB_TAG_INDIRECT) {
- id->flag |= LIB_INDIRECT_WEAK_LINK;
- }
- }
-}
-
-/**
- * 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 library.c,
- * so think we can wait later to make this change.
- */
-void id_us_ensure_real(ID *id)
-{
- if (id) {
- const int limit = ID_FAKE_USERS(id);
- id->tag |= LIB_TAG_EXTRAUSER;
- if (id->us <= limit) {
- if (id->us < limit || ((id->us == limit) && (id->tag & LIB_TAG_EXTRAUSER_SET))) {
- CLOG_ERROR(&LOG,
- "ID user count error: %s (from '%s')",
- id->name,
- id->lib ? id->lib->filepath : "[Main]");
- BLI_assert(0);
- }
- id->us = limit + 1;
- id->tag |= LIB_TAG_EXTRAUSER_SET;
- }
- }
-}
-
-void id_us_clear_real(ID *id)
-{
- if (id && (id->tag & LIB_TAG_EXTRAUSER)) {
- if (id->tag & LIB_TAG_EXTRAUSER_SET) {
- id->us--;
- BLI_assert(id->us >= ID_FAKE_USERS(id));
- }
- id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET);
- }
-}
-
-/**
- * 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) {
- if ((id->tag & LIB_TAG_EXTRAUSER) && (id->tag & LIB_TAG_EXTRAUSER_SET)) {
- BLI_assert(id->us >= 1);
- /* No need to increase count, just tag extra user as no more set.
- * Avoids annoying & inconsistent +1 in user count. */
- id->tag &= ~LIB_TAG_EXTRAUSER_SET;
- }
- else {
- BLI_assert(id->us >= 0);
- id->us++;
- }
- }
-}
-
-void id_us_plus(ID *id)
-{
- if (id) {
- id_us_plus_no_lib(id);
- id_lib_extern(id);
- }
-}
-
-/* decrements the user count for *id. */
-void id_us_min(ID *id)
-{
- if (id) {
- const int limit = ID_FAKE_USERS(id);
-
- if (id->us <= limit) {
- CLOG_ERROR(&LOG,
- "ID user decrement error: %s (from '%s'): %d <= %d",
- id->name,
- id->lib ? id->lib->filepath : "[Main]",
- id->us,
- limit);
- BLI_assert(0);
- id->us = limit;
- }
- else {
- id->us--;
- }
-
- if ((id->us == limit) && (id->tag & LIB_TAG_EXTRAUSER)) {
- /* We need an extra user here, but never actually incremented user count for it so far,
- * do it now. */
- id_us_ensure_real(id);
- }
- }
-}
-
-void id_fake_user_set(ID *id)
-{
- if (id && !(id->flag & LIB_FAKEUSER)) {
- id->flag |= LIB_FAKEUSER;
- id_us_plus(id);
- }
-}
-
-void id_fake_user_clear(ID *id)
-{
- if (id && (id->flag & LIB_FAKEUSER)) {
- id->flag &= ~LIB_FAKEUSER;
- id_us_min(id);
- }
-}
-
-void BKE_id_clear_newpoin(ID *id)
-{
- if (id->newid) {
- id->newid->tag &= ~LIB_TAG_NEW;
- }
- id->newid = NULL;
-}
-
-static int id_expand_local_callback(void *UNUSED(user_data),
- struct ID *id_self,
- struct ID **id_pointer,
- int cb_flag)
-{
- if (cb_flag & IDWALK_CB_PRIVATE) {
- return IDWALK_RET_NOP;
- }
-
- /* Can happen that we get un-linkable ID here, e.g. with shape-key referring to itself
- * (through drivers)...
- * Just skip it, shape key can only be either indirectly linked, or fully local, period.
- * And let's curse one more time that stupid useless shapekey ID type! */
- if (*id_pointer && *id_pointer != id_self && BKE_idcode_is_linkable(GS((*id_pointer)->name))) {
- id_lib_extern(*id_pointer);
- }
-
- 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_id_expand_local(Main *bmain, ID *id)
-{
- BKE_library_foreach_ID_link(bmain, id, id_expand_local_callback, NULL, IDWALK_READONLY);
-}
-
-/**
- * Ensure new (copied) ID is fully made local.
- */
-void BKE_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id)
-{
- if (ID_IS_LINKED(old_id)) {
- BKE_id_expand_local(bmain, new_id);
- BKE_id_lib_local_paths(bmain, old_id->lib, new_id);
- }
-}
-
-/**
- * Generic 'make local' function, works for most of data-block types...
- */
-void BKE_id_make_local_generic(Main *bmain,
- ID *id,
- const bool id_in_mainlist,
- const bool lib_local)
-{
- bool is_local = false, is_lib = false;
-
- /* - only lib users: do nothing (unless force_local is set)
- * - only local users: set flag
- * - mixed: make copy
- * In case we make a whole lib's content local,
- * we always want to localize, and we skip remapping (done later).
- */
-
- if (!ID_IS_LINKED(id)) {
- return;
- }
-
- BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
-
- if (lib_local || is_local) {
- if (!is_lib) {
- id_clear_lib_data_ex(bmain, id, id_in_mainlist);
- BKE_id_expand_local(bmain, id);
- }
- else {
- ID *id_new;
-
- /* Should not fail in expected use cases,
- * but a few ID types cannot be copied (LIB, WM, SCR...). */
- if (BKE_id_copy(bmain, id, &id_new)) {
- id_new->us = 0;
-
- /* setting newid is mandatory for complex make_lib_local logic... */
- ID_NEW_SET(id, id_new);
- Key *key = BKE_key_from_id(id), *key_new = BKE_key_from_id(id);
- if (key && key_new) {
- ID_NEW_SET(key, key_new);
- }
- bNodeTree *ntree = ntreeFromID(id), *ntree_new = ntreeFromID(id_new);
- if (ntree && ntree_new) {
- ID_NEW_SET(ntree, ntree_new);
- }
-
- if (!lib_local) {
- BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE);
- }
- }
- }
- }
-}
-
-/**
- * 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 lib_local: Special flag used when making a whole library's content local,
- * it needs specific handling.
- *
- * \return true if the block can be made local.
- */
-bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
-{
- /* We don't care whether ID is directly or indirectly linked
- * in case we are making a whole lib local... */
- if (!lib_local && (id->tag & LIB_TAG_INDIRECT)) {
- return false;
- }
-
- switch ((ID_Type)GS(id->name)) {
- case ID_SCE:
- if (!test) {
- BKE_scene_make_local(bmain, (Scene *)id, lib_local);
- }
- return true;
- case ID_OB:
- if (!test) {
- BKE_object_make_local(bmain, (Object *)id, lib_local);
- }
- return true;
- case ID_ME:
- if (!test) {
- BKE_mesh_make_local(bmain, (Mesh *)id, lib_local);
- }
- return true;
- case ID_CU:
- if (!test) {
- BKE_curve_make_local(bmain, (Curve *)id, lib_local);
- }
- return true;
- case ID_MB:
- if (!test) {
- BKE_mball_make_local(bmain, (MetaBall *)id, lib_local);
- }
- return true;
- case ID_MA:
- if (!test) {
- BKE_material_make_local(bmain, (Material *)id, lib_local);
- }
- return true;
- case ID_TE:
- if (!test) {
- BKE_texture_make_local(bmain, (Tex *)id, lib_local);
- }
- return true;
- case ID_IM:
- if (!test) {
- BKE_image_make_local(bmain, (Image *)id, lib_local);
- }
- return true;
- case ID_LT:
- if (!test) {
- BKE_lattice_make_local(bmain, (Lattice *)id, lib_local);
- }
- return true;
- case ID_LA:
- if (!test) {
- BKE_light_make_local(bmain, (Light *)id, lib_local);
- }
- return true;
- case ID_CA:
- if (!test) {
- BKE_camera_make_local(bmain, (Camera *)id, lib_local);
- }
- return true;
- case ID_SPK:
- if (!test) {
- BKE_speaker_make_local(bmain, (Speaker *)id, lib_local);
- }
- return true;
- case ID_LP:
- if (!test) {
- BKE_lightprobe_make_local(bmain, (LightProbe *)id, lib_local);
- }
- return true;
- case ID_WO:
- if (!test) {
- BKE_world_make_local(bmain, (World *)id, lib_local);
- }
- return true;
- case ID_VF:
- if (!test) {
- BKE_vfont_make_local(bmain, (VFont *)id, lib_local);
- }
- return true;
- case ID_TXT:
- if (!test) {
- BKE_text_make_local(bmain, (Text *)id, lib_local);
- }
- return true;
- case ID_SO:
- if (!test) {
- BKE_sound_make_local(bmain, (bSound *)id, lib_local);
- }
- return true;
- case ID_GR:
- if (!test) {
- BKE_collection_make_local(bmain, (Collection *)id, lib_local);
- }
- return true;
- case ID_AR:
- if (!test) {
- BKE_armature_make_local(bmain, (bArmature *)id, lib_local);
- }
- return true;
- case ID_AC:
- if (!test) {
- BKE_action_make_local(bmain, (bAction *)id, lib_local);
- }
- return true;
- case ID_NT:
- if (!test) {
- ntreeMakeLocal(bmain, (bNodeTree *)id, true, lib_local);
- }
- return true;
- case ID_BR:
- if (!test) {
- BKE_brush_make_local(bmain, (Brush *)id, lib_local);
- }
- return true;
- case ID_PA:
- if (!test) {
- BKE_particlesettings_make_local(bmain, (ParticleSettings *)id, lib_local);
- }
- return true;
- case ID_GD:
- if (!test) {
- BKE_gpencil_make_local(bmain, (bGPdata *)id, lib_local);
- }
- return true;
- case ID_MC:
- if (!test) {
- BKE_movieclip_make_local(bmain, (MovieClip *)id, lib_local);
- }
- return true;
- case ID_MSK:
- if (!test) {
- BKE_mask_make_local(bmain, (Mask *)id, lib_local);
- }
- return true;
- case ID_LS:
- if (!test) {
- BKE_linestyle_make_local(bmain, (FreestyleLineStyle *)id, lib_local);
- }
- return true;
- case ID_PAL:
- if (!test) {
- BKE_palette_make_local(bmain, (Palette *)id, lib_local);
- }
- return true;
- case ID_PC:
- if (!test) {
- BKE_paint_curve_make_local(bmain, (PaintCurve *)id, lib_local);
- }
- return true;
- case ID_CF:
- if (!test) {
- BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local);
- }
- return true;
- case ID_WS:
- case ID_SCR:
- /* A bit special: can be appended but not linked. Return false
- * since supporting make-local doesn't make much sense. */
- return false;
- case ID_LI:
- case ID_KE:
- case ID_WM:
- return false; /* can't be linked */
- case ID_IP:
- return false; /* deprecated */
- }
-
- return false;
-}
-
-struct IDCopyLibManagementData {
- const ID *id_src;
- ID *id_dst;
- int flag;
-};
-
-/* Increases usercount as required, and remap self ID pointers. */
-static int id_copy_libmanagement_cb(void *user_data,
- ID *UNUSED(id_self),
- ID **id_pointer,
- int cb_flag)
-{
- struct IDCopyLibManagementData *data = user_data;
- ID *id = *id_pointer;
-
- /* Remap self-references to new copied ID. */
- if (id == data->id_src) {
- /* We cannot use id_self here, it is not *always* id_dst (thanks to $£!+@#&/? nodetrees). */
- id = *id_pointer = data->id_dst;
- }
-
- /* Increase used IDs refcount if needed and required. */
- if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) {
- id_us_plus(id);
- }
-
- return IDWALK_RET_NOP;
-}
-
-bool BKE_id_copy_is_allowed(const ID *id)
-{
-#define LIB_ID_TYPES_NOCOPY \
- ID_LI, ID_SCR, ID_WM, ID_WS, /* Not supported */ \
- ID_IP /* Deprecated */
-
- return !ELEM(GS(id->name), LIB_ID_TYPES_NOCOPY);
-
-#undef LIB_ID_TYPES_NOCOPY
-}
-
-/**
- * Generic entry point for copying a data-block (new API).
- *
- * \note Copy is only affecting given data-block
- * (no ID used by copied one will be affected, besides usercount).
- * There is only one exception, if #LIB_ID_COPY_ACTIONS is defined,
- * actions used by animdata will be duplicated.
- *
- * \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.
- * \param flag: Set of copy options, see DNA_ID.h enum for details
- * (leave to zero for default, full copy).
- * \return False when copying that ID type is not supported, true otherwise.
- */
-bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
-{
- BLI_assert(r_newid != NULL);
- /* Make sure destination pointer is all good. */
- if ((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0) {
- *r_newid = NULL;
- }
- else {
- if (*r_newid != NULL) {
- /* Allow some garbage non-initialized memory to go in, and clean it up here. */
- const size_t size = BKE_libblock_get_alloc_info(GS(id->name), NULL);
- memset(*r_newid, 0, size);
- }
- }
-
- /* Early output is source is NULL. */
- if (id == NULL) {
- return false;
- }
- if (!BKE_id_copy_is_allowed(id)) {
- return false;
- }
-
- BKE_libblock_copy_ex(bmain, id, r_newid, flag);
-
- switch ((ID_Type)GS(id->name)) {
- case ID_SCE:
- BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag);
- break;
- case ID_OB:
- BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag);
- break;
- case ID_ME:
- BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag);
- break;
- case ID_CU:
- BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag);
- break;
- case ID_MB:
- BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag);
- break;
- case ID_MA:
- BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag);
- break;
- case ID_TE:
- BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag);
- break;
- case ID_IM:
- BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag);
- break;
- case ID_LT:
- BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag);
- break;
- case ID_LA:
- BKE_light_copy_data(bmain, (Light *)*r_newid, (Light *)id, flag);
- break;
- case ID_SPK:
- BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag);
- break;
- case ID_LP:
- BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag);
- break;
- case ID_CA:
- BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag);
- break;
- case ID_KE:
- BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag);
- break;
- case ID_WO:
- BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag);
- break;
- case ID_TXT:
- BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag);
- break;
- case ID_GR:
- BKE_collection_copy_data(bmain, (Collection *)*r_newid, (Collection *)id, flag);
- break;
- case ID_AR:
- BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag);
- break;
- case ID_AC:
- BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag);
- break;
- case ID_NT:
- BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag);
- break;
- case ID_BR:
- BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag);
- break;
- case ID_PA:
- BKE_particlesettings_copy_data(
- bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag);
- break;
- case ID_GD:
- BKE_gpencil_copy_data((bGPdata *)*r_newid, (bGPdata *)id, flag);
- break;
- case ID_MC:
- BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag);
- break;
- case ID_MSK:
- BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag);
- break;
- case ID_LS:
- BKE_linestyle_copy_data(
- bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag);
- break;
- case ID_PAL:
- BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag);
- break;
- case ID_PC:
- BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag);
- break;
- case ID_CF:
- BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag);
- break;
- case ID_SO:
- BKE_sound_copy_data(bmain, (bSound *)*r_newid, (bSound *)id, flag);
- break;
- case ID_VF:
- BKE_vfont_copy_data(bmain, (VFont *)*r_newid, (VFont *)id, flag);
- break;
- case ID_LI:
- case ID_SCR:
- case ID_WM:
- case ID_WS:
- case ID_IP:
- BLI_assert(0); /* Should have been rejected at start of function! */
- break;
- }
-
- /* Update ID refcount, remap pointers to self in new ID. */
- struct IDCopyLibManagementData data = {
- .id_src = id,
- .id_dst = *r_newid,
- .flag = flag,
- };
- BKE_library_foreach_ID_link(bmain, *r_newid, id_copy_libmanagement_cb, &data, IDWALK_NOP);
-
- /* Do not make new copy local in case we are copying outside of main...
- * XXX TODO: is this behavior OK, or should we need own flag to control that? */
- if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
- BLI_assert((flag & LIB_ID_COPY_KEEP_LIB) == 0);
- BKE_id_copy_ensure_local(bmain, id, *r_newid);
- }
- else {
- (*r_newid)->lib = id->lib;
- }
-
- return true;
-}
-
-/**
- * Invokes the appropriate copy method for the block and returns the result in
- * newid, unless test. Returns true if the block can be copied.
- */
-bool BKE_id_copy(Main *bmain, const ID *id, ID **newid)
-{
- return BKE_id_copy_ex(bmain, id, newid, LIB_ID_COPY_DEFAULT);
-}
-
-/**
- * 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).
- */
-void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
-{
- BLI_assert(GS(id_a->name) == GS(id_b->name));
-
- const ID id_a_back = *id_a;
- const ID id_b_back = *id_b;
-
-#define CASE_SWAP(_gs, _type) \
- case _gs: \
- SWAP(_type, *(_type *)id_a, *(_type *)id_b); \
- break
-
- switch ((ID_Type)GS(id_a->name)) {
- CASE_SWAP(ID_SCE, Scene);
- CASE_SWAP(ID_LI, Library);
- CASE_SWAP(ID_OB, Object);
- CASE_SWAP(ID_ME, Mesh);
- CASE_SWAP(ID_CU, Curve);
- CASE_SWAP(ID_MB, MetaBall);
- CASE_SWAP(ID_MA, Material);
- CASE_SWAP(ID_TE, Tex);
- CASE_SWAP(ID_IM, Image);
- CASE_SWAP(ID_LT, Lattice);
- CASE_SWAP(ID_LA, Light);
- CASE_SWAP(ID_LP, LightProbe);
- CASE_SWAP(ID_CA, Camera);
- CASE_SWAP(ID_KE, Key);
- CASE_SWAP(ID_WO, World);
- CASE_SWAP(ID_SCR, bScreen);
- CASE_SWAP(ID_VF, VFont);
- CASE_SWAP(ID_TXT, Text);
- CASE_SWAP(ID_SPK, Speaker);
- CASE_SWAP(ID_SO, bSound);
- CASE_SWAP(ID_GR, Collection);
- CASE_SWAP(ID_AR, bArmature);
- CASE_SWAP(ID_AC, bAction);
- CASE_SWAP(ID_NT, bNodeTree);
- CASE_SWAP(ID_BR, Brush);
- CASE_SWAP(ID_PA, ParticleSettings);
- CASE_SWAP(ID_WM, wmWindowManager);
- CASE_SWAP(ID_WS, WorkSpace);
- CASE_SWAP(ID_GD, bGPdata);
- CASE_SWAP(ID_MC, MovieClip);
- CASE_SWAP(ID_MSK, Mask);
- CASE_SWAP(ID_LS, FreestyleLineStyle);
- CASE_SWAP(ID_PAL, Palette);
- CASE_SWAP(ID_PC, PaintCurve);
- CASE_SWAP(ID_CF, CacheFile);
- case ID_IP:
- break; /* Deprecated. */
- }
-
-#undef CASE_SWAP
-
- /* Restore original ID's internal data. */
- *id_a = id_a_back;
- *id_b = id_b_back;
-
- /* Exception: IDProperties. */
- id_a->properties = id_b_back.properties;
- id_b->properties = id_a_back.properties;
- /* Swap will have broken internal references to itself, restore them. */
- BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, ID_REMAP_SKIP_NEVER_NULL_USAGE);
- BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, ID_REMAP_SKIP_NEVER_NULL_USAGE);
-}
-
-/** Does *not* set ID->newid pointer. */
-bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
-{
- ID *newid = NULL;
- PointerRNA idptr;
-
- if (id) {
- /* If property isn't editable,
- * we're going to have an extra block hanging around until we save. */
- if (RNA_property_editable(ptr, prop)) {
- Main *bmain = CTX_data_main(C);
- /* copy animation actions too */
- if (BKE_id_copy_ex(bmain, id, &newid, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS) && newid) {
- /* us is 1 by convention with new IDs, but RNA_property_pointer_set
- * will also increment it, decrement it here. */
- id_us_min(newid);
-
- /* assign copy */
- RNA_id_pointer_create(newid, &idptr);
- RNA_property_pointer_set(ptr, prop, idptr, NULL);
- RNA_property_update(C, ptr, prop);
-
- /* tag grease pencil data-block and disable onion */
- if (GS(id->name) == ID_GD) {
- DEG_id_tag_update(id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(newid, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- bGPdata *gpd = (bGPdata *)newid;
- gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS;
- }
-
- return true;
- }
- }
- }
-
- return false;
-}
-
-static int libblock_management_us_plus(void *UNUSED(user_data),
- ID *UNUSED(id_self),
- ID **id_pointer,
- int cb_flag)
-{
- if (cb_flag & IDWALK_CB_USER) {
- id_us_plus(*id_pointer);
- }
- if (cb_flag & IDWALK_CB_USER_ONE) {
- id_us_ensure_real(*id_pointer);
- }
-
- return IDWALK_RET_NOP;
-}
-
-static int libblock_management_us_min(void *UNUSED(user_data),
- ID *UNUSED(id_self),
- ID **id_pointer,
- int cb_flag)
-{
- if (cb_flag & IDWALK_CB_USER) {
- id_us_min(*id_pointer);
- }
- /* We can do nothing in IDWALK_CB_USER_ONE case! */
-
- 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;
-
- BLI_assert(bmain != NULL);
- if ((id->tag & LIB_TAG_NO_MAIN) == 0) {
- return;
- }
-
- if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) {
- /* We cannot add non-allocated ID to Main! */
- return;
- }
-
- /* We cannot allow non-userrefcounting IDs in Main database! */
- if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) {
- BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP);
- }
-
- ListBase *lb = which_libbase(bmain, GS(id->name));
- BKE_main_lock(bmain);
- BLI_addtail(lb, id);
- BKE_id_new_name_validate(lb, id, NULL);
- /* alphabetic insertion: is in new_id */
- id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
- bmain->is_memfile_undo_written = false;
- BKE_main_unlock(bmain);
-}
-
-/** 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;
-
- BLI_assert(bmain != NULL);
- if ((id->tag & LIB_TAG_NO_MAIN) != 0) {
- return;
- }
-
- /* For now, allow userrefcounting IDs to get out of Main - can be handy in some cases... */
-
- ListBase *lb = which_libbase(bmain, GS(id->name));
- BKE_main_lock(bmain);
- BLI_remlink(lb, id);
- id->tag |= LIB_TAG_NO_MAIN;
- bmain->is_memfile_undo_written = false;
- BKE_main_unlock(bmain);
-}
-
-void BKE_libblock_management_usercounts_set(Main *bmain, void *idv)
-{
- ID *id = idv;
-
- if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) == 0) {
- return;
- }
-
- BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP);
- id->tag &= ~LIB_TAG_NO_USER_REFCOUNT;
-}
-
-void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv)
-{
- ID *id = idv;
-
- /* We do not allow IDs in Main database to not be userrefcounting. */
- if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0 || (id->tag & LIB_TAG_NO_MAIN) != 0) {
- return;
- }
-
- BKE_library_foreach_ID_link(bmain, id, libblock_management_us_min, NULL, IDWALK_NOP);
- 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;
- if (value) {
- for (id = lb->first; id; id = id->next) {
- id->tag |= tag;
- }
- }
- else {
- const int ntag = ~tag;
- for (id = lb->first; id; id = id->next) {
- id->tag &= ntag;
- }
- }
-}
-
-/**
- * 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,
- const bool value)
-{
- ListBase *lb = which_libbase(mainvar, type);
-
- 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[MAX_LIBARRAY];
- int a;
-
- a = set_listbasepointers(mainvar, lbarray);
- while (a--) {
- BKE_main_id_tag_listbase(lbarray[a], tag, 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;
- if (value) {
- for (id = lb->first; id; id = id->next) {
- id->tag |= flag;
- }
- }
- else {
- const int nflag = ~flag;
- for (id = lb->first; id; id = id->next) {
- id->tag &= nflag;
- }
- }
-}
-
-/**
- * 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[MAX_LIBARRAY];
- int a;
- a = set_listbasepointers(bmain, lbarray);
- while (a--) {
- BKE_main_id_flag_listbase(lbarray[a], flag, value);
- }
-}
-
-void BKE_main_id_repair_duplicate_names_listbase(ListBase *lb)
-{
- int lb_len = 0;
- for (ID *id = lb->first; id; id = id->next) {
- if (id->lib == NULL) {
- lb_len += 1;
- }
- }
- if (lb_len <= 1) {
- return;
- }
-
- /* Fill an array because renaming sorts. */
- ID **id_array = MEM_mallocN(sizeof(*id_array) * lb_len, __func__);
- GSet *gset = BLI_gset_str_new_ex(__func__, lb_len);
- int i = 0;
- for (ID *id = lb->first; id; id = id->next) {
- if (id->lib == NULL) {
- id_array[i] = id;
- i++;
- }
- }
- for (i = 0; i < lb_len; i++) {
- if (!BLI_gset_add(gset, id_array[i]->name + 2)) {
- BKE_id_new_name_validate(lb, id_array[i], NULL);
- }
- }
- BLI_gset_free(gset, NULL);
- MEM_freeN(id_array);
-}
-
-void BKE_main_lib_objects_recalc_all(Main *bmain)
-{
- Object *ob;
-
- /* flag for full recalc */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ID_IS_LINKED(ob)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- }
- }
-
- DEG_id_type_tag(bmain, ID_OB);
-}
-
-/* *********** ALLOC AND FREE *****************
- *
- * BKE_libblock_free(ListBase *lb, ID *id )
- * provide a list-basis and data-block, but only ID is read
- *
- * void *BKE_libblock_alloc(ListBase *lb, type, name)
- * inserts in list and returns a new ID
- *
- * **************************** */
-
-/**
- * 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)
-{
-#define CASE_RETURN(id_code, type) \
- case id_code: \
- do { \
- if (name != NULL) { \
- *name = #type; \
- } \
- return sizeof(type); \
- } while (0)
-
- switch ((ID_Type)type) {
- CASE_RETURN(ID_SCE, Scene);
- CASE_RETURN(ID_LI, Library);
- CASE_RETURN(ID_OB, Object);
- CASE_RETURN(ID_ME, Mesh);
- CASE_RETURN(ID_CU, Curve);
- CASE_RETURN(ID_MB, MetaBall);
- CASE_RETURN(ID_MA, Material);
- CASE_RETURN(ID_TE, Tex);
- CASE_RETURN(ID_IM, Image);
- CASE_RETURN(ID_LT, Lattice);
- CASE_RETURN(ID_LA, Light);
- CASE_RETURN(ID_CA, Camera);
- CASE_RETURN(ID_IP, Ipo);
- CASE_RETURN(ID_KE, Key);
- CASE_RETURN(ID_WO, World);
- CASE_RETURN(ID_SCR, bScreen);
- CASE_RETURN(ID_VF, VFont);
- CASE_RETURN(ID_TXT, Text);
- CASE_RETURN(ID_SPK, Speaker);
- CASE_RETURN(ID_LP, LightProbe);
- CASE_RETURN(ID_SO, bSound);
- CASE_RETURN(ID_GR, Collection);
- CASE_RETURN(ID_AR, bArmature);
- CASE_RETURN(ID_AC, bAction);
- CASE_RETURN(ID_NT, bNodeTree);
- CASE_RETURN(ID_BR, Brush);
- CASE_RETURN(ID_PA, ParticleSettings);
- CASE_RETURN(ID_WM, wmWindowManager);
- CASE_RETURN(ID_GD, bGPdata);
- CASE_RETURN(ID_MC, MovieClip);
- CASE_RETURN(ID_MSK, Mask);
- CASE_RETURN(ID_LS, FreestyleLineStyle);
- CASE_RETURN(ID_PAL, Palette);
- CASE_RETURN(ID_PC, PaintCurve);
- CASE_RETURN(ID_CF, CacheFile);
- CASE_RETURN(ID_WS, WorkSpace);
- }
- return 0;
-#undef CASE_RETURN
-}
-
-/**
- * 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;
- size_t size = BKE_libblock_get_alloc_info(type, &name);
- if (size != 0) {
- return MEM_callocN(size, name);
- }
- BLI_assert(!"Request to allocate unknown data 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);
-
- ID *id = BKE_libblock_alloc_notest(type);
-
- if (id) {
- if ((flag & LIB_ID_CREATE_NO_MAIN) != 0) {
- id->tag |= LIB_TAG_NO_MAIN;
- }
- if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) {
- id->tag |= LIB_TAG_NO_USER_REFCOUNT;
- }
-
- id->icon_id = 0;
- *((short *)id->name) = type;
- if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
- id->us = 1;
- }
- if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
- ListBase *lb = which_libbase(bmain, type);
-
- BKE_main_lock(bmain);
- BLI_addtail(lb, id);
- BKE_id_new_name_validate(lb, id, name);
- bmain->is_memfile_undo_written = false;
- /* alphabetic insertion: is in new_id */
- BKE_main_unlock(bmain);
-
- /* TODO to be removed from here! */
- if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
- DEG_id_type_tag(bmain, type);
- }
- }
- else {
- BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
- }
- }
-
- 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)
-{
- /* Note that only ID types that are not valid when filled of zero should have a callback here. */
- switch ((ID_Type)GS(id->name)) {
- case ID_SCE:
- BKE_scene_init((Scene *)id);
- break;
- case ID_LI:
- /* Nothing to do. */
- break;
- case ID_OB: {
- Object *ob = (Object *)id;
- BKE_object_init(ob, OB_EMPTY);
- break;
- }
- case ID_ME:
- BKE_mesh_init((Mesh *)id);
- break;
- case ID_CU:
- BKE_curve_init((Curve *)id, 0);
- break;
- case ID_MB:
- BKE_mball_init((MetaBall *)id);
- break;
- case ID_MA:
- BKE_material_init((Material *)id);
- break;
- case ID_TE:
- BKE_texture_default((Tex *)id);
- break;
- case ID_IM:
- BKE_image_init((Image *)id);
- break;
- case ID_LT:
- BKE_lattice_init((Lattice *)id);
- break;
- case ID_LA:
- BKE_light_init((Light *)id);
- break;
- case ID_SPK:
- BKE_speaker_init((Speaker *)id);
- break;
- case ID_LP:
- BKE_lightprobe_init((LightProbe *)id);
- break;
- case ID_CA:
- BKE_camera_init((Camera *)id);
- break;
- case ID_WO:
- BKE_world_init((World *)id);
- break;
- case ID_SCR:
- /* Nothing to do. */
- break;
- case ID_VF:
- BKE_vfont_init((VFont *)id);
- break;
- case ID_TXT:
- BKE_text_init((Text *)id);
- break;
- case ID_SO:
- /* Another fuzzy case, think NULLified content is OK here... */
- break;
- case ID_GR:
- /* Nothing to do. */
- break;
- case ID_AR:
- /* Nothing to do. */
- break;
- case ID_AC:
- /* Nothing to do. */
- break;
- case ID_NT:
- ntreeInitDefault((bNodeTree *)id);
- break;
- case ID_BR:
- BKE_brush_init((Brush *)id);
- break;
- case ID_PA:
- /* Nothing to do. */
- break;
- case ID_PC:
- /* Nothing to do. */
- break;
- case ID_GD:
- /* Nothing to do. */
- break;
- case ID_MSK:
- /* Nothing to do. */
- break;
- case ID_LS:
- BKE_linestyle_init((FreestyleLineStyle *)id);
- break;
- case ID_CF:
- BKE_cachefile_init((CacheFile *)id);
- break;
- case ID_KE:
- /* Shapekeys are a complex topic too - they depend on their 'user' data type...
- * They are not linkable, though, so it should never reach here anyway. */
- BLI_assert(0);
- break;
- case ID_WM:
- /* We should never reach this. */
- BLI_assert(0);
- break;
- case ID_IP:
- /* Should not be needed - animation from lib pre-2.5 is broken anyway. */
- BLI_assert(0);
- break;
- case ID_PAL:
- BKE_palette_init((Palette *)id);
- break;
- default:
- BLI_assert(0); /* Should never reach this point... */
- }
-}
-
-/**
- * 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);
-
- if (name == NULL) {
- name = DATA_(BKE_idcode_to_name(type));
- }
-
- ID *id = BKE_libblock_alloc(bmain, type, name, 0);
- BKE_libblock_init_empty(id);
-
- 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) {
- name = DATA_(BKE_idcode_to_name(type));
- }
-
- ID *id = BKE_libblock_alloc(NULL,
- type,
- name,
- LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT |
- LIB_ID_CREATE_NO_DEG_TAG);
- BKE_libblock_init_empty(id);
-
- return id;
-}
-
-void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int orig_flag)
-{
- ID *new_id = *r_newid;
- int flag = orig_flag;
-
- const bool is_private_id_data = (id->flag & LIB_PRIVATE_DATA) != 0;
-
- BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
- BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
- if (!is_private_id_data) {
- /* When we are handling private ID data, we might still want to manage usercounts, even though
- * that ID data-block is actually outside of Main... */
- BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 ||
- (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
- }
- /* Never implicitly copy shapekeys when generating temp data outside of Main database. */
- BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_COPY_SHAPEKEY) == 0);
-
- /* 'Private ID' data handling. */
- if ((bmain != NULL) && is_private_id_data) {
- flag |= LIB_ID_CREATE_NO_MAIN;
- }
-
- /* The id->flag bits to copy over. */
- const int copy_idflag_mask = LIB_PRIVATE_DATA;
-
- if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
- /* r_newid already contains pointer to allocated memory. */
- /* TODO do we want to memset(0) whole mem before filling it? */
- BLI_strncpy(new_id->name, id->name, sizeof(new_id->name));
- new_id->us = 0;
- new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT;
- /* TODO Do we want/need to copy more from ID struct itself? */
- }
- else {
- new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag);
- }
- BLI_assert(new_id != NULL);
-
- const size_t id_len = BKE_libblock_get_alloc_info(GS(new_id->name), NULL);
- const size_t id_offset = sizeof(ID);
- if ((int)id_len - (int)id_offset > 0) { /* signed to allow neg result */ /* XXX ????? */
- const char *cp = (const char *)id;
- char *cpn = (char *)new_id;
-
- memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset);
- }
-
- new_id->flag = (new_id->flag & ~copy_idflag_mask) | (id->flag & copy_idflag_mask);
-
- /* We do not want any handling of usercount in code duplicating the data here, we do that all
- * at once in id_copy_libmanagement_cb() at the end. */
- const int copy_data_flag = orig_flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
-
- if (id->properties) {
- new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag);
- }
-
- /* XXX Again... We need a way to control what we copy in a much more refined way.
- * We cannot always copy this, some internal copying will die on it! */
- /* For now, upper level code will have to do that itself when required. */
-#if 0
- if (id->override != NULL) {
- BKE_override_copy(new_id, id);
- }
-#endif
-
- if (id_can_have_animdata(new_id)) {
- IdAdtTemplate *iat = (IdAdtTemplate *)new_id;
-
- /* the duplicate should get a copy of the animdata */
- if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) {
- /* Note that even though horrors like root nodetrees are not in bmain, the actions they use
- * in their anim data *are* in bmain... super-mega-hooray. */
- BLI_assert((copy_data_flag & LIB_ID_COPY_ACTIONS) == 0 ||
- (copy_data_flag & LIB_ID_CREATE_NO_MAIN) == 0);
- iat->adt = BKE_animdata_copy(bmain, iat->adt, copy_data_flag);
- }
- else {
- iat->adt = NULL;
- }
- }
-
- if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) {
- DEG_id_type_tag(bmain, GS(new_id->name));
- }
-
- *r_newid = new_id;
-}
-
-/* used everywhere in blenkernel */
-void *BKE_libblock_copy(Main *bmain, const ID *id)
-{
- ID *idn;
-
- BKE_libblock_copy_ex(bmain, id, &idn, 0);
-
- return idn;
-}
-
-/* XXX TODO: get rid of this useless wrapper at some point... */
-void *BKE_libblock_copy_for_localize(const ID *id)
-{
- ID *idn;
- BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
- return idn;
-}
+/* Unused currently. */
+// static CLG_LogRef LOG = {.identifier = "bke.library"};
void BKE_library_free(Library *lib)
{
@@ -1539,971 +49,6 @@ void BKE_library_free(Library *lib)
}
}
-/* ***************** ID ************************ */
-ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *name)
-{
- ListBase *lb = which_libbase(bmain, type);
- BLI_assert(lb != NULL);
- return BLI_findstring(lb, name, offsetof(ID, name) + 2);
-}
-
-/**
- * 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
-
- ID *idtest;
-
- /* insert alphabetically */
- if (lb->first == lb->last) {
- return;
- }
-
- BLI_remlink(lb, id);
-
- /* Check if we can actually insert id before or after id_sorting_hint, if given. */
- if (id_sorting_hint != NULL && id_sorting_hint != id) {
- BLI_assert(BLI_findindex(lb, id_sorting_hint) >= 0);
-
- ID *id_sorting_hint_next = id_sorting_hint->next;
- if (BLI_strcasecmp(id_sorting_hint->name, id->name) < 0 &&
- (id_sorting_hint_next == NULL ||
- BLI_strcasecmp(id_sorting_hint_next->name, id->name) > 0)) {
- BLI_insertlinkafter(lb, id_sorting_hint, id);
- return;
- }
-
- ID *id_sorting_hint_prev = id_sorting_hint->prev;
- if (BLI_strcasecmp(id_sorting_hint->name, id->name) > 0 &&
- (id_sorting_hint_prev == NULL ||
- BLI_strcasecmp(id_sorting_hint_prev->name, id->name) < 0)) {
- BLI_insertlinkbefore(lb, id_sorting_hint, id);
- return;
- }
- }
-
- void *item_array[ID_SORT_STEP_SIZE];
- int item_array_index;
-
- /* Step one: We go backward over a whole chunk of items at once, until we find a limit item
- * that is lower than, or equal (should never happen!) to the one we want to insert. */
- /* Note: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at
- * once using the same base name), newly inserted items will generally be towards the end
- * (higher extension numbers). */
- for (idtest = lb->last, item_array_index = ID_SORT_STEP_SIZE - 1; idtest != NULL;
- idtest = idtest->prev, item_array_index--) {
- item_array[item_array_index] = idtest;
- if (item_array_index == 0) {
- if ((idtest->lib == NULL && id->lib != NULL) ||
- BLI_strcasecmp(idtest->name, id->name) <= 0) {
- break;
- }
- item_array_index = ID_SORT_STEP_SIZE;
- }
- }
-
- /* Step two: we go forward in the selected chunk of items and check all of them, as we know
- * that our target is in there. */
-
- /* If we reached start of the list, current item_array_index is off-by-one.
- * Otherwise, we already know that it points to an item lower-or-equal-than the one we want to
- * insert, no need to redo the check for that one.
- * So we can increment that index in any case. */
- for (item_array_index++; item_array_index < ID_SORT_STEP_SIZE; item_array_index++) {
- idtest = item_array[item_array_index];
- if ((idtest->lib != NULL && id->lib == NULL) || BLI_strcasecmp(idtest->name, id->name) > 0) {
- BLI_insertlinkbefore(lb, idtest, id);
- break;
- }
- }
- if (item_array_index == ID_SORT_STEP_SIZE) {
- if (idtest == NULL) {
- /* If idtest is NULL here, it means that in the first loop, the last comparison was
- * performed exactly on the first item of the list, and that it also failed. In other
- * words, all items in the list are greater than inserted one, so we can put it at the
- * start of the list. */
- /* Note that BLI_insertlinkafter() would have same behavior in that case, but better be
- * explicit here. */
- BLI_addhead(lb, id);
- }
- else {
- BLI_insertlinkafter(lb, idtest, id);
- }
- }
-
-#undef ID_SORT_STEP_SIZE
-}
-
-/* Note: this code assumes and ensures that the suffix number can never go beyond 1 billion. */
-#define MAX_NUMBER 1000000000
-/* We do not want to get "name.000", so minimal number is 1. */
-#define MIN_NUMBER 1
-/* The maximum value up to which we search for the actual smallest unused number. Beyond that
- * value, we will only use the first biggest unused number, without trying to 'fill the gaps'
- * in-between already used numbers... */
-#define MAX_NUMBERS_IN_USE 1024
-
-/**
- * Helper building final ID name from given base_name and number.
- *
- * If everything goes well and we do generate a valid final ID name in given name, we return true.
- * In case the final name would overflow the allowed ID name length, or given number is bigger than
- * maximum allowed value, we truncate further the base_name (and given name, which is assumed to
- * have the same 'base_name' part), and return false.
- */
-static bool id_name_final_build(char *name, char *base_name, size_t base_name_len, int number)
-{
- char number_str[11]; /* Dot + nine digits + NULL terminator. */
- size_t number_str_len = BLI_snprintf_rlen(number_str, ARRAY_SIZE(number_str), ".%.3d", number);
-
- /* If the number would lead to an overflow of the maximum ID name length, we need to truncate
- * the base name part and do all the number checks again. */
- if (base_name_len + number_str_len >= MAX_ID_NAME - 2 || number >= MAX_NUMBER) {
- if (base_name_len + number_str_len >= MAX_ID_NAME - 2) {
- base_name_len = MAX_ID_NAME - 2 - number_str_len - 1;
- }
- else {
- base_name_len--;
- }
- base_name[base_name_len] = '\0';
-
- /* Code above may have generated invalid utf-8 string, due to raw truncation.
- * Ensure we get a valid one now. */
- base_name_len -= (size_t)BLI_utf8_invalid_strip(base_name, base_name_len);
-
- /* Also truncate orig name, and start the whole check again. */
- name[base_name_len] = '\0';
- return false;
- }
-
- /* We have our final number, we can put it in name and exit the function. */
- BLI_strncpy(name + base_name_len, number_str, number_str_len + 1);
- return true;
-}
-
-/**
- * Check to see if an ID name is already used, and find a new one if so.
- * Return true if a new name was created (returned in name).
- *
- * Normally the ID that's being checked is already in the ListBase, so ID *id points at the new
- * entry. The Python Library module needs to know what the name of a data-block will be before it
- * is appended, in this case ID *id is NULL.
- */
-static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_hint)
-{
- BLI_assert(strlen(name) < MAX_ID_NAME - 2);
-
- *r_id_sorting_hint = NULL;
-
- ID *id_test = lb->first;
- bool is_name_changed = false;
-
- if (id_test == NULL) {
- return is_name_changed;
- }
-
- const short id_type = (short)GS(id_test->name);
-
- /* Static storage of previous handled ID/name info, used to perform a quicker test and optimize
- * creation of huge number of IDs using the same given base name. */
- static char prev_orig_base_name[MAX_ID_NAME - 2] = {0};
- static char prev_final_base_name[MAX_ID_NAME - 2] = {0};
- static short prev_id_type = ID_LINK_PLACEHOLDER; /* Should never exist in actual ID list. */
- static int prev_number = MIN_NUMBER - 1;
-
- /* Initial test to check whether we can 'shortcut' the more complex loop of the main code below.
- * Note that we do not do that for low numbers, as that would prevent using actual smallest
- * available number in some cases, and benefits of this special case handling mostly show up with
- * high numbers anyway. */
- if (id_type == prev_id_type && prev_number >= MAX_NUMBERS_IN_USE &&
- prev_number < MAX_NUMBER - 1 && name[0] == prev_final_base_name[0]) {
-
- /* Get the name and number parts ("name.number"). */
- char base_name[MAX_ID_NAME - 2];
- int number = MIN_NUMBER;
- size_t base_name_len = BLI_split_name_num(base_name, &number, name, '.');
- size_t prev_final_base_name_len = strlen(prev_final_base_name);
- size_t prev_orig_base_name_len = strlen(prev_orig_base_name);
-
- if (base_name_len == prev_orig_base_name_len &&
- STREQLEN(base_name, prev_orig_base_name, prev_orig_base_name_len)) {
- /* Once we have ensured given base_name and original previous one are the same, we can check
- * that previously used number is actually used, and that next one is free. */
- /* Note that from now on, we only used previous final base name, as it might have been
- * truncated from original one due to number suffix length. */
- char final_name[MAX_ID_NAME - 2];
- char prev_final_name[MAX_ID_NAME - 2];
- BLI_strncpy(final_name, prev_final_base_name, prev_final_base_name_len + 1);
- BLI_strncpy(prev_final_name, prev_final_base_name, prev_final_base_name_len + 1);
-
- if (id_name_final_build(final_name, base_name, prev_final_base_name_len, prev_number + 1) &&
- id_name_final_build(prev_final_name, base_name, prev_final_base_name_len, prev_number)) {
- /* We successfully built valid final names of previous and current iterations,
- * now we have to ensure that previous final name is indeed used in current ID list,
- * and that current one is not. */
- bool is_valid = false;
- for (id_test = lb->first; id_test; id_test = id_test->next) {
- if (id != id_test && !ID_IS_LINKED(id_test)) {
- if (id_test->name[2] == final_name[0] && STREQ(final_name, id_test->name + 2)) {
- /* We expect final_name to not be already used, so this is a failure. */
- is_valid = false;
- break;
- }
- /* Previous final name should only be found once in the list, so if it was found
- * already, no need to do a string comparison again. */
- if (!is_valid && id_test->name[2] == prev_final_name[0] &&
- STREQ(prev_final_name, id_test->name + 2)) {
- is_valid = true;
- *r_id_sorting_hint = id_test;
- }
- }
- }
-
- if (is_valid) {
- /* Only the number changed, prev_orig_base_name, prev_final_base_name and prev_id_type
- * remain the same. */
- prev_number++;
-
- strcpy(name, final_name);
- return true;
- }
- }
- }
- }
-
- /* To speed up finding smallest unused number within [0 .. MAX_NUMBERS_IN_USE - 1].
- * We do not bother beyond that point. */
- ID *ids_in_use[MAX_NUMBERS_IN_USE] = {NULL};
-
- bool is_first_run = true;
- while (true) {
- /* Get the name and number parts ("name.number"). */
- char base_name[MAX_ID_NAME - 2];
- int number = MIN_NUMBER;
- size_t base_name_len = BLI_split_name_num(base_name, &number, name, '.');
-
- /* Store previous original given base name now, as we might alter it later in code below. */
- if (is_first_run) {
- strcpy(prev_orig_base_name, base_name);
- is_first_run = false;
- }
-
- /* In case we get an insane initial number suffix in given name. */
- /* Note: BLI_split_name_num() cannot return negative numbers, so we do not have to check for
- * that here. */
- if (number >= MAX_NUMBER || number < MIN_NUMBER) {
- number = MIN_NUMBER;
- }
-
- bool is_orig_name_used = false;
- for (id_test = lb->first; id_test; id_test = id_test->next) {
- char base_name_test[MAX_ID_NAME - 2];
- int number_test;
- if ((id != id_test) && !ID_IS_LINKED(id_test) && (name[0] == id_test->name[2]) &&
- (id_test->name[base_name_len + 2] == '.' || id_test->name[base_name_len + 2] == '\0') &&
- STREQLEN(name, id_test->name + 2, base_name_len) &&
- (BLI_split_name_num(base_name_test, &number_test, id_test->name + 2, '.') ==
- base_name_len)) {
- /* If we did not yet encounter exact same name as the given one, check the remaining parts
- * of the strings. */
- if (!is_orig_name_used) {
- is_orig_name_used = STREQ(name + base_name_len, id_test->name + 2 + base_name_len);
- }
- /* Mark number of current id_test name as used, if possible. */
- if (number_test < MAX_NUMBERS_IN_USE) {
- ids_in_use[number_test] = id_test;
- }
- /* Keep track of first largest unused number. */
- if (number <= number_test) {
- *r_id_sorting_hint = id_test;
- number = number_test + 1;
- }
- }
- }
-
- /* If there is no double, we are done.
- * Note however that name might have been changed (truncated) in a previous iteration already.
- */
- if (!is_orig_name_used) {
- /* Don't bother updating prev_ static variables here, this case is not supposed to happen
- * that often, and is not straight-forward here, so just ignore and reset them to default. */
- prev_id_type = ID_LINK_PLACEHOLDER;
- prev_final_base_name[0] = '\0';
- prev_number = MIN_NUMBER - 1;
-
- /* Value set previously is meaningless in that case. */
- *r_id_sorting_hint = NULL;
-
- return is_name_changed;
- }
-
- /* Decide which value of number to use, either the smallest unused one if possible, or default
- * to the first largest unused one we got from previous loop. */
- for (int i = MIN_NUMBER; i < MAX_NUMBERS_IN_USE; i++) {
- if (ids_in_use[i] == NULL) {
- number = i;
- if (i > 0) {
- *r_id_sorting_hint = ids_in_use[i - 1];
- }
- break;
- }
- }
- /* At this point, number is either the lowest unused number within
- * [MIN_NUMBER .. MAX_NUMBERS_IN_USE - 1], or 1 greater than the largest used number if all
- * those low ones are taken.
- * We can't be bothered to look for the lowest unused number beyond
- * (MAX_NUMBERS_IN_USE - 1).
- */
- /* We know for wure that name will be changed. */
- is_name_changed = true;
-
- /* If id_name_final_build helper returns false, it had to truncate further given name, hence we
- * have to go over the whole check again. */
- if (!id_name_final_build(name, base_name, base_name_len, number)) {
- /* We have to clear our list of small used numbers before we do the whole check again. */
- memset(ids_in_use, 0, sizeof(ids_in_use));
-
- continue;
- }
-
- /* Update prev_ static variables, in case next call is for the same type of IDs and with the
- * same initial base name, we can skip a lot of above process. */
- prev_id_type = id_type;
- strcpy(prev_final_base_name, base_name);
- prev_number = number;
-
- return is_name_changed;
- }
-
-#undef MAX_NUMBERS_IN_USE
-}
-
-#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).
- *
- * \return true if a new name had to be created.
- */
-bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname)
-{
- bool result;
- char name[MAX_ID_NAME - 2];
-
- /* if library, don't rename */
- if (ID_IS_LINKED(id)) {
- return false;
- }
-
- /* if no name given, use name of current ID
- * else make a copy (tname args can be const) */
- if (tname == NULL) {
- tname = id->name + 2;
- }
-
- BLI_strncpy(name, tname, sizeof(name));
-
- if (name[0] == '\0') {
- /* Disallow empty names. */
- BLI_strncpy(name, DATA_(BKE_idcode_to_name(GS(id->name))), sizeof(name));
- }
- else {
- /* disallow non utf8 chars,
- * the interface checks for this but new ID's based on file names don't */
- BLI_utf8_invalid_strip(name, strlen(name));
- }
-
- ID *id_sorting_hint = NULL;
- result = check_for_dupid(lb, id, name, &id_sorting_hint);
- strcpy(id->name + 2, name);
-
- /* This was in 2.43 and previous releases
- * however all data in blender should be sorted, not just duplicate names
- * sorting should not hurt, but noting just in case it alters the way other
- * functions work, so sort every time. */
-#if 0
- if (result) {
- id_sort_by_name(lb, id, id_sorting_hint);
- }
-#endif
-
- id_sort_by_name(lb, id, id_sorting_hint);
-
- return result;
-}
-
-/**
- * Pull an ID out of a library (make it local). Only call this for IDs that
- * don't have other library users.
- */
-void id_clear_lib_data_ex(Main *bmain, ID *id, const bool id_in_mainlist)
-{
- bNodeTree *ntree = NULL;
- Key *key = NULL;
-
- BKE_id_lib_local_paths(bmain, id->lib, id);
-
- id_fake_user_clear(id);
-
- id->lib = NULL;
- id->tag &= ~(LIB_TAG_INDIRECT | LIB_TAG_EXTERN);
- id->flag &= ~LIB_INDIRECT_WEAK_LINK;
- if (id_in_mainlist) {
- if (BKE_id_new_name_validate(which_libbase(bmain, GS(id->name)), id, NULL)) {
- bmain->is_memfile_undo_written = false;
- }
- }
-
- /* Internal bNodeTree blocks inside data-blocks also stores id->lib,
- * make sure this stays in sync. */
- if ((ntree = ntreeFromID(id))) {
- id_clear_lib_data_ex(bmain, &ntree->id, false); /* Datablocks' nodetree is never in Main. */
- }
-
- /* Same goes for shapekeys. */
- if ((key = BKE_key_from_id(id))) {
- id_clear_lib_data_ex(bmain, &key->id, id_in_mainlist); /* sigh, why are keys in Main? */
- }
-}
-
-void id_clear_lib_data(Main *bmain, ID *id)
-{
- id_clear_lib_data_ex(bmain, id, true);
-}
-
-/* next to indirect usage in read/writefile also in editobject.c scene.c */
-void BKE_main_id_clear_newpoins(Main *bmain)
-{
- ID *id;
-
- FOREACH_MAIN_ID_BEGIN (bmain, id) {
- id->newid = NULL;
- id->tag &= ~LIB_TAG_NEW;
- }
- FOREACH_MAIN_ID_END;
-}
-
-static int id_refcount_recompute_callback(void *user_data,
- struct ID *UNUSED(id_self),
- struct ID **id_pointer,
- int cb_flag)
-{
- const bool do_linked_only = (bool)POINTER_AS_INT(user_data);
-
- if (*id_pointer == NULL) {
- return IDWALK_RET_NOP;
- }
- if (do_linked_only && !ID_IS_LINKED(*id_pointer)) {
- return IDWALK_RET_NOP;
- }
-
- if (cb_flag & IDWALK_CB_USER) {
- /* Do not touch to direct/indirect linked status here... */
- id_us_plus_no_lib(*id_pointer);
- }
- if (cb_flag & IDWALK_CB_USER_ONE) {
- id_us_ensure_real(*id_pointer);
- }
-
- return IDWALK_RET_NOP;
-}
-
-void BKE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only)
-{
- ID *id;
-
- FOREACH_MAIN_ID_BEGIN (bmain, id) {
- if (!ID_IS_LINKED(id) && do_linked_only) {
- continue;
- }
- id->us = ID_FAKE_USERS(id);
- /* Note that we keep EXTRAUSER tag here, since some UI users may define it too... */
- if (id->tag & LIB_TAG_EXTRAUSER) {
- id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET);
- id_us_ensure_real(id);
- }
- }
- FOREACH_MAIN_ID_END;
-
- /* Go over whole Main database to re-generate proper usercounts... */
- FOREACH_MAIN_ID_BEGIN (bmain, id) {
- BKE_library_foreach_ID_link(bmain,
- id,
- id_refcount_recompute_callback,
- POINTER_FROM_INT((int)do_linked_only),
- IDWALK_READONLY);
- }
- FOREACH_MAIN_ID_END;
-}
-
-static void library_make_local_copying_check(ID *id,
- GSet *loop_tags,
- MainIDRelations *id_relations,
- GSet *done_ids)
-{
- if (BLI_gset_haskey(done_ids, id)) {
- return; /* Already checked, nothing else to do. */
- }
-
- MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
- BLI_gset_insert(loop_tags, id);
- for (; entry != NULL; entry = entry->next) {
-
- /* Used_to_user stores ID pointer, not pointer to ID pointer. */
- ID *par_id = (ID *)entry->id_pointer;
-
- /* Our oh-so-beloved 'from' pointers... */
- if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
- /* We totally disregard Object->proxy_from 'usage' here,
- * this one would only generate fake positives. */
- if (GS(par_id->name) == ID_OB) {
- BLI_assert(((Object *)par_id)->proxy_from == (Object *)id);
- continue;
- }
-
- /* Shapekeys are considered 'private' to their owner ID here, and never tagged
- * (since they cannot be linked), * so we have to switch effective parent to their owner.
- */
- if (GS(par_id->name) == ID_KE) {
- par_id = ((Key *)par_id)->from;
- }
- }
-
- if (par_id->lib == NULL) {
- /* Local user, early out to avoid some gset querying... */
- continue;
- }
- if (!BLI_gset_haskey(done_ids, par_id)) {
- if (BLI_gset_haskey(loop_tags, par_id)) {
- /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
- * Note that this is the situation that can lead to archipelagoes of linked data-blocks
- * (since all of them have non-local users, they would all be duplicated,
- * leading to a loop of unused linked data-blocks that cannot be freed since they all use
- * each other...). */
- continue;
- }
- /* Else, recursively check that user ID. */
- library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids);
- }
-
- if (par_id->tag & LIB_TAG_DOIT) {
- /* This user will be fully local in future, so far so good,
- * nothing to do here but check next user. */
- }
- else {
- /* This user won't be fully local in future, so current ID won't be either.
- * And we are done checking it. */
- id->tag &= ~LIB_TAG_DOIT;
- break;
- }
- }
- BLI_gset_add(done_ids, 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...
- */
-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[MAX_LIBARRAY];
-
- LinkNode *todo_ids = NULL;
- LinkNode *copied_ids = NULL;
- MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__);
-
- GSet *done_ids = BLI_gset_ptr_new(__func__);
-
-#ifdef DEBUG_TIME
- TIMEIT_START(make_local);
-#endif
-
- BKE_main_relations_create(bmain);
-
-#ifdef DEBUG_TIME
- printf("Pre-compute current ID relations: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- /* Step 1: Detect data-blocks to make local. */
- for (int a = set_listbasepointers(bmain, lbarray); a--;) {
- ID *id = lbarray[a]->first;
-
- /* Do not explicitly make local non-linkable IDs (shapekeys, in fact),
- * they are assumed to be handled by real data-blocks responsible of them. */
- const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name)));
-
- for (; id; id = id->next) {
- ID *ntree = (ID *)ntreeFromID(id);
-
- id->tag &= ~LIB_TAG_DOIT;
- if (ntree != NULL) {
- ntree->tag &= ~LIB_TAG_DOIT;
- }
-
- if (id->lib == NULL) {
- id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
- id->flag &= ~LIB_INDIRECT_WEAK_LINK;
- }
- /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data
- * you don't want to be made local, used for appending data,
- * so any libdata already linked wont become local (very nasty
- * to discover all your links are lost after appending).
- * Also, never ever make proxified objects local, would not make any sense. */
- /* Some more notes:
- * - Shapekeys are never tagged here (since they are not linkable).
- * - Nodetrees used in materials etc. have to be tagged manually,
- * since they do not exist in Main (!).
- * This is ok-ish on 'make local' side of things
- * (since those are handled by their 'owner' IDs),
- * but complicates slightly the pre-processing of relations between IDs at step 2... */
- else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) &&
- ELEM(lib, NULL, id->lib) &&
- !(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) &&
- ((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING))) {
- BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
- id->tag |= LIB_TAG_DOIT;
-
- /* Tag those nasty non-ID nodetrees,
- * but do not add them to todo list, making them local is handled by 'owner' ID.
- * This is needed for library_make_local_copying_check() to work OK at step 2. */
- if (ntree != NULL) {
- ntree->tag |= LIB_TAG_DOIT;
- }
- }
- else {
- /* Linked ID that we won't be making local (needed info for step 2, see below). */
- BLI_gset_add(done_ids, id);
- }
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Step 1: Detect data-blocks to make local: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- /* Step 2: Check which data-blocks we can directly make local
- * (because they are only used by already, or future, local data),
- * others will need to be duplicated. */
- GSet *loop_tags = BLI_gset_ptr_new(__func__);
- for (LinkNode *it = todo_ids; it; it = it->next) {
- library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids);
- BLI_assert(BLI_gset_len(loop_tags) == 0);
- }
- BLI_gset_free(loop_tags, NULL);
- BLI_gset_free(done_ids, NULL);
-
- /* Next step will most likely add new IDs, better to get rid of this mapping now. */
- BKE_main_relations_free(bmain);
-
-#ifdef DEBUG_TIME
- printf("Step 2: Check which data-blocks we can directly make local: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- /* Step 3: Make IDs local, either directly (quick and simple), or using generic process,
- * which involves more complex checks and might instead
- * create a local copy of original linked ID. */
- for (LinkNode *it = todo_ids, *it_next; it; it = it_next) {
- it_next = it->next;
- ID *id = it->link;
-
- if (id->tag & LIB_TAG_DOIT) {
- /* We know all users of this object are local or will be made fully local, even if
- * currently there are some indirect usages. So instead of making a copy that we'll likely
- * get rid of later, directly make that data block local.
- * Saves a tremendous amount of time with complex scenes... */
- id_clear_lib_data_ex(bmain, id, true);
- BKE_id_expand_local(bmain, id);
- id->tag &= ~LIB_TAG_DOIT;
-
- if (GS(id->name) == ID_OB) {
- BKE_rigidbody_ensure_local_object(bmain, (Object *)id);
- }
- }
- else {
- /* In this specific case, we do want to make ID local even if it has no local usage yet...
- */
- if (GS(id->name) == ID_OB) {
- /* Special case for objects because we don't want proxy pointers to be
- * cleared yet. This will happen down the road in this function.
- */
- BKE_object_make_local_ex(bmain, (Object *)id, true, false);
- }
- else {
- id_make_local(bmain, id, false, true);
- }
-
- if (id->newid) {
- if (GS(id->newid->name) == ID_OB) {
- BKE_rigidbody_ensure_local_object(bmain, (Object *)id->newid);
- }
-
- /* Reuse already allocated LinkNode (transferring it from todo_ids to copied_ids). */
- BLI_linklist_prepend_nlink(&copied_ids, id, it);
- }
- }
-
- if (set_fake) {
- if (!ELEM(GS(id->name), ID_OB, ID_GR)) {
- /* do not set fake user on objects, groups (instancing) */
- id_fake_user_set(id);
- }
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Step 3: Make IDs local: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- /* At this point, we are done with directly made local IDs.
- * Now we have to handle duplicated ones, since their
- * remaining linked original counterpart may not be needed anymore... */
- todo_ids = NULL;
-
- /* Step 4: We have to remap local usages of old (linked) ID to new (local)
- * ID in a separated loop,
- * as lbarray ordering is not enough to ensure us we did catch all dependencies
- * (e.g. if making local a parent object before its child...). See T48907. */
- /* TODO This is now the biggest step by far (in term of processing time).
- * We may be able to gain here by using again main->relations mapping, but...
- * this implies BKE_libblock_remap & co to be able to update main->relations on the fly.
- * Have to think about it a bit more, and see whether new code is OK first, anyway. */
- for (LinkNode *it = copied_ids; it; it = it->next) {
- ID *id = it->link;
-
- BLI_assert(id->newid != NULL);
- BLI_assert(id->lib != NULL);
-
- BKE_libblock_remap(bmain, id, id->newid, ID_REMAP_SKIP_INDIRECT_USAGE);
- if (old_to_new_ids) {
- BLI_ghash_insert(old_to_new_ids, id, id->newid);
- }
-
- /* Special hack for groups... Thing is, since we can't instantiate them here, we need to
- * ensure they remain 'alive' (only instantiation is a real group 'user'... *sigh* See
- * T49722. */
- if (GS(id->name) == ID_GR && (id->tag & LIB_TAG_INDIRECT) != 0) {
- id_us_ensure_real(id->newid);
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Step 4: Remap local usages of old (linked) ID to new (local) ID: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- /* Step 5: proxy 'remapping' hack. */
- for (LinkNode *it = copied_ids; it; it = it->next) {
- ID *id = it->link;
-
- /* 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 (ob->proxy->id.lib == NULL) {
- CLOG_WARN(&LOG,
- "proxy object %s will loose 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 loose 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 BKE_object_make_local_ex() (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;
- }
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Step 5: Proxy 'remapping' hack: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- /* This is probably more of a hack than something we should do here, but...
- * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels
- * of armatures in complete invalid state (more precisely, the bone pointers of the
- * pose-channels - very crappy cross-data-blocks relationship), se we tag it to be fully
- * recomputed, but this does not seems to be enough in some cases, and evaluation code ends up
- * trying to evaluate a not-yet-updated armature object's deformations.
- * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL &&
- ob->pose->flag & POSE_RECALC) {
- BKE_pose_rebuild(bmain, ob, ob->data, true);
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Hack: Forcefully rebuild armature object poses: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
- BKE_main_id_clear_newpoins(bmain);
- BLI_memarena_free(linklist_mem);
-
-#ifdef DEBUG_TIME
- printf("Cleanup and finish: Done.\n");
- TIMEIT_END(make_local);
-#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;
- ID *idtest;
-
- lb = which_libbase(bmain, GS(name));
- if (lb == NULL) {
- return;
- }
-
- /* search for id */
- idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2);
- if (idtest != NULL) {
- /* BKE_id_new_name_validate also takes care of sorting. */
- BKE_id_new_name_validate(lb, idtest, NULL);
- bmain->is_memfile_undo_written = false;
- }
-}
-
-/**
- * Sets the name of a block to name, suitably adjusted for uniqueness.
- */
-void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
-{
- ListBase *lb = which_libbase(bmain, GS(id->name));
- if (BKE_id_new_name_validate(lb, id, name)) {
- bmain->is_memfile_undo_written = false;
- }
-}
-
-/**
- * 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.
- */
-void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id)
-{
- strcpy(name, id->name + 2);
-
- if (id->lib != NULL) {
- const size_t idname_len = strlen(id->name + 2);
- const size_t libname_len = strlen(id->lib->id.name + 2);
-
- name[idname_len] = ' ';
- name[idname_len + 1] = '[';
- strcpy(name + idname_len + 2, id->lib->id.name + 2);
- name[idname_len + 2 + libname_len] = ']';
- name[idname_len + 2 + libname_len + 1] = '\0';
- }
-}
-
-/**
- * Generate full name of the data-block (without ID code, but with library if any),
- * with a 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.
- */
-void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const ID *id)
-{
- name[0] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
- name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
- name[2] = ' ';
-
- BKE_id_full_name_get(name + 3, id);
-}
-
-/**
- * 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->lib == NULL) {
- return BLI_strdup(id->name);
- }
- else {
- /* Prefix with an ascii character in the range of 32..96 (visible)
- * this ensures we can't have a library ID pair that collide.
- * Where 'LIfooOBbarOBbaz' could be ('LIfoo, OBbarOBbaz') or ('LIfooOBbar', 'OBbaz'). */
- const char ascii_len = strlen(id->lib->id.name + 2) + 32;
- return BLI_sprintfN("%c%s%s", ascii_len, id->lib->id.name, id->name);
- }
-}
-
void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
{
/* in some cases this is used to update the absolute path from the
@@ -2528,119 +73,3 @@ void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
BLI_path_abs(lib->filepath, basepath);
}
}
-
-void BKE_id_tag_set_atomic(ID *id, int tag)
-{
- atomic_fetch_and_or_int32(&id->tag, tag);
-}
-
-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...
- */
- return (id == NULL || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1);
-}
-
-/************************* Datablock order in UI **************************/
-
-static int *id_order_get(ID *id)
-{
- /* Only for workspace tabs currently. */
- switch (GS(id->name)) {
- case ID_WS:
- return &((WorkSpace *)id)->order;
- default:
- return NULL;
- }
-}
-
-static int id_order_compare(const void *a, const void *b)
-{
- ID *id_a = ((LinkData *)a)->data;
- ID *id_b = ((LinkData *)b)->data;
-
- int *order_a = id_order_get(id_a);
- int *order_b = id_order_get(id_b);
-
- if (order_a && order_b) {
- if (*order_a < *order_b) {
- return -1;
- }
- else if (*order_a > *order_b) {
- return 1;
- }
- }
-
- 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);
-
- for (ID *id = lb->first; id; id = id->next) {
- BLI_addtail(ordered_lb, BLI_genericNodeN(id));
- }
-
- BLI_listbase_sort(ordered_lb, id_order_compare);
-
- int num = 0;
- for (LinkData *link = ordered_lb->first; link; link = link->next) {
- int *order = id_order_get(link->data);
- if (order) {
- *order = num++;
- }
- }
-}
-
-/**
- * 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);
- int relative_order;
-
- if (relative) {
- relative_order = *id_order_get(relative);
- }
- else {
- relative_order = (after) ? BLI_listbase_count(lb) : 0;
- }
-
- if (after) {
- /* Insert after. */
- for (ID *other = lb->first; other; other = other->next) {
- int *order = id_order_get(other);
- if (*order > relative_order) {
- (*order)++;
- }
- }
-
- *id_order = relative_order + 1;
- }
- else {
- /* Insert before. */
- for (ID *other = lb->first; other; other = other->next) {
- int *order = id_order_get(other);
- if (*order < relative_order) {
- (*order)--;
- }
- }
-
- *id_order = relative_order - 1;
- }
-}
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index ea728f61733..e517b4f8f18 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -41,7 +41,7 @@
#include "BKE_colortools.h"
#include "BKE_icons.h"
#include "BKE_light.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -74,7 +74,7 @@ Light *BKE_light_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_light_copy_data(Main *bmain, Light *la_dst, const Light *la_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index 3cba3aa9611..c6d025439d5 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -30,7 +30,7 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_lightprobe.h"
#include "BKE_main.h"
@@ -84,7 +84,7 @@ void *BKE_lightprobe_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_lightprobe_copy_data(Main *UNUSED(bmain),
LightProbe *UNUSED(probe_dst),
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 3efc493b43e..3396a2e448e 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -40,7 +40,7 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_freestyle.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_linestyle.h"
#include "BKE_node.h"
#include "BKE_colortools.h"
@@ -134,7 +134,7 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_linestyle_copy_data(struct Main *bmain,
FreestyleLineStyle *linestyle_dst,
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index 8e2c3a11ac0..0c17a2c0856 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -35,8 +35,8 @@
#include "DNA_ID.h"
#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "IMB_imbuf.h"
diff --git a/source/blender/blenkernel/intern/library_idmap.c b/source/blender/blenkernel/intern/main_idmap.c
index ab0ff5b0096..a210961b212 100644
--- a/source/blender/blenkernel/intern/library_idmap.c
+++ b/source/blender/blenkernel/intern/main_idmap.c
@@ -26,8 +26,8 @@
#include "DNA_ID.h"
#include "BKE_idcode.h"
-#include "BKE_library_idmap.h" /* own include */
#include "BKE_main.h"
+#include "BKE_main_idmap.h" /* own include */
/** \file
* \ingroup bke
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index fc087ff91b2..513e2863dd5 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -46,7 +46,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_node.h"
@@ -883,7 +883,7 @@ Mask *BKE_mask_copy_nolib(Mask *mask)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_mask_copy_data(Main *UNUSED(bmain),
Mask *mask_dst,
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index f4f93fcb698..cb8b3b5ecc9 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -198,7 +198,7 @@ float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline,
float (*BKE_mask_spline_differentiate(
MaskSpline *spline, int width, int height, unsigned int *tot_diff_point))[2]
{
- int unsigned resol = BKE_mask_spline_resolution(spline, width, height);
+ uint resol = BKE_mask_spline_resolution(spline, width, height);
return BKE_mask_spline_differentiate_with_resolution(spline, tot_diff_point, resol);
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 84b3ea27025..af5e867ac38 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -55,7 +55,7 @@
#include "BKE_gpencil.h"
#include "BKE_icons.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -157,7 +157,7 @@ Material *BKE_gpencil_material_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index c5cb95927ec..1659199656b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -51,7 +51,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_scene.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_displist.h"
#include "BKE_mball.h"
#include "BKE_object.h"
@@ -102,7 +102,7 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_mball_copy_data(Main *UNUSED(bmain),
MetaBall *mb_dst,
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3835e405630..09529582a43 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -44,7 +44,7 @@
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
@@ -563,7 +563,7 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int flag)
{
@@ -1200,7 +1200,7 @@ 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, unsigned vert)
+int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, uint vert)
{
int j;
for (j = 0; j < poly->totloop; j++, loopstart++) {
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index c48b3b511d9..68d535e6405 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -40,12 +40,12 @@
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_displist.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mball.h"
/* these 2 are only used by conversion functions */
diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c
index ae808b85323..d646e988c60 100644
--- a/source/blender/blenkernel/intern/mesh_merge.c
+++ b/source/blender/blenkernel/intern/mesh_merge.c
@@ -33,7 +33,7 @@
#include "BLI_ghash.h"
#include "BKE_customdata.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index 271591d98f0..47338aef3cf 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -27,8 +27,8 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mirror.h"
#include "BKE_modifier.h"
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index d616ff30787..afc380fd369 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -41,7 +41,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_customdata.h"
#include "BKE_bvhutils.h"
#include "BKE_mesh_remesh_voxel.h" /* own include */
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index 4c3761c7ffc..3e21e044a02 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -33,7 +33,7 @@
#include "BLI_threads.h"
#include "BKE_bvhutils.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_subdiv_ccg.h"
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 4aa5bfa04ab..e4de75b923f 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -784,22 +784,24 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
/* note, greater than max defgroups is accounted for in our code, but not < 0 */
if (!isfinite(dw->weight)) {
- PRINT_ERR("\tVertex deform %u, group %d has weight: %f", i, dw->def_nr, dw->weight);
+ PRINT_ERR("\tVertex deform %u, group %u has weight: %f", i, dw->def_nr, dw->weight);
if (do_fixes) {
dw->weight = 0.0f;
fix_flag.verts_weight = true;
}
}
else if (dw->weight < 0.0f || dw->weight > 1.0f) {
- PRINT_ERR("\tVertex deform %u, group %d has weight: %f", i, dw->def_nr, dw->weight);
+ PRINT_ERR("\tVertex deform %u, group %u has weight: %f", i, dw->def_nr, dw->weight);
if (do_fixes) {
CLAMP(dw->weight, 0.0f, 1.0f);
fix_flag.verts_weight = true;
}
}
- if (dw->def_nr < 0) {
- PRINT_ERR("\tVertex deform %u, has invalid group %d", i, dw->def_nr);
+ /* Not technically incorrect since this is unsigned, however,
+ * a value over INT_MAX is almost certainly caused by wrapping an unsigned int. */
+ if (dw->def_nr >= INT_MAX) {
+ PRINT_ERR("\tVertex deform %u, has invalid group %u", i, dw->def_nr);
if (do_fixes) {
defvert_remove_group(dv, dw);
fix_flag.verts_weight = true;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index a784be9c645..2591edb502e 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -53,8 +53,8 @@
#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_object.h"
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 9385a9ae24d..6ea642f9876 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -54,7 +54,7 @@
#include "BKE_animsys.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_node.h"
@@ -1639,7 +1639,7 @@ void BKE_movieclip_free(MovieClip *clip)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_movieclip_copy_data(Main *UNUSED(bmain),
MovieClip *clip_dst,
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index 4e4a8831518..0a8248b25f1 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -32,7 +32,7 @@
#include "BLI_task.h"
#include "BKE_ccg.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 7aa8837d139..2a29644f0d7 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -48,7 +48,7 @@
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_sound.h"
@@ -161,7 +161,7 @@ void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user)
*
* \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_library.h
+ * flags in BKE_lib_id.h
*/
NlaStrip *BKE_nlastrip_copy(Main *bmain,
NlaStrip *strip,
@@ -215,7 +215,7 @@ NlaStrip *BKE_nlastrip_copy(Main *bmain,
/**
* Copy a single NLA Track.
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
- * flags in BKE_library.h
+ * flags in BKE_lib_id.h
*/
NlaTrack *BKE_nlatrack_copy(Main *bmain,
NlaTrack *nlt,
@@ -249,7 +249,7 @@ NlaTrack *BKE_nlatrack_copy(Main *bmain,
/**
* Copy all NLA data.
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
- * flags in BKE_library.h
+ * flags in BKE_lib_id.h
*/
void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, ListBase *src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 75e0d044c7c..64897d05c96 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -53,7 +53,7 @@
#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -1499,7 +1499,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_node_tree_copy_data(Main *UNUSED(bmain),
bNodeTree *ntree_dst,
@@ -2242,27 +2242,37 @@ void ntreeSetOutput(bNodeTree *ntree)
* might be different for editor or for "real" use... */
}
-/* Returns the private NodeTree object of the datablock, if it has one. */
-bNodeTree *ntreeFromID(const ID *id)
+/** Get address of potential nodetree 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)) {
case ID_MA:
- return ((const Material *)id)->nodetree;
+ return &((Material *)id)->nodetree;
case ID_LA:
- return ((const Light *)id)->nodetree;
+ return &((Light *)id)->nodetree;
case ID_WO:
- return ((const World *)id)->nodetree;
+ return &((World *)id)->nodetree;
case ID_TE:
- return ((const Tex *)id)->nodetree;
+ return &((Tex *)id)->nodetree;
case ID_SCE:
- return ((const Scene *)id)->nodetree;
+ return &((Scene *)id)->nodetree;
case ID_LS:
- return ((const FreestyleLineStyle *)id)->nodetree;
+ return &((FreestyleLineStyle *)id)->nodetree;
default:
return NULL;
}
}
+/* Returns the private NodeTree object of the datablock, if it has one. */
+bNodeTree *ntreeFromID(ID *id)
+{
+ bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
+ return (nodetree != NULL) ? *nodetree : NULL;
+}
+
/* Finds and returns the datablock that privately owns the given tree, or NULL. */
ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
{
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index cf43dec132a..51d397a44bc 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -89,9 +89,9 @@
#include "BKE_light.h"
#include "BKE_layer.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_linestyle.h"
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
@@ -1325,7 +1325,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 46c2f735761..e72540ed499 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -55,7 +55,7 @@
#include "BKE_gpencil.h"
#include "BKE_image.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
@@ -498,7 +498,7 @@ PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_paint_curve_copy_data(Main *UNUSED(bmain),
PaintCurve *pc_dst,
@@ -587,7 +587,7 @@ Palette *BKE_palette_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_palette_copy_data(Main *UNUSED(bmain),
Palette *palette_dst,
@@ -846,7 +846,7 @@ bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *m
/* 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)
+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 */
return (BLI_BITMAP_TEST(grid_hidden, y * gridsize + x) ||
@@ -871,7 +871,7 @@ bool paint_is_bmesh_face_hidden(BMFace *f)
return false;
}
-float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, unsigned x, unsigned y)
+float paint_grid_paint_mask(const GridPaintMask *gpm, uint level, uint x, uint y)
{
int factor = BKE_ccg_factor(level, gpm->level);
int gridsize = BKE_ccg_gridsize(gpm->level);
diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c
index 1d10db06139..e9601109fd5 100644
--- a/source/blender/blenkernel/intern/paint_toolslots.c
+++ b/source/blender/blenkernel/intern/paint_toolslots.c
@@ -29,7 +29,7 @@
#include "BLI_utildefines.h"
#include "BKE_main.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_brush.h"
#include "BKE_paint.h"
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 7a352f8c9f8..bda768626b4 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -65,7 +65,7 @@
#include "BKE_particle.h"
#include "BKE_material.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_cdderivedmesh.h" /* for weight_to_rgb() */
@@ -3638,12 +3638,14 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob
}
}
- /* clear modifier */
+ /* Clear modifier, skip empty ones. */
psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
+ if (psmd) {
+ BLI_remlink(&ob->modifiers, psmd);
+ modifier_free((ModifierData *)psmd);
+ }
- /* clear particle system */
+ /* Clear particle system. */
BLI_remlink(&ob->particlesystem, psys);
if (psys->part) {
id_us_min(&psys->part->id);
@@ -3810,7 +3812,7 @@ void BKE_particlesettings_twist_curve_init(ParticleSettings *part)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_particlesettings_copy_data(Main *UNUSED(bmain),
ParticleSettings *part_dst,
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 1189785ce0f..7a0998a1ee7 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -41,7 +41,7 @@
#include "DNA_scene_types.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 95726e145b4..2f6ffdfe607 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -62,8 +62,8 @@
#include "BKE_collision.h"
#include "BKE_colortools.h"
#include "BKE_effect.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_particle.h"
#include "BKE_collection.h"
@@ -4378,7 +4378,6 @@ static void particles_fluid_step(ParticleSimulationData *sim,
1. / fabsf(ob->scale[0]), 1. / fabsf(ob->scale[1]), 1. / fabsf(ob->scale[2])};
mul_v3_fl(scaleAbs, max_size);
mul_v3_v3(pa->state.co, scaleAbs);
- ;
/* Match domain scale. */
mul_m4_v3(ob->obmat, pa->state.co);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index ec520e188f1..141e93183fb 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1410,7 +1410,7 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_UpdateNormals) {
- for (unsigned i = 0; i < node->totprim; i++) {
+ for (uint i = 0; i < node->totprim; i++) {
void *face = bvh->gridfaces[node->prim_indices[i]];
BLI_gset_add(face_set, face);
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 5e1611cb3f9..90a4a2dee23 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -57,7 +57,7 @@
#include "BKE_collection.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index c57808f3dee..c2180e50b74 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -62,8 +62,8 @@
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#ifdef WITH_BULLET
-# include "BKE_library.h"
-# include "BKE_library_query.h"
+# include "BKE_lib_id.h"
+# include "BKE_lib_query.h"
#endif
#include "DEG_depsgraph.h"
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 86b15641f81..fd1f030c3d3 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -73,8 +73,8 @@
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_remap.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_mask.h"
@@ -145,7 +145,7 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
-/* flag -- copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */
+/* 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) {
@@ -243,7 +243,7 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 8dfe01ae1fd..fc5831ed132 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -43,7 +43,7 @@
#include "DNA_space_types.h"
#include "BKE_fcurve.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_sequencer.h"
diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c
index 8c9097e1d4e..915935addcd 100644
--- a/source/blender/blenkernel/intern/seqprefetch.c
+++ b/source/blender/blenkernel/intern/seqprefetch.c
@@ -40,7 +40,7 @@
#include "IMB_imbuf_types.h"
#include "BKE_animsys.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_scene.h"
#include "BKE_main.h"
#include "BKE_context.h"
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 747ce18cada..0908fb7eeb8 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -68,7 +68,7 @@
#include "BKE_fcurve.h"
#include "BKE_scene.h"
#include "BKE_mask.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_idprop.h"
#include "DEG_depsgraph.h"
@@ -4147,146 +4147,6 @@ ImBuf *BKE_sequencer_give_ibuf_direct(const SeqRenderData *context, float cfra,
return ibuf;
}
-/* *********************** threading api ******************* */
-
-static ListBase running_threads;
-static ListBase prefetch_wait;
-static ListBase prefetch_done;
-
-static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t wakeup_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER;
-
-// static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER;
-// static pthread_cond_t prefetch_ready_cond = PTHREAD_COND_INITIALIZER;
-
-static pthread_mutex_t frame_done_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER;
-
-static volatile bool seq_thread_shutdown = true;
-static volatile int seq_last_given_monoton_cfra = 0;
-static int monoton_cfra = 0;
-
-typedef struct PrefetchThread {
- struct PrefetchThread *next, *prev;
-
- Scene *scene;
- struct PrefetchQueueElem *current;
- pthread_t pthread;
- int running;
-
-} PrefetchThread;
-
-typedef struct PrefetchQueueElem {
- struct PrefetchQueueElem *next, *prev;
-
- int rectx;
- int recty;
- float cfra;
- int chanshown;
- int preview_render_size;
-
- int monoton_cfra;
-
- ImBuf *ibuf;
-} PrefetchQueueElem;
-
-void BKE_sequencer_give_ibuf_prefetch_request(const SeqRenderData *context,
- float cfra,
- int chanshown)
-{
- PrefetchQueueElem *e;
- if (seq_thread_shutdown) {
- return;
- }
-
- e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
- e->rectx = context->rectx;
- e->recty = context->recty;
- e->cfra = cfra;
- e->chanshown = chanshown;
- e->preview_render_size = context->preview_render_size;
- e->monoton_cfra = monoton_cfra++;
-
- pthread_mutex_lock(&queue_lock);
- BLI_addtail(&prefetch_wait, e);
- pthread_mutex_unlock(&queue_lock);
-
- pthread_mutex_lock(&wakeup_lock);
- pthread_cond_signal(&wakeup_cond);
- pthread_mutex_unlock(&wakeup_lock);
-}
-
-ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context, float cfra, int chanshown)
-{
- PrefetchQueueElem *e = NULL;
- bool found_something = false;
-
- if (seq_thread_shutdown) {
- return BKE_sequencer_give_ibuf(context, cfra, chanshown);
- }
-
- while (!e) {
- bool success = false;
- pthread_mutex_lock(&queue_lock);
-
- for (e = prefetch_done.first; e; e = e->next) {
- if (cfra == e->cfra && chanshown == e->chanshown && context->rectx == e->rectx &&
- context->recty == e->recty && context->preview_render_size == e->preview_render_size) {
- success = true;
- found_something = true;
- break;
- }
- }
-
- if (!e) {
- for (e = prefetch_wait.first; e; e = e->next) {
- if (cfra == e->cfra && chanshown == e->chanshown && context->rectx == e->rectx &&
- context->recty == e->recty && context->preview_render_size == e->preview_render_size) {
- found_something = true;
- break;
- }
- }
- }
-
- if (!e) {
- PrefetchThread *tslot;
-
- for (tslot = running_threads.first; tslot; tslot = tslot->next) {
- if (tslot->current && cfra == tslot->current->cfra &&
- chanshown == tslot->current->chanshown && context->rectx == tslot->current->rectx &&
- context->recty == tslot->current->recty &&
- context->preview_render_size == tslot->current->preview_render_size) {
- found_something = true;
- break;
- }
- }
- }
-
- /* e->ibuf is unrefed by render thread on next round. */
-
- if (e) {
- seq_last_given_monoton_cfra = e->monoton_cfra;
- }
-
- pthread_mutex_unlock(&queue_lock);
-
- if (!success) {
- e = NULL;
-
- if (!found_something) {
- fprintf(stderr, "SEQ-THREAD: Requested frame not in queue ???\n");
- break;
- }
- pthread_mutex_lock(&frame_done_lock);
- pthread_cond_wait(&frame_done_cond, &frame_done_lock);
- pthread_mutex_unlock(&frame_done_lock);
- }
- }
-
- return e ? e->ibuf : NULL;
-}
-
/* check whether sequence cur depends on seq */
bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
{
diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c
index c999e1ad14e..49799aff1d6 100644
--- a/source/blender/blenkernel/intern/shader_fx.c
+++ b/source/blender/blenkernel/intern/shader_fx.c
@@ -38,8 +38,8 @@
#include "DNA_gpencil_types.h"
#include "DNA_shader_fx_types.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_gpencil.h"
#include "BKE_shader_fx.h"
#include "BKE_object.h"
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 49a295c6a9e..adc344c29d8 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -44,7 +44,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 84d135c7f32..719978c64ad 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -52,7 +52,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_sound.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_packedFile.h"
#include "BKE_sequencer.h"
#include "BKE_scene.h"
@@ -192,7 +192,7 @@ void BKE_sound_free(bSound *sound)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_sound_copy_data(Main *UNUSED(bmain),
bSound *sound_dst,
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 46a74e25b8b..7ab0f9231fa 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -27,7 +27,7 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_speaker.h"
@@ -57,7 +57,7 @@ void *BKE_speaker_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_speaker_copy_data(Main *UNUSED(bmain),
Speaker *UNUSED(spk_dst),
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 9008348ed3b..4a69fcfa9d0 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -56,17 +56,6 @@ static int last_studiolight_id = 0;
#define STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * 2)
#define STUDIOLIGHT_PASSNAME_DIFFUSE "diffuse"
#define STUDIOLIGHT_PASSNAME_SPECULAR "specular"
-/*
- * The method to calculate the irradiance buffers
- * The irradiance buffer is only shown in the background when in LookDev.
- *
- * STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE is very slow, but very accurate
- * STUDIOLIGHT_IRRADIANCE_METHOD_SPHERICAL_HARMONICS is faster but has artifacts
- * Cannot have both enabled at the same time!!!
- */
-// #define STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
-#define STUDIOLIGHT_IRRADIANCE_METHOD_SPHERICAL_HARMONICS
-
/* Temporarily disabled due to the creation of textures with -nan(ind)s */
#define STUDIOLIGHT_SH_WINDOWING 0.0f /* 0.0 is disabled */
@@ -1024,40 +1013,6 @@ BLI_INLINE void studiolight_evaluate_specular_radiance_buffer(ImBuf *radiance_bu
madd_v3_v3fl(color, accum, 1.0f / accum_weight);
}
-#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
-static void studiolight_irradiance_eval(StudioLight *sl, float color[3], const float normal[3])
-{
- copy_v3_fl(color, 0.0f);
-
- /* XXX: This is madness, iterating over all cubemap pixels for each destination pixels
- * even if their weight is 0.0f.
- * It should use hemisphere, cosine sampling at least. */
-
- /* back */
- studiolight_evaluate_specular_radiance_buffer(
- sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, 0, 2, 1, 1);
- /* front */
- studiolight_evaluate_specular_radiance_buffer(
- sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, 0, 2, 1, -1);
-
- /* left */
- studiolight_evaluate_specular_radiance_buffer(
- sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, 1, 2, 0, 1);
- /* right */
- studiolight_evaluate_specular_radiance_buffer(
- sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, 1, 2, 0, -1);
-
- /* top */
- studiolight_evaluate_specular_radiance_buffer(
- sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, 0, 1, 2, 1);
- /* bottom */
- studiolight_evaluate_specular_radiance_buffer(
- sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, 0, 1, 2, -1);
-
- mul_v3_fl(color, 1.0 / M_PI);
-}
-#endif
-
static float brdf_approx(float spec_color, float roughness, float NV)
{
/* Very rough own approx. We don't need it to be correct, just fast.
@@ -1185,11 +1140,7 @@ static bool studiolight_load_spherical_harmonics_coefficients(StudioLight *sl)
static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl)
{
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
-#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
- BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED);
-#else
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED);
-#endif
float *colbuf = MEM_mallocN(STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH *
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * sizeof(float[4]),
@@ -1202,11 +1153,7 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl)
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT) {
float dir[3];
equirect_to_direction(dir, x, y);
-#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
- studiolight_irradiance_eval(sl, pixel, dir);
-#else
studiolight_spherical_harmonics_eval(sl, pixel, dir);
-#endif
pixel[3] = 1.0f;
}
ITER_PIXELS_END;
@@ -1217,15 +1164,6 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl)
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT,
4);
MEM_freeN(colbuf);
-
-#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
- /*
- * Only store cached files when using STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
- */
- if (sl->flag & STUDIOLIGHT_USER_DEFINED) {
- IMB_saveiff(sl->equirect_irradiance_buffer, sl->path_irr_cache, IB_rectfloat);
- }
-#endif
}
sl->flag |= STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED;
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 163792984ad..c6428211db3 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -47,7 +47,7 @@
#include "DNA_node_types.h"
#include "DNA_material_types.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_text.h"
#include "BKE_node.h"
@@ -401,7 +401,7 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_text_copy_data(Main *UNUSED(bmain),
Text *ta_dst,
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index b1ae71c609f..35026288663 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -48,7 +48,7 @@
#include "BKE_main.h"
#include "BKE_colorband.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_image.h"
#include "BKE_material.h"
#include "BKE_texture.h"
@@ -313,7 +313,7 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 1e7b3af53d5..500c58095e6 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -49,7 +49,7 @@
#include "BKE_fcurve.h"
#include "BKE_tracking.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_movieclip.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -80,9 +80,7 @@ static struct {
/* Free the whole list of tracks, list's head and tail are set to NULL. */
static void tracking_tracks_free(ListBase *tracks)
{
- MovieTrackingTrack *track;
-
- for (track = tracks->first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks) {
BKE_tracking_track_free(track);
}
@@ -92,9 +90,7 @@ static void tracking_tracks_free(ListBase *tracks)
/* Free the whole list of plane tracks, list's head and tail are set to NULL. */
static void tracking_plane_tracks_free(ListBase *plane_tracks)
{
- MovieTrackingPlaneTrack *plane_track;
-
- for (plane_track = plane_tracks->first; plane_track; plane_track = plane_track->next) {
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks) {
BKE_tracking_plane_track_free(plane_track);
}
@@ -128,10 +124,8 @@ static void tracking_object_free(MovieTrackingObject *object)
/* Free list of tracking objects, list's head and tail is set to NULL. */
static void tracking_objects_free(ListBase *objects)
{
- MovieTrackingObject *object;
-
/* Free objects contents. */
- for (object = objects->first; object; object = object->next) {
+ LISTBASE_FOREACH (MovieTrackingObject *, object, objects) {
tracking_object_free(object);
}
@@ -191,13 +185,11 @@ static void tracking_tracks_copy(ListBase *tracks_dst,
GHash *tracks_mapping,
const int flag)
{
- MovieTrackingTrack *track_dst, *track_src;
-
BLI_listbase_clear(tracks_dst);
BLI_ghash_clear(tracks_mapping, NULL, NULL);
- for (track_src = tracks_src->first; track_src != NULL; track_src = track_src->next) {
- track_dst = MEM_dupallocN(track_src);
+ LISTBASE_FOREACH (MovieTrackingTrack *, track_src, tracks_src) {
+ MovieTrackingTrack *track_dst = MEM_dupallocN(track_src);
if (track_src->markers) {
track_dst->markers = MEM_dupallocN(track_src->markers);
}
@@ -217,13 +209,10 @@ static void tracking_plane_tracks_copy(ListBase *plane_tracks_list_dst,
GHash *tracks_mapping,
const int flag)
{
- MovieTrackingPlaneTrack *plane_track_dst, *plane_track_src;
-
BLI_listbase_clear(plane_tracks_list_dst);
- for (plane_track_src = plane_tracks_list_src->first; plane_track_src != NULL;
- plane_track_src = plane_track_src->next) {
- plane_track_dst = MEM_dupallocN(plane_track_src);
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track_src, plane_tracks_list_src) {
+ MovieTrackingPlaneTrack *plane_track_dst = MEM_dupallocN(plane_track_src);
if (plane_track_src->markers) {
plane_track_dst->markers = MEM_dupallocN(plane_track_src->markers);
}
@@ -278,12 +267,10 @@ static void tracking_objects_copy(ListBase *objects_dst,
GHash *tracks_mapping,
const int flag)
{
- MovieTrackingObject *object_dst, *object_src;
-
BLI_listbase_clear(objects_dst);
- for (object_src = objects_src->first; object_src != NULL; object_src = object_src->next) {
- object_dst = MEM_mallocN(sizeof(*object_dst), __func__);
+ LISTBASE_FOREACH (MovieTrackingObject *, object_src, objects_src) {
+ MovieTrackingObject *object_dst = MEM_mallocN(sizeof(*object_dst), __func__);
tracking_object_copy(object_dst, object_src, tracks_mapping, flag);
BLI_addtail(objects_dst, object_dst);
}
@@ -408,23 +395,20 @@ MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTrackin
/* 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(Scene *scene, Object *ob, float mat[4][4])
+void BKE_tracking_get_camera_object_matrix(Object *camera_object, float mat[4][4])
{
- if (!ob) {
- if (scene->camera) {
- ob = scene->camera;
- }
- else {
- ob = BKE_view_layer_camera_find(BKE_view_layer_context_active_PLACEHOLDER(scene));
- }
- }
-
- if (ob) {
- BKE_object_where_is_calc_mat4(ob, mat);
- }
- else {
- unit_m4(mat);
- }
+ BLI_assert(camera_object != NULL);
+ /* NOTE: Construct matrix from scratch rather than using obmat because the camera object here
+ * will have camera solver constraint taken into account. But here we do not want or need it:
+ * object is solved in camera space (as in, camera is stationary and object is moving).
+ *
+ * This will include animation applied on the camera, but not possible camera rig. This isn't
+ * an issue in practice due to the way how VFX is constructed.
+ *
+ * If we ever need to support crazy setups like that one possible solution would be to use
+ * final camera matrix and multiple it by an inverse of solved camera matrix at the current
+ * frame. */
+ BKE_object_where_is_calc_mat4(camera_object, mat);
}
/* Get projection matrix for camera specified by given tracking object
@@ -844,7 +828,7 @@ void BKE_tracking_tracks_join(MovieTracking *tracking,
MovieTrackingMarker *marker_a, *marker_b;
int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr;
- int j, inverse = 0;
+ int inverse = 0;
inverse = (b == 0) || (dst_track->markers[b - 1].flag & MARKER_DISABLED) ||
(dst_track->markers[b - 1].framenr != frame - 1);
@@ -872,7 +856,7 @@ void BKE_tracking_tracks_join(MovieTracking *tracking,
b = start_b;
/* linear interpolation for intersecting frames */
- for (j = 0; j < len; j++) {
+ for (int j = 0; j < len; j++) {
float fac = 0.5f;
if (len > 1) {
@@ -1180,9 +1164,7 @@ void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
void BKE_tracking_tracks_deselect_all(ListBase *tracksbase)
{
- MovieTrackingTrack *track;
-
- for (track = tracksbase->first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
if ((track->flag & TRACK_HIDDEN) == 0) {
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
@@ -1269,13 +1251,12 @@ void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr)
void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
{
- int a;
float pat_min[2], pat_max[2];
BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
if (event == CLAMP_PAT_DIM) {
- for (a = 0; a < 2; a++) {
+ for (int a = 0; a < 2; a++) {
/* search shouldn't be resized smaller than pattern */
marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
@@ -1286,23 +1267,22 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
sub_v2_v2v2(dim, pat_max, pat_min);
- for (a = 0; a < 2; a++) {
- int b;
+ for (int a = 0; a < 2; a++) {
/* pattern shouldn't be moved outside of search */
if (pat_min[a] < marker->search_min[a]) {
- for (b = 0; b < 4; b++) {
+ for (int b = 0; b < 4; b++) {
marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a];
}
}
if (pat_max[a] > marker->search_max[a]) {
- for (b = 0; b < 4; b++) {
+ for (int b = 0; b < 4; b++) {
marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a];
}
}
}
}
else if (event == CLAMP_SEARCH_DIM) {
- for (a = 0; a < 2; a++) {
+ for (int a = 0; a < 2; a++) {
/* search shouldn't be resized smaller than pattern */
marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
@@ -1313,7 +1293,7 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
sub_v2_v2v2(dim, marker->search_max, marker->search_min);
- for (a = 0; a < 2; a++) {
+ for (int a = 0; a < 2; a++) {
/* search shouldn't be moved inside pattern */
if (marker->search_min[a] > pat_min[a]) {
marker->search_min[a] = pat_min[a];
@@ -1457,15 +1437,14 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking,
{
MovieTrackingPlaneTrack *plane_track;
MovieTrackingPlaneMarker plane_marker;
- MovieTrackingTrack *track;
float tracks_min[2], tracks_max[2];
- int track_index, num_selected_tracks = 0;
+ int num_selected_tracks = 0;
(void)tracking; /* Ignored. */
/* Use bounding box of selected markers as an initial size of plane. */
INIT_MINMAX2(tracks_min, tracks_max);
- for (track = tracks->first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks) {
if (TRACK_SELECTED(track)) {
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
float pattern_min[2], pattern_max[2];
@@ -1493,7 +1472,8 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking,
/* Use selected tracks from given list as a plane. */
plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks,
"new plane tracks array");
- for (track = tracks->first, track_index = 0; track; track = track->next) {
+ int track_index = 0;
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks) {
if (TRACK_SELECTED(track)) {
plane_track->point_tracks[track_index] = track;
track_index++;
@@ -1552,9 +1532,8 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *track
const char *name)
{
ListBase *plane_tracks_base = BKE_tracking_object_get_plane_tracks(tracking, object);
- MovieTrackingPlaneTrack *plane_track;
- for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
if (STREQ(plane_track->name, name)) {
return plane_track;
}
@@ -1565,13 +1544,11 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *track
MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking)
{
- ListBase *plane_tracks_base;
-
if (tracking->act_plane_track == NULL) {
return NULL;
}
- plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
/* Check that active track is in current plane tracks list */
if (BLI_findindex(plane_tracks_base, tracking->act_plane_track) != -1) {
@@ -1583,9 +1560,7 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTrackin
void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
{
- MovieTrackingPlaneTrack *plane_track;
-
- for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
plane_track->flag &= ~SELECT;
}
}
@@ -1593,8 +1568,7 @@ void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track,
MovieTrackingTrack *track)
{
- int i;
- for (i = 0; i < plane_track->point_tracksnr; i++) {
+ for (int i = 0; i < plane_track->point_tracksnr; i++) {
if (plane_track->point_tracks[i] == track) {
return true;
}
@@ -1605,17 +1579,14 @@ bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_tra
bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track,
MovieTrackingTrack *track)
{
- int i, track_index;
- MovieTrackingTrack **new_point_tracks;
-
if (plane_track->point_tracksnr <= 4) {
return false;
}
- new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1),
- "new point tracks array");
+ MovieTrackingTrack **new_point_tracks = MEM_mallocN(
+ sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), "new point tracks array");
- for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
+ for (int i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
if (plane_track->point_tracks[i] != track) {
new_point_tracks[track_index++] = plane_track->point_tracks[i];
}
@@ -1631,10 +1602,8 @@ bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_
void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking,
MovieTrackingTrack *track)
{
- MovieTrackingPlaneTrack *plane_track, *next_plane_track;
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- for (plane_track = plane_tracks_base->first; plane_track; plane_track = next_plane_track) {
- next_plane_track = plane_track->next;
+ LISTBASE_FOREACH_MUTABLE (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) {
/* Delete planes with less than 3 point tracks in it. */
@@ -1649,8 +1618,7 @@ void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane
MovieTrackingTrack *old_track,
MovieTrackingTrack *new_track)
{
- int i;
- for (i = 0; i < plane_track->point_tracksnr; i++) {
+ for (int i = 0; i < plane_track->point_tracksnr; i++) {
if (plane_track->point_tracks[i] == old_track) {
plane_track->point_tracks[i] = new_track;
break;
@@ -1662,9 +1630,8 @@ void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking,
MovieTrackingTrack *old_track,
MovieTrackingTrack *new_track)
{
- MovieTrackingPlaneTrack *plane_track;
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) {
BKE_tracking_plane_track_replace_point_track(plane_track, old_track, new_track);
}
@@ -1838,23 +1805,22 @@ void BKE_tracking_plane_marker_get_subframe_corners(MovieTrackingPlaneTrack *pla
{
MovieTrackingPlaneMarker *marker = BKE_tracking_plane_marker_get(plane_track, (int)framenr);
MovieTrackingPlaneMarker *marker_last = plane_track->markers + (plane_track->markersnr - 1);
- int i;
if (marker != marker_last) {
MovieTrackingPlaneMarker *marker_next = marker + 1;
if (marker_next->framenr == marker->framenr + 1) {
float fac = (framenr - (int)framenr) / (marker_next->framenr - marker->framenr);
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
interp_v2_v2v2(corners[i], marker->corners[i], marker_next->corners[i], fac);
}
}
else {
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
copy_v2_v2(corners[i], marker->corners[i]);
}
}
}
else {
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
copy_v2_v2(corners[i], marker->corners[i]);
}
}
@@ -2399,7 +2365,6 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
bool undistort,
float delta[2])
{
- int a;
float pos[2], warped_pos[2];
const int coord_delta = 5;
void (*apply_distortion)(MovieTracking * tracking, const float pos[2], float out[2]);
@@ -2413,7 +2378,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
delta[0] = delta[1] = -FLT_MAX;
- for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
+ for (int a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
if (a > rect->xmax) {
a = rect->xmax;
}
@@ -2441,7 +2406,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
}
}
- for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
+ for (int a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
if (a > rect->ymax) {
a = rect->ymax;
}
@@ -2515,9 +2480,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width,
* fractional part of offset
*/
if (from_anchor) {
- int a;
-
- for (a = 0; a < 5; a++) {
+ for (int a = 0; a < 5; a++) {
src_pixel_x[a] += (double)((track->offset[0] * frame_width) -
((int)(track->offset[0] * frame_width)));
src_pixel_y[a] += (double)((track->offset[1] * frame_height) -
@@ -2664,9 +2627,6 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf,
void BKE_tracking_disable_channels(
ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale)
{
- int x, y;
- float scale;
-
if (!disable_red && !disable_green && !disable_blue && !grayscale) {
return;
}
@@ -2674,11 +2634,11 @@ void BKE_tracking_disable_channels(
/* if only some components are selected, it's important to rescale the result
* appropriately so that e.g. if only blue is selected, it's not zeroed out.
*/
- scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) +
- (disable_blue ? 0.0f : 0.0722f);
+ float scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) +
+ (disable_blue ? 0.0f : 0.0722f);
- for (y = 0; y < ibuf->y; y++) {
- for (x = 0; x < ibuf->x; x++) {
+ for (int y = 0; y < ibuf->y; y++) {
+ for (int x = 0; x < ibuf->x; x++) {
int pixel = ibuf->x * y + x;
if (ibuf->rect_float) {
@@ -2916,7 +2876,6 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking)
{
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
- MovieTrackingTrack *track;
MovieTrackingReconstruction *reconstruction = BKE_tracking_object_get_reconstruction(tracking,
object);
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
@@ -2924,9 +2883,7 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking)
bool sel_only = (dopesheet->flag & TRACKING_DOPE_SELECTED_ONLY) != 0;
bool show_hidden = (dopesheet->flag & TRACKING_DOPE_SHOW_HIDDEN) != 0;
- for (track = tracksbase->first; track; track = track->next) {
- MovieTrackingDopesheetChannel *channel;
-
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
if (!show_hidden && (track->flag & TRACK_HIDDEN) != 0) {
continue;
}
@@ -2935,7 +2892,8 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking)
continue;
}
- channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel), "tracking dopesheet channel");
+ MovieTrackingDopesheetChannel *channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel),
+ "tracking dopesheet channel");
channel->track = track;
if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
@@ -3012,13 +2970,12 @@ static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- MovieTrackingTrack *track;
int frames, start_frame = INT_MAX, end_frame = -INT_MAX;
int *per_frame_counter;
int prev_coverage, last_segment_frame;
/* find frame boundaries */
- for (track = tracksbase->first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
start_frame = min_ii(start_frame, track->markers[0].framenr);
end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr);
}
@@ -3029,7 +2986,7 @@ static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter");
/* find per-frame markers count */
- for (track = tracksbase->first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
for (int i = 0; i < track->markersnr; i++) {
MovieTrackingMarker *marker = &track->markers[i];
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index fad928c12fe..9d8395defcd 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -127,13 +127,12 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
libmv_Marker *libmv_marker)
{
const int frame_dimensions[2] = {frame_width, frame_height};
- int i;
libmv_marker->clip = clip;
libmv_marker->frame = marker->framenr;
libmv_marker->track = track_index;
normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center);
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
normalized_relative_to_libmv_frame(
marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]);
}
@@ -183,11 +182,10 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
MovieTrackingMarker *marker)
{
const int frame_dimensions[2] = {frame_width, frame_height};
- int i;
marker->framenr = libmv_marker->frame;
libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos);
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
libmv_frame_to_normalized_relative(libmv_marker->patch[i],
libmv_marker->center,
frame_dimensions,
@@ -260,7 +258,7 @@ static void fill_autotrack_tracks(const int frame_width,
{
/* Count number of markers to be put to a context. */
size_t num_trackable_markers = 0;
- for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
for (int i = 0; i < track->markersnr; i++) {
const MovieTrackingMarker *marker = track->markers + i;
if ((marker->flag & MARKER_DISABLED) == 0) {
@@ -277,7 +275,7 @@ static void fill_autotrack_tracks(const int frame_width,
"libmv markers array");
/* Fill in markers array. */
int track_index = 0, num_filled_libmv_markers = 0;
- for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
for (int i = 0; i < track->markersnr; i++) {
MovieTrackingMarker *marker = track->markers + i;
if ((marker->flag & MARKER_DISABLED) != 0) {
@@ -307,7 +305,7 @@ static void create_per_track_tracking_options(const MovieClip *clip,
AutoTrackContext *context)
{
/* Count number of trackable tracks. */
- for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
if (check_track_trackable(clip, track, user)) {
context->num_tracks++;
}
@@ -317,7 +315,7 @@ static void create_per_track_tracking_options(const MovieClip *clip,
"auto track options");
/* Fill in all the settings. */
int i = 0, track_index = 0;
- for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
if (!check_track_trackable(clip, track, user)) {
track_index++;
continue;
@@ -461,17 +459,16 @@ bool BKE_autotrack_context_step(AutoTrackContext *context)
void BKE_autotrack_context_sync(AutoTrackContext *context)
{
int newframe, frame_delta = context->backwards ? -1 : 1;
- int frame;
BLI_spin_lock(&context->spin_lock);
newframe = context->user.framenr;
- for (frame = context->sync_frame; frame != (context->backwards ? newframe - 1 : newframe + 1);
+ for (int frame = context->sync_frame;
+ frame != (context->backwards ? newframe - 1 : newframe + 1);
frame += frame_delta) {
MovieTrackingMarker marker;
libmv_Marker libmv_marker;
int clip = 0;
- int track;
- for (track = 0; track < context->num_tracks; track++) {
+ for (int track = 0; track < context->num_tracks; track++) {
AutoTrackOptions *options = &context->options[track];
int track_frame = BKE_movieclip_remap_scene_to_clip_frame(
context->clips[options->clip_index], frame);
@@ -522,17 +519,13 @@ void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *u
void BKE_autotrack_context_finish(AutoTrackContext *context)
{
- int clip_index;
-
- for (clip_index = 0; clip_index < context->num_clips; clip_index++) {
+ for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
MovieClip *clip = context->clips[clip_index];
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
- MovieTrackingPlaneTrack *plane_track;
- for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- int track;
- for (track = 0; track < context->num_tracks; track++) {
+ for (int track = 0; track < context->num_tracks; track++) {
if (BKE_tracking_plane_track_has_point_track(plane_track,
context->options[track].track)) {
BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame);
diff --git a/source/blender/blenkernel/intern/tracking_detect.c b/source/blender/blenkernel/intern/tracking_detect.c
index ec044f14fa8..08719161e1a 100644
--- a/source/blender/blenkernel/intern/tracking_detect.c
+++ b/source/blender/blenkernel/intern/tracking_detect.c
@@ -38,7 +38,6 @@
/* Check whether point is inside grease pencil stroke. */
static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y)
{
- int i, prev;
int count = 0;
bGPDspoint *points = stroke->points;
@@ -50,9 +49,7 @@ static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y)
* work, but such situation is crappy anyway.
*/
- prev = stroke->totpoints - 1;
-
- for (i = 0; i < stroke->totpoints; i++) {
+ for (int i = 0, prev = stroke->totpoints - 1; i < stroke->totpoints; prev = i, i++) {
if ((points[i].y < y && points[prev].y >= y) || (points[prev].y < y && points[i].y >= y)) {
float fac = (y - points[i].y) / (points[prev].y - points[i].y);
@@ -60,8 +57,6 @@ static bool check_point_in_stroke(bGPDstroke *stroke, float x, float y)
count++;
}
}
-
- prev = i;
}
return (count % 2) ? true : false;
diff --git a/source/blender/blenkernel/intern/tracking_plane_tracker.c b/source/blender/blenkernel/intern/tracking_plane_tracker.c
index 602243a7d50..e0e8a68bb1e 100644
--- a/source/blender/blenkernel/intern/tracking_plane_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_plane_tracker.c
@@ -39,13 +39,13 @@ typedef double Vec2[2];
static int point_markers_correspondences_on_both_image(
MovieTrackingPlaneTrack *plane_track, int frame1, int frame2, Vec2 **x1_r, Vec2 **x2_r)
{
- int i, correspondence_index;
Vec2 *x1, *x2;
*x1_r = x1 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x1");
*x2_r = x2 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x2");
- for (i = 0, correspondence_index = 0; i < plane_track->point_tracksnr; i++) {
+ int correspondence_index = 0;
+ for (int i = 0; i < plane_track->point_tracksnr; i++) {
MovieTrackingTrack *point_track = plane_track->point_tracks[i];
MovieTrackingMarker *point_marker1, *point_marker2;
@@ -77,11 +77,11 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
start_frame);
MovieTrackingPlaneMarker *keyframe_plane_marker = NULL;
MovieTrackingPlaneMarker new_plane_marker;
- int current_frame, frame_delta = direction > 0 ? 1 : -1;
+ int frame_delta = direction > 0 ? 1 : -1;
if (plane_track->flag & PLANE_TRACK_AUTOKEY) {
/* Find a keyframe in given direction. */
- for (current_frame = start_frame;; current_frame += frame_delta) {
+ for (int current_frame = start_frame;; current_frame += frame_delta) {
MovieTrackingPlaneMarker *next_plane_marker = BKE_tracking_plane_marker_get_exact(
plane_track, current_frame + frame_delta);
@@ -102,11 +102,10 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
new_plane_marker = *start_plane_marker;
new_plane_marker.flag |= PLANE_MARKER_TRACKED;
- for (current_frame = start_frame;; current_frame += frame_delta) {
+ for (int current_frame = start_frame;; current_frame += frame_delta) {
MovieTrackingPlaneMarker *next_plane_marker = BKE_tracking_plane_marker_get_exact(
plane_track, current_frame + frame_delta);
Vec2 *x1, *x2;
- int i, num_correspondences;
double H_double[3][3];
float H[3][3];
@@ -118,13 +117,11 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
}
}
- num_correspondences = point_markers_correspondences_on_both_image(
+ const int num_correspondences = point_markers_correspondences_on_both_image(
plane_track, current_frame, current_frame + frame_delta, &x1, &x2);
-
if (num_correspondences < 4) {
MEM_freeN(x1);
MEM_freeN(x2);
-
break;
}
@@ -132,7 +129,7 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
copy_m3_m3d(H, H_double);
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
float vec[3] = {0.0f, 0.0f, 1.0f}, vec2[3];
copy_v2_v2(vec, new_plane_marker.corners[i]);
@@ -155,7 +152,7 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
fac = 3 * fac * fac - 2 * fac * fac * fac;
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
interp_v2_v2v2(new_plane_marker.corners[i],
new_plane_marker.corners[i],
next_plane_marker->corners[i],
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index 1d6bb88c3f4..967642c03a8 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -50,9 +50,7 @@ static void float_rgba_to_gray(const float *rgba,
float weight_green,
float weight_blue)
{
- int i;
-
- for (i = 0; i < num_pixels; i++) {
+ for (int i = 0; i < num_pixels; i++) {
const float *pixel = rgba + 4 * i;
gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2];
@@ -66,9 +64,7 @@ static void uint8_rgba_to_float_gray(const unsigned char *rgba,
float weight_green,
float weight_blue)
{
- int i;
-
- for (i = 0; i < num_pixels; i++) {
+ for (int i = 0; i < num_pixels; i++) {
const unsigned char *pixel = rgba + i * 4;
gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f;
diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c
index ab741eed410..527a2f59491 100644
--- a/source/blender/blenkernel/intern/tracking_solver.c
+++ b/source/blender/blenkernel/intern/tracking_solver.c
@@ -90,13 +90,10 @@ static struct libmv_Tracks *libmv_tracks_new(MovieClip *clip,
track = tracksbase->first;
while (track) {
- FCurve *weight_fcurve;
- int a = 0;
-
- weight_fcurve = id_data_find_fcurve(
+ FCurve *weight_fcurve = id_data_find_fcurve(
&clip->id, track, &RNA_MovieTrackingTrack, "weight", 0, NULL);
- for (a = 0; a < track->markersnr; a++) {
+ for (int a = 0; a < track->markersnr; a++) {
MovieTrackingMarker *marker = &track->markers[a];
if ((marker->flag & MARKER_DISABLED) == 0) {
@@ -149,7 +146,7 @@ static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context,
MovieReconstructedCamera *reconstructed;
MovieTrackingTrack *track;
ListBase *tracksbase = NULL;
- int tracknr = 0, a;
+ int tracknr = 0;
bool ok = true;
bool origin_set = false;
int sfra = context->sfra, efra = context->efra;
@@ -200,16 +197,16 @@ static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context,
reconstructed = MEM_callocN((efra - sfra + 1) * sizeof(MovieReconstructedCamera),
"temp reconstructed camera");
- for (a = sfra; a <= efra; a++) {
+ for (int a = sfra; a <= efra; a++) {
double matd[4][4];
if (libmv_reprojectionCameraForImage(libmv_reconstruction, a, matd)) {
- int i, j;
float mat[4][4];
float error = libmv_reprojectionErrorForImage(libmv_reconstruction, a);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
+ /* TODO(sergey): Use transpose utility. */
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
mat[i][j] = matd[i][j];
}
}
@@ -591,21 +588,19 @@ static void tracking_scale_reconstruction(ListBase *tracksbase,
MovieTrackingReconstruction *reconstruction,
const float scale[3])
{
- MovieTrackingTrack *track;
- int i;
float first_camera_delta[3] = {0.0f, 0.0f, 0.0f};
if (reconstruction->camnr > 0) {
mul_v3_v3v3(first_camera_delta, reconstruction->cameras[0].mat[3], scale);
}
- for (i = 0; i < reconstruction->camnr; i++) {
+ for (int i = 0; i < reconstruction->camnr; i++) {
MovieReconstructedCamera *camera = &reconstruction->cameras[i];
mul_v3_v3(camera->mat[3], scale);
sub_v3_v3(camera->mat[3], first_camera_delta);
}
- for (track = tracksbase->first; track; track = track->next) {
+ for (MovieTrackingTrack *track = tracksbase->first; track; track = track->next) {
if (track->flag & TRACK_HAS_BUNDLE) {
mul_v3_v3(track->bundle_pos, scale);
sub_v3_v3(track->bundle_pos, first_camera_delta);
@@ -618,14 +613,10 @@ static void tracking_scale_reconstruction(ListBase *tracksbase,
*/
void BKE_tracking_reconstruction_scale(MovieTracking *tracking, float scale[3])
{
- MovieTrackingObject *object;
-
- for (object = tracking->objects.first; object; object = object->next) {
- ListBase *tracksbase;
- MovieTrackingReconstruction *reconstruction;
-
- tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
+ LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ MovieTrackingReconstruction *reconstruction = BKE_tracking_object_get_reconstruction(tracking,
+ object);
tracking_scale_reconstruction(tracksbase, reconstruction, scale);
}
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 2c270f10908..b5b33353ed7 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -34,6 +34,7 @@
#include "BLI_sort_utils.h"
#include "BLI_ghash.h"
#include "BLI_math_vector.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_task.h"
@@ -332,8 +333,7 @@ static void find_next_working_frames(StabContext *ctx,
int *next_lower,
int *next_higher)
{
- for (MovieTrackingTrack *track = ctx->tracking->tracks.first; track != NULL;
- track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &ctx->tracking->tracks) {
if (is_usable_for_stabilization(ctx, track)) {
int startpoint = search_closest_marker_index(track, framenr);
retrieve_next_higher_usable_frame(ctx, track, startpoint, framenr, next_higher);
@@ -545,7 +545,6 @@ static bool average_track_contributions(StabContext *ctx,
{
bool ok;
float weight_sum;
- MovieTrackingTrack *track;
MovieTracking *tracking = ctx->tracking;
MovieTrackingStabilization *stab = &tracking->stabilization;
float ref_pos[2];
@@ -559,7 +558,7 @@ static bool average_track_contributions(StabContext *ctx,
ok = false;
weight_sum = 0.0f;
- for (track = tracking->tracks.first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
if (!is_init_for_stabilization(ctx, track)) {
continue;
}
@@ -597,7 +596,7 @@ static bool average_track_contributions(StabContext *ctx,
ok = false;
weight_sum = 0.0f;
- for (track = tracking->tracks.first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
if (!is_init_for_stabilization(ctx, track)) {
continue;
}
@@ -652,12 +651,11 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
{
bool ok = false;
float weight_sum;
- MovieTrackingTrack *track;
MovieTracking *tracking = ctx->tracking;
zero_v2(r_ref_pos);
weight_sum = 0.0f;
- for (track = tracking->tracks.first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
if (track->flag & TRACK_USE_2D_STAB) {
float weight = 0.0f;
MovieTrackingMarker *marker = get_tracking_data_point(ctx, track, framenr, &weight);
@@ -680,7 +678,7 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
int next_lower = MINAFRAME;
int next_higher = MAXFRAME;
use_values_from_fcurves(ctx, true);
- for (track = tracking->tracks.first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
/* Note: we deliberately do not care if this track
* is already initialized for stabilization. */
if (track->flag & TRACK_USE_2D_STAB) {
@@ -771,11 +769,10 @@ static bool interpolate_averaged_track_contributions(StabContext *ctx,
static int establish_track_initialization_order(StabContext *ctx, TrackInitOrder *order)
{
size_t tracknr = 0;
- MovieTrackingTrack *track;
MovieTracking *tracking = ctx->tracking;
int anchor_frame = tracking->stabilization.anchor_frame;
- for (track = tracking->tracks.first; track != NULL; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
MovieTrackingMarker *marker;
order[tracknr].data = track;
marker = get_closest_marker(ctx, track, anchor_frame);
@@ -880,10 +877,9 @@ static void initialize_track_for_stabilization(StabContext *ctx,
static void initialize_all_tracks(StabContext *ctx, float aspect)
{
- size_t i, track_len = 0;
+ size_t track_len = 0;
MovieClip *clip = ctx->clip;
MovieTracking *tracking = ctx->tracking;
- MovieTrackingTrack *track;
TrackInitOrder *order;
/* Attempt to start initialization at anchor_frame.
@@ -896,7 +892,7 @@ static void initialize_all_tracks(StabContext *ctx, float aspect)
zero_v2(pivot);
/* Initialize private working data. */
- for (track = tracking->tracks.first; track != NULL; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
TrackStabilizationBase *local_data = access_stabilization_baseline_data(ctx, track);
if (!local_data) {
local_data = MEM_callocN(sizeof(TrackStabilizationBase),
@@ -927,8 +923,8 @@ static void initialize_all_tracks(StabContext *ctx, float aspect)
average_marker_positions(ctx, reference_frame, average_pos);
setup_pivot(average_pos, pivot);
- for (i = 0; i < track_len; i++) {
- track = order[i].data;
+ for (int i = 0; i < track_len; i++) {
+ MovieTrackingTrack *track = order[i].data;
if (reference_frame != order[i].reference_frame) {
reference_frame = order[i].reference_frame;
average_track_contributions(ctx,
@@ -1142,12 +1138,11 @@ static float calculate_autoscale_factor(StabContext *ctx, int size, float aspect
float pixel_aspect = ctx->tracking->camera.pixel_aspect;
int height = size, width = aspect * size;
- int sfra = INT_MAX, efra = INT_MIN, cfra;
+ int sfra = INT_MAX, efra = INT_MIN;
float scale = 1.0f, scale_step = 0.0f;
- MovieTrackingTrack *track;
/* Calculate maximal frame range of tracks where stabilization is active. */
- for (track = ctx->tracking->tracks.first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, &ctx->tracking->tracks) {
if ((track->flag & TRACK_USE_2D_STAB) ||
((stab->flag & TRACKING_STABILIZE_ROTATION) && (track->flag & TRACK_USE_2D_STAB_ROT))) {
int first_frame = track->markers[0].framenr;
@@ -1158,7 +1153,7 @@ static float calculate_autoscale_factor(StabContext *ctx, int size, float aspect
}
use_values_from_fcurves(ctx, true);
- for (cfra = sfra; cfra <= efra; cfra++) {
+ for (int cfra = sfra; cfra <= efra; cfra++) {
float translation[2], pivot[2], angle, tmp_scale;
float mat[4][4];
const float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index ed582dc5b94..ada6ce96d58 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -126,7 +126,6 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
MovieTrackingTrack *track;
ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
ListBase *old_tracks;
- int a;
if (map->is_camera) {
old_tracks = &tracking->tracks;
@@ -146,7 +145,7 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
* this is needed to keep names in unique state and it's faster to change names
* of currently operating tracks (if needed)
*/
- for (a = 0; a < map->num_tracks; a++) {
+ for (int a = 0; a < map->num_tracks; a++) {
MovieTrackingTrack *old_track;
bool mapped_to_old = false;
@@ -221,11 +220,9 @@ void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
{
- int i = 0;
-
BLI_ghash_free(map->hash, NULL, NULL);
- for (i = 0; i < map->num_tracks; i++) {
+ for (int i = 0; i < map->num_tracks; i++) {
if (map->customdata && customdata_free) {
customdata_free(&map->customdata[i * map->customdata_size]);
}
@@ -345,12 +342,11 @@ void tracking_get_marker_coords_for_tracking(int frame_width,
double search_pixel_x[5],
double search_pixel_y[5])
{
- int i;
float unified_coords[2];
float pixel_coords[2];
/* Convert the corners into search space coordinates. */
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
marker_unified_to_search_pixel(
frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
search_pixel_x[i] = pixel_coords[0] - 0.5f;
@@ -373,12 +369,11 @@ void tracking_set_marker_coords_from_tracking(int frame_width,
const double search_pixel_x[5],
const double search_pixel_y[5])
{
- int i;
float marker_unified[2];
float search_pixel[2];
/* Convert the corners into search space coordinates. */
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
search_pixel[0] = search_pixel_x[i] + 0.5;
search_pixel[1] = search_pixel_y[i] + 0.5;
search_pixel_to_marker_unified(
@@ -394,7 +389,7 @@ void tracking_set_marker_coords_from_tracking(int frame_width,
* Otherwise, the entire patch shifted, and that delta should be applied to
* all the coordinates.
*/
- for (i = 0; i < 4; i++) {
+ for (int i = 0; i < 4; i++) {
marker->pattern_corners[i][0] -= marker_unified[0];
marker->pattern_corners[i][1] -= marker_unified[1];
}
@@ -672,8 +667,6 @@ static ImBuf *accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor,
static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf)
{
ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0);
- size_t size;
- int i;
BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
@@ -682,13 +675,13 @@ static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf)
*
* Will generalize it later.
*/
- size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
+ const size_t size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
grayscale->channels = 1;
if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) {
grayscale->mall |= IB_rectfloat;
grayscale->flags |= IB_rectfloat;
- for (i = 0; i < grayscale->x * grayscale->y; i++) {
+ for (int i = 0; i < grayscale->x * grayscale->y; i++) {
const float *pixel = ibuf->rect_float + ibuf->channels * i;
grayscale->rect_float[i] = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2];
@@ -785,14 +778,12 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
clamped_height);
}
else {
- int y;
/* TODO(sergey): We don't do any color space or alpha conversion
* here. Probably Libmv is better to work in the linear space,
* but keep sRGB space here for compatibility for now.
*/
- for (y = 0; y < clamped_height; y++) {
- int x;
- for (x = 0; x < clamped_width; x++) {
+ for (int y = 0; y < clamped_height; y++) {
+ for (int x = 0; x < clamped_width; x++) {
int src_x = x + clamped_origin_x, src_y = y + clamped_origin_y;
int dst_x = x + dst_offset_x, dst_y = y + dst_offset_y;
int dst_index = (dst_y * width + dst_x) * 4,
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 36a58a6ca02..74b322aeab7 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -36,7 +36,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_undo_system.h"
@@ -504,8 +504,8 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack,
/* Might not be final place for this to be called - probably only want to call it from some
* undo handlers, not all of them? */
- if (BKE_override_library_is_enabled()) {
- BKE_main_override_library_operations_create(G_MAIN, false);
+ if (BKE_lib_override_library_is_enabled()) {
+ BKE_lib_override_library_main_operations_create(G_MAIN, false);
}
/* Remove all undos after (also when 'ustack->step_active == NULL'). */
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index f58c20a7d72..cd1bae6d798 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -28,7 +28,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_object.h"
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 992e4333049..02c2a884bda 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -37,7 +37,7 @@
#include "BKE_animsys.h"
#include "BKE_icons.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_world.h"
@@ -94,7 +94,7 @@ World *BKE_world_add(Main *bmain, const char *name)
*
* WARNING! This function will not handle ID user count!
*
- * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
*/
void BKE_world_copy_data(Main *bmain, World *wrld_dst, const World *wrld_src, const int flag)
{
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 5152643aaa1..deb9592b4f9 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -42,7 +42,7 @@
# include "BKE_global.h"
# include "BKE_idprop.h"
# include "BKE_image.h"
-# include "BKE_library.h"
+# include "BKE_lib_id.h"
# include "BKE_main.h"
# include "BKE_report.h"
# include "BKE_sound.h"
diff --git a/source/blender/blenlib/BLI_allocator.h b/source/blender/blenlib/BLI_allocator.h
index 52fa8d2b705..075c181833c 100644
--- a/source/blender/blenlib/BLI_allocator.h
+++ b/source/blender/blenlib/BLI_allocator.h
@@ -30,12 +30,12 @@
*/
#include <stdlib.h>
+#include <algorithm>
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
-#include "BLI_temporary_allocator.h"
namespace BLI {
@@ -52,7 +52,6 @@ class GuardedAllocator {
void *allocate_aligned(uint size, uint alignment, const char *name)
{
- alignment = std::max<uint>(alignment, 8);
return MEM_mallocN_aligned(size, alignment, name);
}
@@ -101,29 +100,6 @@ class RawAllocator {
}
};
-/**
- * Use this only under specific circumstances as described in BLI_temporary_allocator.h.
- */
-class TemporaryAllocator {
- public:
- void *allocate(uint size, const char *UNUSED(name))
- {
- return BLI_temporary_allocate(size);
- }
-
- void *allocate_aligned(uint size, uint alignment, const char *UNUSED(name))
- {
- BLI_assert(alignment <= 64);
- UNUSED_VARS_NDEBUG(alignment);
- return BLI_temporary_allocate(size);
- }
-
- void deallocate(void *ptr)
- {
- BLI_temporary_deallocate(ptr);
- }
-};
-
} // namespace BLI
#endif /* __BLI_ALLOCATOR_H__ */
diff --git a/source/blender/blenlib/BLI_array_cxx.h b/source/blender/blenlib/BLI_array_cxx.h
index c7704e20fb1..adb00c95f28 100644
--- a/source/blender/blenlib/BLI_array_cxx.h
+++ b/source/blender/blenlib/BLI_array_cxx.h
@@ -27,26 +27,28 @@
#include "BLI_allocator.h"
#include "BLI_array_ref.h"
#include "BLI_memory_utils_cxx.h"
+#include "BLI_index_range.h"
namespace BLI {
-template<typename T, typename Allocator = GuardedAllocator> class Array {
+template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Array {
private:
T *m_data;
uint m_size;
Allocator m_allocator;
+ AlignedBuffer<sizeof(T) * N, alignof(T)> m_inline_storage;
public:
Array()
{
- m_data = nullptr;
+ m_data = this->inline_storage();
m_size = 0;
}
Array(ArrayRef<T> values)
{
m_size = values.size();
- m_data = this->allocate(m_size);
+ m_data = this->get_buffer_for_size(values.size());
uninitialized_copy_n(values.begin(), m_size, m_data);
}
@@ -56,8 +58,8 @@ template<typename T, typename Allocator = GuardedAllocator> class Array {
explicit Array(uint size)
{
- m_data = this->allocate(size);
m_size = size;
+ m_data = this->get_buffer_for_size(size);
for (uint i = 0; i < m_size; i++) {
new (m_data + i) T();
@@ -66,8 +68,8 @@ template<typename T, typename Allocator = GuardedAllocator> class Array {
Array(uint size, const T &value)
{
- m_data = this->allocate(size);
m_size = size;
+ m_data = this->get_buffer_for_size(size);
uninitialized_fill_n(m_data, m_size, value);
}
@@ -76,30 +78,31 @@ template<typename T, typename Allocator = GuardedAllocator> class Array {
m_size = other.size();
m_allocator = other.m_allocator;
- if (m_size == 0) {
- m_data = nullptr;
- return;
- }
- else {
- m_data = this->allocate(m_size);
- copy_n(other.begin(), m_size, m_data);
- }
+ m_data = this->get_buffer_for_size(other.size());
+ copy_n(other.begin(), m_size, m_data);
}
Array(Array &&other) noexcept
{
- m_data = other.m_data;
m_size = other.m_size;
m_allocator = other.m_allocator;
- other.m_data = nullptr;
+ if (!other.uses_inline_storage()) {
+ m_data = other.m_data;
+ }
+ else {
+ m_data = this->get_buffer_for_size(m_size);
+ uninitialized_relocate_n(other.m_data, m_size, m_data);
+ }
+
+ other.m_data = other.inline_storage();
other.m_size = 0;
}
~Array()
{
destruct_n(m_data, m_size);
- if (m_data != nullptr) {
+ if (!this->uses_inline_storage()) {
m_allocator.deallocate((void *)m_data);
}
}
@@ -141,12 +144,23 @@ template<typename T, typename Allocator = GuardedAllocator> class Array {
return *this;
}
+ MutableArrayRef<T> as_mutable_ref()
+ {
+ return *this;
+ }
+
T &operator[](uint index)
{
BLI_assert(index < m_size);
return m_data[index];
}
+ const T &operator[](uint index) const
+ {
+ BLI_assert(index < m_size);
+ return m_data[index];
+ }
+
uint size() const
{
return m_size;
@@ -182,15 +196,38 @@ template<typename T, typename Allocator = GuardedAllocator> class Array {
return m_data + m_size;
}
+ IndexRange index_range() const
+ {
+ return IndexRange(m_size);
+ }
+
private:
+ T *get_buffer_for_size(uint size)
+ {
+ if (size <= N) {
+ return this->inline_storage();
+ }
+ else {
+ return this->allocate(size);
+ }
+ }
+
+ T *inline_storage() const
+ {
+ return (T *)m_inline_storage.ptr();
+ }
+
T *allocate(uint size)
{
return (T *)m_allocator.allocate_aligned(
size * sizeof(T), std::alignment_of<T>::value, __func__);
}
-};
-template<typename T> using TemporaryArray = Array<T, TemporaryAllocator>;
+ bool uses_inline_storage() const
+ {
+ return m_data == this->inline_storage();
+ }
+};
} // namespace BLI
diff --git a/source/blender/blenlib/BLI_array_ref.h b/source/blender/blenlib/BLI_array_ref.h
index e34647676d8..6cc96cedc83 100644
--- a/source/blender/blenlib/BLI_array_ref.h
+++ b/source/blender/blenlib/BLI_array_ref.h
@@ -79,6 +79,16 @@ template<typename T> class ArrayRef {
}
/**
+ * ArrayRef<T *> -> ArrayRef<const T *>
+ * ArrayRef<Derived *> -> ArrayRef<Base *>
+ */
+ template<typename U,
+ typename std::enable_if<std::is_convertible<U *, T>::value>::type * = nullptr>
+ ArrayRef(ArrayRef<U *> array) : ArrayRef((T *)array.begin(), array.size())
+ {
+ }
+
+ /**
* Return a continuous part of the array.
* Asserts that the slice stays within the array.
*/
@@ -247,14 +257,85 @@ template<typename T> class ArrayRef {
}
/**
+ * Check if the array contains duplicates. Does a linear search for every element. So the total
+ * running time is O(n^2). Only use this for small arrays.
+ */
+ bool has_duplicates__linear_search() const
+ {
+ /* The size should really be smaller than that. If it is not, the calling code should be
+ * changed. */
+ BLI_assert(m_size < 1000);
+
+ for (uint i = 0; i < m_size; i++) {
+ const T &value = m_start[i];
+ for (uint j = i + 1; j < m_size; j++) {
+ if (value == m_start[j]) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool intersects__linear_search(ArrayRef other) const
+ {
+ /* The size should really be smaller than that. If it is not, the calling code should be
+ * changed. */
+ BLI_assert(m_size < 1000);
+
+ for (uint i = 0; i < m_size; i++) {
+ const T &value = m_start[i];
+ if (other.contains(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ uint first_index(const T &search_value) const
+ {
+ int index = this->first_index_try(search_value);
+ BLI_assert(index >= 0);
+ return (uint)index;
+ }
+
+ int first_index_try(const T &search_value) const
+ {
+ for (uint i = 0; i < m_size; i++) {
+ if (m_start[i] == search_value) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ template<typename PredicateT> bool any(const PredicateT predicate)
+ {
+ for (uint i = 0; i < m_size; i++) {
+ if (predicate(m_start[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Utility to make it more convenient to iterate over all indices that can be used with this
+ * array.
+ */
+ IndexRange index_range() const
+ {
+ return IndexRange(m_size);
+ }
+
+ /**
* Get a new array ref to the same underlying memory buffer. No conversions are done.
- * Asserts when the sizes of the types don't match.
*/
template<typename NewT> ArrayRef<NewT> cast() const
{
- /* Can be adjusted to allow different type sizes when necessary. */
- BLI_STATIC_ASSERT(sizeof(T) == sizeof(NewT), "");
- return ArrayRef<NewT>((NewT *)m_start, m_size);
+ BLI_assert((m_size * sizeof(T)) % sizeof(NewT) == 0);
+ uint new_size = m_size * sizeof(T) / sizeof(NewT);
+ return ArrayRef<NewT>(reinterpret_cast<const NewT *>(m_start), new_size);
}
/**
@@ -270,6 +351,11 @@ template<typename T> class ArrayRef {
std::cout << '\n';
}
}
+
+ void print_as_lines(std::string name) const
+ {
+ this->print_as_lines(name, [](const T &value) { std::cout << value; });
+ }
};
/**
@@ -300,7 +386,7 @@ template<typename T> class MutableArrayRef {
{
}
- operator ArrayRef<T>()
+ operator ArrayRef<T>() const
{
return ArrayRef<T>(m_start, m_size);
}
@@ -411,6 +497,17 @@ template<typename T> class MutableArrayRef {
{
return ArrayRef<T>(m_start, m_size);
}
+
+ IndexRange index_range() const
+ {
+ return IndexRange(m_size);
+ }
+
+ const T &last() const
+ {
+ BLI_assert(m_size > 0);
+ return m_start[m_size - 1];
+ }
};
/**
@@ -421,6 +518,28 @@ template<typename T> ArrayRef<T> ref_c_array(const T *array, uint size)
return ArrayRef<T>(array, size);
}
+template<typename T1, typename T2> void assert_same_size(const T1 &v1, const T2 &v2)
+{
+ UNUSED_VARS_NDEBUG(v1, v2);
+#ifdef DEBUG
+ uint size = v1.size();
+ BLI_assert(size == v1.size());
+ BLI_assert(size == v2.size());
+#endif
+}
+
+template<typename T1, typename T2, typename T3>
+void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3)
+{
+ UNUSED_VARS_NDEBUG(v1, v2, v3);
+#ifdef DEBUG
+ uint size = v1.size();
+ BLI_assert(size == v1.size());
+ BLI_assert(size == v2.size());
+ BLI_assert(size == v3.size());
+#endif
+}
+
} /* namespace BLI */
#endif /* __BLI_ARRAY_REF_H__ */
diff --git a/source/blender/blenlib/BLI_hash_cxx.h b/source/blender/blenlib/BLI_hash_cxx.h
index e899f27c9ee..a369774a471 100644
--- a/source/blender/blenlib/BLI_hash_cxx.h
+++ b/source/blender/blenlib/BLI_hash_cxx.h
@@ -58,6 +58,7 @@ TRIVIAL_DEFAULT_INT_HASH(uint16_t);
TRIVIAL_DEFAULT_INT_HASH(int32_t);
TRIVIAL_DEFAULT_INT_HASH(uint32_t);
TRIVIAL_DEFAULT_INT_HASH(int64_t);
+TRIVIAL_DEFAULT_INT_HASH(uint64_t);
template<> struct DefaultHash<float> {
uint32_t operator()(float value) const
diff --git a/source/blender/blenlib/BLI_index_range.h b/source/blender/blenlib/BLI_index_range.h
index a1fed5bd97c..f67cc259227 100644
--- a/source/blender/blenlib/BLI_index_range.h
+++ b/source/blender/blenlib/BLI_index_range.h
@@ -31,6 +31,11 @@
#include "BLI_utildefines.h"
+/* Forward declare tbb::blocked_range for conversion operations. */
+namespace tbb {
+template<typename Value> class blocked_range;
+}
+
namespace BLI {
template<typename T> class ArrayRef;
@@ -51,6 +56,11 @@ class IndexRange {
{
}
+ template<typename T>
+ IndexRange(const tbb::blocked_range<T> &range) : m_start(range.begin()), m_size(range.size())
+ {
+ }
+
class Iterator {
private:
uint m_current;
@@ -179,6 +189,11 @@ class IndexRange {
return IndexRange(new_start, size);
}
+ IndexRange slice(IndexRange range) const
+ {
+ return this->slice(range.start(), range.size());
+ }
+
/**
* Get read-only access to a memory buffer that contains the range as actual numbers.
*/
diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h
index 9e966ffb798..9ba045fdbf8 100644
--- a/source/blender/blenlib/BLI_kdtree.h
+++ b/source/blender/blenlib/BLI_kdtree.h
@@ -17,6 +17,10 @@
#ifndef __BLI_KDTREE_H__
#define __BLI_KDTREE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/** \file
* \ingroup bli
* \brief A kd-tree for nearest neighbor search.
@@ -66,4 +70,8 @@
#undef KDTreeNearest
#undef KDTREE_PREFIX_ID
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_KDTREE_H__ */
diff --git a/source/blender/blenlib/BLI_listbase_wrapper.h b/source/blender/blenlib/BLI_listbase_wrapper.h
index 34197fe9c45..d6832166e35 100644
--- a/source/blender/blenlib/BLI_listbase_wrapper.h
+++ b/source/blender/blenlib/BLI_listbase_wrapper.h
@@ -93,6 +93,19 @@ template<typename T> class IntrusiveListBaseWrapper {
BLI_assert(ptr);
return (T *)ptr;
}
+
+ uint index_of(const T *value) const
+ {
+ uint index = 0;
+ for (T *ptr : *this) {
+ if (ptr == value) {
+ return index;
+ }
+ index++;
+ }
+ BLI_assert(false);
+ return 0;
+ }
};
} /* namespace BLI */
diff --git a/source/blender/blenlib/BLI_map.h b/source/blender/blenlib/BLI_map.h
index 1edf7653c71..73b731252b6 100644
--- a/source/blender/blenlib/BLI_map.h
+++ b/source/blender/blenlib/BLI_map.h
@@ -413,6 +413,19 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator>
return m_array.slots_set();
}
+ template<typename FuncT> void foreach_item(const FuncT &func) const
+ {
+ for (const Item &item : m_array) {
+ for (uint offset = 0; offset < 4; offset++) {
+ if (item.is_set(offset)) {
+ const KeyT &key = *item.key(offset);
+ const ValueT &value = *item.value(offset);
+ func(key, value);
+ }
+ }
+ }
+ }
+
void print_table() const
{
std::cout << "Hash Table:\n";
diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h
index 2e756b14424..47bafff3a49 100644
--- a/source/blender/blenlib/BLI_math_color_blend.h
+++ b/source/blender/blenlib/BLI_math_color_blend.h
@@ -64,53 +64,49 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4],
const unsigned char src2[4]);
MINLINE void blend_color_overlay_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_hardlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
-MINLINE void blend_color_burn_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
+MINLINE void blend_color_burn_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4]);
MINLINE void blend_color_linearburn_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_dodge_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_screen_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_softlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_pinlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_linearlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_vividlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_difference_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_exclusion_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_color_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
-MINLINE void blend_color_hue_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
+MINLINE void blend_color_hue_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4]);
MINLINE void blend_color_saturation_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_luminosity_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4]);
+ const uchar src1[4],
+ const uchar src2[4]);
MINLINE void blend_color_interpolate_byte(unsigned char dst[4],
const unsigned char src1[4],
diff --git a/source/blender/blenlib/BLI_memory_utils_cxx.h b/source/blender/blenlib/BLI_memory_utils_cxx.h
index 22f333c6303..f15621b4e41 100644
--- a/source/blender/blenlib/BLI_memory_utils_cxx.h
+++ b/source/blender/blenlib/BLI_memory_utils_cxx.h
@@ -33,6 +33,11 @@ using std::uninitialized_copy_n;
using std::uninitialized_fill;
using std::uninitialized_fill_n;
+template<typename T> void construct_default(T *ptr)
+{
+ new (ptr) T();
+}
+
template<typename T> void destruct(T *ptr)
{
ptr->~T();
@@ -79,6 +84,38 @@ template<typename T> void relocate_n(T *src, uint n, T *dst)
destruct_n(src, n);
}
+template<typename T, typename... Args> std::unique_ptr<T> make_unique(Args &&... args)
+{
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+template<typename T> struct DestructValueAtAddress {
+ void operator()(T *ptr)
+ {
+ ptr->~T();
+ }
+};
+
+template<typename T> using destruct_ptr = std::unique_ptr<T, DestructValueAtAddress<T>>;
+
+template<uint Size, uint Alignment> class alignas(Alignment) AlignedBuffer {
+ private:
+ /* Don't create an empty array. This causes problems with some compilers. */
+ static constexpr uint ActualSize = (Size > 0) ? Size : 1;
+ char m_buffer[ActualSize];
+
+ public:
+ void *ptr()
+ {
+ return (void *)m_buffer;
+ }
+
+ const void *ptr() const
+ {
+ return (const void *)m_buffer;
+ }
+};
+
} // namespace BLI
#endif /* __BLI_MEMORY_UTILS_CXX_H__ */
diff --git a/source/blender/blenlib/BLI_open_addressing.h b/source/blender/blenlib/BLI_open_addressing.h
index 8ca5156a952..a238902c631 100644
--- a/source/blender/blenlib/BLI_open_addressing.h
+++ b/source/blender/blenlib/BLI_open_addressing.h
@@ -70,7 +70,7 @@ class OpenAddressingArray {
/* Can be used to map a hash value into the range of valid slot indices. */
uint32_t m_slot_mask;
Allocator m_allocator;
- char m_local_storage[sizeof(Item) * ItemsInSmallStorage];
+ AlignedBuffer<sizeof(Item) * ItemsInSmallStorage, alignof(Item)> m_local_storage;
public:
explicit OpenAddressingArray(uint8_t item_exponent = 0)
@@ -291,7 +291,7 @@ class OpenAddressingArray {
private:
Item *small_storage() const
{
- return reinterpret_cast<Item *>((char *)m_local_storage);
+ return reinterpret_cast<Item *>((char *)m_local_storage.ptr());
}
bool is_in_small_storage() const
diff --git a/source/blender/blenlib/BLI_optional.h b/source/blender/blenlib/BLI_optional.h
new file mode 100644
index 00000000000..90bded604ea
--- /dev/null
+++ b/source/blender/blenlib/BLI_optional.h
@@ -0,0 +1,199 @@
+/*
+ * 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 bli
+ *
+ * Simple version of std::optional, which is only available since C++17.
+ */
+
+#ifndef __BLI_OPTIONAL_H__
+#define __BLI_OPTIONAL_H__
+
+#include "BLI_utildefines.h"
+#include "BLI_memory_utils_cxx.h"
+
+#include <algorithm>
+#include <memory>
+
+namespace BLI {
+
+template<typename T> class Optional {
+ private:
+ AlignedBuffer<sizeof(T), alignof(T)> m_storage;
+ bool m_set;
+
+ public:
+ static Optional FromPointer(const T *ptr)
+ {
+ if (ptr == nullptr) {
+ return Optional();
+ }
+ else {
+ return Optional(*ptr);
+ }
+ }
+
+ Optional() : m_set(false)
+ {
+ }
+
+ ~Optional()
+ {
+ this->reset();
+ }
+
+ Optional(const T &value) : Optional()
+ {
+ this->set(value);
+ }
+
+ Optional(T &&value) : Optional()
+ {
+ this->set(std::forward<T>(value));
+ }
+
+ Optional(const Optional &other) : Optional()
+ {
+ if (other.has_value()) {
+ this->set(other.value());
+ }
+ }
+
+ Optional(Optional &&other) : Optional()
+ {
+ if (other.has_value()) {
+ this->set(std::move(other.value()));
+ }
+ }
+
+ Optional &operator=(const Optional &other)
+ {
+ if (this == &other) {
+ return *this;
+ }
+ if (other.has_value()) {
+ this->set(other.value());
+ }
+ else {
+ this->reset();
+ }
+ return *this;
+ }
+
+ Optional &operator=(Optional &&other)
+ {
+ if (this == &other) {
+ return *this;
+ }
+ if (other.has_value()) {
+ this->set(std::move(other.value()));
+ }
+ else {
+ this->reset();
+ }
+ return *this;
+ }
+
+ bool has_value() const
+ {
+ return m_set;
+ }
+
+ const T &value() const
+ {
+ BLI_assert(m_set);
+ return *this->value_ptr();
+ }
+
+ T &value()
+ {
+ BLI_assert(m_set);
+ return *this->value_ptr();
+ }
+
+ void set(const T &value)
+ {
+ if (m_set) {
+ this->value() = value;
+ }
+ else {
+ new (this->value_ptr()) T(value);
+ m_set = true;
+ }
+ }
+
+ void set(T &&value)
+ {
+ if (m_set) {
+ this->value() = std::move(value);
+ }
+ else {
+ new (this->value_ptr()) T(std::move(value));
+ m_set = true;
+ }
+ }
+
+ void set_new(const T &value)
+ {
+ BLI_assert(!m_set);
+ new (this->value_ptr()) T(value);
+ m_set = true;
+ }
+
+ void set_new(T &&value)
+ {
+ BLI_assert(!m_set);
+ new (this->value_ptr()) T(std::move(value));
+ m_set = true;
+ }
+
+ void reset()
+ {
+ if (m_set) {
+ this->value_ptr()->~T();
+ m_set = false;
+ }
+ }
+
+ T extract()
+ {
+ BLI_assert(m_set);
+ T value = std::move(this->value());
+ this->reset();
+ return value;
+ }
+
+ T *operator->()
+ {
+ return this->value_ptr();
+ }
+
+ T &operator*()
+ {
+ return *this->value_ptr();
+ }
+
+ private:
+ T *value_ptr() const
+ {
+ return (T *)m_storage.ptr();
+ }
+};
+
+} /* namespace BLI */
+
+#endif /* __BLI_OPTIONAL_H__ */
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index be2b18b05fd..ad8a90b3977 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -20,6 +20,8 @@
#ifndef __BLI_RAND_H__
#define __BLI_RAND_H__
+#include "BLI_compiler_attrs.h"
+
/** \file
* \ingroup bli
* \brief Random number functions.
diff --git a/source/blender/blenlib/BLI_stack_cxx.h b/source/blender/blenlib/BLI_stack_cxx.h
index 7915acadfac..a26318a3dcb 100644
--- a/source/blender/blenlib/BLI_stack_cxx.h
+++ b/source/blender/blenlib/BLI_stack_cxx.h
@@ -58,7 +58,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St
/**
* Return true when the stack is empty, otherwise false.
*/
- bool empty() const
+ bool is_empty() const
{
return this->size() == 0;
}
@@ -76,6 +76,11 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St
m_elements.append(std::move(value));
}
+ void push_multiple(ArrayRef<T> values)
+ {
+ m_elements.extend(values);
+ }
+
/**
* Remove the element from the top of the stack and return it.
* This will assert when the stack is empty.
@@ -91,7 +96,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St
*/
T &peek()
{
- BLI_assert(!this->empty());
+ BLI_assert(!this->is_empty());
return m_elements[this->size() - 1];
}
diff --git a/source/blender/blenlib/BLI_string_map.h b/source/blender/blenlib/BLI_string_map.h
index ba870eb878a..2f09e489a7a 100644
--- a/source/blender/blenlib/BLI_string_map.h
+++ b/source/blender/blenlib/BLI_string_map.h
@@ -30,6 +30,7 @@
#include "BLI_map.h"
#include "BLI_string_ref.h"
#include "BLI_vector.h"
+#include "BLI_optional.h"
namespace BLI {
@@ -190,6 +191,22 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap {
}
/**
+ * Add a new element to the map if the key does not exist yet.
+ */
+ void add(StringRef key, const T &value)
+ {
+ if (!this->contains(key)) {
+ this->add_new(key, value);
+ }
+ }
+ void add(StringRef key, T &&value)
+ {
+ if (!this->contains(key)) {
+ this->add_new(key, std::move(value));
+ }
+ }
+
+ /**
* Return true when the key exists in the map, otherwise false.
*/
bool contains(StringRef key) const
@@ -263,6 +280,11 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap {
return const_cast<T *>(const_cast<const StringMap *>(this)->lookup_ptr(key));
}
+ Optional<T> try_lookup(StringRef key) const
+ {
+ return Optional<T>::FromPointer(this->lookup_ptr(key));
+ }
+
/**
* Get a copy of the value corresponding to the key. If the key does not exist, return the
* default value.
@@ -326,7 +348,7 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap {
/**
* Run a function for every key-value-pair in the map.
*/
- template<typename FuncT> void foreach_key_value_pair(const FuncT &func)
+ template<typename FuncT> void foreach_item(const FuncT &func)
{
for (Item &item : m_array) {
for (uint offset = 0; offset < 4; offset++) {
@@ -339,6 +361,19 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap {
}
}
+ template<typename FuncT> void foreach_item(const FuncT &func) const
+ {
+ for (const Item &item : m_array) {
+ for (uint offset = 0; offset < 4; offset++) {
+ if (item.is_set(offset)) {
+ StringRefNull key = item.get_key(offset, m_chars);
+ const T &value = *item.value(offset);
+ func(key, value);
+ }
+ }
+ }
+ }
+
private:
uint32_t compute_string_hash(StringRef key) const
{
@@ -415,6 +450,15 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap {
}
ITER_SLOTS_END(offset);
}
+
+ template<typename ForwardT> void add__impl(StringRef key, ForwardT &&value)
+ {
+ this->ensure_can_add();
+ uint32_t hash = this->compute_string_hash(key);
+ ITER_SLOTS_BEGIN (hash, m_array, , item, offset) {
+ }
+ ITER_SLOTS_END(offset);
+ }
};
#undef ITER_SLOTS_BEGIN
diff --git a/source/blender/blenlib/BLI_string_ref.h b/source/blender/blenlib/BLI_string_ref.h
index 76163a2754c..54c2f0e7209 100644
--- a/source/blender/blenlib/BLI_string_ref.h
+++ b/source/blender/blenlib/BLI_string_ref.h
@@ -109,6 +109,8 @@ class StringRefBase {
* Returns true when the string ends with the given suffix. Otherwise false.
*/
bool endswith(StringRef suffix) const;
+
+ StringRef substr(uint start, uint size) const;
};
/**
@@ -242,6 +244,12 @@ inline bool StringRefBase::endswith(StringRef suffix) const
return true;
}
+inline StringRef StringRefBase::substr(uint start, uint size) const
+{
+ BLI_assert(start + size <= m_size);
+ return StringRef(m_data + start, size);
+}
+
} // namespace BLI
#endif /* __BLI_STRING_REF_H__ */
diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h
index 13dbb2de659..b3aed438641 100644
--- a/source/blender/blenlib/BLI_string_utils.h
+++ b/source/blender/blenlib/BLI_string_utils.h
@@ -44,6 +44,11 @@ void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, cons
void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len);
/* Join strings, return newly allocated string. */
+char *BLI_string_join_array(char *result,
+ size_t result_len,
+ const char *strings[],
+ uint strings_len) ATTR_NONNULL();
+
char *BLI_string_join_arrayN(const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
char *BLI_string_join_array_by_sep_charN(char sep,
@@ -54,6 +59,9 @@ char *BLI_string_join_array_by_sep_char_with_tableN(char sep,
const char *strings[],
uint strings_len) ATTR_NONNULL();
/* Take multiple arguments, pass as (array, length). */
+#define BLI_string_join(result, result_len, ...) \
+ BLI_string_join_array( \
+ result, result_len, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define BLI_string_joinN(...) \
BLI_string_join_arrayN(((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
#define BLI_string_join_by_sep_charN(sep, ...) \
diff --git a/source/blender/blenlib/BLI_temporary_allocator.h b/source/blender/blenlib/BLI_temporary_allocator.h
deleted file mode 100644
index b378e5869c0..00000000000
--- a/source/blender/blenlib/BLI_temporary_allocator.h
+++ /dev/null
@@ -1,64 +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.
- */
-
-/** \file
- * \ingroup bli
- *
- * This allocation method assumes
- * 1. The allocations are short-lived.
- * 2. The total number of allocations is bound by a constant per thread.
- *
- * These two assumptions make it possible to cache and reuse relatively large buffers. They allow
- * to hand out buffers that are much larger than the requested size, without the fear of running
- * out of memory.
- *
- * The assumptions might feel a bit limiting at first, but hold true in many cases. For example,
- * many algorithms need to store temporary data. With this allocator, the allocation can become
- * very cheap for common cases.
- *
- * Many cpu-bound algorithms can benefit from being split up into several stages, whereby the
- * output of one stage is written into an array that is read by the next stage. This makes them
- * easier to debug, profile and optimize. Often a reason this is not done is that the memory
- * allocation might be expensive. The goal of this allocator is to make this a non-issue, by
- * reusing the same long buffers over and over again.
- *
- * All allocated buffers are 64 byte aligned, to make them as reusable as possible.
- * If the requested size is too large, there is a fallback to normal allocation. The allocation
- * overhead is probably very small in these cases anyway.
- *
- * The best way to use this allocator is to use one of the prepared containers like TemporaryVector
- * and TemporaryArray.
- */
-
-#ifndef __BLI_TEMPORARY_ALLOCATOR_H__
-#define __BLI_TEMPORARY_ALLOCATOR_H__
-
-#include "BLI_utildefines.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BLI_TEMPORARY_BUFFER_ALIGNMENT 64
-
-void *BLI_temporary_allocate(uint size);
-void BLI_temporary_deallocate(void *buffer);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __BLI_TEMPORARY_ALLOCATOR_H__ */
diff --git a/source/blender/blenlib/BLI_utility_mixins.h b/source/blender/blenlib/BLI_utility_mixins.h
new file mode 100644
index 00000000000..ce7a4ce094a
--- /dev/null
+++ b/source/blender/blenlib/BLI_utility_mixins.h
@@ -0,0 +1,52 @@
+/*
+ * 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 bli
+ */
+
+#ifndef __BLI_UTILITY_MIXINS_H__
+#define __BLI_UTILITY_MIXINS_H__
+
+namespace BLI {
+
+class NonCopyable {
+ public:
+ /* Disable copy construction and assignment. */
+ NonCopyable(const NonCopyable &other) = delete;
+ NonCopyable &operator=(const NonCopyable &other) = delete;
+
+ /* Explicitly enable default construction, move construction and move assignment. */
+ NonCopyable() = default;
+ NonCopyable(NonCopyable &&other) = default;
+ NonCopyable &operator=(NonCopyable &&other) = default;
+};
+
+class NonMovable {
+ public:
+ /* Disable move construction and assignment. */
+ NonMovable(NonMovable &&other) = delete;
+ NonMovable &operator=(NonMovable &&other) = delete;
+
+ /* Explicitly enable default construction, copy construction and copy assignment. */
+ NonMovable() = default;
+ NonMovable(const NonMovable &other) = default;
+ NonMovable &operator=(const NonMovable &other) = default;
+};
+
+} // namespace BLI
+
+#endif /* __BLI_UTILITY_MIXINS_H__ */
diff --git a/source/blender/blenlib/BLI_vector.h b/source/blender/blenlib/BLI_vector.h
index 46c46a1440f..60251347795 100644
--- a/source/blender/blenlib/BLI_vector.h
+++ b/source/blender/blenlib/BLI_vector.h
@@ -37,6 +37,7 @@
#include "BLI_listbase_wrapper.h"
#include "BLI_math_base.h"
#include "BLI_allocator.h"
+#include "BLI_index_range.h"
#include "MEM_guardedalloc.h"
@@ -48,7 +49,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
T *m_end;
T *m_capacity_end;
Allocator m_allocator;
- char m_small_buffer[sizeof(T) * N];
+ AlignedBuffer<sizeof(T) * N, alignof(T)> m_small_buffer;
#ifndef NDEBUG
/* Storing size in debug builds, because it makes debugging much easier sometimes. */
@@ -215,6 +216,16 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
return MutableArrayRef<T>(m_begin, this->size());
}
+ ArrayRef<T> as_ref() const
+ {
+ return *this;
+ }
+
+ MutableArrayRef<T> as_mutable_ref()
+ {
+ return *this;
+ }
+
Vector &operator=(const Vector &other)
{
if (this == &other) {
@@ -233,6 +244,8 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
return *this;
}
+ /* This can fail, when the vector is used to build a recursive data structure.
+ See https://youtu.be/7Qgd9B1KuMQ?t=840. */
this->~Vector();
new (this) Vector(std::move(other));
@@ -293,6 +306,20 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
this->append_unchecked(std::move(value));
}
+ uint append_and_get_index(const T &value)
+ {
+ uint index = this->size();
+ this->append(value);
+ return index;
+ }
+
+ void append_non_duplicates(const T &value)
+ {
+ if (!this->contains(value)) {
+ this->append(value);
+ }
+ }
+
void append_unchecked(const T &value)
{
BLI_assert(m_end < m_capacity_end);
@@ -341,6 +368,13 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
this->extend_unchecked(start, amount);
}
+ void extend_non_duplicates(ArrayRef<T> array)
+ {
+ for (const T &value : array) {
+ this->append_non_duplicates(value);
+ }
+ }
+
void extend_unchecked(ArrayRef<T> array)
{
this->extend_unchecked(array.begin(), array.size());
@@ -441,11 +475,17 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
UPDATE_VECTOR_SIZE(this);
}
+ void remove_first_occurrence_and_reorder(const T &value)
+ {
+ uint index = this->index(value);
+ this->remove_and_reorder((uint)index);
+ }
+
/**
* Do a linear search to find the value in the vector.
* When found, return the first index, otherwise return -1.
*/
- int index(const T &value) const
+ int index_try(const T &value) const
{
for (T *current = m_begin; current != m_end; current++) {
if (*current == value) {
@@ -456,12 +496,23 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
}
/**
+ * Do a linear search to find the value in the vector.
+ * When found, return the first index, otherwise fail.
+ */
+ uint index(const T &value) const
+ {
+ int index = this->index_try(value);
+ BLI_assert(index >= 0);
+ return (uint)index;
+ }
+
+ /**
* Do a linear search to see of the value is in the vector.
* Return true when it exists, otherwise false.
*/
bool contains(const T &value) const
{
- return this->index(value) != -1;
+ return this->index_try(value) != -1;
}
/**
@@ -520,6 +571,11 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
return (uint)(m_capacity_end - m_begin);
}
+ IndexRange index_range() const
+ {
+ return IndexRange(this->size());
+ }
+
void print_stats() const
{
std::cout << "Small Vector at " << (void *)this << ":" << std::endl;
@@ -531,7 +587,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
private:
T *small_buffer() const
{
- return (T *)m_small_buffer;
+ return (T *)m_small_buffer.ptr();
}
bool is_small() const
@@ -555,10 +611,11 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
/* Round up to the next power of two. Otherwise consecutive calls to grow can cause a
* reallocation every time even though the min_capacity only increments. */
min_capacity = power_of_2_max_u(min_capacity);
+
uint size = this->size();
T *new_array = (T *)m_allocator.allocate_aligned(
- min_capacity * (uint)sizeof(T), std::alignment_of<T>::value, __func__);
+ min_capacity * (uint)sizeof(T), std::alignment_of<T>::value, "grow BLI::Vector");
uninitialized_relocate_n(m_begin, size, new_array);
if (!this->is_small()) {
@@ -600,7 +657,11 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
#undef UPDATE_VECTOR_SIZE
-template<typename T, uint N = 4> using TemporaryVector = Vector<T, N, TemporaryAllocator>;
+/**
+ * Use when the vector is used in the local scope of a function. It has a larger inline storage by
+ * default to make allocations less likely.
+ */
+template<typename T, uint N = 20> using ScopedVector = Vector<T, N, GuardedAllocator>;
} /* namespace BLI */
diff --git a/source/blender/blenlib/BLI_vector_set.h b/source/blender/blenlib/BLI_vector_set.h
index fb21f7ed987..99d955c60d8 100644
--- a/source/blender/blenlib/BLI_vector_set.h
+++ b/source/blender/blenlib/BLI_vector_set.h
@@ -292,12 +292,12 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet {
return m_elements[index];
}
- operator ArrayRef<T>() const
+ ArrayRef<T> as_ref() const
{
- return m_elements;
+ return *this;
}
- operator MutableArrayRef<T>()
+ operator ArrayRef<T>() const
{
return m_elements;
}
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index d22b1cd0ddb..1e4e07d63b3 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -52,7 +52,6 @@ set(SRC
intern/BLI_memblock.c
intern/BLI_memiter.c
intern/BLI_mempool.c
- intern/BLI_temporary_allocator.cc
intern/BLI_timer.c
intern/DLRB_tree.c
intern/array_store.c
@@ -213,6 +212,7 @@ set(SRC
BLI_mempool.h
BLI_noise.h
BLI_open_addressing.h
+ BLI_optional.h
BLI_path_util.h
BLI_polyfill_2d.h
BLI_polyfill_2d_beautify.h
@@ -236,8 +236,6 @@ set(SRC
BLI_sys_types.h
BLI_system.h
BLI_task.h
- BLI_temporary_allocator.h
- BLI_temporary_allocator_cxx.h
BLI_threads.h
BLI_timecode.h
BLI_timer.h
@@ -245,6 +243,7 @@ set(SRC
BLI_utildefines_iter.h
BLI_utildefines_stack.h
BLI_utildefines_variadic.h
+ BLI_utility_mixins.h
BLI_uvproject.h
BLI_vector.h
BLI_vector_set.h
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 05ffb02597d..1c518cf1487 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -220,8 +220,8 @@ static void ghash_buckets_resize(GHash *gh, const uint nbuckets)
if (nbuckets > nbuckets_old) {
for (i = 0; i < nbuckets_old; i++) {
for (Entry *e = buckets_old[i], *e_next; e; e = e_next) {
- const unsigned hash = ghash_entryhash(gh, e);
- const unsigned bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_entryhash(gh, e);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
e_next = e->next;
e->next = buckets_new[bucket_index];
buckets_new[bucket_index] = e;
@@ -232,8 +232,8 @@ static void ghash_buckets_resize(GHash *gh, const uint nbuckets)
for (i = 0; i < nbuckets_old; i++) {
#ifdef GHASH_USE_MODULO_BUCKETS
for (Entry *e = buckets_old[i], *e_next; e; e = e_next) {
- const unsigned hash = ghash_entryhash(gh, e);
- const unsigned bucket_index = ghash_bucket_index(gh, hash);
+ const uint hash = ghash_entryhash(gh, e);
+ const uint bucket_index = ghash_bucket_index(gh, hash);
e_next = e->next;
e->next = buckets_new[bucket_index];
buckets_new[bucket_index] = e;
@@ -241,7 +241,7 @@ static void ghash_buckets_resize(GHash *gh, const uint nbuckets)
#else
/* No need to recompute hashes in this case, since our mask is just smaller,
* all items in old bucket 'i' will go in same new bucket (i & new_mask)! */
- const unsigned bucket_index = ghash_bucket_index(gh, i);
+ const uint bucket_index = ghash_bucket_index(gh, i);
BLI_assert(!buckets_old[i] ||
(bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i]))));
Entry *e;
diff --git a/source/blender/blenlib/intern/BLI_index_range.cc b/source/blender/blenlib/intern/BLI_index_range.cc
index fde4dcf6d41..6421eb0794b 100644
--- a/source/blender/blenlib/intern/BLI_index_range.cc
+++ b/source/blender/blenlib/intern/BLI_index_range.cc
@@ -24,7 +24,7 @@
namespace BLI {
-static Vector<Array<uint, RawAllocator>, 1, RawAllocator> arrays;
+static Vector<Array<uint, 0, RawAllocator>, 1, RawAllocator> arrays;
static uint current_array_size = 0;
static uint *current_array = nullptr;
static std::mutex current_array_mutex;
@@ -44,7 +44,7 @@ ArrayRef<uint> IndexRange::as_array_ref() const
}
uint new_size = std::max<uint>(1000, power_of_2_max_u(min_required_size));
- Array<uint, RawAllocator> new_array(new_size);
+ Array<uint, 0, RawAllocator> new_array(new_size);
for (uint i = 0; i < new_size; i++) {
new_array[i] = i;
}
diff --git a/source/blender/blenlib/intern/BLI_temporary_allocator.cc b/source/blender/blenlib/intern/BLI_temporary_allocator.cc
deleted file mode 100644
index b145e65530d..00000000000
--- a/source/blender/blenlib/intern/BLI_temporary_allocator.cc
+++ /dev/null
@@ -1,115 +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 <mutex>
-#include <stack>
-
-#include "BLI_temporary_allocator.h"
-#include "BLI_stack_cxx.h"
-
-using namespace BLI;
-
-constexpr uint ALIGNMENT = BLI_TEMPORARY_BUFFER_ALIGNMENT;
-constexpr uint SMALL_BUFFER_SIZE = 64 * 1024;
-constexpr uintptr_t ALIGNMENT_MASK = ~(uintptr_t)(ALIGNMENT - 1);
-
-enum TemporaryBufferType {
- Small,
- Large,
-};
-
-struct MemHead {
- void *raw_ptr;
- TemporaryBufferType type;
-};
-
-static MemHead &get_memhead(void *aligned_ptr)
-{
- return *((MemHead *)aligned_ptr - 1);
-}
-
-static void *raw_allocate(uint size)
-{
- uint total_allocation_size = size + ALIGNMENT + sizeof(MemHead);
-
- uintptr_t raw_ptr = (uintptr_t)malloc(total_allocation_size);
- uintptr_t aligned_ptr = (raw_ptr + ALIGNMENT + sizeof(MemHead)) & ALIGNMENT_MASK;
-
- MemHead &memhead = get_memhead((void *)aligned_ptr);
- memhead.raw_ptr = (void *)raw_ptr;
- return (void *)aligned_ptr;
-}
-
-static void raw_deallocate(void *ptr)
-{
- BLI_assert(((uintptr_t)ptr & ~ALIGNMENT_MASK) == 0);
- MemHead &memhead = get_memhead(ptr);
- void *raw_ptr = memhead.raw_ptr;
- free(raw_ptr);
-}
-
-struct ThreadLocalBuffers {
- uint allocated_amount = 0;
- Stack<void *, 32, RawAllocator> buffers;
-
- ~ThreadLocalBuffers()
- {
- for (void *ptr : buffers) {
- raw_deallocate(ptr);
- }
- }
-};
-
-static thread_local ThreadLocalBuffers local_storage;
-
-void *BLI_temporary_allocate(uint size)
-{
- /* The total amount of allocated buffers using this allocator should be limited by a constant. If
- * it grows unbounded, there is likely a memory leak somewhere. */
- BLI_assert(local_storage.allocated_amount < 100);
-
- if (size <= SMALL_BUFFER_SIZE) {
- auto &buffers = local_storage.buffers;
- if (buffers.empty()) {
- void *ptr = raw_allocate(SMALL_BUFFER_SIZE);
- MemHead &memhead = get_memhead(ptr);
- memhead.type = TemporaryBufferType::Small;
- local_storage.allocated_amount++;
- return ptr;
- }
- else {
- return buffers.pop();
- }
- }
- else {
- void *ptr = raw_allocate(size);
- MemHead &memhead = get_memhead(ptr);
- memhead.type = TemporaryBufferType::Large;
- return ptr;
- }
-}
-
-void BLI_temporary_deallocate(void *buffer)
-{
- MemHead &memhead = get_memhead(buffer);
- if (memhead.type == TemporaryBufferType::Small) {
- auto &buffers = local_storage.buffers;
- buffers.push(buffer);
- }
- else {
- raw_deallocate(buffer);
- }
-}
diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c
index 118949d1c46..7287bec0849 100644
--- a/source/blender/blenlib/intern/delaunay_2d.c
+++ b/source/blender/blenlib/intern/delaunay_2d.c
@@ -389,7 +389,6 @@ static CDTEdge *connect_separate_parts(CDT_state *cdt, SymEdge *se1, SymEdge *se
{
CDTEdge *e;
SymEdge *se1_rot, *se1_rotsym, *se2_rot, *se2_rotsym, *new_se, *new_se_sym;
- ;
BLI_assert(se1->face == cdt->outer_face && se2->face == cdt->outer_face);
se1_rot = se1->rot;
@@ -1735,7 +1734,7 @@ static bool can_collapse(const SymEdge *se)
* edges may end up with zero or negative area (see can_collapse, above).
* So don't choose a collapse direction that is not allowed or one that has an original vertex
* as origin and a non-original vertex as destination.
- * If both collapse directions are allowed by that rule, picke the one with the lower original
+ * If both collapse directions are allowed by that rule, pick the one with the lower original
* index.
*
* After merging, the faces abc and adb disappear (if they are not the outer face).
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index a1c88edca6f..0a496d2bd68 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -224,7 +224,7 @@ MINLINE unsigned int power_of_2_max_u(unsigned int x)
return x + 1;
}
-MINLINE unsigned power_of_2_min_u(unsigned x)
+MINLINE unsigned int power_of_2_min_u(unsigned int x)
{
x |= (x >> 1);
x |= (x >> 2);
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 7241779b32a..eb82bb81a89 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -49,9 +49,7 @@
/* straight alpha byte blending modes */
-MINLINE void blend_color_mix_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_mix_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight over operation */
@@ -64,10 +62,10 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4],
tmp[2] = (mt * src1[3] * src1[2]) + (t * 255 * src2[2]);
tmp[3] = (mt * src1[3]) + (t * 255);
- dst[0] = (unsigned char)divide_round_i(tmp[0], tmp[3]);
- dst[1] = (unsigned char)divide_round_i(tmp[1], tmp[3]);
- dst[2] = (unsigned char)divide_round_i(tmp[2], tmp[3]);
- dst[3] = (unsigned char)divide_round_i(tmp[3], 255);
+ dst[0] = (uchar)divide_round_i(tmp[0], tmp[3]);
+ dst[1] = (uchar)divide_round_i(tmp[1], tmp[3]);
+ dst[2] = (uchar)divide_round_i(tmp[2], tmp[3]);
+ dst[3] = (uchar)divide_round_i(tmp[3], 255);
}
else {
/* no op */
@@ -75,9 +73,7 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_add_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_add_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight add operation */
@@ -88,9 +84,9 @@ MINLINE void blend_color_add_byte(unsigned char dst[4],
tmp[1] = (src1[1] * 255) + (src2[1] * t);
tmp[2] = (src1[2] * 255) + (src2[2] * t);
- dst[0] = (unsigned char)min_ii(divide_round_i(tmp[0], 255), 255);
- dst[1] = (unsigned char)min_ii(divide_round_i(tmp[1], 255), 255);
- dst[2] = (unsigned char)min_ii(divide_round_i(tmp[2], 255), 255);
+ dst[0] = (uchar)min_ii(divide_round_i(tmp[0], 255), 255);
+ dst[1] = (uchar)min_ii(divide_round_i(tmp[1], 255), 255);
+ dst[2] = (uchar)min_ii(divide_round_i(tmp[2], 255), 255);
dst[3] = src1[3];
}
else {
@@ -99,9 +95,7 @@ MINLINE void blend_color_add_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_sub_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_sub_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight sub operation */
@@ -112,9 +106,9 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4],
tmp[1] = (src1[1] * 255) - (src2[1] * t);
tmp[2] = (src1[2] * 255) - (src2[2] * t);
- dst[0] = (unsigned char)max_ii(divide_round_i(tmp[0], 255), 0);
- dst[1] = (unsigned char)max_ii(divide_round_i(tmp[1], 255), 0);
- dst[2] = (unsigned char)max_ii(divide_round_i(tmp[2], 255), 0);
+ dst[0] = (uchar)max_ii(divide_round_i(tmp[0], 255), 0);
+ dst[1] = (uchar)max_ii(divide_round_i(tmp[1], 255), 0);
+ dst[2] = (uchar)max_ii(divide_round_i(tmp[2], 255), 0);
dst[3] = src1[3];
}
else {
@@ -123,9 +117,7 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_mul_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_mul_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight multiply operation */
@@ -137,9 +129,9 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4],
tmp[1] = (mt * src1[1] * 255) + (t * src1[1] * src2[1]);
tmp[2] = (mt * src1[2] * 255) + (t * src1[2] * src2[2]);
- dst[0] = (unsigned char)divide_round_i(tmp[0], 255 * 255);
- dst[1] = (unsigned char)divide_round_i(tmp[1], 255 * 255);
- dst[2] = (unsigned char)divide_round_i(tmp[2], 255 * 255);
+ dst[0] = (uchar)divide_round_i(tmp[0], 255 * 255);
+ dst[1] = (uchar)divide_round_i(tmp[1], 255 * 255);
+ dst[2] = (uchar)divide_round_i(tmp[2], 255 * 255);
dst[3] = src1[3];
}
else {
@@ -148,9 +140,7 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_lighten_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_lighten_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight lighten operation */
@@ -162,9 +152,9 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4],
tmp[1] = (mt * src1[1]) + (t * max_ii(src1[1], src2[1]));
tmp[2] = (mt * src1[2]) + (t * max_ii(src1[2], src2[2]));
- dst[0] = (unsigned char)divide_round_i(tmp[0], 255);
- dst[1] = (unsigned char)divide_round_i(tmp[1], 255);
- dst[2] = (unsigned char)divide_round_i(tmp[2], 255);
+ dst[0] = (uchar)divide_round_i(tmp[0], 255);
+ dst[1] = (uchar)divide_round_i(tmp[1], 255);
+ dst[2] = (uchar)divide_round_i(tmp[2], 255);
dst[3] = src1[3];
}
else {
@@ -173,9 +163,7 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_darken_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_darken_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight darken operation */
@@ -187,9 +175,9 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4],
tmp[1] = (mt * src1[1]) + (t * min_ii(src1[1], src2[1]));
tmp[2] = (mt * src1[2]) + (t * min_ii(src1[2], src2[2]));
- dst[0] = (unsigned char)divide_round_i(tmp[0], 255);
- dst[1] = (unsigned char)divide_round_i(tmp[1], 255);
- dst[2] = (unsigned char)divide_round_i(tmp[2], 255);
+ dst[0] = (uchar)divide_round_i(tmp[0], 255);
+ dst[1] = (uchar)divide_round_i(tmp[1], 255);
+ dst[2] = (uchar)divide_round_i(tmp[2], 255);
dst[3] = src1[3];
}
else {
@@ -198,9 +186,7 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_erase_alpha_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight so just modify alpha channel */
@@ -209,7 +195,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4],
dst[0] = src1[0];
dst[1] = src1[1];
dst[2] = src1[2];
- dst[3] = (unsigned char)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0);
+ dst[3] = (uchar)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0);
}
else {
/* no op */
@@ -217,9 +203,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_add_alpha_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4])
+MINLINE void blend_color_add_alpha_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
if (src2[3] != 0) {
/* straight so just modify alpha channel */
@@ -228,7 +212,7 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4],
dst[0] = src1[0];
dst[1] = src1[1];
dst[2] = src1[2];
- dst[3] = (unsigned char)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255);
+ dst[3] = (uchar)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255);
}
else {
/* no op */
@@ -236,9 +220,7 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_overlay_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_overlay_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = (int)src2[3];
if (fac != 0) {
@@ -254,7 +236,7 @@ MINLINE void blend_color_overlay_byte(unsigned char dst[4],
else {
temp = (2 * src1[i] * src2[i]) >> 8;
}
- dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
+ dst[i] = (uchar)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
}
}
else {
@@ -263,9 +245,7 @@ MINLINE void blend_color_overlay_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_hardlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_hardlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = (int)src2[3];
if (fac != 0) {
@@ -281,7 +261,7 @@ MINLINE void blend_color_hardlight_byte(unsigned char dst[4],
else {
temp = (2 * src2[i] * src1[i]) >> 8;
}
- dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
+ dst[i] = (uchar)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
}
}
else {
@@ -290,9 +270,7 @@ MINLINE void blend_color_hardlight_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_burn_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_burn_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -301,7 +279,7 @@ MINLINE void blend_color_burn_byte(unsigned char dst[4],
while (i--) {
const int temp = (src2[i] == 0) ? 0 : max_ii(255 - ((255 - src1[i]) * 255) / src2[i], 0);
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -310,9 +288,7 @@ MINLINE void blend_color_burn_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_linearburn_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_linearburn_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -321,7 +297,7 @@ MINLINE void blend_color_linearburn_byte(unsigned char dst[4],
while (i--) {
const int temp = max_ii(src1[i] + src2[i] - 255, 0);
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -330,9 +306,7 @@ MINLINE void blend_color_linearburn_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_dodge_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_dodge_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -341,7 +315,7 @@ MINLINE void blend_color_dodge_byte(unsigned char dst[4],
while (i--) {
const int temp = (src2[i] == 255) ? 255 : min_ii((src1[i] * 255) / (255 - src2[i]), 255);
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -350,9 +324,7 @@ MINLINE void blend_color_dodge_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_screen_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_screen_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -361,7 +333,7 @@ MINLINE void blend_color_screen_byte(unsigned char dst[4],
while (i--) {
const int temp = max_ii(255 - (((255 - src1[i]) * (255 - src2[i])) / 255), 0);
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -370,9 +342,7 @@ MINLINE void blend_color_screen_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_softlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_softlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -388,7 +358,7 @@ MINLINE void blend_color_softlight_byte(unsigned char dst[4],
else {
temp = 255 - (2 * (255 - ((src2[i] / 2) + 64)) * (255 - src1[i]) / 255);
}
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -397,9 +367,7 @@ MINLINE void blend_color_softlight_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_pinlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_pinlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -415,7 +383,7 @@ MINLINE void blend_color_pinlight_byte(unsigned char dst[4],
else {
temp = min_ii(2 * src2[i], src1[i]);
}
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -424,9 +392,7 @@ MINLINE void blend_color_pinlight_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_linearlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_linearlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -442,7 +408,7 @@ MINLINE void blend_color_linearlight_byte(unsigned char dst[4],
else {
temp = max_ii(src1[i] + 2 * src2[i] - 255, 0);
}
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -451,9 +417,7 @@ MINLINE void blend_color_linearlight_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_vividlight_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_vividlight_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -475,7 +439,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4],
else {
temp = max_ii(255 - ((255 - src1[i]) * 255 / (2 * src2[i])), 0);
}
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -484,9 +448,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_difference_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_difference_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -495,7 +457,7 @@ MINLINE void blend_color_difference_byte(unsigned char dst[4],
while (i--) {
const int temp = abs(src1[i] - src2[i]);
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -504,9 +466,7 @@ MINLINE void blend_color_difference_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_exclusion_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_exclusion_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -515,7 +475,7 @@ MINLINE void blend_color_exclusion_byte(unsigned char dst[4],
while (i--) {
const int temp = 127 - ((2 * (src1[i] - 127) * (src2[i] - 127)) / 255);
- dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ dst[i] = (uchar)((temp * fac + src1[i] * mfac) / 255);
}
}
else {
@@ -524,9 +484,7 @@ MINLINE void blend_color_exclusion_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_color_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_color_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -542,9 +500,9 @@ MINLINE void blend_color_color_byte(unsigned char dst[4],
hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
- dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
- dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
}
else {
/* no op */
@@ -552,9 +510,7 @@ MINLINE void blend_color_color_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_hue_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_hue_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -569,9 +525,9 @@ MINLINE void blend_color_hue_byte(unsigned char dst[4],
hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
- dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
- dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
}
else {
/* no op */
@@ -579,9 +535,7 @@ MINLINE void blend_color_hue_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_saturation_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_saturation_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -598,9 +552,9 @@ MINLINE void blend_color_saturation_byte(unsigned char dst[4],
hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
- dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
- dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
}
else {
/* no op */
@@ -608,9 +562,7 @@ MINLINE void blend_color_saturation_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_luminosity_byte(unsigned char dst[4],
- unsigned const char src1[4],
- unsigned const char src2[4])
+MINLINE void blend_color_luminosity_byte(uchar dst[4], const uchar src1[4], const uchar src2[4])
{
const int fac = src2[3];
if (fac != 0) {
@@ -625,9 +577,9 @@ MINLINE void blend_color_luminosity_byte(unsigned char dst[4],
hsv_to_rgb(h1, s1, v1, &r, &g, &b);
- dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
- dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
- dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ dst[0] = (uchar)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (uchar)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (uchar)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
}
else {
/* no op */
@@ -635,9 +587,9 @@ MINLINE void blend_color_luminosity_byte(unsigned char dst[4],
}
}
-MINLINE void blend_color_interpolate_byte(unsigned char dst[4],
- const unsigned char src1[4],
- const unsigned char src2[4],
+MINLINE void blend_color_interpolate_byte(uchar dst[4],
+ const uchar src1[4],
+ const uchar src2[4],
float ft)
{
/* do color interpolation, but in premultiplied space so that RGB colors
@@ -647,10 +599,10 @@ MINLINE void blend_color_interpolate_byte(unsigned char dst[4],
int tmp = (mt * src1[3] + t * src2[3]);
if (tmp > 0) {
- dst[0] = (unsigned char)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp);
- dst[1] = (unsigned char)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp);
- dst[2] = (unsigned char)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp);
- dst[3] = (unsigned char)divide_round_i(tmp, 255);
+ dst[0] = (uchar)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp);
+ dst[1] = (uchar)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp);
+ dst[2] = (uchar)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp);
+ dst[3] = (uchar)divide_round_i(tmp, 255);
}
else {
copy_v4_v4_uchar(dst, src1);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index a17fecca303..e0e463615e5 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -4152,33 +4152,36 @@ struct Float2_Len {
static float mean_value_half_tan_v3(const struct Float3_Len *d_curr,
const struct Float3_Len *d_next)
{
- float cross[3], area;
+ float cross[3];
cross_v3_v3v3(cross, d_curr->dir, d_next->dir);
- area = len_v3(cross);
- if (LIKELY(fabsf(area) > FLT_EPSILON)) {
+ const float area = len_v3(cross);
+ /* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */
+ if (LIKELY(area != 0.0f)) {
const float dot = dot_v3v3(d_curr->dir, d_next->dir);
const float len = d_curr->len * d_next->len;
- return (len - dot) / area;
- }
- else {
- return 0.0f;
+ const float result = (len - dot) / area;
+ if (isfinite(result)) {
+ return result;
+ }
}
+ return 0.0f;
}
static float mean_value_half_tan_v2(const struct Float2_Len *d_curr,
const struct Float2_Len *d_next)
{
- float area;
/* different from the 3d version but still correct */
- area = cross_v2v2(d_curr->dir, d_next->dir);
- if (LIKELY(fabsf(area) > FLT_EPSILON)) {
+ const float area = cross_v2v2(d_curr->dir, d_next->dir);
+ /* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */
+ if (LIKELY(area != 0.0f)) {
const float dot = dot_v2v2(d_curr->dir, d_next->dir);
const float len = d_curr->len * d_next->len;
- return (len - dot) / area;
- }
- else {
- return 0.0f;
+ const float result = (len - dot) / area;
+ if (isfinite(result)) {
+ return result;
+ }
}
+ return 0.0f;
}
void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 55f21250659..5919b7e1dd6 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -240,10 +240,7 @@ void interp_v3_v3v3v3_uv(
p[2] = v1[2] + ((v2[2] - v1[2]) * uv[0]) + ((v3[2] - v1[2]) * uv[1]);
}
-void interp_v3_v3v3_uchar(char unsigned target[3],
- const unsigned char a[3],
- const unsigned char b[3],
- const float t)
+void interp_v3_v3v3_uchar(uchar target[3], const uchar a[3], const uchar b[3], const float t)
{
const float s = 1.0f - t;
@@ -253,14 +250,10 @@ void interp_v3_v3v3_uchar(char unsigned target[3],
}
void interp_v3_v3v3_char(char target[3], const char a[3], const char b[3], const float t)
{
- interp_v3_v3v3_uchar(
- (unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t);
+ interp_v3_v3v3_uchar((uchar *)target, (const uchar *)a, (const uchar *)b, t);
}
-void interp_v4_v4v4_uchar(char unsigned target[4],
- const unsigned char a[4],
- const unsigned char b[4],
- const float t)
+void interp_v4_v4v4_uchar(uchar target[4], const uchar a[4], const uchar b[4], const float t)
{
const float s = 1.0f - t;
@@ -271,8 +264,7 @@ void interp_v4_v4v4_uchar(char unsigned target[4],
}
void interp_v4_v4v4_char(char target[4], const char a[4], const char b[4], const float t)
{
- interp_v4_v4v4_uchar(
- (unsigned char *)target, (const unsigned char *)a, (const unsigned char *)b, t);
+ interp_v4_v4v4_uchar((uchar *)target, (const uchar *)a, (const uchar *)b, t);
}
void mid_v3_v3v3(float v[3], const float v1[3], const float v2[3])
@@ -303,12 +295,12 @@ void mid_v3_v3v3v3v3(
v[2] = (v1[2] + v2[2] + v3[2] + v4[2]) / 4.0f;
}
-void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const unsigned int nbr)
+void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const uint nbr)
{
const float factor = 1.0f / (float)nbr;
zero_v3(r);
- for (unsigned int i = 0; i < nbr; i++) {
+ for (uint i = 0; i < nbr; i++) {
madd_v3_v3fl(r, vec_arr[i], factor);
}
}
@@ -1119,10 +1111,10 @@ void range_vn_i(int *array_tar, const int size, const int start)
}
}
-void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start)
+void range_vn_u(uint *array_tar, const int size, const uint start)
{
- unsigned int *array_pt = array_tar + (size - 1);
- unsigned int j = start + (unsigned int)(size - 1);
+ uint *array_pt = array_tar + (size - 1);
+ uint j = start + (uint)(size - 1);
int i = size;
while (i--) {
*(array_pt--) = j--;
@@ -1329,18 +1321,18 @@ void copy_vn_short(short *array_tar, const int size, const short val)
}
}
-void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val)
+void copy_vn_ushort(ushort *array_tar, const int size, const ushort val)
{
- unsigned short *tar = array_tar + (size - 1);
+ ushort *tar = array_tar + (size - 1);
int i = size;
while (i--) {
*(tar--) = val;
}
}
-void copy_vn_uchar(unsigned char *array_tar, const int size, const unsigned char val)
+void copy_vn_uchar(uchar *array_tar, const int size, const uchar val)
{
- unsigned char *tar = array_tar + (size - 1);
+ uchar *tar = array_tar + (size - 1);
int i = size;
while (i--) {
*(tar--) = val;
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 63657f33bba..7fc95a33092 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -600,7 +600,7 @@ uint BLI_str_utf8_as_unicode(const char *p)
uint BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index)
{
int i, len;
- unsigned mask = 0;
+ uint mask = 0;
uint result;
const unsigned char c = (unsigned char)*p;
diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c
index b956e1c0a7e..85cb32b6457 100644
--- a/source/blender/blenlib/intern/string_utils.c
+++ b/source/blender/blenlib/intern/string_utils.c
@@ -410,12 +410,30 @@ bool BLI_uniquename(
/** \name Join Strings
*
* For non array versions of these functions, use the macros:
+ * - #BLI_string_join
* - #BLI_string_joinN
* - #BLI_string_join_by_sep_charN
* - #BLI_string_join_by_sep_char_with_tableN
*
* \{ */
+char *BLI_string_join_array(char *result,
+ size_t result_len,
+ const char *strings[],
+ uint strings_len)
+{
+ char *c = result;
+ char *c_end = &result[result_len - 1];
+ for (uint i = 0; i < strings_len; i++) {
+ const char *p = strings[i];
+ while (*p && (c < c_end)) {
+ *c++ = *p++;
+ }
+ }
+ *c = '\0';
+ return c;
+}
+
/**
* Join an array of strings into a newly allocated, null terminated string.
*/
diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c
index 7fe06d90ac1..cc447196507 100644
--- a/source/blender/blenloader/intern/blend_validate.c
+++ b/source/blender/blenloader/intern/blend_validate.c
@@ -37,6 +37,7 @@
#include "DNA_windowmanager_types.h"
#include "BKE_key.h"
+#include "BKE_lib_id.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 651f390d23e..d9849cfa770 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -120,10 +120,10 @@
#include "BKE_idcode.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_idmap.h"
-#include "BKE_library_override.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_main_idmap.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h" // for Main
#include "BKE_material.h"
#include "BKE_mesh.h" // for ME_ defines (patching)
@@ -2613,7 +2613,29 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p
/** \name Read ID
* \{ */
-static void lib_link_id(FileData *fd, Main *UNUSED(bmain), ID *id)
+static void lib_link_id(FileData *fd, Main *bmain, ID *id);
+static void lib_link_nodetree(FileData *fd, Main *bmain, bNodeTree *ntree);
+static void lib_link_collection(FileData *fd, Main *bmain, Collection *collection);
+
+static void lib_link_id_private_id(FileData *fd, Main *bmain, ID *id)
+{
+ /* Handle 'private IDs'. */
+ bNodeTree *nodetree = ntreeFromID(id);
+ if (nodetree != NULL) {
+ lib_link_id(fd, bmain, &nodetree->id);
+ lib_link_nodetree(fd, bmain, nodetree);
+ }
+
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ if (scene->master_collection != NULL) {
+ lib_link_id(fd, bmain, &scene->master_collection->id);
+ lib_link_collection(fd, bmain, scene->master_collection);
+ }
+ }
+}
+
+static void lib_link_id(FileData *fd, Main *bmain, ID *id)
{
/* Note: WM IDProperties are never written to file, hence they should always be NULL here. */
BLI_assert((GS(id->name) != ID_WM) || id->properties == NULL);
@@ -2628,6 +2650,8 @@ static void lib_link_id(FileData *fd, Main *UNUSED(bmain), ID *id)
id->override_library->reference = newlibadr_us(fd, id->lib, id->override_library->reference);
id->override_library->storage = newlibadr_us(fd, id->lib, id->override_library->storage);
}
+
+ lib_link_id_private_id(fd, bmain, id);
}
static void direct_link_id_override_property_operation_cb(FileData *fd, void *data)
@@ -2646,6 +2670,30 @@ static void direct_link_id_override_property_cb(FileData *fd, void *data)
link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb);
}
+static void direct_link_id(FileData *fd, ID *id);
+static void direct_link_nodetree(FileData *fd, bNodeTree *ntree);
+static void direct_link_collection(FileData *fd, Collection *collection);
+
+static void direct_link_id_private_id(FileData *fd, ID *id)
+{
+ /* Handle 'private IDs'. */
+ bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
+ if (nodetree != NULL && *nodetree != NULL) {
+ *nodetree = newdataadr(fd, *nodetree);
+ direct_link_id(fd, (ID *)*nodetree);
+ direct_link_nodetree(fd, *nodetree);
+ }
+
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ if (scene->master_collection != NULL) {
+ scene->master_collection = newdataadr(fd, scene->master_collection);
+ direct_link_id(fd, &scene->master_collection->id);
+ direct_link_collection(fd, scene->master_collection);
+ }
+ }
+}
+
static void direct_link_id(FileData *fd, ID *id)
{
/*link direct data of ID properties*/
@@ -2685,6 +2733,9 @@ static void direct_link_id(FileData *fd, ID *id)
if (drawdata) {
BLI_listbase_clear((ListBase *)drawdata);
}
+
+ /* Handle 'private IDs'. */
+ direct_link_id_private_id(fd, id);
}
/** \} */
@@ -3874,14 +3925,9 @@ static void direct_link_camera(FileData *fd, Camera *ca)
/** \name Read ID: Light
* \{ */
-static void lib_link_light(FileData *fd, Main *bmain, Light *la)
+static void lib_link_light(FileData *fd, Main *UNUSED(bmain), Light *la)
{
la->ipo = newlibadr_us(fd, la->id.lib, la->ipo); // XXX deprecated - old animation system
-
- if (la->nodetree) {
- lib_link_id(fd, bmain, &la->nodetree->id);
- lib_link_ntree(fd, la->id.lib, la->nodetree);
- }
}
static void direct_link_light(FileData *fd, Light *la)
@@ -3894,12 +3940,6 @@ static void direct_link_light(FileData *fd, Light *la)
direct_link_curvemapping(fd, la->curfalloff);
}
- la->nodetree = newdataadr(fd, la->nodetree);
- if (la->nodetree) {
- direct_link_id(fd, &la->nodetree->id);
- direct_link_nodetree(fd, la->nodetree);
- }
-
la->preview = direct_link_preview_image(fd, la->preview);
}
@@ -4016,14 +4056,9 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
/** \name Read ID: World
* \{ */
-static void lib_link_world(FileData *fd, Main *bmain, World *wrld)
+static void lib_link_world(FileData *fd, Main *UNUSED(bmain), World *wrld)
{
wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system
-
- if (wrld->nodetree) {
- lib_link_id(fd, bmain, &wrld->nodetree->id);
- lib_link_ntree(fd, wrld->id.lib, wrld->nodetree);
- }
}
static void direct_link_world(FileData *fd, World *wrld)
@@ -4031,12 +4066,6 @@ static void direct_link_world(FileData *fd, World *wrld)
wrld->adt = newdataadr(fd, wrld->adt);
direct_link_animdata(fd, wrld->adt);
- wrld->nodetree = newdataadr(fd, wrld->nodetree);
- if (wrld->nodetree) {
- direct_link_id(fd, &wrld->nodetree->id);
- direct_link_nodetree(fd, wrld->nodetree);
- }
-
wrld->preview = direct_link_preview_image(fd, wrld->preview);
BLI_listbase_clear(&wrld->gpumaterial);
}
@@ -4278,15 +4307,10 @@ static void direct_link_curve(FileData *fd, Curve *cu)
/** \name Read ID: Texture
* \{ */
-static void lib_link_texture(FileData *fd, Main *bmain, Tex *tex)
+static void lib_link_texture(FileData *fd, Main *UNUSED(bmain), Tex *tex)
{
tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima);
tex->ipo = newlibadr_us(fd, tex->id.lib, tex->ipo); // XXX deprecated - old animation system
-
- if (tex->nodetree) {
- lib_link_id(fd, bmain, &tex->nodetree->id);
- lib_link_ntree(fd, tex->id.lib, tex->nodetree);
- }
}
static void direct_link_texture(FileData *fd, Tex *tex)
@@ -4296,12 +4320,6 @@ static void direct_link_texture(FileData *fd, Tex *tex)
tex->coba = newdataadr(fd, tex->coba);
- tex->nodetree = newdataadr(fd, tex->nodetree);
- if (tex->nodetree) {
- direct_link_id(fd, &tex->nodetree->id);
- direct_link_nodetree(fd, tex->nodetree);
- }
-
tex->preview = direct_link_preview_image(fd, tex->preview);
tex->iuser.ok = 1;
@@ -4314,15 +4332,10 @@ static void direct_link_texture(FileData *fd, Tex *tex)
/** \name Read ID: Material
* \{ */
-static void lib_link_material(FileData *fd, Main *bmain, Material *ma)
+static void lib_link_material(FileData *fd, Main *UNUSED(bmain), Material *ma)
{
ma->ipo = newlibadr_us(fd, ma->id.lib, ma->ipo); // XXX deprecated - old animation system
- if (ma->nodetree) {
- lib_link_id(fd, bmain, &ma->nodetree->id);
- lib_link_ntree(fd, ma->id.lib, ma->nodetree);
- }
-
/* relink grease pencil settings */
if (ma->gp_style != NULL) {
MaterialGPencilStyle *gp_style = ma->gp_style;
@@ -4342,12 +4355,6 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->texpaintslot = NULL;
- ma->nodetree = newdataadr(fd, ma->nodetree);
- if (ma->nodetree) {
- direct_link_id(fd, &ma->nodetree->id);
- direct_link_nodetree(fd, ma->nodetree);
- }
-
ma->preview = direct_link_preview_image(fd, ma->preview);
BLI_listbase_clear(&ma->gpumaterial);
@@ -6325,7 +6332,7 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
}
#endif
-static void lib_link_scene(FileData *fd, Main *bmain, Scene *sce)
+static void lib_link_scene(FileData *fd, Main *UNUSED(bmain), Scene *sce)
{
lib_link_keyingsets(fd, &sce->id, &sce->keyingsets);
@@ -6459,8 +6466,6 @@ static void lib_link_scene(FileData *fd, Main *bmain, Scene *sce)
}
if (sce->nodetree) {
- lib_link_id(fd, bmain, &sce->nodetree->id);
- lib_link_ntree(fd, sce->id.lib, sce->nodetree);
composite_patch(sce->nodetree, sce);
}
@@ -6483,11 +6488,6 @@ static void lib_link_scene(FileData *fd, Main *bmain, Scene *sce)
}
#endif
- if (sce->master_collection) {
- lib_link_id(fd, bmain, &sce->master_collection->id);
- lib_link_collection_data(fd, sce->id.lib, sce->master_collection);
- }
-
for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
lib_link_view_layer(fd, sce->id.lib, view_layer);
}
@@ -6817,12 +6817,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
link_list(fd, &(srl->freestyleConfig.linesets));
}
- sce->nodetree = newdataadr(fd, sce->nodetree);
- if (sce->nodetree) {
- direct_link_id(fd, &sce->nodetree->id);
- direct_link_nodetree(fd, sce->nodetree);
- }
-
direct_link_view_settings(fd, &sce->view_settings);
sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world);
@@ -6878,13 +6872,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
#endif
- if (sce->master_collection) {
- sce->master_collection = newdataadr(fd, sce->master_collection);
- /* Needed because this is an ID outside of Main. */
- direct_link_id(fd, &sce->master_collection->id);
- direct_link_collection(fd, sce->master_collection);
- }
-
/* insert into global old-new map for reading without UI (link_global accesses it again) */
link_glob_list(fd, &sce->view_layers);
for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -8576,7 +8563,7 @@ static void lib_link_mask(FileData *fd, Main *UNUSED(bmain), Mask *mask)
/** \name Read ID: Line Style
* \{ */
-static void lib_link_linestyle(FileData *fd, Main *bmain, FreestyleLineStyle *linestyle)
+static void lib_link_linestyle(FileData *fd, Main *UNUSED(bmain), FreestyleLineStyle *linestyle)
{
LineStyleModifier *m;
@@ -8617,10 +8604,6 @@ static void lib_link_linestyle(FileData *fd, Main *bmain, FreestyleLineStyle *li
mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object);
}
}
- if (linestyle->nodetree) {
- lib_link_id(fd, bmain, &linestyle->nodetree->id);
- lib_link_ntree(fd, linestyle->id.lib, linestyle->nodetree);
- }
}
static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier *modifier)
@@ -8811,11 +8794,6 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
for (a = 0; a < MAX_MTEX; a++) {
linestyle->mtex[a] = newdataadr(fd, linestyle->mtex[a]);
}
- linestyle->nodetree = newdataadr(fd, linestyle->nodetree);
- if (linestyle->nodetree) {
- direct_link_id(fd, &linestyle->nodetree->id);
- direct_link_nodetree(fd, linestyle->nodetree);
- }
}
/** \} */
@@ -9805,7 +9783,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
* we can re-generate overrides from their references. */
if (fd->memfile == NULL) {
/* Do not apply in undo case! */
- BKE_main_override_library_update(bfd->main);
+ BKE_lib_override_library_main_update(bfd->main);
}
BKE_collections_after_lib_link(bfd->main);
@@ -10104,39 +10082,6 @@ static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *ch
}
}
-static void expand_id(FileData *fd, Main *mainvar, ID *id)
-{
- if (id->override_library) {
- expand_doit(fd, mainvar, id->override_library->reference);
- expand_doit(fd, mainvar, id->override_library->storage);
- }
-}
-
-static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop)
-{
- if (!prop) {
- return;
- }
-
- switch (prop->type) {
- case IDP_ID:
- expand_doit(fd, mainvar, IDP_Id(prop));
- break;
- case IDP_IDPARRAY: {
- IDProperty *idp_array = IDP_IDPArray(prop);
- for (int i = 0; i < prop->len; i++) {
- expand_idprops(fd, mainvar, &idp_array[i]);
- }
- break;
- }
- case IDP_GROUP:
- for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
- expand_idprops(fd, mainvar, loop);
- }
- break;
- }
-}
-
static void expand_fmodifiers(FileData *fd, Main *mainvar, ListBase *list)
{
FModifier *fcm;
@@ -10179,40 +10124,6 @@ static void expand_fcurves(FileData *fd, Main *mainvar, ListBase *list)
}
}
-static void expand_action(FileData *fd, Main *mainvar, bAction *act)
-{
- bActionChannel *chan;
-
- // XXX deprecated - old animation system --------------
- for (chan = act->chanbase.first; chan; chan = chan->next) {
- expand_doit(fd, mainvar, chan->ipo);
- expand_constraint_channels(fd, mainvar, &chan->constraintChannels);
- }
- // ---------------------------------------------------
-
- /* F-Curves in Action */
- expand_fcurves(fd, mainvar, &act->curves);
-
- for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
- if (marker->camera) {
- expand_doit(fd, mainvar, marker->camera);
- }
- }
-}
-
-static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
-{
- KeyingSet *ks;
- KS_Path *ksp;
-
- /* expand the ID-pointers in KeyingSets's paths */
- for (ks = list->first; ks; ks = ks->next) {
- for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
- expand_doit(fd, mainvar, ksp->id);
- }
- }
-}
-
static void expand_animdata_nlastrips(FileData *fd, Main *mainvar, ListBase *list)
{
NlaStrip *strip;
@@ -10249,6 +10160,104 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
}
}
+static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop)
+{
+ if (!prop) {
+ return;
+ }
+
+ switch (prop->type) {
+ case IDP_ID:
+ expand_doit(fd, mainvar, IDP_Id(prop));
+ break;
+ case IDP_IDPARRAY: {
+ IDProperty *idp_array = IDP_IDPArray(prop);
+ for (int i = 0; i < prop->len; i++) {
+ expand_idprops(fd, mainvar, &idp_array[i]);
+ }
+ break;
+ }
+ case IDP_GROUP:
+ for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
+ expand_idprops(fd, mainvar, loop);
+ }
+ break;
+ }
+}
+
+static void expand_id(FileData *fd, Main *mainvar, ID *id);
+static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree);
+static void expand_collection(FileData *fd, Main *mainvar, Collection *collection);
+
+static void expand_id_private_id(FileData *fd, Main *mainvar, ID *id)
+{
+ /* Handle 'private IDs'. */
+ bNodeTree *nodetree = ntreeFromID(id);
+ if (nodetree != NULL) {
+ expand_id(fd, mainvar, &nodetree->id);
+ expand_nodetree(fd, mainvar, nodetree);
+ }
+
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ if (scene->master_collection != NULL) {
+ expand_id(fd, mainvar, &scene->master_collection->id);
+ expand_collection(fd, mainvar, scene->master_collection);
+ }
+ }
+}
+
+static void expand_id(FileData *fd, Main *mainvar, ID *id)
+{
+ expand_idprops(fd, mainvar, id->properties);
+
+ if (id->override_library) {
+ expand_doit(fd, mainvar, id->override_library->reference);
+ expand_doit(fd, mainvar, id->override_library->storage);
+ }
+
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt != NULL) {
+ expand_animdata(fd, mainvar, adt);
+ }
+
+ expand_id_private_id(fd, mainvar, id);
+}
+
+static void expand_action(FileData *fd, Main *mainvar, bAction *act)
+{
+ bActionChannel *chan;
+
+ // XXX deprecated - old animation system --------------
+ for (chan = act->chanbase.first; chan; chan = chan->next) {
+ expand_doit(fd, mainvar, chan->ipo);
+ expand_constraint_channels(fd, mainvar, &chan->constraintChannels);
+ }
+ // ---------------------------------------------------
+
+ /* F-Curves in Action */
+ expand_fcurves(fd, mainvar, &act->curves);
+
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
+ if (marker->camera) {
+ expand_doit(fd, mainvar, marker->camera);
+ }
+ }
+}
+
+static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
+{
+ KeyingSet *ks;
+ KS_Path *ksp;
+
+ /* expand the ID-pointers in KeyingSets's paths */
+ for (ks = list->first; ks; ks = ks->next) {
+ for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
+ expand_doit(fd, mainvar, ksp->id);
+ }
+ }
+}
+
static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)
{
int a;
@@ -10259,10 +10268,6 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
expand_doit(fd, mainvar, part->bb_ob);
expand_doit(fd, mainvar, part->collision_group);
- if (part->adt) {
- expand_animdata(fd, mainvar, part->adt);
- }
-
for (a = 0; a < MAX_MTEX; a++) {
if (part->mtex[a]) {
expand_doit(fd, mainvar, part->mtex[a]->tex);
@@ -10326,10 +10331,6 @@ static void expand_collection(FileData *fd, Main *mainvar, Collection *collectio
static void expand_key(FileData *fd, Main *mainvar, Key *key)
{
expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system
-
- if (key->adt) {
- expand_animdata(fd, mainvar, key->adt);
- }
}
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
@@ -10337,10 +10338,6 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
bNode *node;
bNodeSocket *sock;
- if (ntree->adt) {
- expand_animdata(fd, mainvar, ntree->adt);
- }
-
if (ntree->gpd) {
expand_doit(fd, mainvar, ntree->gpd);
}
@@ -10372,14 +10369,6 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
{
expand_doit(fd, mainvar, tex->ima);
expand_doit(fd, mainvar, tex->ipo); // XXX deprecated - old animation system
-
- if (tex->adt) {
- expand_animdata(fd, mainvar, tex->adt);
- }
-
- if (tex->nodetree) {
- expand_nodetree(fd, mainvar, tex->nodetree);
- }
}
static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
@@ -10397,14 +10386,6 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
{
expand_doit(fd, mainvar, ma->ipo); // XXX deprecated - old animation system
- if (ma->adt) {
- expand_animdata(fd, mainvar, ma->adt);
- }
-
- if (ma->nodetree) {
- expand_nodetree(fd, mainvar, ma->nodetree);
- }
-
if (ma->gp_style) {
MaterialGPencilStyle *gp_style = ma->gp_style;
expand_doit(fd, mainvar, gp_style->sima);
@@ -10415,37 +10396,17 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
static void expand_light(FileData *fd, Main *mainvar, Light *la)
{
expand_doit(fd, mainvar, la->ipo); // XXX deprecated - old animation system
-
- if (la->adt) {
- expand_animdata(fd, mainvar, la->adt);
- }
-
- if (la->nodetree) {
- expand_nodetree(fd, mainvar, la->nodetree);
- }
}
static void expand_lattice(FileData *fd, Main *mainvar, Lattice *lt)
{
expand_doit(fd, mainvar, lt->ipo); // XXX deprecated - old animation system
expand_doit(fd, mainvar, lt->key);
-
- if (lt->adt) {
- expand_animdata(fd, mainvar, lt->adt);
- }
}
static void expand_world(FileData *fd, Main *mainvar, World *wrld)
{
expand_doit(fd, mainvar, wrld->ipo); // XXX deprecated - old animation system
-
- if (wrld->adt) {
- expand_animdata(fd, mainvar, wrld->adt);
- }
-
- if (wrld->nodetree) {
- expand_nodetree(fd, mainvar, wrld->nodetree);
- }
}
static void expand_mball(FileData *fd, Main *mainvar, MetaBall *mb)
@@ -10455,10 +10416,6 @@ static void expand_mball(FileData *fd, Main *mainvar, MetaBall *mb)
for (a = 0; a < mb->totcol; a++) {
expand_doit(fd, mainvar, mb->mat[a]);
}
-
- if (mb->adt) {
- expand_animdata(fd, mainvar, mb->adt);
- }
}
static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
@@ -10478,20 +10435,12 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
expand_doit(fd, mainvar, cu->bevobj);
expand_doit(fd, mainvar, cu->taperobj);
expand_doit(fd, mainvar, cu->textoncurve);
-
- if (cu->adt) {
- expand_animdata(fd, mainvar, cu->adt);
- }
}
static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
{
int a;
- if (me->adt) {
- expand_animdata(fd, mainvar, me->adt);
- }
-
for (a = 0; a < me->totcol; a++) {
expand_doit(fd, mainvar, me->mat[a]);
}
@@ -10560,10 +10509,6 @@ static void expand_bones(FileData *fd, Main *mainvar, Bone *bone)
static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
{
- if (arm->adt) {
- expand_animdata(fd, mainvar, arm->adt);
- }
-
for (Bone *curBone = arm->bonebase.first; curBone; curBone = curBone->next) {
expand_bones(fd, mainvar, curBone);
}
@@ -10649,10 +10594,6 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
}
// XXX deprecated - old animation system (for version patching only)
- if (ob->adt) {
- expand_animdata(fd, mainvar, ob->adt);
- }
-
for (a = 0; a < ob->totcol; a++) {
expand_doit(fd, mainvar, ob->mat[a]);
}
@@ -10728,19 +10669,12 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
expand_doit(fd, mainvar, sce->camera);
expand_doit(fd, mainvar, sce->world);
- if (sce->adt) {
- expand_animdata(fd, mainvar, sce->adt);
- }
expand_keyingsets(fd, mainvar, &sce->keyingsets);
if (sce->set) {
expand_doit(fd, mainvar, sce->set);
}
- if (sce->nodetree) {
- expand_nodetree(fd, mainvar, sce->nodetree);
- }
-
for (srl = sce->r.layers.first; srl; srl = srl->next) {
expand_doit(fd, mainvar, srl->mat_override);
for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
@@ -10826,10 +10760,6 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
#endif
- if (sce->master_collection) {
- expand_collection(fd, mainvar, sce->master_collection);
- }
-
if (sce->r.bake.cage_object) {
expand_doit(fd, mainvar, sce->r.bake.cage_object);
}
@@ -10847,26 +10777,17 @@ static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
expand_doit(fd, mainvar, bgpic->ima);
}
}
-
- if (ca->adt) {
- expand_animdata(fd, mainvar, ca->adt);
- }
}
-static void expand_cachefile(FileData *fd, Main *mainvar, CacheFile *cache_file)
+static void expand_cachefile(FileData *UNUSED(fd),
+ Main *UNUSED(mainvar),
+ CacheFile *UNUSED(cache_file))
{
- if (cache_file->adt) {
- expand_animdata(fd, mainvar, cache_file->adt);
- }
}
static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk)
{
expand_doit(fd, mainvar, spk->sound);
-
- if (spk->adt) {
- expand_animdata(fd, mainvar, spk->adt);
- }
}
static void expand_sound(FileData *fd, Main *mainvar, bSound *snd)
@@ -10874,18 +10795,12 @@ static void expand_sound(FileData *fd, Main *mainvar, bSound *snd)
expand_doit(fd, mainvar, snd->ipo); // XXX deprecated - old animation system
}
-static void expand_lightprobe(FileData *fd, Main *mainvar, LightProbe *prb)
+static void expand_lightprobe(FileData *UNUSED(fd), Main *UNUSED(mainvar), LightProbe *UNUSED(prb))
{
- if (prb->adt) {
- expand_animdata(fd, mainvar, prb->adt);
- }
}
-static void expand_movieclip(FileData *fd, Main *mainvar, MovieClip *clip)
+static void expand_movieclip(FileData *UNUSED(fd), Main *UNUSED(mainvar), MovieClip *UNUSED(clip))
{
- if (clip->adt) {
- expand_animdata(fd, mainvar, clip->adt);
- }
}
static void expand_mask_parent(FileData *fd, Main *mainvar, MaskParent *parent)
@@ -10899,10 +10814,6 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
{
MaskLayer *mask_layer;
- if (mask->adt) {
- expand_animdata(fd, mainvar, mask->adt);
- }
-
for (mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
MaskSpline *spline;
@@ -10931,13 +10842,7 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li
expand_doit(fd, mainvar, linestyle->mtex[a]->object);
}
}
- if (linestyle->nodetree) {
- expand_nodetree(fd, mainvar, linestyle->nodetree);
- }
- if (linestyle->adt) {
- expand_animdata(fd, mainvar, linestyle->adt);
- }
for (m = linestyle->color_modifiers.first; m; m = m->next) {
if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
expand_doit(fd, mainvar, ((LineStyleColorModifier_DistanceFromObject *)m)->target);
@@ -10957,10 +10862,6 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li
static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
{
- if (gpd->adt) {
- expand_animdata(fd, mainvar, gpd->adt);
- }
-
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
expand_doit(fd, mainvar, gpl->parent);
}
@@ -11013,7 +10914,6 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
while (id) {
if (id->tag & LIB_TAG_NEED_EXPAND) {
expand_id(fd, mainvar, id);
- expand_idprops(fd, mainvar, id->properties);
switch (GS(id->name)) {
case ID_OB:
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index a5ab0c0acb7..a4b51f91be4 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -65,7 +65,7 @@
#include "BKE_armature.h"
#include "BKE_colortools.h"
#include "BKE_global.h" // for G
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index d8541975f86..cb12efd0ec2 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -73,7 +73,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -1558,7 +1558,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
}
}
- /* This versionning could probably be done only on earlier versions, not sure however
+ /* This versioning could probably be done only on earlier versions, not sure however
* which exact version fully deprecated tessfaces, so think we can keep that one here, no
* harm to be expected anyway for being over-conservative. */
for (Mesh *me = bmain->meshes.first; me != NULL; me = me->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 8c7a0c4f7b2..446cfa4163f 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -45,7 +45,7 @@
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 401f0ef6a85..30ba20b97da 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -157,7 +157,7 @@
#include "BKE_gpencil_modifier.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
@@ -3782,7 +3782,7 @@ static bool write_file_handle(Main *mainvar,
mywrite_flush(wd);
OverrideLibraryStorage *override_storage =
- wd->use_memfile ? NULL : BKE_override_library_operations_store_initialize();
+ wd->use_memfile ? NULL : BKE_lib_override_library_operations_store_initialize();
/* This outer loop allows to save first data-blocks from real mainvar,
* then the temp ones from override process,
@@ -3807,7 +3807,7 @@ static bool write_file_handle(Main *mainvar,
const bool do_override = !ELEM(override_storage, NULL, bmain) && id->override_library;
if (do_override) {
- BKE_override_library_operations_store_start(bmain, override_storage, id);
+ BKE_lib_override_library_operations_store_start(bmain, override_storage, id);
}
switch ((ID_Type)GS(id->name)) {
@@ -3927,7 +3927,7 @@ static bool write_file_handle(Main *mainvar,
}
if (do_override) {
- BKE_override_library_operations_store_end(override_storage, id);
+ BKE_lib_override_library_operations_store_end(override_storage, id);
}
}
@@ -3936,7 +3936,7 @@ static bool write_file_handle(Main *mainvar,
} while ((bmain != override_storage) && (bmain = override_storage));
if (override_storage) {
- BKE_override_library_operations_store_finalize(override_storage);
+ BKE_lib_override_library_operations_store_finalize(override_storage);
override_storage = NULL;
}
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 8cbbf765f66..d14b7a51a94 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -476,7 +476,7 @@ BMLog *BM_log_create(BMesh *bm)
BMLog *log = MEM_callocN(sizeof(*log), __func__);
const uint reserve_num = (uint)(bm->totvert + bm->totface);
- log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
+ log->unused_ids = range_tree_uint_alloc(0, (uint)-1);
log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
@@ -618,7 +618,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
/* Create BMVert index remap array */
id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert);
BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
- const unsigned id = bm_log_vert_id_get(log, v);
+ const uint id = bm_log_vert_id_get(log, v);
const void *key = POINTER_FROM_UINT(id);
const void *val = BLI_ghash_lookup(id_to_idx, key);
varr[i] = POINTER_AS_UINT(val);
@@ -628,7 +628,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
/* Create BMFace index remap array */
id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface);
BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
- const unsigned id = bm_log_face_id_get(log, f);
+ const uint id = bm_log_face_id_get(log, f);
const void *key = POINTER_FROM_UINT(id);
const void *val = BLI_ghash_lookup(id_to_idx, key);
farr[i] = POINTER_AS_UINT(val);
@@ -1039,7 +1039,7 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
+ uint v_id = bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@@ -1057,7 +1057,7 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
+ uint v_id = bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@@ -1075,7 +1075,7 @@ float BM_log_original_mask(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
+ uint v_id = bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
@@ -1090,7 +1090,7 @@ void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const
{
BMLogEntry *entry = log->current_entry;
const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
+ uint v_id = bm_log_vert_id_get(log, v);
void *key = POINTER_FROM_UINT(v_id);
BLI_assert(entry);
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 374c912e3f5..f6ed95d322d 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -1298,7 +1298,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm,
if (use_partial_connect) {
for (uint i = 0; i < edge_net_init_len; i++) {
- for (unsigned j = 0; j < 2; j++) {
+ for (uint j = 0; j < 2; j++) {
BMVert *v_delimit = (&edge_arr[i]->v1)[j];
BMVert *v_other;
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index d5cbe947293..8b4a59d5b9b 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -86,7 +86,7 @@ enum {
} \
(void)0
-void poly_rotate_plane(const float normal[3], float (*verts)[3], unsigned const int nverts);
+void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts);
/* include the rest of our private declarations */
#include "bmesh_structure.h"
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index e52467614ac..2f0b21667e4 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -41,7 +41,7 @@
static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenerate)
{
- const unsigned pair_split_max = f->len / 2;
+ const uint pair_split_max = f->len / 2;
BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max);
STACK_DECLARE(loops_split);
BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max);
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index c3d19862ffb..adc612cfb54 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -205,7 +205,7 @@ static void barycentric_weights_v2_grid_cache(const uint xtot,
static void bm_grid_fill_array(BMesh *bm,
BMVert **v_grid,
const uint xtot,
- unsigned const int ytot,
+ const uint ytot,
const short mat_nr,
const bool use_smooth,
const bool use_flip,
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 848669301c3..efb8b810581 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -260,7 +260,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BMEdge *e;
/* data: edge-to-join, sort_value: error weight */
struct SortPtrByFloat *jedges;
- unsigned i, totedge;
+ uint i, totedge;
uint totedge_tag = 0;
struct DelimitData delimit_data = {0};
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index d3b3541a539..d8c2057bb56 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -66,7 +66,7 @@
/* for testing */
// #pragma GCC diagnostic error "-Wpadded"
-/* Constructed vertex, sometimes later instantiated as BMVert */
+/* Constructed vertex, sometimes later instantiated as BMVert. */
typedef struct NewVert {
BMVert *v;
float co[3];
@@ -75,31 +75,31 @@ typedef struct NewVert {
struct BoundVert;
-/* Data for one end of an edge involved in a bevel */
+/* Data for one end of an edge involved in a bevel. */
typedef struct EdgeHalf {
/** Other EdgeHalves connected to the same BevVert, in CCW order. */
struct EdgeHalf *next, *prev;
- /** Original mesh edge */
+ /** Original mesh edge. */
BMEdge *e;
- /** Face between this edge and previous, if any */
+ /** Face between this edge and previous, if any. */
BMFace *fprev;
- /** Face between this edge and next, if any */
+ /** Face between this edge and next, if any. */
BMFace *fnext;
- /** Left boundary vert (looking along edge to end) */
+ /** Left boundary vert (looking along edge to end). */
struct BoundVert *leftv;
- /** Right boundary vert, if beveled */
+ /** Right boundary vert, if beveled. */
struct BoundVert *rightv;
- /** Offset into profile to attach non-beveled edge */
+ /** Offset into profile to attach non-beveled edge. */
int profile_index;
- /** How many segments for the bevel */
+ /** How many segments for the bevel. */
int seg;
- /** Offset for this edge, on left side */
+ /** Offset for this edge, on left side. */
float offset_l;
- /** Offset for this edge, on right side */
+ /** Offset for this edge, on right side. */
float offset_r;
- /** User specification for offset_l */
+ /** User specification for offset_l. */
float offset_l_spec;
- /** User specification for offset_r */
+ /** User specification for offset_r. */
float offset_r_spec;
/** Is this edge beveled? */
bool is_bev;
@@ -107,44 +107,45 @@ typedef struct EdgeHalf {
bool is_rev;
/** Is e a seam for custom loopdata (e.g., UVs)? */
bool is_seam;
- /** Used during the custom profile orientation pass */
+ /** Used during the custom profile orientation pass. */
bool visited_rpo;
char _pad[4];
} EdgeHalf;
-/* Profile specification:
+/**
+ * Profile specification:
+ * The profile is a path defined with start, middle, and end control points projected onto a
+ * plane (plane_no is normal, plane_co is a point on it) via lines in a given direction (proj_dir).
+ *
* Many interesting profiles are in family of superellipses:
* (abs(x/a))^r + abs(y/b))^r = 1
* r==2 => ellipse; r==1 => line; r < 1 => concave; r > 1 => bulging out.
* Special cases: let r==0 mean straight-inward, and r==4 mean straight outward.
- * The profile is a path defined with start, middle, and end control points
- * projected onto a plane (plane_no is normal, plane_co is a point on it)
- * via lines in a given direction (proj_dir).
- * After the parameters are all set, the actual profile points are calculated
- * and pointed to by prof_co. We also may need profile points for a higher resolution
- * number of segments for the subdivision while making the ADJ vertex mesh pattern,
- * and that goes in prof_co_2.
+ *
+ * After the parameters are all set, the actual profile points are calculated and pointed to
+ * by prof_co. We also may need profile points for a higher resolution number of segments
+ * for the subdivision while making the ADJ vertex mesh pattern, and that goes in prof_co_2.
*/
typedef struct Profile {
- /** Superellipse r parameter */
+ /** Superellipse r parameter. */
float super_r;
- /** Height for profile cutoff face sides */
+ /** Height for profile cutoff face sides. */
float height;
- /** Start control point for profile */
+ /** Start control point for profile. */
float start[3];
- /** Mid control point for profile */
+ /** Mid control point for profile. */
float middle[3];
- /** End control point for profile */
+ /** End control point for profile. */
float end[3];
- /** Normal of plane to project to */
+ /** Normal of plane to project to. */
float plane_no[3];
- /** Coordinate on plane to project to */
+ /** Coordinate on plane to project to. */
float plane_co[3];
- /** Direction of projection line */
+ /** Direction of projection line. */
float proj_dir[3];
- /** seg+1 profile coordinates (triples of floats) */
+ /** seg+1 profile coordinates (triples of floats). */
float *prof_co;
- /** Like prof_co, but for seg power of 2 >= seg */
+ /** Like prof_co, but for seg power of 2 >= seg. */
float *prof_co_2;
/** Mark a special case so the these parameters aren't reset with others. */
bool special_params;
@@ -155,27 +156,29 @@ typedef struct Profile {
#define PRO_SQUARE_IN_R 0.0f
/**
- * The un-transformed 2D storage of profile vertex locations. Also for non-custom profiles
+ * The un-transformed 2D storage of profile vertex locations. Also, for non-custom profiles
* this serves as a cache for the results of the expensive calculation of u parameter values to
- * get even spacing on superellipse for current BevelParams seg
- * and pro_super_r.
+ * get even spacing on superellipse for current BevelParams seg and pro_super_r.
*/
typedef struct ProfileSpacing {
- /** The profile's seg+1 x values */
+ /** The profile's seg+1 x values. */
double *xvals;
- /** The profile's seg+1 y values */
+ /** The profile's seg+1 y values. */
double *yvals;
- /** The profile's seg_2+1 x values, (seg_2 = power of 2 >= seg) */
+ /** The profile's seg_2+1 x values, (seg_2 = power of 2 >= seg). */
double *xvals_2;
- /** The profile's seg_2+1 y values, (seg_2 = power of 2 >= seg) */
+ /** The profile's seg_2+1 y values, (seg_2 = power of 2 >= seg). */
double *yvals_2;
/** The power of two greater than or equal to the number of segments. */
int seg_2;
- /** How far "out" the profile is, used at the start of subdivision */
+ /** How far "out" the profile is, used at the start of subdivision. */
float fullness;
} ProfileSpacing;
-/** An element in a cyclic boundary of a Vertex Mesh (VMesh) */
+/**
+ * An element in a cyclic boundary of a Vertex Mesh (VMesh), placed on each side of beveled edges
+ * where each profile starts, or on each side of a miter.
+ */
typedef struct BoundVert {
/** In CCW order. */
struct BoundVert *next, *prev;
@@ -197,107 +200,107 @@ typedef struct BoundVert {
Profile profile;
/** Are any of the edges attached here seams? */
bool any_seam;
- /** Used during delta adjust pass */
+ /** Used during delta adjust pass. */
bool visited;
- /** This boundvert begins an arc profile */
+ /** This boundvert begins an arc profile. */
bool is_arc_start;
- /** This boundvert begins a patch profile */
+ /** This boundvert begins a patch profile. */
bool is_patch_start;
- /** Is this boundvert the side of the custom profile's start */
+ /** Is this boundvert the side of the custom profile's start. */
bool is_profile_start;
char _pad[3];
- /** Length of seam starting from current boundvert to next boundvert with ccw ordering */
+ /** Length of seam starting from current boundvert to next boundvert with ccw ordering. */
int seam_len;
- /** Same as seam_len but defines length of sharp edges */
+ /** Same as seam_len but defines length of sharp edges. */
int sharp_len;
} BoundVert;
-/** Mesh structure replacing a vertex */
+/** Data for the mesh structure replacing a vertex. */
typedef struct VMesh {
- /** Allocated array - size and structure depends on kind */
+ /** Allocated array - size and structure depends on kind. */
NewVert *mesh;
- /** Start of boundary double-linked list */
+ /** Start of boundary double-linked list. */
BoundVert *boundstart;
- /** Number of vertices in the boundary */
+ /** Number of vertices in the boundary. */
int count;
- /** Common number of segments for segmented edges (same as bp->seg) */
+ /** Common number of segments for segmented edges (same as bp->seg). */
int seg;
- /** The kind of mesh to build at the corner vertex meshes */
+ /** The kind of mesh to build at the corner vertex meshes. */
enum {
- M_NONE, /* no polygon mesh needed */
- M_POLY, /* a simple polygon */
- M_ADJ, /* "adjacent edges" mesh pattern */
- M_TRI_FAN, /* a simple polygon - fan filled */
- M_CUTOFF, /* A triangulated face at the end of each profile */
+ M_NONE, /* No polygon mesh needed. */
+ M_POLY, /* A simple polygon. */
+ M_ADJ, /* "Adjacent edges" mesh pattern. */
+ M_TRI_FAN, /* A simple polygon - fan filled. */
+ M_CUTOFF, /* A triangulated face at the end of each profile. */
} mesh_kind;
int _pad;
} VMesh;
-/* Data for a vertex involved in a bevel */
+/* Data for a vertex involved in a bevel. */
typedef struct BevVert {
- /** Original mesh vertex */
+ /** Original mesh vertex. */
BMVert *v;
- /** Total number of edges around the vertex (excluding wire edges if edge beveling) */
+ /** Total number of edges around the vertex (excluding wire edges if edge beveling). */
int edgecount;
- /** Number of selected edges around the vertex */
+ /** Number of selected edges around the vertex. */
int selcount;
- /** Count of wire edges */
+ /** Count of wire edges. */
int wirecount;
- /** Offset for this vertex, if vertex_only bevel */
+ /** Offset for this vertex, if vertex_only bevel. */
float offset;
/** Any seams on attached edges? */
bool any_seam;
- /** Used in graph traversal */
+ /** Used in graph traversal for adjusting offsets. */
bool visited;
- /** Array of size edgecount; CCW order from vertex normal side */
+ /** Array of size edgecount; CCW order from vertex normal side. */
char _pad[6];
EdgeHalf *edges;
- /** Array of size wirecount of wire edges */
+ /** Array of size wirecount of wire edges. */
BMEdge **wire_edges;
- /** Mesh structure for replacing vertex */
+ /** Mesh structure for replacing vertex. */
VMesh *vmesh;
} BevVert;
-/* Face classification. Note: depends on F_RECON > F_EDGE > F_VERT */
+/* Face classification. Note: depends on F_RECON > F_EDGE > F_VERT .*/
typedef enum {
- /** Used when there is no face at all */
+ /** Used when there is no face at all. */
F_NONE,
- /** Original face, not touched */
+ /** Original face, not touched. */
F_ORIG,
- /** Face for construction around a vert */
+ /** Face for construction around a vert. */
F_VERT,
- /** Face for a beveled edge */
+ /** Face for a beveled edge. */
F_EDGE,
- /** Reconstructed original face with some new verts */
+ /** Reconstructed original face with some new verts. */
F_RECON,
} FKind;
/** Helper for keeping track of angle kind. */
enum {
- /** Angle less than 180 degrees */
+ /** Angle less than 180 degrees. */
ANGLE_SMALLER = -1,
- /** 180 degree angle */
+ /** 180 degree angle. */
ANGLE_STRAIGHT = 0,
- /** Angle greater than 180 degrees */
+ /** Angle greater than 180 degrees. */
ANGLE_LARGER = 1,
};
-/** Bevel parameters and state */
+/** Bevel parameters and state. */
typedef struct BevelParams {
/** Records BevVerts made: key BMVert*, value BevVert* */
GHash *vert_hash;
- /** Records new faces: key BMFace*, value one of {VERT/EDGE/RECON}_POLY */
+ /** Records new faces: key BMFace*, value one of {VERT/EDGE/RECON}_POLY. */
GHash *face_hash;
- /** Use for all allocs while bevel runs, if we need to free we can switch to mempool. */
+ /** Use for all allocs while bevel runs. Note: If we need to free we can switch to mempool. */
MemArena *mem_arena;
- /** Profile vertex location and spacings */
+ /** Profile vertex location and spacings. */
ProfileSpacing pro_spacing;
- /** Parameter values for evenly spaced profile points for the miter profiles */
+ /** Parameter values for evenly spaced profile points for the miter profiles. */
ProfileSpacing pro_spacing_miter;
/** Blender units to offset each side of a beveled edge. */
float offset;
- /** How offset is measured; enum defined in bmesh_operators.h */
+ /** How offset is measured; enum defined in bmesh_operators.h. */
int offset_type;
/** Number of segments in beveled edge profile. */
int seg;
@@ -324,7 +327,7 @@ typedef struct BevelParams {
/** Should we use the custom profiles feature? */
bool use_custom_profile;
char _pad[3];
- /** The struct used to store the custom profile input */
+ /** The struct used to store the custom profile input. */
const struct CurveProfile *custom_profile;
/** Vertex group array, maybe set if vertex_only. */
const struct MDeformVert *dvert;
@@ -348,14 +351,14 @@ typedef struct BevelParams {
// #pragma GCC diagnostic ignored "-Wpadded"
-/* Only for debugging, shouldn't be in blender repo. */
+/* Only for debugging, this file shouldn't be in blender repo. */
// #include "bevdebug.c"
-/* use the unused _BM_ELEM_TAG_ALT flag to flag the 'long' loops (parallel to beveled edge)
+/* Use the unused _BM_ELEM_TAG_ALT flag to flag the 'long' loops (parallel to beveled edge)
* of edge-polygons. */
#define BM_ELEM_LONG_TAG (1 << 6)
-/* these flag values will get set on geom we want to return in 'out' slots for edges and verts */
+/* These flag values will get set on geom we want to return in 'out' slots for edges and verts. */
#define EDGE_OUT 4
#define VERT_OUT 8
@@ -404,7 +407,7 @@ static bool nearly_parallel(const float d1[3], const float d2[3])
return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
}
-/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
+/* Make a new BoundVert of the given kind, inserting it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
{
@@ -445,7 +448,7 @@ BLI_INLINE void adjust_bound_vert(BoundVert *bv, const float co[3])
* i = boundvert index (0 <= i < nv)
* j = ring index (0 <= j <= ns2)
* k = segment index (0 <= k <= ns)
- * Not all of these are used, and some will share BMVerts */
+ * Not all of these are used, and some will share BMVerts. */
static NewVert *mesh_vert(VMesh *vm, int i, int j, int k)
{
int nj = (vm->seg / 2) + 1;
@@ -472,7 +475,7 @@ static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, int ifrom, int
copy_v3_v3(nvto->co, nvfrom->co);
}
-/* find the EdgeHalf in bv's array that has edge bme */
+/* Find the EdgeHalf in bv's array that has edge bme. */
static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme)
{
int i;
@@ -485,15 +488,17 @@ static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme)
return NULL;
}
-/* find the BevVert corresponding to BMVert bmv */
+/* Find the BevVert corresponding to BMVert bmv. */
static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv)
{
return BLI_ghash_lookup(bp->vert_hash, bmv);
}
-/* Find the EdgeHalf representing the other end of e->e.
- * Return other end's BevVert in *bvother, if r_bvother is provided.
- * That may not have been constructed yet, in which case return NULL. */
+/**
+ * Find the EdgeHalf representing the other end of e->e.
+ * \return Return other end's BevVert in *r_bvother, if r_bvother is provided. That may not have
+ * been constructed yet, in which case return NULL.
+ */
static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert **r_bvother)
{
BevVert *bvo;
@@ -532,7 +537,7 @@ static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
return NULL;
}
-/* return count of edges between e1 and e2 when going around bv CCW */
+/* Return the count of edges between e1 and e2 when going around bv CCW. */
static int count_ccw_edges_between(EdgeHalf *e1, EdgeHalf *e2)
{
int cnt = 0;
@@ -564,11 +569,13 @@ static bool edges_face_connected_at_vert(BMEdge *bme1, BMEdge *bme2)
return false;
}
-/* Return a good representative face (for materials, etc.) for faces
+/**
+ * Return a good representative face (for materials, etc.) for faces
* created around/near BoundVert v.
* Sometimes care about a second choice, if there is one.
* If r_fother parameter is non-NULL and there is another, different,
- * possible frep, return the other one in that parameter. */
+ * possible frep, return the other one in that parameter.
+ */
static BMFace *boundvert_rep_face(BoundVert *v, BMFace **r_fother)
{
BMFace *frep, *frep2;
@@ -657,7 +664,7 @@ static BMFace *bev_create_ngon(BMesh *bm,
i = 0;
BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
if (face_arr) {
- /* assume loops of created face are in same order as verts */
+ /* Assume loops of created face are in same order as verts. */
BLI_assert(l->v == vert_arr[i]);
interp_f = face_arr[i];
}
@@ -683,8 +690,8 @@ static BMFace *bev_create_ngon(BMesh *bm,
}
}
- /* not essential for bevels own internal logic,
- * this is done so the operator can select newly created geometry */
+ /* Not essential for bevels own internal logic,
+ * this is done so the operator can select newly created geometry. */
if (f) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
BM_ITER_ELEM (bme, &iter, f, BM_EDGES_OF_FACE) {
@@ -832,7 +839,7 @@ static void bev_merge_uvs(BMesh *bm, BMVert *v)
}
/* Merge (using average) the UV values for two specific loops of v: those for faces containing v,
- * and part of faces that share edge bme */
+ * and part of faces that share edge bme. */
static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
{
BMIter iter;
@@ -876,7 +883,7 @@ static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
}
}
-/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */
+/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco. */
static void slide_dist(EdgeHalf *e, BMVert *v, float d, float r_slideco[3])
{
float dir[3], len;
@@ -890,7 +897,7 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float r_slideco[3])
madd_v3_v3fl(r_slideco, dir, -d);
}
-/* Is co not on the edge e? if not, return the closer end of e in ret_closer_v */
+/* Is co not on the edge e? If not, return the closer end of e in ret_closer_v. */
static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_v)
{
float h[3], u[3], lambda, lenu, *l1 = e->e->v1->co;
@@ -912,7 +919,7 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
}
}
-/* Return -1, 0, or 1 as angle from e1 to e2 is <. =, or > 180 degrees */
+/* Return whether the angle is less than, equal to, or larger than 180 degrees. */
static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
{
BMVert *v1, *v2;
@@ -924,7 +931,7 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
sub_v3_v3v3(dir2, v->co, v2->co);
normalize_v3(dir1);
normalize_v3(dir2);
- /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
+ /* Angles are in [0,pi]. Need to compare cross product with normal to see if they are reflex. */
cross_v3_v3v3(cross, dir1, dir2);
normalize_v3(cross);
if (e1->fnext) {
@@ -948,9 +955,8 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
}
}
-/* co should be approximately on the plane between e1 and e2, which share common vert v
- * and common face f (which cannot be NULL).
- * Is it between those edges, sweeping CCW? */
+/* co should be approximately on the plane between e1 and e2, which share common vert v and common
+ * face f (which cannot be NULL). Is it between those edges, sweeping CCW? */
static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, EdgeHalf *e2)
{
BMVert *v1, *v2;
@@ -967,7 +973,7 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1,
normalize_v3(dirco);
ang11 = angle_normalized_v3v3(dir1, dir2);
ang1co = angle_normalized_v3v3(dir1, dirco);
- /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
+ /* Angles are in [0,pi]. Need to compare cross product with normal to see if they are reflex. */
cross_v3_v3v3(no, dir1, dir2);
if (dot_v3v3(no, f->no) < 0.0f) {
ang11 = (float)(M_PI * 2.0) - ang11;
@@ -1039,7 +1045,7 @@ static void offset_meet(EdgeHalf *e1,
* so use the average of the two, and the offset formula for angle bisector.
* If offsets are different, we're out of luck:
* Use the max of the two (so get consistent looking results if the same situation
- * arises elsewhere in the object but with opposite roles for e1 and e2 */
+ * arises elsewhere in the object but with opposite roles for e1 and e2. */
if (f) {
copy_v3_v3(norm_v, f->no);
}
@@ -1066,8 +1072,8 @@ static void offset_meet(EdgeHalf *e1,
* in case f is non-planar.
* Except: sometimes locally there can be a small angle between dir1 and dir2 that leads
* to a normal that is actually almost perpendicular to the face normal;
- * in this case it looks wrong to use the local (cross-product) normal,
- * so use the face normal if the angle between dir1 and dir2 is smallish.
+ * in this case it looks wrong to use the local (cross-product) normal, so use the face normal
+ * if the angle between dir1 and dir2 is smallish.
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
* Use f->no to figure out which side to look at angle from, as even if f is non-planar,
* will be more accurate than vertex normal. */
@@ -1121,7 +1127,7 @@ static void offset_meet(EdgeHalf *e1,
}
else {
/* The lines intersect, but is it at a reasonable place?
- * One problem to check: if one of the offsets is 0, then don't want an intersection
+ * One problem to check: if one of the offsets is 0, then we don't want an intersection
* that is outside that edge itself. This can happen if angle between them is > 180 degrees,
* or if the offset amount is > the edge length. */
if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
@@ -1163,11 +1169,13 @@ static void offset_meet(EdgeHalf *e1,
/* Chosen so 1/sin(BEVEL_GOOD_ANGLE) is about 4, giving that expansion factor to bevel width. */
#define BEVEL_GOOD_ANGLE 0.25f
-/* Calculate the meeting point between e1 and e2 (one of which should have zero offsets),
+/**
+ * Calculate the meeting point between e1 and e2 (one of which should have zero offsets),
* where e1 precedes e2 in CCW order around their common vertex v (viewed from normal side).
* If r_angle is provided, return the angle between e and emeet in *r_angle.
* If the angle is 0, or it is 180 degrees or larger, there will be no meeting point;
- * return false in that case, else true. */
+ * return false in that case, else true.
+ */
static bool offset_meet_edge(
EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetco[3], float *r_angle)
{
@@ -1214,8 +1222,10 @@ static bool offset_meet_edge(
return true;
}
-/* Return true if it will look good to put the meeting point where offset_on_edge_between
- * would put it. This means that neither side sees a reflex angle. */
+/**
+ * Return true if it will look good to put the meeting point where offset_on_edge_between
+ * would put it. This means that neither side sees a reflex angle.
+ */
static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v)
{
float ang;
@@ -1224,11 +1234,12 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em
return offset_meet_edge(e1, emid, v, meet, &ang) && offset_meet_edge(emid, e2, v, meet, &ang);
}
-/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
- * on the in-between edge emid. Viewed from the vertex normal side, the CCW
- * order of these edges is e1, emid, e2.
- * Return true if we placed meetco as compromise between where two edges met.
- * If we did, put ration of sines of angles in *r_sinratio too */
+/**
+ * Calculate the best place for a meeting point for the offsets from edges e1 and e2 on the
+ * in-between edge emid. Viewed from the vertex normal side, the CCW order of these edges is e1,
+ * emid, e2. Return true if we placed meetco as compromise between where two edges met. If we did,
+ * put the ratio of sines of angles in *r_sinratio too.
+ */
static bool offset_on_edge_between(
EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio)
{
@@ -1264,9 +1275,9 @@ static bool offset_on_edge_between(
return retval;
}
-/* Offset by e->offset in plane with normal plane_no, on left if left==true,
- * else on right. If no is NULL, choose an arbitrary plane different from eh's direction. */
-static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, float r[3])
+/* Offset by e->offset in plane with normal plane_no, on left if left==true, else on right.
+ * If plane_no is NULL, choose an arbitrary plane different from eh's direction. */
+static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, float r_co[3])
{
float dir[3], no[3], fdir[3];
BMVert *v;
@@ -1294,8 +1305,8 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, flo
cross_v3_v3v3(fdir, no, dir);
}
normalize_v3(fdir);
- copy_v3_v3(r, v->co);
- madd_v3_v3fl(r, fdir, left ? e->offset_l : e->offset_r);
+ copy_v3_v3(r_co, v->co);
+ madd_v3_v3fl(r_co, fdir, left ? e->offset_l : e->offset_r);
}
/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco. */
@@ -1328,7 +1339,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
if (e) {
do_linear_interp = false;
pro->super_r = bp->pro_super_r;
- /* projection direction is direction of the edge. */
+ /* Projection direction is direction of the edge. */
sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
if (e->is_rev) {
negate_v3(pro->proj_dir);
@@ -1346,14 +1357,13 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
/* Start - middle - end are collinear.
- * Should be case that beveled edge is coplanar with two boundary verts.
+ * It should be the case that beveled edge is coplanar with two boundary verts.
* We want to move the profile to that common plane, if possible.
* That makes the multi-segment bevels curve nicely in that plane, as users expect.
* The new middle should be either v (when neighbor edges are unbeveled)
* or the intersection of the offset lines (if they are).
* If the profile is going to lead into unbeveled edges on each side
- * (that is, both BoundVerts are "on-edge" points on non-beveled edges)
- */
+ * (that is, both BoundVerts are "on-edge" points on non-beveled edges). */
copy_v3_v3(pro->middle, bv->v->co);
if (e->prev->is_bev && e->next->is_bev && bv->selcount >= 3) {
/* Want mid at the meet point of next and prev offset edges. */
@@ -1434,17 +1444,19 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
}
-/* Maybe move the profile plane for bndv->ebev to the plane its profile's start, and the
+/**
+ * Maybe move the profile plane for bndv->ebev to the plane its profile's start, and the
* original beveled vert, bmv. This will usually be the plane containing its adjacent
* non-beveled edges, but sometimes the start and the end are not on those edges.
*
- * Currently just used in #build_boundary_terminal_edge */
+ * Currently just used in #build_boundary_terminal_edge.
+ */
static void move_profile_plane(BoundVert *bndv, BMVert *bmvert)
{
float d1[3], d2[3], no[3], no2[3], no3[3], dot2, dot3;
Profile *pro = &bndv->profile;
- /* only do this if projecting, and start, end, and proj_dir are not coplanar */
+ /* Only do this if projecting, and start, end, and proj_dir are not coplanar. */
if (is_zero_v3(pro->proj_dir)) {
return;
}
@@ -1468,16 +1480,18 @@ static void move_profile_plane(BoundVert *bndv, BMVert *bmvert)
pro->special_params = true;
}
-/* Move the profile plane for the two BoundVerts involved in a weld.
+/**
+ * Move the profile plane for the two BoundVerts involved in a weld.
* We want the plane that is most likely to have the intersections of the
- * two edges' profile projections on it. bndv1 and bndv2 are by
- * construction the intersection points of the outside parts of the profiles.
- * The original vertex should form a third point of the desired plane. */
+ * two edges' profile projections on it. bndv1 and bndv2 are by construction the
+ * intersection points of the outside parts of the profiles.
+ * The original vertex should form a third point of the desired plane.
+ */
static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *bndv2)
{
float d1[3], d2[3], no[3], no2[3], no3[3], dot1, dot2, l1, l2, l3;
- /* only do this if projecting, and d1, d2, and proj_dir are not coplanar */
+ /* Only do this if projecting, and d1, d2, and proj_dir are not coplanar. */
if (is_zero_v3(bndv1->profile.proj_dir) || is_zero_v3(bndv2->profile.proj_dir)) {
return;
}
@@ -1485,8 +1499,8 @@ static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *b
sub_v3_v3v3(d2, bv->v->co, bndv2->nv.co);
cross_v3_v3v3(no, d1, d2);
l1 = normalize_v3(no);
- /* "no" is new normal projection plane, but don't move if
- * it is coplanar with both of the projection dirs */
+ /* "no" is new normal projection plane, but don't move if it is coplanar with both of the
+ * projection dirs. */
cross_v3_v3v3(no2, d1, bndv1->profile.proj_dir);
l2 = normalize_v3(no2);
cross_v3_v3v3(no3, d2, bndv2->profile.proj_dir);
@@ -1507,8 +1521,8 @@ static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *b
bndv2->profile.special_params = true;
}
-/* return 1 if a and b are in CCW order on the normal side of f,
- * and -1 if they are reversed, and 0 if there is no shared face f */
+/* Return 1 if a and b are in CCW order on the normal side of f,
+ * and -1 if they are reversed, and 0 if there is no shared face f. */
static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
{
BMLoop *la, *lb;
@@ -1524,10 +1538,11 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
return lb->next == la ? 1 : -1;
}
-/* Fill matrix r_mat so that a point in the sheared parallelogram with corners
+/**
+ * Fill matrix r_mat so that a point in the sheared parallelogram with corners
* va, vmid, vb (and the 4th that is implied by it being a parallelogram)
* is the result of transforming the unit square by multiplication with r_mat.
- * If it can't be done because the parallelogram is degenerate, return false
+ * If it can't be done because the parallelogram is degenerate, return false,
* else return true.
* Method:
* Find vo, the origin of the parallelogram with other three points va, vmid, vb.
@@ -1568,7 +1583,7 @@ static bool make_unit_square_map(const float va[3],
add_v3_v3v3(vd, vo, vddir);
/* The cols of m are: {vmid - va, vmid - vb, vmid + vd - va -vb, va + vb - vmid;
- * blender transform matrices are stored such that m[i][*] is ith column;
+ * Blender transform matrices are stored such that m[i][*] is ith column;
* the last elements of each col remain as they are in unity matrix. */
sub_v3_v3v3(&r_mat[0][0], vmid, va);
r_mat[0][3] = 0.0f;
@@ -1585,7 +1600,8 @@ static bool make_unit_square_map(const float va[3],
return true;
}
-/* Like make_unit_square_map, but this one makes a matrix that transforms the
+/**
+ * Like make_unit_square_map, but this one makes a matrix that transforms the
* (1,1,1) corner of a unit cube into an arbitrary corner with corner vert d
* and verts around it a, b, c (in ccw order, viewed from d normal dir).
* The matrix mat is calculated to map:
@@ -1629,10 +1645,12 @@ static void make_unit_cube_map(
r_mat[3][3] = 1.0f;
}
-/* Get the coordinate on the superellipse (x^r + y^r = 1),
- * at parameter value x (or, if !rbig, mirrored (y=x)-line).
+/**
+ * Get the coordinate on the superellipse (x^r + y^r = 1), at parameter value x
+ * (or, if !rbig, mirrored (y=x)-line).
* rbig should be true if r > 1.0 and false if <= 1.0.
- * Assume r > 0.0 */
+ * Assume r > 0.0.
+ */
static double superellipse_co(double x, float r, bool rbig)
{
BLI_assert(r > 0.0f);
@@ -1647,13 +1665,15 @@ static double superellipse_co(double x, float r, bool rbig)
}
}
-/* Find the point on given profile at parameter i which goes from 0 to n as
- * the profile is moved from pro->start to pro->end.
- * We assume that n is either the global seg number or a power of 2 less than
+/**
+ * Find the point on given profile at parameter i which goes from 0 to nseg as
+ * the profile moves from pro->start to pro->end.
+ * We assume that nseg is either the global seg number or a power of 2 less than
* or equal to the power of 2 >= seg.
* In the latter case, we subsample the profile for seg_2, which will not necessarily
* give equal spaced chords, but is in fact more what is desired by the cubic subdivision
- * method used to make the vmesh pattern. */
+ * method used to make the vmesh pattern.
+ */
static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int nseg, float r_co[3])
{
int subsample_spacing;
@@ -1674,20 +1694,21 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int ns
}
else {
BLI_assert(is_power_of_2_i(nseg) && nseg <= bp->pro_spacing.seg_2);
- /* Find spacing between subsamples in prof_co_2 */
+ /* Find spacing between subsamples in prof_co_2. */
subsample_spacing = bp->pro_spacing.seg_2 / nseg;
copy_v3_v3(r_co, pro->prof_co_2 + 3 * i * subsample_spacing);
}
}
}
-/* Calculate the actual coordinate values for bndv's profile.
+/**
+ * Calculate the actual coordinate values for bndv's profile.
* This is only needed if bp->seg > 1.
* Allocate the space for them if that hasn't been done already.
* If bp->seg is not a power of 2, also need to calculate
- * the coordinate values for the power of 2 >= bp->seg,
- * because the ADJ pattern needs power-of-2 boundaries
- * during construction. */
+ * the coordinate values for the power of 2 >= bp->seg, because the ADJ pattern needs power-of-2
+ * boundaries during construction.
+ */
static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, bool miter)
{
int i, k, ns;
@@ -1735,7 +1756,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
pro->height = len_v3v3(bottom_corner, top_corner);
}
- /* The first iteration is the nseg case, the second is the seg_2 case (if it's needed) */
+ /* The first iteration is the nseg case, the second is the seg_2 case (if it's needed) .*/
for (i = 0; i < 2; i++) {
if (i == 0) {
ns = bp->seg;
@@ -1745,7 +1766,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
}
else {
if (!need_2) {
- break; /* shares coords with pro->prof_co */
+ break; /* Shares coords with pro->prof_co. */
}
ns = bp->pro_spacing.seg_2;
xvals = pro_spacing->xvals_2;
@@ -1753,7 +1774,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
prof_co = pro->prof_co_2;
}
- /* Iterate over the vertices along the boundary arc */
+ /* Iterate over the vertices along the boundary arc. */
for (k = 0; k <= ns; k++) {
if (k == 0) {
copy_v3_v3(co, pro->start);
@@ -1772,20 +1793,20 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
p[1] = (float)yvals[k];
}
p[2] = 0.0f;
- /* Do the 2D->3D transformation of the profile coordinates */
+ /* Do the 2D->3D transformation of the profile coordinates. */
mul_v3_m4v3(co, map, p);
}
else {
interp_v3_v3v3(co, pro->start, pro->end, (float)k / (float)ns);
}
}
- /* Finish the 2D->3D transformation by projecting onto the final profile plane */
- prof_co_k = prof_co + 3 * k; /* Each coord takes up 3 spaces */
+ /* Finish the 2D->3D transformation by projecting onto the final profile plane. */
+ prof_co_k = prof_co + 3 * k; /* Each coord takes up 3 spaces. */
if (!is_zero_v3(pro->proj_dir)) {
add_v3_v3v3(co2, co, pro->proj_dir);
- /* pro->plane_co and pro->plane_no are filled in "set_profile_params" */
+ /* pro->plane_co and pro->plane_no are filled in "set_profile_params". */
if (!isect_line_plane_v3(prof_co_k, co, co2, pro->plane_co, pro->plane_no)) {
- /* shouldn't happen */
+ /* Shouldn't happen. */
copy_v3_v3(prof_co_k, co);
}
}
@@ -1796,10 +1817,12 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
}
}
-/* Snap a direction co to a superellipsoid with parameter super_r.
+/**
+ * Snap a direction co to a superellipsoid with parameter super_r.
* For square profiles, midline says whether or not to snap to both planes.
*
- * Only currently used for the pipe and cube corner special cases */
+ * Only currently used for the pipe and cube corner special cases.
+ */
static void snap_to_superellipsoid(float co[3], const float super_r, bool midline)
{
float a, b, c, x, y, z, r, rinv, dx, dy;
@@ -1813,13 +1836,13 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
y = b = max_ff(0.0f, co[1]);
z = c = max_ff(0.0f, co[2]);
if (r == PRO_SQUARE_R || r == PRO_SQUARE_IN_R) {
- /* will only be called for 2d profile */
+ /* Will only be called for 2d profile. */
BLI_assert(fabsf(z) < BEVEL_EPSILON);
z = 0.0f;
x = min_ff(1.0f, x);
y = min_ff(1.0f, y);
if (r == PRO_SQUARE_R) {
- /* snap to closer of x==1 and y==1 lines, or maybe both */
+ /* Snap to closer of x==1 and y==1 lines, or maybe both. */
dx = 1.0f - x;
dy = 1.0f - y;
if (dx < dy) {
@@ -1832,7 +1855,7 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
}
}
else {
- /* snap to closer of x==0 and y==0 lines, or maybe both */
+ /* Snap to closer of x==0 and y==0 lines, or maybe both. */
if (x < y) {
x = 0.0f;
y = midline ? 0.0f : y;
@@ -1874,7 +1897,7 @@ static void check_edge_data_seam_sharp_edges(BevVert *bv, int flag, bool neg)
{
EdgeHalf *e = &bv->edges[0], *efirst = &bv->edges[0];
- /* First first edge with seam or sharp edge data */
+ /* First first edge with seam or sharp edge data. */
while ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) ||
(neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
e = e->next;
@@ -1883,7 +1906,7 @@ static void check_edge_data_seam_sharp_edges(BevVert *bv, int flag, bool neg)
}
}
- /* If no such edge found, return */
+ /* If no such edge found, return. */
if ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) ||
(neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
return;
@@ -1908,7 +1931,7 @@ static void check_edge_data_seam_sharp_edges(BevVert *bv, int flag, bool neg)
(neg && BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag))))) {
break;
}
- /* Set seam_len / sharp_len of starting edge */
+ /* Set seam_len / sharp_len of starting edge. */
if (flag == BM_ELEM_SEAM) {
e->rightv->seam_len = flag_count;
}
@@ -1930,15 +1953,15 @@ static void bevel_extend_edge_data(BevVert *bv)
BoundVert *bcur = bv->vmesh->boundstart, *start = bcur;
do {
- /* If current boundvert has a seam length > 0 then it has a seam running along its edges */
+ /* If current boundvert has a seam length > 0 then it has a seam running along its edges. */
if (bcur->seam_len) {
if (!bv->vmesh->boundstart->seam_len && start == bv->vmesh->boundstart) {
- start = bcur; /* set start to first boundvert with seam_len > 0 */
+ start = bcur; /* Set start to first boundvert with seam_len > 0. */
}
/* Now for all the mesh_verts starting at current index and ending at idxlen
- * We go through outermost ring and through all its segments and add seams
- * for those edges */
+ * we go through outermost ring and through all its segments and add seams
+ * for those edges. */
int idxlen = bcur->index + bcur->seam_len;
for (int i = bcur->index; i < idxlen; i++) {
BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
@@ -1961,7 +1984,7 @@ static void bevel_extend_edge_data(BevVert *bv)
v1 = v2;
}
BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
- e = v1->e; // Do same as above for first and last vert
+ e = v1->e; /* Do same as above for first and last vert. */
while (e->v1 != v3 && e->v2 != v3) {
if (e->v1 == v1) {
e = e->v1_disk_link.next;
@@ -2042,7 +2065,7 @@ static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
continue;
}
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- /* cases we care about will have exactly one adjacent face */
+ /* Cases we care about will have exactly one adjacent face. */
lother = l->radial_next;
fother = lother->f;
if (lother != l && fother) {
@@ -2056,8 +2079,9 @@ static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
}
/**
- * Harden normals for bevel.
- * The desired effect is that the newly created #F_EDGE and F_VERT faces appear smoothly shaded
+ * \brief Harden normals for bevel.
+ *
+ * The desired effect is that the newly created #F_EDGE and #F_VERT faces appear smoothly shaded
* with the normals at the boundaries with #F_RECON faces matching those recon faces.
* And at boundaries between #F_EDGE and #F_VERT faces, the normals should match the #F_EDGE ones.
* Assumes custom loop normals are in use.
@@ -2077,24 +2101,23 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
return;
}
- /* recalculate all face and vertex normals; side effect: ensures vertex, edge, face indices */
- /* I suspect this is not necessary: TODO: test that guess */
+ /* Recalculate all face and vertex normals. Side effect: ensures vertex, edge, face indices. */
+ /* I suspect this is not necessary. TODO: test that guess. */
BM_mesh_normals_update(bm);
cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
/* If there is not already a custom split normal layer then making one (with BM_lnorspace_update)
* will not respect the autosmooth angle between smooth faces. To get that to happen, we have
- * to mark the sharpen the edges that are only sharp because
- * of the angle test -- otherwise would be smooth.
- */
+ * to mark the sharpen the edges that are only sharp because of the angle test -- otherwise would
+ * be smooth. */
if (cd_clnors_offset == -1) {
BM_edges_sharp_from_angle_set(bm, bp->smoothresh);
bevel_edges_sharp_boundary(bm, bp);
}
- /* Ensure that bm->lnor_spacearr has properly stored loop normals;
- * side effect: ensures loop indices. */
+ /* Ensure that bm->lnor_spacearr has properly stored loop normals.
+ * Side effect: ensures loop indices. */
BM_lnorspace_update(bm);
if (cd_clnors_offset == -1) {
@@ -2107,9 +2130,9 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
continue;
}
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- estep = l->prev->e; /* causes CW walk around l->v fan */
+ estep = l->prev->e; /* Causes CW walk around l->v fan. */
lprev = BM_vert_step_fan_loop(l, &estep);
- estep = l->e; /* causes CCW walk around l->v fan */
+ estep = l->e; /* Causes CCW walk around l->v fan. */
lnext = BM_vert_step_fan_loop(l, &estep);
fprevkind = lprev ? get_face_kind(bp, lprev->f) : F_NONE;
fnextkind = lnext ? get_face_kind(bp, lnext->f) : F_NONE;
@@ -2236,7 +2259,7 @@ static void bevel_set_weighted_normal_face_strength(BMesh *bm, BevelParams *bp)
}
}
-/* Set the any_seam property for a BevVert and all its BoundVerts */
+/* Set the any_seam property for a BevVert and all its BoundVerts. */
static void set_bound_vert_seams(BevVert *bv, bool mark_seam, bool mark_sharp)
{
BoundVert *v;
@@ -2294,7 +2317,12 @@ static bool eh_on_plane(EdgeHalf *e)
return false;
}
-/* Calculate the profiles for all the BoundVerts of VMesh vm */
+/**
+ * Calculate the profiles for all the BoundVerts of VMesh vm.
+ *
+ * \note This should only be called once for each BevVert, after all changes have been made to the
+ * profile's parameters.
+ */
static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
{
BoundVert *bndv = vm->boundstart;
@@ -2315,7 +2343,7 @@ static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
} while ((bndv = bndv->next) != vm->boundstart);
}
-/* Implements build_boundary for vertex-only case */
+/* Implements build_boundary for the vertex-only case. */
static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool construct)
{
VMesh *vm = bv->vmesh;
@@ -2372,7 +2400,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
e = efirst;
if (bv->edgecount == 2) {
- /* only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge */
+ /* Only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge. */
no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
offset_in_plane(e, no, true, co);
if (construct) {
@@ -2393,7 +2421,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
else {
adjust_bound_vert(e->rightv, co);
}
- /* make artificial extra point along unbeveled edge, and form triangle */
+ /* Make artificial extra point along unbeveled edge, and form triangle. */
slide_dist(e->next, bv->v, e->offset_l, co);
if (construct) {
bndv = add_new_bound_vert(mem_arena, vm, co);
@@ -2406,9 +2434,9 @@ static void build_boundary_terminal_edge(BevelParams *bp,
}
}
else {
- /* More than 2 edges in. Put on-edge verts on all the other edges
- * and join with the beveled edge to make a poly or adj mesh,
- * Because e->prev has offset 0, offset_meet will put co on that edge. */
+ /* More than 2 edges in. Put on-edge verts on all the other edges and join with the beveled
+ * edge to make a poly or adj mesh, because e->prev has offset 0, offset_meet will put co on
+ * that edge. */
/* TODO: should do something else if angle between e and e->prev > 180 */
offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
@@ -2468,11 +2496,11 @@ static void build_boundary_terminal_edge(BevelParams *bp,
else if (vm->count == 3) {
use_tri_fan = true;
if (bp->use_custom_profile) {
- /* Use M_POLY if the extra point is planar with the profile to prevent overhanging edges */
+ /* Prevent overhanging edges: use M_POLY if the extra point is planar with the profile. */
bndv = efirst->leftv;
float profile_plane[4];
plane_from_point_normal_v3(profile_plane, bndv->profile.plane_co, bndv->profile.plane_no);
- bndv = efirst->rightv->next; /* The added boundvert placed along the non-adjacent edge */
+ bndv = efirst->rightv->next; /* The added boundvert placed along the non-adjacent edge. */
if (dist_squared_to_plane_v3(bndv->nv.co, profile_plane) < BEVEL_EPSILON_BIG) {
use_tri_fan = false;
}
@@ -2485,7 +2513,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
}
}
-/* Helper for build_boundary to handle special miters */
+/* Helper for build_boundary to handle special miters. */
static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
{
float co1[3], co2[3], co3[3], edge_dir[3], line_p[3];
@@ -2512,19 +2540,19 @@ static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
}
/* co1 is intersection of line through co2 in dir of emiter->e
- * and plane with normal the dir of emiter->e and through v1prev */
+ * and plane with normal the dir of emiter->e and through v1prev. */
vother = BM_edge_other_vert(emiter->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
normalize_v3(edge_dir);
- float d = bp->offset / (bp->seg / 2.0f); /* a fallback amount to move */
+ float d = bp->offset / (bp->seg / 2.0f); /* A fallback amount to move. */
madd_v3_v3v3fl(line_p, co2, edge_dir, d);
if (!isect_line_plane_v3(co1, co2, line_p, v1prev->nv.co, edge_dir)) {
copy_v3_v3(co1, line_p);
}
adjust_bound_vert(v1, co1);
- /* co3 is similar, but plane is through v3next and line is other side of miter edge */
- emiter_other = v3->elast; /*v3->efirst;*/
+ /* co3 is similar, but plane is through v3next and line is other side of miter edge. */
+ emiter_other = v3->elast;
vother = BM_edge_other_vert(emiter_other->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
normalize_v3(edge_dir);
@@ -2659,7 +2687,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else {
- /* n_in_plane > 0 and n_not_in_plane == 0 */
+ /* n_in_plane > 0 and n_not_in_plane == 0. */
if (bp->loop_slide && in_plane == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) {
eon = eip;
@@ -2687,7 +2715,6 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
ang_kind = edges_angle_kind(e, e2, bv->v);
/* Are we doing special mitering?
- * ang_kind is -1, 0, 1 as angle is <, =, > 180 degrees.
* There can only be one outer reflex angle, so only one outer miter,
* and emiter will be set to the first edge of such an edge.
* A miter kind of BEVEL_MITER_SHARP means no special miter */
@@ -2696,7 +2723,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
if (ang_kind == ANGLE_LARGER) {
emiter = e;
}
- /* make one or two more boundverts; for now all will have same co */
+ /* Make one or two more boundverts; for now all will have same co. */
v1 = v;
v1->ebev = NULL;
if (ang_kind == ANGLE_LARGER && miter_outer == BEVEL_MITER_PATCH) {
@@ -2743,7 +2770,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
bool betodd = (between % 2) == 1;
int i = 0;
/* Put first half of in-between edges at index 0, second half at index bp->seg.
- * If between is odd, put middle one at midindex */
+ * If between is odd, put middle one at midindex. */
for (e3 = e->next; e3 != e2; e3 = e3->next) {
v1->elast = e3;
if (i < bet2) {
@@ -2761,7 +2788,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
}
- else { /* construct == false */
+ else { /* construct == false. */
ang_kind = edges_angle_kind(e, e2, bv->v);
if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == ANGLE_LARGER) ||
(miter_inner != BEVEL_MITER_SHARP && ang_kind == ANGLE_SMALLER)) {
@@ -2960,7 +2987,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
if (iscycle) {
gprod *= g[0];
if (fabs(gprod - 1.0f) > BEVEL_EPSILON) {
- /* fast cycle calc only works if total product is 1 */
+ /* Fast cycle calc only works if total product is 1. */
MEM_freeN(g);
MEM_freeN(g_prod);
return false;
@@ -2973,7 +3000,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
}
p = spec_sum / gprod_sum;
- /* apply the new offsets */
+ /* Apply the new offsets. */
v = vstart;
i = 0;
do {
@@ -2986,7 +3013,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
}
}
else {
- /* not a cycle, and last of chain */
+ /* Not a cycle, and last of chain. */
eleft = v->elast;
eleft->offset_l = p;
}
@@ -3067,7 +3094,7 @@ static EdgeHalf *next_edgehalf_bev(BevelParams *bp,
}
normalize_v3(dir_new_edge);
- /* Use this edge if it is the most parallel to the orignial so far */
+ /* Use this edge if it is the most parallel to the orignial so far. */
new_dot = dot_v3v3(dir_new_edge, dir_start_edge);
if (new_dot > best_dot) {
second_best_dot = best_dot; /* For remembering if the choice was too close. */
@@ -3149,7 +3176,8 @@ static void regularize_profile_orientation(BevelParams *bp, BMEdge *bme)
}
}
-/* Adjust the offsets for a single cycle or chain.
+/**
+ * Adjust the offsets for a single cycle or chain.
* For chains and some cycles, a fast solution exists.
* Otherwise, we set up and solve a linear least squares problem
* that tries to minimize the squared differences of lengths
@@ -3194,9 +3222,9 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
v = vstart;
i = 0;
- weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */
+ weight = BEVEL_MATCH_SPEC_WEIGHT; /* Sqrt of factor to weight down importance of spec match. */
do {
- /* except at end of chain, v's indep variable is offset_r of v->efirst */
+ /* Except at end of chain, v's indep variable is offset_r of v->efirst. */
if (iscycle || i < np - 1) {
eright = v->efirst;
eleft = v->elast;
@@ -3211,7 +3239,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
}
#endif
- /* residue i: width difference between eright and eleft of next */
+ /* Residue i: width difference between eright and eleft of next. */
EIG_linear_solver_matrix_add(solver, i, i, 1.0);
EIG_linear_solver_right_hand_side_add(solver, 0, i, 0.0);
if (iscycle) {
@@ -3223,8 +3251,8 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
}
}
- /* residue np + 2*i (if cycle) else np - 1 + 2*i:
- * right offset for parm i matches its spec; weighted */
+ /* Residue np + 2*i (if cycle) else np - 1 + 2*i:
+ * right offset for parm i matches its spec; weighted. */
row = iscycle ? np + 2 * i : np - 1 + 2 * i;
EIG_linear_solver_matrix_add(solver, row, i, weight);
EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r);
@@ -3236,8 +3264,8 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
BM_elem_index_get(eright->e));
#endif
- /* residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1:
- * left offset for parm i matches its spec; weighted */
+ /* Residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1:
+ * left offset for parm i matches its spec; weighted. */
row = row + 1;
EIG_linear_solver_matrix_add(
solver, row, (i == np - 1) ? 0 : i + 1, weight * v->adjchain->sinratio);
@@ -3251,12 +3279,12 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
#endif
}
else {
- /* not a cycle, and last of chain */
+ /* Not a cycle, and last of chain. */
eleft = v->elast;
#ifdef DEBUG_ADJUST
printf("p%d: e%d->offset_l = %f\n", i, BM_elem_index_get(eleft->e), eleft->offset_l);
#endif
- /* second part of residue i for last i */
+ /* Second part of residue i for last i. */
EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0);
}
i++;
@@ -3264,7 +3292,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
} while (v && v != vstart);
EIG_linear_solver_solve(solver);
#ifdef DEBUG_ADJUST
- /* Note: this print only works after solve, but by that time b has been cleared */
+ /* Note: this print only works after solve, but by that time b has been cleared. */
EIG_linear_solver_print_matrix(solver);
printf("\nSolution:\n");
for (i = 0; i < np; i++) {
@@ -3272,7 +3300,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
}
#endif
- /* Use the solution to set new widths */
+ /* Use the solution to set new widths. */
v = vstart;
i = 0;
do {
@@ -3292,7 +3320,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
}
}
else {
- /* not a cycle, and last of chain */
+ /* Not a cycle, and last of chain. */
eleft = v->elast;
eleft->offset_l = (float)val;
#ifdef DEBUG_ADJUST
@@ -3311,7 +3339,8 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
EIG_linear_solver_delete(solver);
}
-/* Adjust the offsets to try to make them, as much as possible,
+/**
+ * Adjust the offsets to try to make them, as much as possible,
* have even-width bevels with offsets that match their specs.
* The problem that we can try to ameliorate is that when loop slide
* is active, the meet point will probably not be the one that makes
@@ -3331,8 +3360,8 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
bool iscycle;
int chainlen;
- /* find and process chains and cycles of unvisited BoundVerts that have eon set */
- /* note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts */
+ /* Find and process chains and cycles of unvisited BoundVerts that have eon set. */
+ /* Note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts. */
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
continue;
@@ -3357,7 +3386,7 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
* them in left->right direction, meaning that the left side of one edge
* pairs with the right side of the next edge in the cycle or chain. */
- /* first follow paired edges in left->right direction */
+ /* First follow paired edges in left->right direction. */
v = vchainstart = vchainend = vanchor;
iscycle = false;
chainlen = 1;
@@ -3385,7 +3414,7 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
v = vnext;
}
if (!iscycle) {
- /* right->left direction, changing vchainstart at each step */
+ /* right->left direction, changing vchainstart at each step. */
v->adjchain = NULL;
v = vchainstart;
bvcur = bv;
@@ -3411,7 +3440,7 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
} while ((vanchor = vanchor->next) != bv->vmesh->boundstart);
}
- /* Rebuild boundaries with new width specs */
+ /* Rebuild boundaries with new width specs. */
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
bv = find_bevvert(bp, bmv);
@@ -3422,13 +3451,15 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
}
}
-/* Do the edges at bv form a "pipe"?
+/**
+ * Do the edges at bv form a "pipe"?
* Current definition: 3 or 4 beveled edges, 2 in line with each other,
* with other edges on opposite sides of the pipe if there are 4.
* Also, the vertex boundary should have 3 or 4 vertices in it,
* and all of the faces involved should be parallel to the pipe edges.
* Return the boundary vert whose ebev is one of the pipe edges, and
- * whose next boundary vert has a beveled, non-pipe edge. */
+ * whose next boundary vert has a beveled, non-pipe edge.
+ */
static BoundVert *pipe_test(BevVert *bv)
{
EdgeHalf *e, *epipe;
@@ -3441,7 +3472,7 @@ static BoundVert *pipe_test(BevVert *bv)
return NULL;
}
- /* find v1, v2, v3 all with beveled edges, where v1 and v3 have collinear edges */
+ /* Find v1, v2, v3 all with beveled edges, where v1 and v3 have collinear edges. */
epipe = NULL;
v1 = vm->boundstart;
do {
@@ -3463,7 +3494,7 @@ static BoundVert *pipe_test(BevVert *bv)
return NULL;
}
- /* check face planes: all should have normals perpendicular to epipe */
+ /* Check face planes: all should have normals perpendicular to epipe. */
for (e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
if (e->fnext) {
if (fabsf(dot_v3v3(dir1, e->fnext->no)) > BEVEL_EPSILON_BIG) {
@@ -3488,14 +3519,16 @@ static VMesh *new_adj_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *
return vm;
}
-/* VMesh verts for vertex i have data for (i, 0 <= j <= ns2, 0 <= k <= ns),
+/**
+ * VMesh verts for vertex i have data for (i, 0 <= j <= ns2, 0 <= k <= ns),
* where ns2 = floor(nseg / 2).
* But these overlap data from previous and next i: there are some forced equivalences.
* Let's call these indices the canonical ones: we will just calculate data for these
* 0 <= j <= ns2, 0 <= k < ns2 (for odd ns2)
* 0 <= j < ns2, 0 <= k <= ns2 (for even ns2)
- * also (j=ns2, k=ns2) at i=0 (for even ns2)
- * This function returns the canonical one for any i, j, k in [0,n],[0,ns],[0,ns] */
+ * also (j=ns2, k=ns2) at i=0 (for even ns2)
+ * This function returns the canonical one for any i, j, k in [0,n],[0,ns],[0,ns].
+ */
static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k)
{
int n, ns, ns2, odd;
@@ -3525,15 +3558,15 @@ static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k)
static bool is_canon(VMesh *vm, int i, int j, int k)
{
int ns2 = vm->seg / 2;
- if (vm->seg % 2 == 1) { /* odd */
+ if (vm->seg % 2 == 1) { /* Odd. */
return (j <= ns2 && k <= ns2);
}
- else { /* even */
+ else { /* Even. */
return ((j < ns2 && k <= ns2) || (j == ns2 && k == ns2 && i == 0));
}
}
-/* Copy the vertex data to all of vm verts from canonical ones */
+/* Copy the vertex data to all of vm verts from canonical ones. */
static void vmesh_copy_equiv_verts(VMesh *vm)
{
int n, ns, ns2, i, j, k;
@@ -3557,7 +3590,7 @@ static void vmesh_copy_equiv_verts(VMesh *vm)
}
}
-/* Calculate and return in r_cent the centroid of the center poly */
+/* Calculate and return in r_cent the centroid of the center poly. */
static void vmesh_center(VMesh *vm, float r_cent[3])
{
int n, ns2, i;
@@ -3585,12 +3618,12 @@ static void avg4(
mul_v3_fl(co, 0.25f);
}
-/* gamma needed for smooth Catmull-Clark, Sabin modification */
+/* Gamma needed for smooth Catmull-Clark, Sabin modification. */
static float sabin_gamma(int n)
{
double ans, k, k2, k4, k6, x, y;
- /* precalculated for common cases of n */
+ /* pPrecalculated for common cases of n. */
if (n < 3) {
return 0.0f;
}
@@ -3608,8 +3641,8 @@ static float sabin_gamma(int n)
}
else {
k = cos(M_PI / (double)n);
- /* need x, real root of x^3 + (4k^2 - 3)x - 2k = 0.
- * answer calculated via Wolfram Alpha */
+ /* Need x, real root of x^3 + (4k^2 - 3)x - 2k = 0.
+ * Answer calculated via Wolfram Alpha. */
k2 = k * k;
k4 = k2 * k2;
k6 = k4 * k2;
@@ -3620,7 +3653,8 @@ static float sabin_gamma(int n)
return (float)ans;
}
-/* Fill frac with fractions of way along ring 0 for vertex i, for use with interp_range function */
+/* Fill frac with fractions of the way along ring 0 for vertex i, for use with interp_range
+ * function. */
static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
{
int k, ns;
@@ -3642,7 +3676,7 @@ static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
}
}
-/* Like fill_vmesh_fracs but want fractions for profile points of bndv, with ns segments */
+/* Like fill_vmesh_fracs but want fractions for profile points of bndv, with ns segments. */
static void fill_profile_fracs(BevelParams *bp, BoundVert *bndv, float *frac, int ns)
{
int k;
@@ -3668,13 +3702,13 @@ static void fill_profile_fracs(BevelParams *bp, BoundVert *bndv, float *frac, in
}
/* Return i such that frac[i] <= f <= frac[i + 1], where frac[n] == 1.0
- * and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest */
+ * and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest. */
static int interp_range(const float *frac, int n, const float f, float *r_rest)
{
int i;
float rest;
- /* could binary search in frac, but expect n to be reasonably small */
+ /* Could binary search in frac, but expect n to be reasonably small. */
for (i = 0; i < n; i++) {
if (f <= frac[i + 1]) {
rest = f - frac[i];
@@ -3695,10 +3729,10 @@ static int interp_range(const float *frac, int n, const float f, float *r_rest)
return n;
}
-/* Interpolate given vmesh to make one with target nseg border vertices on the profiles */
-/* HANS-TODO: This puts the center mesh vert at a slightly off location sometimes, which seems to
+/* Interpolate given vmesh to make one with target nseg border vertices on the profiles.
+ * TODO(Hans): This puts the center mesh vert at a slightly off location sometimes, which seems to
* be associated with the rest of that ring being shifted or connected slightly incorrectly to its
- * neighbors */
+ * neighbors. */
static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
{
int n_bndv, ns_in, nseg2, odd, i, j, k, j_in, k_in, k_in_prev, j0inc, k0inc;
@@ -3727,7 +3761,7 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
fill_profile_fracs(bp, bndv, new_frac, nseg);
for (j = 0; j <= nseg2 - 1 + odd; j++) {
for (k = 0; k <= nseg2; k++) {
- /* Finding the locations where "fraction" fits into previous and current "frac" */
+ /* Finding the locations where "fraction" fits into previous and current "frac". */
fraction = new_frac[k];
k_in = interp_range(frac, ns_in, fraction, &restk);
fraction = prev_new_frac[nseg - j];
@@ -3741,7 +3775,7 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
j_in = j_in - 1;
restj = 1.0f + restj;
}
- /* Use bilinear interpolation within the source quad; could be smarter here */
+ /* Use bilinear interpolation within the source quad; could be smarter here. */
if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) {
copy_v3_v3(co, mesh_vert_canon(vm_in, i, j_in, k_in)->co);
}
@@ -3840,13 +3874,13 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
vmesh_copy_equiv_verts(vm_in);
/* Now we do the internal vertices, using standard Catmull-Clark
- * and assuming all boundary vertices have valence 4 */
+ * and assuming all boundary vertices have valence 4. */
- /* The new face vertices */
+ /* The new face vertices. */
for (i = 0; i < n_boundary; i++) {
for (j = 0; j < ns_in2; j++) {
for (k = 0; k < ns_in2; k++) {
- /* face up and right from (j, k) */
+ /* Face up and right from (j, k). */
avg4(co,
mesh_vert(vm_in, i, j, k),
mesh_vert(vm_in, i, j, k + 1),
@@ -3857,11 +3891,11 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
}
- /* The new vertical edge vertices */
+ /* The new vertical edge vertices. */
for (i = 0; i < n_boundary; i++) {
for (j = 0; j < ns_in2; j++) {
for (k = 1; k <= ns_in2; k++) {
- /* vertical edge between (j, k) and (j+1, k) */
+ /* Vertical edge between (j, k) and (j+1, k). */
avg4(co,
mesh_vert(vm_in, i, j, k),
mesh_vert(vm_in, i, j + 1, k),
@@ -3872,11 +3906,11 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
}
- /* The new horizontal edge vertices */
+ /* The new horizontal edge vertices. */
for (i = 0; i < n_boundary; i++) {
for (j = 1; j < ns_in2; j++) {
for (k = 0; k < ns_in2; k++) {
- /* horizontal edge between (j, k) and (j, k+1) */
+ /* Horizontal edge between (j, k) and (j, k+1). */
avg4(co,
mesh_vert(vm_in, i, j, k),
mesh_vert(vm_in, i, j, k + 1),
@@ -3887,26 +3921,26 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
}
- /* The new vertices, not on border */
+ /* The new vertices, not on border. */
gamma = 0.25f;
beta = -gamma;
for (i = 0; i < n_boundary; i++) {
for (j = 1; j < ns_in2; j++) {
for (k = 1; k <= ns_in2; k++) {
- /* co1 = centroid of adjacent new edge verts */
+ /* co1 = centroid of adjacent new edge verts. */
avg4(co1,
mesh_vert_canon(vm_out, i, 2 * j, 2 * k - 1),
mesh_vert_canon(vm_out, i, 2 * j, 2 * k + 1),
mesh_vert_canon(vm_out, i, 2 * j - 1, 2 * k),
mesh_vert_canon(vm_out, i, 2 * j + 1, 2 * k));
- /* co2 = centroid of adjacent new face verts */
+ /* co2 = centroid of adjacent new face verts. */
avg4(co2,
mesh_vert_canon(vm_out, i, 2 * j - 1, 2 * k - 1),
mesh_vert_canon(vm_out, i, 2 * j + 1, 2 * k - 1),
mesh_vert_canon(vm_out, i, 2 * j - 1, 2 * k + 1),
mesh_vert_canon(vm_out, i, 2 * j + 1, 2 * k + 1));
- /* combine with original vert with alpha, beta, gamma factors */
- copy_v3_v3(co, co1); /* alpha = 1.0 */
+ /* Combine with original vert with alpha, beta, gamma factors. */
+ copy_v3_v3(co, co1); /* Alpha = 1.0. */
madd_v3_v3fl(co, co2, beta);
madd_v3_v3fl(co, mesh_vert(vm_in, i, j, k)->co, gamma);
copy_v3_v3(mesh_vert(vm_out, i, 2 * j, 2 * k)->co, co);
@@ -3916,10 +3950,10 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
vmesh_copy_equiv_verts(vm_out);
- /* The center vertex is special */
+ /* The center vertex is special. */
gamma = sabin_gamma(n_boundary);
beta = -gamma;
- /* accumulate edge verts in co1, face verts in co2 */
+ /* Accumulate edge verts in co1, face verts in co2. */
zero_v3(co1);
zero_v3(co2);
for (i = 0; i < n_boundary; i++) {
@@ -3935,7 +3969,7 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
copy_v3_v3(mesh_vert(vm_out, i, ns_in, ns_in)->co, co);
}
- /* Final step: Copy the profile vertices to the VMesh's boundary */
+ /* Final step: Copy the profile vertices to the VMesh's boundary. */
bndv = vm_out->boundstart;
for (i = 0; i < n_boundary; i++) {
inext = (i + 1) % n_boundary;
@@ -3952,7 +3986,7 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
return vm_out;
}
-/* Special case for cube corner, when r is PRO_SQUARE_R, meaning straight sides */
+/* Special case for cube corner, when r is PRO_SQUARE_R, meaning straight sides. */
static VMesh *make_cube_corner_square(MemArena *mem_arena, int nseg)
{
VMesh *vm;
@@ -3984,10 +4018,12 @@ static VMesh *make_cube_corner_square(MemArena *mem_arena, int nseg)
return vm;
}
-/* Special case for cube corner, when r is PRO_SQUARE_IN_R, meaning inward
+/**
+ * Special case for cube corner, when r is PRO_SQUARE_IN_R, meaning inward
* straight sides.
* We mostly don't want a VMesh at all for this case -- just a three-way weld
- * with a triangle in the middle for odd nseg */
+ * with a triangle in the middle for odd nseg.
+ */
static VMesh *make_cube_corner_square_in(MemArena *mem_arena, int nseg)
{
VMesh *vm;
@@ -3998,7 +4034,7 @@ static VMesh *make_cube_corner_square_in(MemArena *mem_arena, int nseg)
ns2 = nseg / 2;
odd = nseg % 2;
vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
- vm->count = 0; // reset, so following loop will end up with correct count
+ vm->count = 0; /* Reset, so following loop will end up with correct count. */
for (i = 0; i < 3; i++) {
zero_v3(co);
co[i] = 1.0f;
@@ -4025,7 +4061,8 @@ static VMesh *make_cube_corner_square_in(MemArena *mem_arena, int nseg)
return vm;
}
-/* Make a VMesh with nseg segments that covers the unit radius sphere octant
+/**
+ * Make a VMesh with nseg segments that covers the unit radius sphere octant
* with center at (0,0,0).
* This has BoundVerts at (1,0,0), (0,1,0) and (0,0,1), with quarter circle arcs
* on the faces for the orthogonal planes through the origin.
@@ -4049,7 +4086,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
}
}
- /* Initial mesh has 3 sides and 2 segments on each side */
+ /* Initial mesh has 3 sides and 2 segments on each side. */
vm0 = new_adj_vmesh(mem_arena, 3, 2, NULL);
vm0->count = 0; /* Reset, so the following loop will end up with correct count. */
for (i = 0; i < 3; i++) {
@@ -4059,7 +4096,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
}
bndv = vm0->boundstart;
for (i = 0; i < 3; i++) {
- /* Get point, 1/2 of the way around profile, on arc between this and next */
+ /* Get point, 1/2 of the way around profile, on arc between this and next. */
coc[i] = 1.0f;
coc[(i + 1) % 3] = 1.0f;
coc[(i + 2) % 3] = 0.0f;
@@ -4074,12 +4111,12 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
/* Calculate profiles again because we started over with new boundverts. */
calculate_profile(bp, bndv, false, false); /* No custom profiles in this case. */
- /* Just building the boundaries here, so sample the profile halfway through */
+ /* Just building the boundaries here, so sample the profile halfway through. */
get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
bndv = bndv->next;
}
- /* center vertex */
+ /* Center vertex. */
copy_v3_fl(co, (float)M_SQRT1_3);
if (nseg > 2) {
@@ -4102,7 +4139,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
vm1 = interp_vmesh(bp, vm1, nseg);
}
- /* Now snap each vertex to the superellipsoid */
+ /* Now snap each vertex to the superellipsoid. */
ns2 = nseg / 2;
for (i = 0; i < 3; i++) {
for (j = 0; j <= ns2; j++) {
@@ -4165,7 +4202,6 @@ static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
VMesh *vm;
BoundVert *bndv;
- /*BLI_assert(bv->edgecount == 3 && bv->selcount == 3); Add support for in plane edges */
bndv = bv->vmesh->boundstart;
copy_v3_v3(co0, bndv->nv.co);
bndv = bndv->next;
@@ -4190,7 +4226,7 @@ static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
return vm;
}
-/* Makes the mesh that replaces the original vertex, bounded by the profiles on the sides */
+/* Makes the mesh that replaces the original vertex, bounded by the profiles on the sides. */
static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
{
int n_bndv, nseg, i;
@@ -4202,7 +4238,7 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
n_bndv = bv->vmesh->count;
- /* Same bevel as that of 3 edges of vert in a cube */
+ /* Same bevel as that of 3 edges of vert in a cube. */
if (n_bndv == 3 && tri_corner_test(bp, bv) != -1 && bp->pro_super_r != PRO_SQUARE_IN_R) {
return tri_corner_adj_vmesh(bp, bv);
}
@@ -4231,7 +4267,7 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
sub_v3_v3v3(negative_fullest, boundverts_center, original_vertex);
add_v3_v3(negative_fullest, boundverts_center);
- /* Find the vertex mesh's start center with the profile's fullness */
+ /* Find the vertex mesh's start center with the profile's fullness. */
fullness = bp->pro_spacing.fullness;
sub_v3_v3v3(center_direction, original_vertex, boundverts_center);
if (len_squared_v3(center_direction) > BEVEL_EPSILON_SQ) {
@@ -4259,10 +4295,12 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
return vm1;
}
-/* Snap co to the closest point on the profile for vpipe projected onto the plane
+/**
+ * Snap co to the closest point on the profile for vpipe projected onto the plane
* containing co with normal in the direction of edge vpipe->ebev.
* For the square profiles, need to decide whether to snap to just one plane
- * or to the midpoint of the profile; do so if midline is true. */
+ * or to the midpoint of the profile; do so if midline is true.
+ */
static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
{
float va[3], vb[3], edir[3], va0[3], vb0[3], vmid0[3];
@@ -4277,7 +4315,7 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
return;
}
- /* Get a plane with the normal pointing along the beveled edge */
+ /* Get a plane with the normal pointing along the beveled edge. */
sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co);
plane_from_point_normal_v3(plane, co, edir);
@@ -4285,7 +4323,7 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
closest_to_plane_v3(vb0, plane, vb);
closest_to_plane_v3(vmid0, plane, pro->middle);
if (make_unit_square_map(va0, vmid0, vb0, m) && invert_m4_m4(minv, m)) {
- /* Transform co and project it onto superellipse */
+ /* Transform co and project it onto superellipse. */
mul_v3_m4v3(p, minv, co);
snap_to_superellipsoid(p, pro->super_r, midline);
@@ -4293,7 +4331,7 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
copy_v3_v3(co, snap);
}
else {
- /* planar case: just snap to line va0--vb0 */
+ /* Planar case: just snap to line va0--vb0. */
closest_to_line_segment_v3(p, co, va0, vb0);
copy_v3_v3(co, p);
}
@@ -4328,6 +4366,7 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
if (!is_canon(vm, i, j, k)) {
continue;
}
+ /* With a custom profile just copy the shape of the profile at each ring. */
if (bp->use_custom_profile) {
/* Find both profile vertices that correspond to this point. */
if (i == ipipe1 || i == ipipe2) {
@@ -4479,7 +4518,7 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
/* Special case of bevel_build_rings when tri-corner and profile is 0.
* There is no corner mesh except, if nseg odd, for a center poly.
* Boundary verts merge with previous ones according to pattern:
- * (i, 0, k) merged with (i+1, 0, ns-k) for k <= ns/2 */
+ * (i, 0, k) merged with (i+1, 0, ns-k) for k <= ns/2. */
static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh *vm1)
{
int n, ns, ns2, odd, i, k;
@@ -4513,7 +4552,7 @@ static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh
}
}
-/* copy whichever of a and b is closer to v into r */
+/* Copy whichever of a and b is closer to v into r. */
static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
{
if (len_squared_v3v3(a, v) <= len_squared_v3v3(b, v)) {
@@ -4524,7 +4563,8 @@ static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
}
}
-/* Special case of VMesh when profile == 1 and there are 3 or more beveled edges.
+/**
+ * Special case of VMesh when profile == 1 and there are 3 or more beveled edges.
* We want the effect of parallel offset lines (n/2 of them)
* on each side of the center, for even n.
* Wherever they intersect with each other between two successive beveled edges,
@@ -4532,8 +4572,8 @@ static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
* We have to move the boundary edges too -- the usual method is to make one profile plane between
* successive BoundVerts, but for the effect we want here, there will be two planes,
* one on each side of the original edge.
- * At the moment, this is not called for odd number of segments,
- * though code does something if it is.
+ * At the moment, this is not called for odd number of segments, though code does something if it
+ * is.
*/
static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
{
@@ -4557,8 +4597,8 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
centerline = MEM_mallocN((size_t)(clstride * n_bndv) * sizeof(float), "bevel");
cset = MEM_callocN((size_t)n_bndv * sizeof(bool), "bevel");
- /* find on_edge, place on bndv[i]'s elast where offset line would meet,
- * taking min-distance-to bv->v with position where next sector's offset line would meet */
+ /* Find on_edge, place on bndv[i]'s elast where offset line would meet,
+ * taking min-distance-to bv->v with position where next sector's offset line would meet. */
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
copy_v3_v3(bndco, bndv->nv.co);
@@ -4577,7 +4617,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
cset[i] = true;
bndv = bndv->next;
i++;
- /* leave cset[i] where it was - probably false, unless i == n - 1 */
+ /* Leave cset[i] where it was - probably false, unless i == n - 1. */
}
else if (bndv->is_arc_start) {
e1 = bndv->efirst;
@@ -4586,24 +4626,24 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
bndv = bndv->next;
cset[i] = true;
i++;
- /* leave cset[i] where it was - probably false, unless i == n - 1 */
+ /* Leave cset[i] where it was - probably false, unless i == n - 1. */
}
else if (ang_kind == ANGLE_SMALLER) {
sub_v3_v3v3(dir1, e1->e->v1->co, e1->e->v2->co);
sub_v3_v3v3(dir2, e2->e->v1->co, e2->e->v2->co);
add_v3_v3v3(co1, bndco, dir1);
add_v3_v3v3(co2, bndco, dir2);
- /* intersect e1 with line through bndv parallel to e2 to get v1co */
+ /* Intersect e1 with line through bndv parallel to e2 to get v1co. */
ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2);
if (ikind == 0) {
v1set = false;
}
else {
- /* if the lines are skew (ikind == 2), want meet1 which is on e1 */
+ /* If the lines are skew (ikind == 2), want meet1 which is on e1. */
copy_v3_v3(v1co, meet1);
v1set = true;
}
- /* intersect e2 with line through bndv parallel to e1 to get v2co */
+ /* Intersect e2 with line through bndv parallel to e1 to get v2co. */
ikind = isect_line_line_v3(e2->e->v1->co, e2->e->v2->co, bndco, co1, meet1, meet2);
if (ikind == 0) {
v2set = false;
@@ -4613,7 +4653,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
copy_v3_v3(v2co, meet1);
}
- /* want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration */
+ /* We want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration. */
on_edge_cur = centerline + clstride * i;
iprev = (i == 0) ? n_bndv - 1 : i - 1;
on_edge_prev = centerline + clstride * iprev;
@@ -4638,7 +4678,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
bndv = bndv->next;
}
- /* Maybe not everything was set by the previous loop */
+ /* Maybe not everything was set by the previous loop. */
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
if (!cset[i]) {
@@ -4672,14 +4712,14 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
bndv = bndv->next;
}
- /* fill in rest of centerlines by interpolation */
+ /* Fill in rest of centerlines by interpolation. */
copy_v3_v3(co2, bv->v->co);
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
if (odd) {
ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co);
if (ang > BEVEL_SMALL_ANG) {
- /* finalfrac is length along arms of isosceles triangle with top angle 2*ang
+ /* finalfrac is the length along arms of isosceles triangle with top angle 2*ang
* such that the base of the triangle is 1.
* This is used in interpolation along center-line in odd case.
* To avoid too big a drop from bv, cap finalfrac a 0.8 arbitrarily */
@@ -4704,7 +4744,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
bndv = bndv->next;
}
- /* coords of edges and mid or near-mid line */
+ /* Coords of edges and mid or near-mid line. */
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
copy_v3_v3(co1, bndv->nv.co);
@@ -4723,7 +4763,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
vmesh_copy_equiv_verts(vm);
- /* fill in interior points by interpolation from edges to centerlines */
+ /* Fill in interior points by interpolation from edges to centerlines. */
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
im1 = (i == 0) ? n_bndv - 1 : i - 1;
@@ -4736,7 +4776,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
meet1,
meet2);
if (ikind == 0) {
- /* how can this happen? fall back on interpolation in one direction if it does */
+ /* How can this happen? fall back on interpolation in one direction if it does. */
interp_v3_v3v3(mesh_vert(vm, i, j, k)->co,
mesh_vert(vm, i, 0, k)->co,
centerline + clstride * im1 + 3 * k,
@@ -4790,8 +4830,8 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
else if (tri_corner_test(bp, bv) == 1) {
vm1 = tri_corner_adj_vmesh(bp, bv);
- /* the PRO_SQUARE_IN_R profile has boundary edges that merge
- * and no internal ring polys except possibly center ngon */
+ /* The PRO_SQUARE_IN_R profile has boundary edges that merge
+ * and no internal ring polys except possibly center ngon. */
if (bp->pro_super_r == PRO_SQUARE_IN_R && !bp->use_custom_profile) {
build_square_in_vmesh(bp, bm, bv, vm1);
return;
@@ -4801,13 +4841,13 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
vm1 = adj_vmesh(bp, bv);
}
- /* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */
+ /* Copy final vmesh into bv->vmesh, make BMVerts and BMFaces. */
vm = bv->vmesh;
for (i = 0; i < n_bndv; i++) {
for (j = 0; j <= ns2; j++) {
for (k = 0; k <= ns; k++) {
if (j == 0 && (k == 0 || k == ns)) {
- continue; /* boundary corners already made */
+ continue; /* Boundary corners already made. */
}
if (!is_canon(vm, i, j, k)) {
continue;
@@ -4818,7 +4858,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
}
vmesh_copy_equiv_verts(vm);
- /* make the polygons */
+ /* Make the polygons. */
bndv = vm->boundstart;
do {
i = bndv->index;
@@ -4834,7 +4874,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
/* For odd ns, make polys with lower left corner at (i,j,k) for
* j in [0, ns2-1], k in [0, ns2]. And then the center ngon.
* For even ns,
- * j in [0, ns2-1], k in [0, ns2-1] */
+ * j in [0, ns2-1], k in [0, ns2-1]. */
for (j = 0; j < ns2; j++) {
for (k = 0; k < ns2 + odd; k++) {
bmv1 = mesh_vert(vm, i, j, k)->v;
@@ -4868,7 +4908,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
}
else { /* j == k */
- /* only one edge attached to v, since vertex_only */
+ /* Only one edge attached to v, since vertex_only. */
if (e->is_seam) {
r_f = bev_create_quad_ex(
bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, bme, NULL, bme, NULL, mat_nr);
@@ -4879,7 +4919,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
}
}
- else { /* edge bevel */
+ else { /* Edge bevel. */
if (odd) {
if (k == ns2) {
if (e && e->is_seam) {
@@ -4910,7 +4950,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
} while ((bndv = bndv->next) != vm->boundstart);
- /* Fix UVs along center lines if even number of segments */
+ /* Fix UVs along center lines if even number of segments. */
if (!odd) {
bndv = vm->boundstart;
do {
@@ -4930,7 +4970,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
}
- /* center ngon */
+ /* Center ngon. */
if (odd) {
build_center_ngon(bp, bm, bv, mat_nr);
}
@@ -5040,7 +5080,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
BLI_array_staticdeclare(bmedges, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(bmfaces, BM_DEFAULT_NGON_STACK_SIZE);
- /* Add the first corner vertex under this boundvert */
+ /* Add the first corner vertex under this boundvert. */
face_bmverts[0] = mesh_vert(bv->vmesh, i, 1, 0)->v;
#ifdef DEBUG_CUSTOM_PROFILE_CUTOFF
@@ -5100,12 +5140,14 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
}
}
-/* If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
+/**
+ * If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
* The uv poly is made by snapping all outside-of-frep vertices to the closest edge in frep.
* Assume that this function is called when the only inside-of-frep vertex is vm->boundstart.
* The poly will have zero area if the distance of that first vertex to some edge e is zero,
* and all the other vertices snap to e or snap to an edge
- * at a point that is essentially on e too. */
+ * at a point that is essentially on e too.
+ */
static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
{
BoundVert *v;
@@ -5160,8 +5202,8 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
bndv = vm->boundstart;
n = 0;
do {
- /* accumulate vertices for vertex ngon */
- /* also accumulate faces in which uv interpolation is to happen for each */
+ /* Accumulate vertices for vertex ngon. */
+ /* Also accumulate faces in which uv interpolation is to happen for each. */
BLI_array_append(bmverts, bndv->nv.v);
if (repface) {
BLI_array_append(bmfaces, repface);
@@ -5211,7 +5253,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
f = bevel_build_poly(bp, bm, bv);
if (f) {
- /* we have a polygon which we know starts at the previous vertex, make it into a fan */
+ /* We have a polygon which we know starts at the previous vertex, make it into a fan. */
BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev;
BMVert *v_fan = l_fan->v;
@@ -5238,7 +5280,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
}
}
else {
- if (l_fan->v == v_fan) { /* l_fan = l_fan; */
+ if (l_fan->v == v_fan) { /* l_fan = l_fan. */
}
else if (l_fan->next->v == v_fan) {
l_fan = l_fan->next;
@@ -5373,7 +5415,7 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
for (k = 1; k < ns; k++) {
if (bndv->ebev) {
get_profile_point(bp, &bndv->profile, k, ns, co);
- copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); /* Get NewVert location from profile coord */
+ copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
if (!weld) {
/* This is done later with (possibly) better positions for the weld case. */
create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
@@ -5454,7 +5496,7 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
static float edge_face_angle(EdgeHalf *e)
{
if (e->fprev && e->fnext) {
- /* angle between faces is supplement of angle between face normals */
+ /* Angle between faces is supplement of angle between face normals. */
return (float)M_PI - angle_normalized_v3v3(e->fprev->no, e->fnext->no);
}
else {
@@ -5462,18 +5504,20 @@ static float edge_face_angle(EdgeHalf *e)
}
}
-/* take care, this flag isn't cleared before use, it just so happens that its not set */
+/* Take care, this flag isn't cleared before use, it just so happens that its not set. */
#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_ELEM_API_FLAG_ENABLE((bme), _FLAG_OVERLAP)
#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE((bme), _FLAG_OVERLAP)
#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_ELEM_API_FLAG_TEST((bme), _FLAG_OVERLAP)
-/* Try to extend the bv->edges[] array beyond i by finding more successor edges.
+/**
+ * Try to extend the bv->edges[] array beyond i by finding more successor edges.
* This is a possibly exponential-time search, but it is only exponential in the number
* of "internal faces" at a vertex -- i.e., faces that bridge between the edges that naturally
* form a manifold cap around bv. It is rare to have more than one of these, so unlikely
* that the exponential time case will be hit in practice.
* Returns the new index i' where bv->edges[i'] ends the best path found.
- * The path will have the tags of all of its edges set. */
+ * The path will have the tags of all of its edges set.
+ */
static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
{
BMEdge *bme, *bme2, *nextbme;
@@ -5482,11 +5526,11 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
int j, tryj, bestj, nsucs, sucindex, k;
BMEdge **sucs = NULL;
BMEdge **save_path = NULL;
- BLI_array_staticdeclare(sucs, 4); /* likely very few faces attached to same edge */
+ BLI_array_staticdeclare(sucs, 4); /* Likely very few faces attached to same edge. */
BLI_array_staticdeclare(save_path, BM_DEFAULT_NGON_STACK_SIZE);
bme = bv->edges[i].e;
- /* fill sucs with all unmarked edges of bmes */
+ /* Fill sucs with all unmarked edges of bmesh. */
BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
@@ -5512,16 +5556,16 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
BLI_array_append(save_path, bv->edges[k].e);
}
}
- /* now reset to path only-going-to-j state */
+ /* Now reset to path only-going-to-j state. */
for (k = j + 1; k <= tryj; k++) {
BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
bv->edges[k].e = NULL;
}
}
- /* at this point we should be back at invariant on entrance: path up to j */
+ /* At this point we should be back at invariant on entrance: path up to j. */
if (bestj > j) {
- /* save_path should have from j + 1 to bestj inclusive
- * edges to add to edges[] before returning. */
+ /* Save_path should have from j + 1 to bestj inclusive.
+ * Edges to add to edges[] before returning. */
for (k = j + 1; k <= bestj; k++) {
BLI_assert(save_path[k - (j + 1)] != NULL);
bv->edges[k].e = save_path[k - (j + 1)];
@@ -5590,17 +5634,17 @@ static bool fast_bevel_edge_order(BevVert *bv)
ntot = bv->edgecount;
- /* add edges to bv->edges in order that keeps adjacent edges sharing
- * a unique face, if possible */
+ /* Add edges to bv->edges in order that keeps adjacent edges sharing
+ * a unique face, if possible. */
e = &bv->edges[0];
bme = e->e;
if (!bme->l) {
return false;
}
for (i = 1; i < ntot; i++) {
- /* find an unflagged edge bme2 that shares a face f with previous bme */
+ /* Find an unflagged edge bme2 that shares a face f with previous bme. */
num_shared_face = 0;
- first_suc = NULL; /* keep track of first successor to match legacy behavior */
+ first_suc = NULL; /* Keep track of first successor to match legacy behavior. */
BM_ITER_ELEM (bme2, &iter, bv->v, BM_EDGES_OF_VERT) {
if (BM_BEVEL_EDGE_TAG_TEST(bme2)) {
continue;
@@ -5635,9 +5679,8 @@ static bool fast_bevel_edge_order(BevVert *bv)
#endif
/* Fill in bv->edges with a good ordering of non-wire edges around bv->v.
- * Use only edges where BM_BEVEL_EDGE_TAG is disabled so far
- * (if edge beveling, others are wire).
- * first_bme is a good edge to start with.*/
+ * Use only edges where BM_BEVEL_EDGE_TAG is disabled so far (if edge beveling, others are wire).
+ * first_bme is a good edge to start with. */
static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
{
BMEdge *bme, *bme2;
@@ -5662,7 +5705,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
if (i >= bv->edgecount) {
break;
}
- /* Not done yet: find a new first_bme */
+ /* Not done yet: find a new first_bme. */
first_bme = NULL;
BM_ITER_ELEM (bme, &iter, bv->v, BM_EDGES_OF_VERT) {
if (BM_BEVEL_EDGE_TAG_TEST(bme)) {
@@ -5677,7 +5720,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
}
}
}
- /* now fill in the faces ... */
+ /* Now fill in the faces. */
for (i = 0; i < ntot; i++) {
e = &bv->edges[i];
e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1];
@@ -5705,7 +5748,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
}
}
-/* Construction around the vertex */
+/* Construction around the vertex. */
static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
{
BMEdge *bme;
@@ -5728,8 +5771,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
* There may be one or more chains of shared faces broken by
* gaps where there are no faces.
* Want to ignore wire edges completely for edge beveling.
- * TODO: make following work when more than one gap.
- */
+ * TODO: make following work when more than one gap. */
first_bme = NULL;
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
@@ -5743,7 +5785,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
}
if (fcnt == 1) {
- /* good to start face chain from this edge */
+ /* Good to start face chain from this edge. */
first_bme = bme;
}
if (fcnt > 0 || bp->vertex_only) {
@@ -5763,7 +5805,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
if ((nsel == 0 && !bp->vertex_only) || (ntot < 2 && bp->vertex_only)) {
- /* signal this vert isn't being beveled */
+ /* Signal this vert isn't being beveled. */
BM_elem_flag_disable(v, BM_ELEM_TAG);
return NULL;
}
@@ -5788,7 +5830,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
find_bevel_edge_order(bm, bv, first_bme);
- /* fill in other attributes of EdgeHalfs */
+ /* Fill in other attributes of EdgeHalfs. */
for (i = 0; i < ntot; i++) {
e = &bv->edges[i];
bme = e->e;
@@ -5805,13 +5847,13 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->profile_index = 0;
}
- /* now done with tag flag */
+ /* Now done with tag flag. */
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
BM_BEVEL_EDGE_TAG_DISABLE(bme);
}
- /* if edge array doesn't go CCW around vertex from average normal side,
- * reverse the array, being careful to reverse face pointers too */
+ /* If edge array doesn't go CCW around vertex from average normal side,
+ * reverse the array, being careful to reverse face pointers too. */
if (ntot > 1) {
ccw_test_sum = 0;
for (i = 0; i < ntot; i++) {
@@ -5832,7 +5874,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
if (bp->vertex_only) {
- /* if weighted, modify offset by weight */
+ /* If weighted, modify offset by weight. */
if (bp->dvert != NULL && bp->vertex_group != -1) {
weight = defvert_find_weight(bp->dvert + BM_elem_index_get(v), bp->vertex_group);
bv->offset *= weight;
@@ -5857,7 +5899,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->next = &bv->edges[(i + 1) % ntot];
e->prev = &bv->edges[(i + ntot - 1) % ntot];
- /* set offsets */
+ /* Set offsets. */
if (e->is_bev) {
/* Convert distance as specified by user into offsets along
* faces on left side and right side of this edgehalf.
@@ -5870,7 +5912,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
case BEVEL_AMT_WIDTH:
z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
if (z < BEVEL_EPSILON) {
- e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
+ e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
else {
e->offset_l_spec = bp->offset / z;
@@ -5879,14 +5921,15 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
case BEVEL_AMT_DEPTH:
z = fabsf(cosf(edge_face_angle(e) / 2.0f));
if (z < BEVEL_EPSILON) {
- e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
+ e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
else {
e->offset_l_spec = bp->offset / z;
}
break;
case BEVEL_AMT_PERCENT:
- /* offset needs to be such that it meets adjacent edges at percentage of their lengths */
+ /* Offset needs to be such that it meets adjacent edges at percentage of their lengths.
+ */
v1 = BM_edge_other_vert(e->prev->e, v);
v2 = BM_edge_other_vert(e->e, v);
z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
@@ -5924,7 +5967,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
z = fabsf(2.0f * sinf(angle_v3v3(vert_axis, edge_dir)));
if (z < BEVEL_EPSILON) {
- e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel. */
+ e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
else {
e->offset_l_spec = bp->offset / z;
@@ -5936,7 +5979,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
z = fabsf(cosf(angle_v3v3(vert_axis, edge_dir)));
if (z < BEVEL_EPSILON) {
- e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel. */
+ e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
else {
e->offset_l_spec = bp->offset / z;
@@ -5978,7 +6021,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
return bv;
}
-/* Face f has at least one beveled vertex. Rebuild f */
+/* Face f has at least one beveled vertex. Rebuild f. */
static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
{
BMIter liter, eiter, fiter;
@@ -6011,28 +6054,28 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
eprev = find_edge_half(bv, lprev->e);
BLI_assert(eprev != NULL);
- /* which direction around our vertex do we travel to match orientation of f? */
+ /* Which direction around our vertex do we travel to match orientation of f? */
if (e->prev == eprev) {
if (eprev->prev == e) {
- /* valence 2 vertex: use f is one of e->fnext or e->fprev to break tie */
+ /* Valence 2 vertex: use f is one of e->fnext or e->fprev to break tie. */
go_ccw = (e->fnext != f);
}
else {
- go_ccw = true; /* going ccw around bv to trace this corner */
+ go_ccw = true; /* Going ccw around bv to trace this corner. */
}
}
else if (eprev->prev == e) {
- go_ccw = false; /* going cw around bv to trace this corner */
+ go_ccw = false; /* Going cw around bv to trace this corner. */
}
else {
- /* edges in face are non-contiguous in our ordering around bv.
+ /* Edges in face are non-contiguous in our ordering around bv.
* Which way should we go when going from eprev to e? */
if (count_ccw_edges_between(eprev, e) < count_ccw_edges_between(e, eprev)) {
- /* go counterclockewise from eprev to e */
+ /* Go counterclockewise from eprev to e. */
go_ccw = true;
}
else {
- /* go clockwise from eprev to e */
+ /* Go clockwise from eprev to e. */
go_ccw = false;
}
}
@@ -6060,7 +6103,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
BLI_array_append(ee, bme);
}
while (v != vend) {
- /* check for special case: multisegment 3rd face opposite a beveled edge with no vmesh */
+ /* Check for special case: multisegment 3rd face opposite a beveled edge with no vmesh. */
corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
if (go_ccw) {
i = v->index;
@@ -6081,7 +6124,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
bmv = mesh_vert(vm, i, 0, k)->v;
if (bmv) {
BLI_array_append(vv, bmv);
- BLI_array_append(ee, bme); /* TODO: maybe better edge here */
+ BLI_array_append(ee, bme); /* TODO: Maybe better edge here. */
if (corner3special && v->ebev && !v->ebev->is_seam && k != vm->seg) {
BLI_array_append(vv_fix, bmv);
}
@@ -6090,7 +6133,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
v = v->next;
}
else {
- /* going cw */
+ /* Going cw. */
i = v->prev->index;
if (on_profile_start) {
kstart = eprev->profile_index;
@@ -6133,7 +6176,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
bev_merge_uvs(bm, vv_fix[k]);
}
- /* copy attributes from old edges */
+ /* Copy attributes from old edges. */
BLI_assert(n == BLI_array_len(ee));
bme_prev = ee[n - 1];
for (k = 0; k < n; k++) {
@@ -6141,14 +6184,14 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
BLI_assert(ee[k] && bme_new);
if (ee[k] != bme_new) {
BM_elem_attrs_copy(bm, bm, ee[k], bme_new);
- /* want to undo seam and smooth for corner segments
- * if those attrs aren't contiguous around face */
+ /* Want to undo seam and smooth for corner segments
+ * if those attrs aren't contiguous around face. */
if (k < n - 1 && ee[k] == ee[k + 1]) {
if (BM_elem_flag_test(ee[k], BM_ELEM_SEAM) &&
!BM_elem_flag_test(bme_prev, BM_ELEM_SEAM)) {
BM_elem_flag_disable(bme_new, BM_ELEM_SEAM);
}
- /* actually want "sharp" to be contiguous, so reverse the test */
+ /* Actually want "sharp" to be contiguous, so reverse the test. */
if (!BM_elem_flag_test(ee[k], BM_ELEM_SMOOTH) &&
BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH)) {
BM_elem_flag_enable(bme_new, BM_ELEM_SMOOTH);
@@ -6160,11 +6203,11 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
}
- /* don't select newly or return created boundary faces... */
+ /* Don't select newly or return created boundary faces. */
if (f_new) {
record_face_kind(bp, f_new, F_RECON);
BM_elem_flag_disable(f_new, BM_ELEM_TAG);
- /* Also don't want new edges that aren't part of a new bevel face */
+ /* Also don't want new edges that aren't part of a new bevel face. */
BM_ITER_ELEM (bme, &eiter, f_new, BM_EDGES_OF_FACE) {
keep = false;
BM_ITER_ELEM (f_other, &fiter, bme, BM_FACES_OF_EDGE) {
@@ -6186,7 +6229,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
return do_rebuild;
}
-/* All polygons touching v need rebuilding because beveling v has made new vertices */
+/* All polygons touching v need rebuilding because beveling v has made new vertices. */
static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v)
{
void *faces_stack[BM_DEFAULT_ITER_STACK_SIZE];
@@ -6208,7 +6251,7 @@ static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *
}
}
-/* If there were any wire edges, they need to be reattached somewhere */
+/* If there were any wire edges, they need to be reattached somewhere. */
static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
{
BMEdge *e;
@@ -6225,7 +6268,7 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
for (i = 0; i < bv->wirecount; i++) {
e = bv->wire_edges[i];
- /* look for the new vertex closest to the other end of e */
+ /* Look for the new vertex closest to the other end of e. */
vclosest = NULL;
dclosest = FLT_MAX;
votherclosest = NULL;
@@ -6234,7 +6277,7 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
if (BM_elem_flag_test(vother, BM_ELEM_TAG)) {
bvother = find_bevvert(bp, vother);
if (!bvother || !bvother->vmesh) {
- return; /* shouldn't happen */
+ return; /* Shouldn't happen. */
}
}
bndv = bv->vmesh->boundstart;
@@ -6288,7 +6331,7 @@ static bool bevvert_is_weld_cross(BevVert *bv)
(bv->edges[1].is_bev && bv->edges[3].is_bev)));
}
-/*
+/**
* Copy edge attribute data across the non-beveled crossing edges of a cross weld.
*
* Situation looks like this:
@@ -6305,7 +6348,7 @@ static bool bevvert_is_weld_cross(BevVert *bv)
* where e is the EdgeHalf of one of the beveled edges,
* e->next and e->prev are EdgeHalfs for the unbeveled edges of the cross
* and their attributes are to be copied to the edges 01, 12, 23.
- * The vert i is mesh_vert(vm, vmindex, 0, i)->v
+ * The vert i is mesh_vert(vm, vmindex, 0, i)->v.
*/
static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex, EdgeHalf *e)
{
@@ -6415,18 +6458,18 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
verts[2] = mesh_vert(vm2, i2, 0, nseg - k)->v;
if (odd && k == mid + 1) {
if (e1->is_seam) {
- /* straddles a seam: choose to interpolate in f1 and snap right edge to bme */
+ /* Straddles a seam: choose to interpolate in f1 and snap right edge to bme. */
edges[0] = edges[1] = NULL;
edges[2] = edges[3] = bme;
r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
}
else {
- /* straddles but not a seam: interpolate left half in f1, right half in f2 */
+ /* Straddles but not a seam: interpolate left half in f1, right half in f2. */
r_f = bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
}
}
else if (!odd && k == mid) {
- /* left poly that touches an even center line on right */
+ /* Left poly that touches an even center line on right. */
edges[0] = edges[1] = NULL;
edges[2] = edges[3] = bme;
r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
@@ -6434,18 +6477,18 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
BLI_assert(center_bme != NULL);
}
else if (!odd && k == mid + 1) {
- /* right poly that touches an even center line on left */
+ /* Right poly that touches an even center line on left. */
edges[0] = edges[1] = bme;
edges[2] = edges[3] = NULL;
r_f = bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
}
else {
- /* doesn't cross or touch the center line, so interpolate in appropriate f1 or f2 */
+ /* Doesn't cross or touch the center line, so interpolate in appropriate f1 or f2. */
f = (k <= mid) ? f1 : f2;
r_f = bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
}
record_face_kind(bp, r_f, F_EDGE);
- /* tag the long edges: those out of verts[0] and verts[2] */
+ /* Tag the long edges: those out of verts[0] and verts[2]. */
BM_ITER_ELEM (l, &iter, r_f, BM_LOOPS_OF_FACE) {
if (l->v == verts[0] || l->v == verts[2]) {
BM_elem_flag_enable(l, BM_ELEM_LONG_TAG);
@@ -6463,8 +6506,8 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
}
}
- /* Fix UVs along end edge joints. A nop unless other side built already. */
- /* TODO: if some seam, may want to do selective merge */
+ /* Fix UVs along end edge joints. A nop unless other side built already. */
+ /* TODO: If some seam, may want to do selective merge. */
if (!bv1->any_seam && bv1->vmesh->mesh_kind == M_NONE) {
bev_merge_end_uvs(bm, bv1, e1);
}
@@ -6472,14 +6515,14 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
bev_merge_end_uvs(bm, bv2, e2);
}
- /* Copy edge data to first and last edge */
+ /* Copy edge data to first and last edge. */
bme1 = BM_edge_exists(bmv1, bmv2);
bme2 = BM_edge_exists(bmv3, bmv4);
BLI_assert(bme1 && bme2);
BM_elem_attrs_copy(bm, bm, bme, bme1);
BM_elem_attrs_copy(bm, bm, bme, bme2);
- /* If either end is a "weld cross", want continuity of edge attributes across end edge(s) */
+ /* If either end is a "weld cross", want continuity of edge attributes across end edge(s). */
if (bevvert_is_weld_cross(bv1)) {
weld_cross_attrs_copy(bm, bv1, vm1, i1, e1);
}
@@ -6491,18 +6534,16 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
/* Find xnew > x0 so that distance((x0,y0), (xnew, ynew)) = dtarget.
* False position Illinois method used because the function is somewhat linear
* -> linear interpolation converges fast.
- * Assumes that the gradient is always between 1 and -1 for
- * x in [x0, x0+dtarget] */
+ * Assumes that the gradient is always between 1 and -1 for x in [x0, x0+dtarget]. */
static double find_superellipse_chord_endpoint(double x0, double dtarget, float r, bool rbig)
{
double xmin, xmax, ymin, ymax, dmaxerr, dminerr, dnewerr, xnew, ynew;
double y0 = superellipse_co(x0, r, rbig);
- const double tol = 1e-13; // accumulates for many segments so use low value
+ const double tol = 1e-13; /* accumulates for many segments so use low value. */
const int maxiter = 10;
bool lastupdated_upper;
- /* For gradient between -1 and 1, xnew can only be in
- * [x0 + sqrt(2)/2*dtarget, x0 + dtarget]. */
+ /* For gradient between -1 and 1, xnew can only be in [x0 + sqrt(2)/2*dtarget, x0 + dtarget]. */
xmin = x0 + M_SQRT2 / 2.0 * dtarget;
if (xmin > 1.0) {
xmin = 1.0;
@@ -6569,7 +6610,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
const int smoothitermax = 10;
const double error_tol = 1e-7;
int i;
- int imax = (seg + 1) / 2 - 1; /* ceiling division - 1 */
+ int imax = (seg + 1) / 2 - 1; /* Ceiling division - 1. */
double d, dmin, dmax;
double davg;
@@ -6597,7 +6638,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
}
yvals[0] = 1;
- /* Smooth distance loop */
+ /* Smooth distance loop. */
for (int iter = 0; iter < smoothitermax; iter++) {
sum = 0.0;
dmin = 2.0;
@@ -6666,8 +6707,8 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
* function in the first quadrant. For special profiles (linear, arc,
* rectangle) the point can be calculated easily, for any other profile a more
* expensive search procedure must be used because there is no known closed
- * form for equidistant parametrization
- * xvals and yvals should be size n+1
+ * form for equidistant parametrization.
+ * xvals and yvals should be size n+1.
*/
static void find_even_superellipse_chords(int n, float r, double *xvals, double *yvals)
{
@@ -6679,7 +6720,7 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
/* Special cases. */
if (r == PRO_LINE_R) {
- /* Linear spacing */
+ /* Linear spacing. */
for (i = 0; i <= n; i++) {
xvals[i] = (double)i / n;
yvals[i] = 1.0 - (double)i / n;
@@ -6807,7 +6848,8 @@ static float find_profile_fullness(BevelParams *bp)
* Use doubles because otherwise we cannot come close to float precision for final results.
*
* \param pro_spacing: The struct to fill. Changes depending on whether there needs
- * to be a separate miter profile. */
+ * to be a separate miter profile.
+ */
static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bool custom)
{
int seg, seg_2;
@@ -6866,7 +6908,7 @@ static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bo
}
}
}
- else { /* Only 1 segment, we don't need any profile information */
+ else { /* Only 1 segment, we don't need any profile information. */
pro_spacing->xvals = NULL;
pro_spacing->yvals = NULL;
pro_spacing->xvals_2 = NULL;
@@ -6875,7 +6917,7 @@ static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bo
}
}
-/*
+/**
* Assume we have a situation like:
*
* a d
@@ -6885,8 +6927,7 @@ static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bo
* b---------c
* B
*
- * where edges are A, B, and C,
- * following a face around vertices a, b, c, d;
+ * where edges are A, B, and C, following a face around vertices a, b, c, d.
* th1 is angle abc and th2 is angle bcd;
* and the argument EdgeHalf eb is B, going from b to c.
* In general case, edge offset specs for A, B, C have
@@ -6911,7 +6952,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
return no_collide_offset;
}
kb = eb->offset_l_spec;
- ea = eb->next; /* note: this is in direction b --> a */
+ ea = eb->next; /* Note: this is in direction b --> a. */
ka = ea->offset_r_spec;
if (eb->is_rev) {
vc = eb->e->v1;
@@ -6925,16 +6966,16 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
bvc = NULL;
ebother = find_other_end_edge_half(bp, eb, &bvc);
if (ebother != NULL) {
- ec = ebother->prev; /* note: this is in direction c --> d*/
+ ec = ebother->prev; /* Note: this is in direction c --> d. */
vc = bvc->v;
kc = ec->offset_l_spec;
vd = ec->is_rev ? ec->e->v1 : ec->e->v2;
}
else {
- /* No bevvert for w, so C can't be beveled */
+ /* No bevvert for w, so C can't be beveled. */
kc = 0.0f;
ec = NULL;
- /* Find an edge from c that has same face */
+ /* Find an edge from c that has same face. */
lb = BM_face_edge_share_loop(eb->fnext, eb->e);
if (!lb) {
return no_collide_offset;
@@ -6960,7 +7001,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
/* First calculate offset at which edge B collapses, which happens
* when advancing clones of A, B, C all meet at a point.
- * This only happens if at least two of those three edges have non-zero k's */
+ * This only happens if at least two of those three edges have non-zero k's. */
sin1 = sinf(th1);
sin2 = sinf(th2);
if ((ka > 0.0f) + (kb > 0.0f) + (kc > 0.0f) >= 2) {
@@ -6978,8 +7019,8 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
}
}
- /* Now check edge slide cases */
- if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2*/) {
+ /* Now check edge slide cases. */
+ if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2 */) {
t = BM_edge_calc_length(ea->e);
t *= sin1 / kb;
if (t >= 0.0f && t < limit) {
@@ -6996,11 +7037,9 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
return limit;
}
-/*
- * We have an edge A between vertices a and b,
- * where EdgeHalf ea is the half of A that starts at a.
- * For vertex-only bevels, the new vertices slide from a at a rate ka*t
- * and from b at a rate kb*t.
+/**
+ * We have an edge A between vertices a and b, where EdgeHalf ea is the half of A that starts at a.
+ * For vertex-only bevels, the new vertices slide from a at a rate ka*t and from b at a rate kb*t.
* We want to calculate the t at which the two meet.
*/
static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
@@ -7024,13 +7063,10 @@ static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
return limit;
}
-/*
- * Calculate an offset that is the lesser of the current
- * bp.offset and the maximum possible offset before geometry
- * collisions happen.
- * If the offset changes as a result of this, adjust the
- * current edge offset specs to reflect this clamping,
- * and store the new offset in bp.offset.
+/**
+ * Calculate an offset that is the lesser of the current bp.offset and the maximum possible offset
+ * before geometry collisions happen. If the offset changes as a result of this, adjust the current
+ * edge offset specs to reflect this clamping, and store the new offset in bp.offset.
*/
static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
{
@@ -7142,7 +7178,7 @@ void BM_mesh_bevel(BMesh *bm,
bp.offset_type = offset_type;
bp.seg = (int)segments;
bp.profile = profile;
- bp.pro_super_r = -logf(2.0) / logf(sqrtf(profile)); /* convert to superellipse exponent */
+ bp.pro_super_r = -logf(2.0) / logf(sqrtf(profile)); /* Convert to superellipse exponent. */
bp.vertex_only = vertex_only;
bp.use_weights = use_weights;
bp.loop_slide = loop_slide;
@@ -7164,7 +7200,8 @@ void BM_mesh_bevel(BMesh *bm,
bp.custom_profile = custom_profile;
bp.vmesh_method = vmesh_method;
- /* Disable the miters with the cutoff vertex mesh method, this combination isn't useful anyway */
+ /* Disable the miters with the cutoff vertex mesh method, this combination isn't useful anyway.
+ */
if (bp.vmesh_method == BEVEL_VMESH_CUTOFF) {
bp.miter_outer = BEVEL_MITER_SHARP;
bp.miter_inner = BEVEL_MITER_SHARP;
@@ -7184,18 +7221,18 @@ void BM_mesh_bevel(BMesh *bm,
}
if (bp.offset > 0) {
- /* primary alloc */
+ /* Primary alloc. */
bp.vert_hash = BLI_ghash_ptr_new(__func__);
bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
BLI_memarena_use_calloc(bp.mem_arena);
- /* Get the 2D profile point locations from either the superellipse or the custom profile */
+ /* Get the 2D profile point locations from either the superellipse or the custom profile. */
set_profile_spacing(&bp, &bp.pro_spacing, bp.use_custom_profile);
if (bp.seg > 1) {
bp.pro_spacing.fullness = find_profile_fullness(&bp);
}
- /* Get separate non-custom profile samples for the miter profiles if they are needed */
+ /* Get separate non-custom profile samples for the miter profiles if they are needed. */
if (bp.use_custom_profile &&
(bp.miter_inner != BEVEL_MITER_SHARP || bp.miter_outer != BEVEL_MITER_SHARP)) {
set_profile_spacing(&bp, &bp.pro_spacing_miter, false);
@@ -7204,7 +7241,7 @@ void BM_mesh_bevel(BMesh *bm,
bp.face_hash = BLI_ghash_ptr_new(__func__);
BLI_ghash_flag_set(bp.face_hash, GHASH_FLAG_ALLOW_DUPES);
- /* Analyze input vertices, sorting edges and assigning initial new vertex positions */
+ /* Analyze input vertices, sorting edges and assigning initial new vertex positions. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = bevel_vert_construct(bm, &bp, v);
@@ -7214,11 +7251,11 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* Perhaps clamp offset to avoid geometry colliisions */
+ /* Perhaps clamp offset to avoid geometry colliisions. */
if (limit_offset) {
bevel_limit_offset(&bp, bm);
- /* Assign initial new vertex positions */
+ /* Assign initial new vertex positions. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = find_bevvert(&bp, v);
@@ -7229,7 +7266,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* Perhaps do a pass to try to even out widths */
+ /* Perhaps do a pass to try to even out widths. */
if (!bp.vertex_only && bp.offset_adjust && bp.offset_type != BEVEL_AMT_PERCENT) {
adjust_offsets(&bp, bm);
}
@@ -7243,7 +7280,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* Build the meshes around vertices, now that positions are final */
+ /* Build the meshes around vertices, now that positions are final. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = find_bevvert(&bp, v);
@@ -7253,7 +7290,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* Build polygons for edges */
+ /* Build polygons for edges. */
if (!bp.vertex_only) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
@@ -7262,7 +7299,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* Extend edge data like sharp edges and precompute normals for harden */
+ /* Extend edge data like sharp edges and precompute normals for harden. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = find_bevvert(&bp, v);
@@ -7272,7 +7309,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* Rebuild face polygons around affected vertices */
+ /* Rebuild face polygons around affected vertices. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bevel_rebuild_existing_polygons(bm, &bp, v);
@@ -7295,7 +7332,7 @@ void BM_mesh_bevel(BMesh *bm,
}
/* When called from operator (as opposed to modifier), bm->use_toolflags
- * will be set, and we need to transfer the oflags to BM_ELEM_TAGs */
+ * will be set, and we need to transfer the oflags to BM_ELEM_TAGs. */
if (bm->use_toolflags) {
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_vert_flag_test(bm, v, VERT_OUT)) {
@@ -7309,7 +7346,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* clear the BM_ELEM_LONG_TAG tags, which were only set on some edges in F_EDGE faces */
+ /* Clear the BM_ELEM_LONG_TAG tags, which were only set on some edges in F_EDGE faces. */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (get_face_kind(&bp, f) != F_EDGE) {
continue;
@@ -7319,7 +7356,7 @@ void BM_mesh_bevel(BMesh *bm,
}
}
- /* primary free */
+ /* Primary free. */
BLI_ghash_free(bp.vert_hash, NULL, NULL);
BLI_ghash_free(bp.face_hash, NULL, NULL);
BLI_memarena_free(bp.mem_arena);
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index 2cc86a7c93f..e2741b806c2 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -177,8 +177,8 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
#else
BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
- unsigned vert_seek_a_tot = 0;
- unsigned vert_seek_b_tot = 0;
+ uint vert_seek_a_tot = 0;
+ uint vert_seek_b_tot = 0;
#endif
BMIter iter;
diff --git a/source/blender/collada/BCAnimationSampler.cpp b/source/blender/collada/BCAnimationSampler.cpp
index f1282e6a347..e6996e95a5b 100644
--- a/source/blender/collada/BCAnimationSampler.cpp
+++ b/source/blender/collada/BCAnimationSampler.cpp
@@ -32,7 +32,7 @@ extern "C" {
#include "BKE_constraint.h"
#include "BKE_key.h"
#include "BKE_main.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BLI_listbase.h"
#include "DNA_anim_types.h"
diff --git a/source/blender/collada/BCAnimationSampler.h b/source/blender/collada/BCAnimationSampler.h
index 0f192a7a68b..96138d0cbca 100644
--- a/source/blender/collada/BCAnimationSampler.h
+++ b/source/blender/collada/BCAnimationSampler.h
@@ -23,7 +23,7 @@
extern "C" {
#include "BKE_action.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BLI_math_rotation.h"
#include "DNA_action_types.h"
}
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index bfec387a199..0119aba7dfd 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -33,7 +33,7 @@
extern "C" {
#include "BKE_global.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
}
@@ -175,21 +175,6 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
* joint names: ob -> vertex group names
* vertex group weights: me->dvert -> groups -> index, weight */
-#if 0
- me->dvert :
-
- typedef struct MDeformVert {
- struct MDeformWeight *dw;
- int totweight;
- int flag; // flag only in use for weightpaint now
- } MDeformVert;
-
- typedef struct MDeformWeight {
- int def_nr;
- float weight;
- } MDeformWeight;
-#endif
-
bool use_instantiation = this->export_settings.get_use_object_instantiation();
Mesh *me;
@@ -245,19 +230,17 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
float sumw = 0.0f;
for (j = 0; j < vert->totweight; j++) {
- int idx = vert->dw[j].def_nr;
+ uint idx = vert->dw[j].def_nr;
if (idx >= joint_index_by_def_index.size()) {
/* XXX: Maybe better find out where and
* why the Out Of Bound indexes get created ? */
oob_counter += 1;
}
else {
- if (idx >= 0) {
- int joint_index = joint_index_by_def_index[idx];
- if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
- jw[joint_index] += vert->dw[j].weight;
- sumw += vert->dw[j].weight;
- }
+ int joint_index = joint_index_by_def_index[idx];
+ if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
+ jw[joint_index] += vert->dw[j].weight;
+ sumw += vert->dw[j].weight;
}
}
}
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index f2c52b125a4..9b66ff429e1 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -59,7 +59,7 @@ extern "C" {
#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_light.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_scene.h"
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 4f70281fb45..286bcbfb759 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -79,7 +79,8 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
error_context = "File access";
}
- else if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_REQUIRED_ATTRIBUTE_MISSING) {
+ else if (parserError.getErrorType() ==
+ GeneratedSaxParser::ParserError::ERROR_REQUIRED_ATTRIBUTE_MISSING) {
isError = true;
}
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 1c8123e8384..640bf3c0633 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -34,7 +34,7 @@ extern "C" {
#include "BKE_customdata.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
}
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index c76cb8c80a6..14c09a95d10 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -37,7 +37,7 @@ extern "C" {
#include "BKE_customdata.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -279,7 +279,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh)
const std::string &name = bc_get_dae_name(mesh);
- for (unsigned i = 0; i < prim_arr.getCount(); i++) {
+ for (unsigned int i = 0; i < prim_arr.getCount(); i++) {
COLLADAFW::MeshPrimitive *mp = prim_arr[i];
COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
@@ -683,7 +683,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
// XXX The proper function of TRIANGLE_FANS is not tested!!!
// XXX In particular the handling of the normal_indices looks very wrong to me
if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
- unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount();
+ unsigned int grouped_vertex_count = mp->getGroupedVertexElementsCount();
for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) {
unsigned int first_vertex = position_indices[0]; // Store first trifan vertex
unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 24449de0ddd..42901bd2a4a 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -23,7 +23,7 @@ extern "C" {
#include "BKE_collection.h"
#include "BKE_object.h"
#include "BLI_listbase.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
}
#include "SceneExporter.h"
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index df79d863391..26b392af0a1 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -54,7 +54,7 @@ extern "C" {
#include "BKE_object.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index fad8bc22e08..737d66e07cb 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -83,8 +83,8 @@ set(SRC
intern/depsgraph_query.cc
intern/depsgraph_query_foreach.cc
intern/depsgraph_query_iter.cc
- intern/depsgraph_relation.cc
intern/depsgraph_registry.cc
+ intern/depsgraph_relation.cc
intern/depsgraph_tag.cc
intern/depsgraph_type.cc
intern/depsgraph_update.cc
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index b74e5715e14..c2222bfcbce 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -44,7 +44,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
@@ -84,7 +84,7 @@ extern "C" {
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_editmesh.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
index 853198109a2..0fbf658ceb3 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -35,7 +35,7 @@ extern "C" {
#include "DNA_anim_types.h"
#include "BKE_animsys.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
}
#include "DEG_depsgraph.h"
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index f21d96a304c..5357d6167be 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -29,7 +29,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_view3d_types.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_gpencil.h"
#include "BKE_object.h"
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index a4e671211eb..0106aae686d 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -23,7 +23,7 @@
#include "DRW_render.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_paint.h"
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index f087b5a70b8..3764994613f 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -876,7 +876,7 @@ static void camera_view3d_reconstruction(OVERLAY_ExtraCallBuffers *cb,
UI_GetThemeColor4ubv(TH_TEXT, text_color_unselected);
float camera_mat[4][4], normal_mat[4][4];
- BKE_tracking_get_camera_object_matrix(scene, ob, camera_mat);
+ BKE_tracking_get_camera_object_matrix(ob, camera_mat);
normalize_m4_m4(normal_mat, ob->obmat);
diff --git a/source/blender/draw/engines/overlay/overlay_facing.c b/source/blender/draw/engines/overlay/overlay_facing.c
index fd974e9b8b8..74d82262019 100644
--- a/source/blender/draw/engines/overlay/overlay_facing.c
+++ b/source/blender/draw/engines/overlay/overlay_facing.c
@@ -21,6 +21,7 @@
*/
#include "DRW_render.h"
+#include "BKE_paint.h"
#include "overlay_private.h"
@@ -45,9 +46,17 @@ void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
- struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
- if (geom) {
- DRW_shgroup_call(pd->facing_grp, geom, ob);
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ !DRW_state_is_image_render();
+ if (use_sculpt_pbvh) {
+ DRW_shgroup_call_sculpt(pd->facing_grp, ob, false, false, false);
+ }
+ else {
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ DRW_shgroup_call(pd->facing_grp, geom, ob);
+ }
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index 1c62d41a3bc..8d78373a057 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -653,7 +653,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
return;
}
- WORKBENCH_MaterialData *material;
+ WORKBENCH_MaterialData *material = NULL;
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c
index 941a6741998..1fb0b394cb1 100644
--- a/source/blender/draw/engines/workbench/workbench_studiolight.c
+++ b/source/blender/draw/engines/workbench/workbench_studiolight.c
@@ -69,63 +69,6 @@ void studiolight_update_world(WORKBENCH_PrivateData *wpd,
}
copy_v3_v3(wd->ambient_color, studiolight->light_ambient);
-
-#if 0
- BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED);
-
-# if STUDIOLIGHT_SH_BANDS == 2
- /* Use Geomerics non-linear SH. */
- mul_v3_v3fl(wd->spherical_harmonics_coefs[0], sl->spherical_harmonics_coefs[0], M_1_PI);
- /* Swizzle to make shader code simpler. */
- for (int i = 0; i < 3; i++) {
- copy_v3_fl3(wd->spherical_harmonics_coefs[i + 1],
- -sl->spherical_harmonics_coefs[3][i],
- sl->spherical_harmonics_coefs[2][i],
- -sl->spherical_harmonics_coefs[1][i]);
-
- /* 1.5f is to improve the contrast a bit. */
- mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], M_1_PI * 1.5f);
- }
-
- /* Precompute as much as we can. See shader code for derivation. */
- float len_r1[3], lr1_r0[3], p[3], a[3];
- for (int i = 0; i < 3; i++) {
- mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 0.5f);
- len_r1[i] = len_v3(wd->spherical_harmonics_coefs[i + 1]);
- mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 1.0f / len_r1[i]);
- }
- /* lr1_r0 = lenR1 / R0; */
- copy_v3_v3(lr1_r0, wd->spherical_harmonics_coefs[0]);
- invert_v3(lr1_r0);
- mul_v3_v3(lr1_r0, len_r1);
- /* p = 1.0 + 2.0 * lr1_r0; */
- copy_v3_v3(p, lr1_r0);
- mul_v3_fl(p, 2.0f);
- add_v3_fl(p, 1.0f);
- /* a = (1.0 - lr1_r0) / (1.0 + lr1_r0); */
- copy_v3_v3(a, lr1_r0);
- add_v3_fl(a, 1.0f);
- invert_v3(a);
- negate_v3(lr1_r0);
- add_v3_fl(lr1_r0, 1.0f);
- mul_v3_v3(a, lr1_r0);
- /* sh_coefs[4] = p; */
- copy_v3_v3(wd->spherical_harmonics_coefs[4], p);
- /* sh_coefs[5] = R0 * a; */
- mul_v3_v3v3(wd->spherical_harmonics_coefs[5], wd->spherical_harmonics_coefs[0], a);
- /* sh_coefs[0] = R0 * (1.0 - a) * (p + 1.0); */
- negate_v3(a);
- add_v3_fl(a, 1.0f);
- add_v3_fl(p, 1.0f);
- mul_v3_v3(a, p);
- mul_v3_v3(wd->spherical_harmonics_coefs[0], a);
-# else
- for (int i = 0; i < STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN; i++) {
- /* Can't memcpy because of alignment */
- copy_v3_v3(wd->spherical_harmonics_coefs[i], sl->spherical_harmonics_coefs[i]);
- }
-# endif
-#endif
}
static void compute_parallel_lines_nor_and_dist(const float v1[2],
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 7408c8d0e38..ed60e16c7cc 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -987,8 +987,9 @@ void DRW_mesh_batch_cache_create_requested(
if (cache->batch_requested == 0) {
#ifdef DEBUG
goto check;
-#endif
+#else
return;
+#endif
}
/* Sanity check. */
@@ -1127,8 +1128,9 @@ void DRW_mesh_batch_cache_create_requested(
if ((batch_requested & ~cache->batch_ready) == 0) {
#ifdef DEBUG
goto check;
-#endif
+#else
return;
+#endif
}
cache->batch_ready |= batch_requested;
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index e90289de963..7a2e4cb5269 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -46,7 +46,7 @@
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mask.h"
#include "BKE_global.h"
#include "BKE_scene.h"
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index dc413e936eb..9c65d5fcd2d 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -501,7 +501,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
ok |= KEYFRAME_OK_KEY; \
\
if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \
- /* Only act on visible items, so check handle visiblity state. */ \
+ /* Only act on visible items, so check handle visibility state. */ \
const bool handles_visible = ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ? \
(BEZT_ISSEL_ANY(bezt)) : \
true); \
@@ -1459,7 +1459,7 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
{
- /* Only act on visible items, so check handle visiblity state. */
+ /* Only act on visible items, so check handle visibility state. */
const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ?
(BEZT_ISSEL_ANY(bezt)) :
true);
@@ -1485,7 +1485,7 @@ static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
{
- /* Only act on visible items, so check handle visiblity state. */
+ /* Only act on visible items, so check handle visibility state. */
const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ?
(BEZT_ISSEL_ANY(bezt)) :
true);
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 4cda7f264aa..63c096abc6d 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -41,7 +41,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 7ed41b5b4d0..4c64f9c7248 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -576,7 +576,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
float quat_diff[4];
/* calculate the delta transform from the previous to the current */
- /* TODO: investigate ways to favour one transform more? */
+ /* TODO: investigate ways to favor one transform more? */
sub_qt_qtqt(quat_diff, quat_curr, quat_prev);
/* increase the original by the delta transform, by an amount determined by percentage */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index f5920bfb258..072cbb29378 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -44,7 +44,7 @@
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index c9206e8df4a..3db27c20d16 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -43,7 +43,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_font.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index 7dc3aa1273f..1277d28e915 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -31,7 +31,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index 539f80846fd..068416595a4 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -31,7 +31,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 77f7df25316..9987e7decff 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -57,7 +57,7 @@
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 7f7778639d6..b5a34606bf3 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -51,7 +51,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index d2d8972c245..de7d2e1a395 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -72,7 +72,7 @@ void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(
- struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos);
+ struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos);
/* node_draw.c */
void ED_node_tree_update(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 37ffb1b9d6d..a1bc3b028b6 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -452,7 +452,7 @@ float ED_view3d_radius_to_dist(const struct View3D *v3d,
const bool use_aspect,
const float radius);
-void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos);
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned int pos);
/* backbuffer select and draw support */
void ED_view3d_backbuf_depth_validate(struct ViewContext *vc);
@@ -622,8 +622,12 @@ void ED_view3d_update_viewmat(struct Depsgraph *depsgraph,
float winmat[4][4],
const struct rcti *rect,
bool offscreen);
-bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
-char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
+bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float quat[4]);
+bool ED_view3d_quat_to_axis_view(const float viewquat[4],
+ const float epsilon,
+ char *r_view,
+ char *r_view_axis_rotation);
+
char ED_view3d_lock_view_from_index(int index);
char ED_view3d_axis_view_opposite(char view);
bool ED_view3d_lock(struct RegionView3D *rv3d);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index cc677f8f7cb..5710be04477 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -40,8 +40,8 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_screen.h"
@@ -650,7 +650,7 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
bool is_strict_find;
/* Remove override operation for given item,
* add singular operations for the other items as needed. */
- IDOverrideLibraryPropertyOperation *opop = BKE_override_library_property_operation_find(
+ IDOverrideLibraryPropertyOperation *opop = BKE_lib_override_library_property_operation_find(
oprop, NULL, NULL, index, index, false, &is_strict_find);
BLI_assert(opop != NULL);
if (!is_strict_find) {
@@ -659,22 +659,22 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
* before removing generic one. */
for (int idx = RNA_property_array_length(&ptr, prop); idx--;) {
if (idx != index) {
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
}
}
}
- BKE_override_library_property_operation_delete(oprop, opop);
+ BKE_lib_override_library_property_operation_delete(oprop, opop);
if (!is_template) {
RNA_property_copy(bmain, &ptr, &src, prop, index);
}
if (BLI_listbase_is_empty(&oprop->operations)) {
- BKE_override_library_property_delete(id->override_library, oprop);
+ BKE_lib_override_library_property_delete(id->override_library, oprop);
}
}
else {
/* Just remove whole generic override operation of this property. */
- BKE_override_library_property_delete(id->override_library, oprop);
+ BKE_lib_override_library_property_delete(id->override_library, oprop);
if (!is_template) {
RNA_property_copy(bmain, &ptr, &src, prop, -1);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 4c86e3252ed..fcb51838d59 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -61,8 +61,8 @@
#include "BKE_idcode.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -544,10 +544,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
case UI_ID_LOCAL:
if (id) {
Main *bmain = CTX_data_main(C);
- if (BKE_override_library_is_enabled() && CTX_wm_window(C)->eventstate->shift) {
+ if (BKE_lib_override_library_is_enabled() && CTX_wm_window(C)->eventstate->shift) {
if (ID_IS_OVERRIDABLE_LIBRARY(id)) {
/* Only remap that specific ID usage to overriding local data-block. */
- ID *override_id = BKE_override_library_create_from_id(bmain, id, false);
+ ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
if (override_id != NULL) {
BKE_main_id_clear_newpoins(bmain);
@@ -570,7 +570,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_OVERRIDE:
if (id && id->override_library) {
- BKE_override_library_free(&id->override_library, true);
+ BKE_lib_override_library_free(&id->override_library, true);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
@@ -894,7 +894,7 @@ static void template_ID(bContext *C,
0,
0,
0,
- BKE_override_library_is_enabled() ?
+ BKE_lib_override_library_is_enabled() ?
TIP_("Direct linked library data-block, click to make local, "
"Shift + Click to create a library override") :
TIP_("Direct linked library data-block, click to make local"));
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index a23bd7dad35..517d8ca51a3 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -722,7 +722,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
* - width is OK, but need to check if outside of boundaries
*
* So, resolution is to just shift view by the gap between the extremities.
- * We favour moving the 'minimum' across, as that's origin for most things
+ * We favor moving the 'minimum' across, as that's origin for most things.
* (XXX - in the past, max was favored... if there are bugs, swap!)
*/
if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
@@ -779,7 +779,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
* - height is OK, but need to check if outside of boundaries
*
* So, resolution is to just shift view by the gap between the extremities.
- * We favour moving the 'minimum' across, as that's origin for most things
+ * We favor moving the 'minimum' across, as that's origin for most things.
*/
if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) {
/* outside boundaries on both sides,
@@ -1343,7 +1343,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_s
uchar grid_line_color[3];
/* Make an estimate of at least how many vertices will be needed */
- unsigned vertex_count = 4;
+ uint vertex_count = 4;
vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index ff2bc72c2f7..6c5abf60272 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -32,7 +32,7 @@
#include "BKE_cachefile.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index ebd1e62e596..2e175cb156c 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -153,7 +153,9 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
else {
- BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection");
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "No other selected objects have wire or boundary edges to use for projection");
return OPERATOR_CANCELLED;
}
}
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 139f05db01c..cb67cb404e4 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -30,7 +30,7 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_paint.h"
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 0c564bb7593..4003a7dd7bb 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -48,7 +48,7 @@
#include "BKE_deform.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -3935,7 +3935,10 @@ static Base *mesh_separate_tagged(
/* DAG_relations_tag_update(bmain); */
/* new in 2.5 */
- BKE_object_material_array_assign(bmain, base_new->object, BKE_object_material_array(obedit), *BKE_object_material_num(obedit));
+ BKE_object_material_array_assign(bmain,
+ base_new->object,
+ BKE_object_material_array(obedit),
+ *BKE_object_material_num(obedit));
ED_object_base_select(base_new, BA_SELECT);
@@ -4002,7 +4005,10 @@ static Base *mesh_separate_arrays(Main *bmain,
/* DAG_relations_tag_update(bmain); */
/* new in 2.5 */
- BKE_object_material_array_assign(bmain, base_new->object, BKE_object_material_array(obedit), *BKE_object_material_num(obedit));
+ BKE_object_material_array_assign(bmain,
+ base_new->object,
+ BKE_object_material_array(obedit),
+ *BKE_object_material_num(obedit));
ED_object_base_select(base_new, BA_SELECT);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index fa282612a8e..832e2a94488 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -45,7 +45,7 @@
#include "BKE_editmesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 04323972666..5cc9f70b9af 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -69,9 +69,9 @@
#include "BKE_light.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 5d7a0efb7bf..46df7e6e1d4 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -39,7 +39,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c
index a00e5e7b198..a278ce90eda 100644
--- a/source/blender/editors/object/object_collection.c
+++ b/source/blender/editors/object/object_collection.c
@@ -32,7 +32,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index d04e15461ab..5e85d47a402 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -543,9 +543,9 @@ bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int f
* is flagged for editmode, without 'obedit' being set [#35489] */
if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
obedit->mode &= ~OB_MODE_EDIT;
+ /* Also happens when mesh is shared across multiple objects. [#T69834] */
+ DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
- /* Also happens when mesh is shared across multiple objects. [#T69834] */
- DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
return true;
}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index db946b63323..e440062738c 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -55,7 +55,7 @@
#include "BKE_gpencil_modifier.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index e00b7fd2dc5..8ee061efc08 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -70,10 +70,10 @@
#include "BKE_light.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -616,8 +616,6 @@ void OBJECT_OT_parent_clear(wmOperatorType *ot)
ot->invoke = WM_menu_invoke;
ot->exec = parent_clear_exec;
- ot->poll = ED_operator_object_active_editable;
-
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1056,7 +1054,9 @@ static int parent_set_invoke_menu(bContext *C, wmOperatorType *ot)
if (parent->type == OB_ARMATURE) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE);
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_NAME);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
+ if (!has_children_of_type.gpencil) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
+ }
if (has_children_of_type.mesh || has_children_of_type.gpencil) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
}
@@ -2453,7 +2453,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- success = BKE_override_library_create_from_tag(bmain);
+ success = BKE_lib_override_library_create_from_tag(bmain);
/* Instantiate our newly overridden objects in scene, if not yet done. */
Scene *scene = CTX_data_scene(C);
@@ -2485,7 +2485,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
new_ob->id.override_library->flag &= ~OVERRIDE_LIBRARY_AUTO;
}
/* We still want to store all objects' current override status (i.e. change of parent). */
- BKE_override_library_operations_create(bmain, &new_ob->id, true);
+ BKE_lib_override_library_operations_create(bmain, &new_ob->id, true);
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
@@ -2520,7 +2520,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
make_override_library_tag_object(obact, ob);
}
- success = BKE_override_library_create_from_tag(bmain);
+ success = BKE_lib_override_library_create_from_tag(bmain);
/* Also, we'd likely want to lock by default things like
* transformations of implicitly overridden objects? */
@@ -2533,7 +2533,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
else {
/* For now, remapp all local usages of linked ID to local override one here. */
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
- success = (BKE_override_library_create_from_id(bmain, &obact->id, true) != NULL);
+ success = (BKE_lib_override_library_create_from_id(bmain, &obact->id, true) != NULL);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
@@ -2547,7 +2547,7 @@ static bool make_override_library_poll(bContext *C)
Object *obact = CTX_data_active_object(C);
/* Object must be directly linked to be overridable. */
- return (BKE_override_library_is_enabled() && ED_operator_objectmode(C) && obact != NULL &&
+ return (BKE_lib_override_library_is_enabled() && ED_operator_objectmode(C) && obact != NULL &&
((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) ||
(!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
ID_IS_LINKED(obact->instance_collection))));
@@ -2645,8 +2645,11 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
ot->description = "Make linked data local to each object";
ot->idname = "OBJECT_OT_make_single_user";
+ /* Note that the invoke callback is only used from operator search,
+ * otherwise this does nothing by default. */
+
/* api callbacks */
- ot->invoke = WM_menu_invoke;
+ ot->invoke = WM_operator_props_popup_confirm;
ot->exec = make_single_user_exec;
ot->poll = ED_operator_objectmode;
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 73fd45693a2..70e3c93cbd9 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -40,7 +40,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 63362f7a86d..43e46f6bef2 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -51,7 +51,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 4f56664ec99..e35c806473a 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -54,7 +54,7 @@
#include "BKE_multires.h"
#include "BKE_armature.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_tracking.h"
#include "BKE_gpencil.h"
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 05fa78aab1c..9ccbc7a1a0a 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -701,7 +701,7 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *
PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop),
bool *r_free,
- const unsigned int selection_mask)
+ const uint selection_mask)
{
Object *ob;
EnumPropertyItem *item = NULL;
@@ -1807,10 +1807,10 @@ static void vgroup_smooth_subset(Object *ob,
float *weight_accum_prev;
float *weight_accum_curr;
- unsigned int subset_index;
+ uint subset_index;
/* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
- unsigned int *verts_used;
+ uint *verts_used;
STACK_DECLARE(verts_used);
BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
@@ -1882,12 +1882,12 @@ static void vgroup_smooth_subset(Object *ob,
memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
for (iter = 0; iter < repeat; iter++) {
- unsigned *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
+ uint *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
/* avoid looping over all verts */
// for (i = 0; i < dvert_tot; i++)
for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
- const unsigned int i = *vi_step;
+ const uint i = *vi_step;
float weight_tot = 0.0f;
float weight = 0.0f;
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index c666697d15a..466b87755fe 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -39,7 +39,7 @@
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index af77d966c9d..c4812d373ab 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -505,7 +505,9 @@ static void fluid_free_startjob(void *customdata, short *stop, short *do_update,
cache_map |= FLUID_DOMAIN_OUTDATED_PARTICLES;
}
if (fluid_is_free_guiding(job) || fluid_is_free_all(job)) {
- cache_map |= FLUID_DOMAIN_OUTDATED_GUIDE;
+ cache_map |= (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_GUIDE);
}
#ifdef WITH_FLUID
BKE_fluid_cache_free(mds, job->ob, cache_map);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 303a0714388..a59b031298c 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -31,7 +31,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 43ca421b9d0..78369345b9a 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -35,7 +35,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 11821fcdc45..f1ded6c21d3 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -50,7 +50,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_object.h"
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 43670c8fb1a..26fd9f14c64 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -50,7 +50,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 3ea583e5b1f..3ca7dde3524 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -62,7 +62,7 @@
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_icons.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_light.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -465,7 +465,8 @@ static Scene *preview_prepare_scene(
copy_v4_v4(base->object->color, sp->color);
if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
- /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI */
+ /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI
+ */
Material ***matar = BKE_object_material_array(base->object);
int actcol = max_ii(base->object->actcol - 1, 0);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 3a3c60a6dd4..95bc90c8e5f 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -51,7 +51,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_material.h"
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index 22c91686bbf..ad940a8e87d 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -28,7 +28,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 7db634660af..c85beefe1f4 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -3290,7 +3290,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy, float x0, float
if (count_fine > 0) {
GPU_vertformat_clear(format);
pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GPU_PRIM_LINES, 4 * count_fine + 4 * count_large);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 501c36286d0..1520566cd9d 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -39,7 +39,7 @@
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 14ea3aca623..bd7475dc1a2 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -51,7 +51,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_icons.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_object.h"
@@ -3812,6 +3812,7 @@ static void region_quadview_init_rv3d(
rv3d->viewlock = viewlock;
rv3d->view = view;
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
rv3d->persp = persp;
ED_view3d_lock(rv3d);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index bbb959c27ff..7f3131a705e 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -29,7 +29,7 @@
#include "BKE_appdir.h"
#include "BKE_blendfile.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_workspace.h"
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 19b4b9f569c..cf796c7dd3c 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1103,8 +1103,11 @@ static void cursor_draw_point_screen_space(
copy_v3_v3(location, true_location);
mul_m4_v3(obmat, location);
ED_view3d_project(ar, location, translation_vertex_cursor);
- imm_draw_circle_fill_3d(
- gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], size, 10);
+ /* Do not draw points behind the view. Z [near, far] is mapped to [-1, 1]. */
+ if (translation_vertex_cursor[2] <= 1.0f) {
+ imm_draw_circle_fill_3d(
+ gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], size, 10);
+ }
}
static void cursor_draw_tiling_preview(const uint gpuattr,
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 62c31c91f8d..8a98b15088f 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -87,39 +87,35 @@ static PaintCurvePoint *paintcurve_point_get_closest(
{
PaintCurvePoint *pcp, *closest = NULL;
int i;
- float dist, closest_dist = FLT_MAX;
+ float closest_dist = threshold;
for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
- dist = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
- if (dist < threshold) {
- if (dist < closest_dist) {
- closest = pcp;
- closest_dist = dist;
- if (point) {
- *point = SEL_F1;
- }
- }
+ float dist[3];
+ char point_sel = 0;
+
+ dist[0] = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
+ dist[1] = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
+ dist[2] = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
+
+ if (dist[1] < closest_dist) {
+ closest_dist = dist[1];
+ point_sel = SEL_F2;
}
- if (!ignore_pivot) {
- dist = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
- if (dist < threshold) {
- if (dist < closest_dist) {
- closest = pcp;
- closest_dist = dist;
- if (point) {
- *point = SEL_F2;
- }
- }
- }
+ if (dist[0] < closest_dist) {
+ closest_dist = dist[0];
+ point_sel = SEL_F1;
+ }
+ if (dist[2] < closest_dist) {
+ closest_dist = dist[2];
+ point_sel = SEL_F3;
}
- dist = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
- if (dist < threshold) {
- if (dist < closest_dist) {
- closest = pcp;
- closest_dist = dist;
- if (point) {
- *point = SEL_F3;
+ if (point_sel) {
+ closest = pcp;
+ if (point) {
+ if (ignore_pivot && point_sel == SEL_F2) {
+ point_sel = (dist[0] < dist[2]) ? SEL_F1 : SEL_F3;
}
+ *point = point_sel;
}
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 7f71110b360..a667c7062e6 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -1646,7 +1646,7 @@ void paint_2d_stroke(void *ps,
continue;
}
- ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, &tile->iuser, NULL);
+ ImBuf *ibuf = tile->canvas;
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
@@ -1711,6 +1711,7 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
}
if (ibuf->channels != 4) {
+ BKE_image_release_ibuf(s->image, ibuf, NULL);
BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
MEM_freeN(s->tiles);
MEM_freeN(s);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 8faf5cba341..34cde8ff48c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -66,7 +66,7 @@
#include "BKE_customdata.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 7863e18394c..8c8fc412663 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -33,7 +33,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_paint.h"
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index e799e54188d..37cc543872e 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -545,7 +545,7 @@ void paint_sample_color(
}
ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, NULL);
- if (ibuf && ibuf->rect) {
+ if (ibuf && (ibuf->rect || ibuf->rect_float)) {
sample_success = true;
u = u * ibuf->x;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 015657318b2..23521b8496c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -50,7 +50,7 @@
#include "BKE_image.h"
#include "BKE_kelvinlet.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -291,7 +291,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
for (i = 0; i < ss->pmap[(int)index].count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
- unsigned f_adj_v[2];
+ uint f_adj_v[2];
if (poly_get_adj_loops_from_vert(p, ss->mloop, (int)index, f_adj_v) != -1) {
int j;
for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
@@ -2203,7 +2203,7 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob)
/* For the smooth brush, uses the neighboring vertices around vert to calculate
* a smoothed location for vert. Skips corner vertices (used by only one
* polygon.) */
-static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert)
+static void neighbor_average(SculptSession *ss, float avg[3], uint vert)
{
const MeshElemMap *vert_map = &ss->pmap[vert];
const MVert *mvert = ss->mvert;
@@ -2217,7 +2217,7 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert)
for (i = 0; i < vert_map->count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
- unsigned f_adj_v[2];
+ uint f_adj_v[2];
if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
int j;
@@ -2243,7 +2243,7 @@ static void neighbor_average(SculptSession *ss, float avg[3], unsigned vert)
/* Similar to neighbor_average(), but returns an averaged mask value
* instead of coordinate. Also does not restrict based on border or
* corner vertices. */
-static float neighbor_average_mask(SculptSession *ss, unsigned vert)
+static float neighbor_average_mask(SculptSession *ss, uint vert)
{
const float *vmask = ss->vmask;
float avg = 0;
@@ -2251,7 +2251,7 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
for (i = 0; i < ss->pmap[vert].count; i++) {
const MPoly *p = &ss->mpoly[ss->pmap[vert].indices[i]];
- unsigned f_adj_v[2];
+ uint f_adj_v[2];
if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
int j;
@@ -7537,7 +7537,9 @@ static void sculpt_flush_update_step(bContext *C, SculptUpdateType update_flags)
ED_region_tag_redraw(ar);
}
else {
- /* Fast path where we just update the BVH nodes that changed. */
+ /* Fast path where we just update the BVH nodes that changed, and redraw
+ * only the part of the 3D viewport where changes happened. */
+ rcti r;
if (update_flags & SCULPT_UPDATE_COORDS) {
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB);
@@ -7547,7 +7549,21 @@ static void sculpt_flush_update_step(bContext *C, SculptUpdateType update_flags)
sculpt_update_object_bounding_box(ob);
}
- ED_region_tag_redraw(ar);
+ if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) {
+ if (ss->cache) {
+ ss->cache->current_r = r;
+ }
+
+ /* previous is not set in the current cache else
+ * the partial rect will always grow */
+ sculpt_extend_redraw_rect_previous(ob, &r);
+
+ r.xmin += ar->winrct.xmin - 2;
+ r.xmax += ar->winrct.xmin + 2;
+ r.ymin += ar->winrct.ymin - 2;
+ r.ymax += ar->winrct.ymin + 2;
+ ED_region_tag_redraw_partial(ar, &r, true);
+ }
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 5d92b202997..b29bbfd1fb0 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -35,9 +35,9 @@
struct KeyBlock;
struct Object;
+struct SculptPoseIKChainSegment;
struct SculptUndoNode;
struct bContext;
-struct SculptPoseIKChainSegment;
bool sculpt_mode_poll(struct bContext *C);
bool sculpt_mode_poll_view3d(struct bContext *C);
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 69745663c02..68e9e6d4ced 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -41,7 +41,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 5fdabea62c1..71802dd844f 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -46,7 +46,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_key.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_nla.h"
#include "BKE_scene.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index fbefc884589..2114c4cac79 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -44,7 +44,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_movieclip.h"
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 3ede0158f7a..71ffb1af434 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -48,7 +48,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 04c939ec41b..a0ac832522d 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -36,7 +36,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
#include "BKE_screen.h"
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index de0025a53d2..8bc77cf82cb 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -210,7 +210,7 @@ static int set_origin_exec(bContext *C, wmOperator *op)
mul_v3_fl(median, 1.0f / selected_count);
float mat[4][4], vec[3];
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
mul_v3_m4v3(vec, mat, median);
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
@@ -267,7 +267,7 @@ static void set_axis(Scene *scene,
BKE_object_to_mat4(ob, obmat);
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
mul_v3_m4v3(vec, mat, track->bundle_pos);
copy_v3_v3(dvec, vec);
@@ -422,7 +422,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
/* Get 3 bundles to use as reference. */
track = tracksbase->first;
@@ -629,7 +629,7 @@ static int do_set_scale(bContext *C, wmOperator *op, bool scale_solution, bool a
}
}
- BKE_tracking_get_camera_object_matrix(scene, camera, mat);
+ BKE_tracking_get_camera_object_matrix(camera, mat);
track = tracksbase->first;
while (track) {
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 7e2671382b9..da3bf0ea8b3 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -33,7 +33,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_movieclip.h"
#include "BKE_report.h"
#include "BKE_tracking.h"
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 0a3663372be..f61eb15b3c2 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -111,14 +111,13 @@ static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt))
/* -------------- */
-/* Graph Editor View Settings */
-static void graph_panel_view(const bContext *C, Panel *pa)
+static void graph_panel_cursor_header(const bContext *C, Panel *pa)
{
bScreen *sc = CTX_wm_screen(C);
SpaceGraph *sipo = CTX_wm_space_graph(C);
Scene *scene = CTX_data_scene(C);
PointerRNA spaceptr, sceneptr;
- uiLayout *col, *sub, *row;
+ uiLayout *col;
/* get RNA pointers for use when creating the UI elements */
RNA_id_pointer_create(&scene->id, &sceneptr);
@@ -126,26 +125,41 @@ static void graph_panel_view(const bContext *C, Panel *pa)
/* 2D-Cursor */
col = uiLayoutColumn(pa->layout, false);
- uiItemR(col, &spaceptr, "show_cursor", 0, NULL, ICON_NONE);
+ uiItemR(col, &spaceptr, "show_cursor", 0, "", ICON_NONE);
+}
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor"));
- uiItemO(sub, IFACE_("Cursor from Selection"), ICON_NONE, "GRAPH_OT_frame_jump");
+static void graph_panel_cursor(const bContext *C, Panel *pa)
+{
+ bScreen *sc = CTX_wm_screen(C);
+ SpaceGraph *sipo = CTX_wm_space_graph(C);
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA spaceptr, sceneptr;
+ uiLayout *layout = pa->layout;
+ uiLayout *col, *sub;
+
+ /* get RNA pointers for use when creating the UI elements */
+ RNA_id_pointer_create(&scene->id, &sceneptr);
+ RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr);
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ /* 2D-Cursor */
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(col, RNA_boolean_get(&spaceptr, "show_cursor"));
sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor"));
- row = uiLayoutSplit(sub, 0.7f, true);
if (sipo->mode == SIPO_MODE_DRIVERS) {
- uiItemR(row, &spaceptr, "cursor_position_x", 0, IFACE_("Cursor X"), ICON_NONE);
+ uiItemR(sub, &spaceptr, "cursor_position_x", 0, IFACE_("Cursor X"), ICON_NONE);
}
else {
- uiItemR(row, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE);
+ uiItemR(sub, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE);
}
- uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_CFRA);
- row = uiLayoutSplit(sub, 0.7f, true);
- uiItemR(row, &spaceptr, "cursor_position_y", 0, IFACE_("Cursor Y"), ICON_NONE);
- uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_VALUE);
+ uiItemR(sub, &spaceptr, "cursor_position_y", 0, IFACE_("Y"), ICON_NONE);
+
+ sub = uiLayoutColumn(col, true);
+ uiItemO(sub, IFACE_("Cursor to Selection"), ICON_NONE, "GRAPH_OT_frame_jump");
}
/* ******************* active F-Curve ************** */
@@ -1429,9 +1443,10 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
strcpy(pt->idname, "GRAPH_PT_view");
- strcpy(pt->label, N_("View Properties"));
+ strcpy(pt->label, N_("Show Cursor"));
strcpy(pt->category, "View");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = graph_panel_view;
+ pt->draw = graph_panel_cursor;
+ pt->draw_header = graph_panel_cursor_header;
BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 42a1566629a..8dd5a7c7d0c 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -164,7 +164,7 @@ static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
}
static void draw_fcurve_selected_keyframe_vertices(
- FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos)
+ FCurve *fcu, View2D *v2d, bool edit, bool sel, uint pos)
{
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
@@ -200,7 +200,7 @@ static void draw_fcurve_selected_keyframe_vertices(
}
/* helper func - draw keyframe vertices only for an F-Curve */
-static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos)
+static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, uint pos)
{
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
@@ -214,7 +214,7 @@ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, u
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
static void draw_fcurve_selected_handle_vertices(
- FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos)
+ FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, uint pos)
{
(void)v2d; /* TODO: use this to draw only points in view */
@@ -259,10 +259,7 @@ static void draw_fcurve_selected_handle_vertices(
}
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
-static void draw_fcurve_handle_vertices(FCurve *fcu,
- View2D *v2d,
- bool sel_handle_only,
- unsigned pos)
+static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, uint pos)
{
/* smooth outlines for more consistent appearance */
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
@@ -353,7 +350,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
BezTriple *bezt = fcu->bezt, *prevbezt = NULL;
int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
const float *fp;
- unsigned char col[4];
+ uchar col[4];
for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
/* if only selected keyframes can get their handles shown,
@@ -428,7 +425,7 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
* have a consistent appearance (due to off-pixel alignments)...
*/
static void draw_fcurve_sample_control(
- float x, float y, float xscale, float yscale, float hsize, unsigned int pos)
+ float x, float y, float xscale, float yscale, float hsize, uint pos)
{
/* adjust view transform before starting */
GPU_matrix_push();
@@ -491,8 +488,7 @@ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *ar, FCurve *fcu)
/* Helper func - just draw the F-Curve by sampling the visible region
* (for drawing curves with modifiers). */
-static void draw_fcurve_curve(
- bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, unsigned int pos)
+static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos)
{
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
float samplefreq;
@@ -684,8 +680,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
}
/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
-static void draw_fcurve_curve_bezts(
- bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos)
+static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos)
{
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 3f563fe9033..c455b7d7c54 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -147,7 +147,7 @@ void ED_image_draw_info(Scene *scene,
int channels,
int x,
int y,
- const unsigned char cp[4],
+ const uchar cp[4],
const float fp[4],
const float linearcol[4],
int *zp,
@@ -164,13 +164,13 @@ void ED_image_draw_info(Scene *scene,
/* text colors */
/* XXX colored text not allowed in Blender UI */
#if 0
- unsigned char red[3] = {255, 50, 50};
- unsigned char green[3] = {0, 255, 0};
- unsigned char blue[3] = {100, 100, 255};
+ uchar red[3] = {255, 50, 50};
+ uchar green[3] = {0, 255, 0};
+ uchar blue[3] = {100, 100, 255};
#else
- unsigned char red[3] = {255, 255, 255};
- unsigned char green[3] = {255, 255, 255};
- unsigned char blue[3] = {255, 255, 255};
+ uchar red[3] = {255, 255, 255};
+ uchar green[3] = {255, 255, 255};
+ uchar blue[3] = {255, 255, 255};
#endif
float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0;
float col[4], finalcol[4];
@@ -613,7 +613,7 @@ static void draw_image_buffer(const bContext *C,
}
else {
float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- unsigned char *display_buffer;
+ uchar *display_buffer;
void *cache_handle;
ColorManagedViewSettings *view_settings;
ColorManagedDisplaySettings *display_settings;
@@ -760,7 +760,7 @@ static void draw_image_paint_helpers(
float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha};
UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
- unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ uchar *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
if (!display_buffer) {
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
@@ -794,8 +794,8 @@ static void draw_image_paint_helpers(
}
}
-static void draw_udim_tile_grid(unsigned int pos_attr,
- unsigned int color_attr,
+static void draw_udim_tile_grid(uint pos_attr,
+ uint color_attr,
ARegion *ar,
int x,
int y,
@@ -832,8 +832,8 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima)
float stepy = BLI_rcti_size_y(&ar->v2d.mask) / BLI_rctf_size_y(&ar->v2d.cur);
GPUVertFormat *format = immVertexFormat();
- unsigned int pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GPU_PRIM_LINES, 8 * num_tiles);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index c1ed049130e..862d32815f4 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -34,7 +34,7 @@
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index e6bd563b02f..deae1afc18d 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -58,7 +58,7 @@
#include "BKE_image.h"
#include "BKE_image_save.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_paint.h"
@@ -2510,7 +2510,7 @@ static bool image_should_be_saved_when_modified(Image *ima)
static bool image_should_be_saved(Image *ima, bool *is_format_writable)
{
if (BKE_image_is_dirty_writable(ima, is_format_writable) &&
- (ima->source == IMA_SRC_FILE || ima->source == IMA_SRC_GENERATED)) {
+ ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_GENERATED, IMA_SRC_TILED)) {
return image_should_be_saved_when_modified(ima);
}
else {
@@ -3148,7 +3148,8 @@ static bool image_pack_test(bContext *C, wmOperator *op)
}
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
+ BKE_report(
+ op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported");
return 0;
}
@@ -3216,7 +3217,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
}
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
+ BKE_report(
+ op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
return OPERATOR_CANCELLED;
}
@@ -3249,7 +3251,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
}
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
+ BKE_report(
+ op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 19d92a520de..e18eb062741 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -40,7 +40,7 @@
#include "BKE_editmesh.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 124e3c08165..430cd95cdd2 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -40,7 +40,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 0f170b1f530..ac6ee125798 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -40,7 +40,7 @@
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 35c9082b54c..121c597c1bb 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -376,7 +376,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
const int font_size = data->label_size / aspect;
const float margin = (float)(NODE_DY / 4);
int label_height;
- unsigned char color[3];
+ uchar color[3];
nodeLabel(ntree, node, label, sizeof(label));
@@ -3483,7 +3483,7 @@ void draw_nodespace_back_pix(const bContext *C,
y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
if (ibuf->rect || ibuf->rect_float) {
- unsigned char *display_buffer = NULL;
+ uchar *display_buffer = NULL;
void *cache_handle = NULL;
if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
@@ -3707,11 +3707,11 @@ static struct {
GPUBatch *batch; /* for batching line together */
GPUBatch *batch_single; /* for single line */
GPUVertBuf *inst_vbo;
- unsigned int p0_id, p1_id, p2_id, p3_id;
- unsigned int colid_id;
+ uint p0_id, p1_id, p2_id, p3_id;
+ uint colid_id;
GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
GPUVertBufRaw colid_step;
- unsigned int count;
+ uint count;
bool enabled;
} g_batch_link = {0};
@@ -3727,11 +3727,11 @@ static void nodelink_batch_reset(void)
}
static void set_nodelink_vertex(GPUVertBuf *vbo,
- unsigned int uv_id,
- unsigned int pos_id,
- unsigned int exp_id,
- unsigned int v,
- const unsigned char uv[2],
+ uint uv_id,
+ uint pos_id,
+ uint exp_id,
+ uint v,
+ const uchar uv[2],
const float pos[2],
const float exp[2])
{
@@ -3756,7 +3756,7 @@ static void nodelink_batch_init(void)
int v = 0;
for (int k = 0; k < 2; k++) {
- unsigned char uv[2] = {0, 0};
+ uchar uv[2] = {0, 0};
float pos[2] = {0.0f, 0.0f};
float exp[2] = {0.0f, 1.0f};
@@ -4000,8 +4000,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}
-void ED_node_draw_snap(
- View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos)
+void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, uint pos)
{
immBegin(GPU_PRIM_LINES, 4);
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 664349b3c3b..31b27adb226 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -32,7 +32,7 @@
#include "BKE_context.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 2081c69a1a4..2202eee3a53 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -37,7 +37,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -722,18 +722,18 @@ static void node_socket_draw(const bContext *C,
bNodeTree *ntree,
PointerRNA node_ptr,
bNodeSocket *sock,
- unsigned pos_id,
- unsigned col_id,
- unsigned shape_id,
- unsigned size_id,
- unsigned outline_col_id,
+ uint pos_id,
+ uint col_id,
+ uint shape_id,
+ uint size_id,
+ uint outline_col_id,
float size,
bool selected)
{
PointerRNA ptr;
float color[4];
float outline_color[4];
- unsigned int flags = 0;
+ uint flags = 0;
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 045e4d28df6..9fba78682dc 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -35,7 +35,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 5d020ff5ab4..64e8358c23c 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -37,7 +37,7 @@
#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 357ef31c51f..df7d5ca6ac1 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -32,7 +32,7 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index c6994dab72d..23bc6b32344 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -33,7 +33,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_scene.h"
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index e114c3dbc05..6eab0dfff40 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -33,7 +33,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_node.h"
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 183a96d1325..4e77d6940b0 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -29,7 +29,7 @@
#include "BKE_context.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index a4a6aadde77..ecacd55debb 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -38,7 +38,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index a341be5bf65..12704777b05 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -48,6 +48,7 @@
#include "BKE_gpencil.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -2700,7 +2701,7 @@ static void outliner_draw_iconrow_number(const uiFontStyle *fstyle,
color);
/* Now the numbers. */
- unsigned char text_col[4];
+ uchar text_col[4];
UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
text_col[3] = 255;
@@ -2953,7 +2954,7 @@ static void outliner_draw_tree_element(bContext *C,
float ufac = UI_UNIT_X / 20.0f;
int offsx = 0;
eOLDrawState active = OL_DRAWSEL_NONE;
- unsigned char text_color[4];
+ uchar text_color[4];
UI_GetThemeColor4ubv(TH_TEXT, text_color);
float icon_bgcolor[4], icon_border[4];
outliner_icon_background_colors(icon_bgcolor, icon_border);
@@ -3208,11 +3209,11 @@ static void outliner_draw_tree_element(bContext *C,
}
}
-static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
+static void outliner_draw_hierarchy_lines_recursive(uint pos,
SpaceOutliner *soops,
ListBase *lb,
int startx,
- const unsigned char col[4],
+ const uchar col[4],
bool draw_grayed_out,
int *starty)
{
@@ -3234,7 +3235,7 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
dash.step_len = UI_UNIT_X / dash.steps_num;
dash.gap_len = dash.step_len / 2;
- const unsigned char grayed_alpha = col[3] / 2;
+ const uchar grayed_alpha = col[3] / 2;
/* For vertical lines between objects. */
y1 = y2 = y1_dashed = y2_dashed = *starty;
@@ -3316,7 +3317,7 @@ static void outliner_draw_hierarchy_lines(SpaceOutliner *soops,
{
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
- unsigned char col[4];
+ uchar col[4];
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
@@ -3369,7 +3370,7 @@ static void outliner_draw_struct_marks(ARegion *ar,
}
}
-static void outliner_draw_highlights_recursive(unsigned pos,
+static void outliner_draw_highlights_recursive(uint pos,
const ARegion *ar,
const SpaceOutliner *soops,
const ListBase *lb,
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 7b59b056264..eafd89620dc 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -46,9 +46,9 @@
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_outliner_treehash.h"
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index c9eeb2cff20..8d6aff1bd6e 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -50,9 +50,9 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_override.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -719,7 +719,7 @@ static void id_override_library_cb(bContext *C,
Main *bmain = CTX_data_main(C);
/* For now, remapp all local usages of linked ID to local override one here. */
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
- ID *override_id = BKE_override_library_create_from_id(bmain, tselem->id, true);
+ ID *override_id = BKE_lib_override_library_create_from_id(bmain, tselem->id, true);
if (override_id != NULL) {
BKE_main_id_clear_newpoins(bmain);
}
@@ -1539,7 +1539,7 @@ static bool outliner_id_operation_item_poll(bContext *C,
switch (enum_value) {
case OUTLINER_IDOP_OVERRIDE_LIBRARY:
- return BKE_override_library_is_enabled();
+ return BKE_lib_override_library_is_enabled();
case OUTLINER_IDOP_SINGLE:
if (!soops || ELEM(soops->outlinevis, SO_SCENES, SO_VIEW_LAYER)) {
return true;
@@ -1652,7 +1652,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
break;
}
case OUTLINER_IDOP_OVERRIDE_LIBRARY: {
- if (BKE_override_library_is_enabled()) {
+ if (BKE_lib_override_library_is_enabled()) {
/* make local */
outliner_do_libdata_operation(
C, op->reports, scene, soops, &soops->tree, id_override_library_cb, NULL);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 1bb1a1c5964..8142d86aac8 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -58,7 +58,7 @@
#include "BKE_fcurve.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_outliner_treehash.h"
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 9e8fa6475a0..49270abf8ce 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -38,7 +38,7 @@
#include "DNA_mask_types.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_movieclip.h"
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index bef4a7cdd22..6ebccf31355 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -449,7 +449,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
}
/* clamp handles to defined size in pixel space */
-static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx)
+float sequence_handle_size_get_clamped(Sequence *seq, const float pixelx)
{
const float minhandle = pixelx * SEQ_HANDLE_SIZE_MIN;
const float maxhandle = pixelx * SEQ_HANDLE_SIZE_MAX;
@@ -806,7 +806,7 @@ static void draw_seq_strip(const bContext *C,
View2D *v2d = &ar->v2d;
float x1, x2, y1, y2;
unsigned char col[4], background_col[4], is_single_image;
- const float handsize_clamped = draw_seq_handle_size_get_clamped(seq, pixelx);
+ const float handsize_clamped = sequence_handle_size_get_clamped(seq, pixelx);
/* we need to know if this is a single image/color or not for drawing */
is_single_image = (char)BKE_sequence_single_check(seq);
@@ -1055,11 +1055,8 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain,
if (special_seq_update) {
ibuf = BKE_sequencer_give_ibuf_direct(&context, cfra + frame_ofs, special_seq_update);
}
- else if (!U.prefetchframes) { // XXX || (G.f & G_PLAYANIM) == 0) {
- ibuf = BKE_sequencer_give_ibuf(&context, cfra + frame_ofs, sseq->chanshown);
- }
else {
- ibuf = BKE_sequencer_give_ibuf_threaded(&context, cfra + frame_ofs, sseq->chanshown);
+ ibuf = BKE_sequencer_give_ibuf(&context, cfra + frame_ofs, sseq->chanshown);
}
if (fb) {
@@ -1622,27 +1619,6 @@ void sequencer_draw_preview(const bContext *C,
seq_prefetch_wm_notify(C, scene);
}
-#if 0
-void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq)
-{
- int rectx, recty;
- int render_size = BKE_sequencer_rendersize_to_scale_factor(sseq->render_size);
- if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
- return;
- }
-
- if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_SCENE) {
- render_size = scene->r.size / 100.0;
- }
- rectx = render_size * scene->r.xsch + 0.5;
- recty = render_size * scene->r.ysch + 0.5;
-
- if (sseq->mainb != SEQ_DRAW_SEQUENCE) {
- give_ibuf_prefetch_request(rectx, recty, (scene->r.cfra), sseq->chanshown, sseq->render_size);
- }
-}
-#endif
-
/* draw backdrop of the sequencer strips view */
static void draw_seq_backdrop(View2D *v2d)
{
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index a1177454acd..2f3f90dc1b1 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -44,7 +44,7 @@
#include "BKE_report.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 0a51578da3b..ef5fed492e5 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -54,6 +54,7 @@ void sequencer_draw_preview(const struct bContext *C,
void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
void sequencer_special_update_set(Sequence *seq);
+float sequence_handle_size_get_clamped(struct Sequence *seq, const float pixelx);
/* UNUSED */
// void seq_reset_imageofs(struct SpaceSeq *sseq);
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index a5bb66ca65f..bf06fa768ca 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -1018,15 +1018,17 @@ void SEQUENCER_OT_select_side(wmOperatorType *ot)
static int sequencer_box_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ View2D *v2d = UI_view2d_fromcontext(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
+
if (ed == NULL) {
return OPERATOR_CANCELLED;
}
- View2D *v2d = UI_view2d_fromcontext(C);
-
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ const bool handles = RNA_boolean_get(op->ptr, "handles");
const bool select = (sel_op != SEL_OP_SUB);
+
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
ED_sequencer_deselect_all(scene);
}
@@ -1039,8 +1041,44 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
rctf rq;
seq_rectf(seq, &rq);
if (BLI_rctf_isect(&rq, &rectf, NULL)) {
- SET_FLAG_FROM_TEST(seq->flag, select, SELECT);
- recurs_sel_seq(seq);
+ if (handles) {
+ /* Get the handles draw size. */
+ float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+ float handsize = sequence_handle_size_get_clamped(seq, pixelx) * 0.75f;
+
+ /* Right handle. */
+ if (rectf.xmax > (seq->enddisp - handsize)) {
+ if (select) {
+ seq->flag |= SELECT | SEQ_RIGHTSEL;
+ }
+ else {
+ /* Deselect the strip if it's left with no handles selected. */
+ if ((seq->flag & SEQ_RIGHTSEL) && ((seq->flag & SEQ_LEFTSEL) == 0)) {
+ seq->flag &= ~SELECT;
+ }
+ seq->flag &= ~SEQ_RIGHTSEL;
+ }
+ }
+ /* Left handle. */
+ if (rectf.xmin < (seq->startdisp + handsize)) {
+ if (select) {
+ seq->flag |= SELECT | SEQ_LEFTSEL;
+ }
+ else {
+ /* Deselect the strip if it's left with no handles selected. */
+ if ((seq->flag & SEQ_LEFTSEL) && ((seq->flag & SEQ_RIGHTSEL) == 0)) {
+ seq->flag &= ~SELECT;
+ }
+ seq->flag &= ~SEQ_LEFTSEL;
+ }
+ }
+ }
+
+ /* Regular box selection. */
+ else {
+ SET_FLAG_FROM_TEST(seq->flag, select, SELECT);
+ seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ }
}
}
@@ -1072,6 +1110,8 @@ static int sequencer_box_select_invoke(bContext *C, wmOperator *op, const wmEven
void SEQUENCER_OT_select_box(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Box Select";
ot->idname = "SEQUENCER_OT_select_box";
@@ -1092,9 +1132,11 @@ void SEQUENCER_OT_select_box(wmOperatorType *ot)
WM_operator_properties_gesture_box(ot);
WM_operator_properties_select_operation_simple(ot);
- PropertyRNA *prop = RNA_def_boolean(
+ prop = RNA_def_boolean(
ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "handles", 0, "Select Handles", "Select the strips' handles");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ****** Selected Grouped ****** */
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 53202b65838..1e2470c1866 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -35,7 +35,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index b477e3838bd..09a2b83d909 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -31,7 +31,7 @@
#include "BKE_global.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_screen.h"
#include "BKE_text.h"
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 96fa9f87398..02914737229 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1338,10 +1338,16 @@ static void draw_text_decoration(SpaceText *st, ARegion *ar)
wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
y1 = ar->winy - (vsell - offl) * lheight;
+ if (st->flags & ST_SCROLL_SELECT) {
+ y1 += st->runtime.scroll_ofs_px[1];
+ }
y2 = y1 - (lheight * visible_lines);
}
else {
y1 = ar->winy - vsell * lheight;
+ if (st->flags & ST_SCROLL_SELECT) {
+ y1 += st->runtime.scroll_ofs_px[1];
+ }
y2 = y1 - (lheight);
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index eea3e4d7958..f496d004ae2 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -29,13 +29,14 @@
#include "DNA_text_types.h"
#include "BLI_blenlib.h"
+#include "BLI_math_base.h"
#include "BLT_translation.h"
#include "PIL_time.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_text.h"
@@ -2544,7 +2545,7 @@ static void text_scroll_state_init(TextScroll *tsc, SpaceText *st, ARegion *ar)
tsc->state.ofs_init[1] = st->top;
tsc->state.ofs_max[0] = INT_MAX;
- tsc->state.ofs_max[1] = text_get_total_lines(st, ar) - (st->runtime.viewlines / 2);
+ tsc->state.ofs_max[1] = max_ii(0, text_get_total_lines(st, ar) - (st->runtime.viewlines / 2));
tsc->state.size_px[0] = st->runtime.cwidth_px;
tsc->state.size_px[1] = TXT_LINE_HEIGHT(st);
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 95d7f79f666..9e3c9d6725d 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -48,7 +48,6 @@ set(SRC
view3d_buttons.c
view3d_camera_control.c
view3d_draw.c
- view3d_draw_legacy.c
view3d_edit.c
view3d_fly.c
view3d_gizmo_armature.c
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 2cdfd8039c1..0daa5aa53ae 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -87,7 +87,7 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3],
}
}
-void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], uint pos)
{
float verts[CIRCLE_RESOL][3];
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 0e5592abfd2..7bfb0460c41 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -27,13 +27,16 @@
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_threads.h"
#include "BLI_jitter_2d.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -56,11 +59,13 @@
#include "DNA_windowmanager_types.h"
#include "DRW_engine.h"
+#include "DRW_select_buffer.h"
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
+#include "ED_screen_types.h"
#include "ED_transform.h"
#include "DEG_depsgraph_query.h"
@@ -1251,21 +1256,44 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffs
{
RegionView3D *rv3d = ar->regiondata;
const char *name = view3d_get_name(v3d, rv3d);
+ const char *name_array[3] = {name, NULL, NULL};
+ int name_array_len = 1;
const int font_id = BLF_default();
+ /* 6 is the maximum size of the axis roll text. */
/* increase size for unicode languages (Chinese in utf-8...) */
#ifdef WITH_INTERNATIONAL
- char tmpstr[96];
+ char tmpstr[96 + 6];
#else
- char tmpstr[32];
+ char tmpstr[32 + 6];
#endif
BLF_enable(font_id, BLF_SHADOW);
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
+ if (RV3D_VIEW_IS_AXIS(rv3d->view) && (rv3d->view_axis_roll != RV3D_VIEW_AXIS_ROLL_0)) {
+ const char *axis_roll;
+ switch (rv3d->view_axis_roll) {
+ case RV3D_VIEW_AXIS_ROLL_90:
+ axis_roll = " 90\xC2\xB0";
+ break;
+ case RV3D_VIEW_AXIS_ROLL_180:
+ axis_roll = " 180\xC2\xB0";
+ break;
+ default:
+ axis_roll = " -90\xC2\xB0";
+ break;
+ }
+ name_array[name_array_len++] = axis_roll;
+ }
+
if (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name_array[name_array_len++] = IFACE_(" (Local)");
+ }
+
+ if (name_array_len > 1) {
+ BLI_string_join_array(tmpstr, sizeof(tmpstr), name_array, name_array_len);
name = tmpstr;
}
@@ -1273,11 +1301,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffs
*yoffset -= U.widget_unit;
-#ifdef WITH_INTERNATIONAL
BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
-#else
- BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
-#endif
BLF_disable(font_id, BLF_SHADOW);
}
@@ -1936,11 +1960,454 @@ static bool view3d_clipping_test(const float co[3], const float clip[6][4])
return true;
}
-/* for 'local' ED_view3d_clipping_local must run first
- * then all comparisons can be done in localspace */
+/* For 'local' ED_view3d_clipping_local must run first
+ * then all comparisons can be done in localspace. */
bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
{
return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
}
+void ED_view3d_clipping_set(RegionView3D *UNUSED(rv3d))
+{
+ for (uint a = 0; a < 6; a++) {
+ glEnable(GL_CLIP_DISTANCE0 + a);
+ }
+}
+
+/* Use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set. */
+void ED_view3d_clipping_disable(void)
+{
+ for (uint a = 0; a < 6; a++) {
+ glDisable(GL_CLIP_DISTANCE0 + a);
+ }
+}
+void ED_view3d_clipping_enable(void)
+{
+ for (uint a = 0; a < 6; a++) {
+ glEnable(GL_CLIP_DISTANCE0 + a);
+ }
+}
+
+/* *********************** backdraw for selection *************** */
+
+/**
+ * \note Only use in object mode.
+ */
+static void validate_object_select_id(
+ struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact)
+{
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+
+ BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+ UNUSED_VARS_NDEBUG(ar);
+
+ if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
+ BKE_paint_select_face_test(obact_eval))) {
+ /* do nothing */
+ }
+ /* texture paint mode sampling */
+ else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->shading.type > OB_WIRE)) {
+ /* do nothing */
+ }
+ else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) {
+ /* do nothing */
+ }
+ else {
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+ return;
+ }
+
+ if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
+ return;
+ }
+
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
+ Base *base = BKE_view_layer_base_find(view_layer, obact);
+ DRW_select_buffer_context_create(&base, 1, -1);
+ }
+
+ /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
+ * made on the backbuffer in this case. */
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+}
+
+/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
+ * Calling this function should be avoided during interactive drawing. */
+static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data)
+{
+ DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport);
+
+ GPUFrameBuffer *tmp_fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0);
+ GPU_framebuffer_bind(tmp_fb);
+
+ glReadPixels(rect->xmin,
+ rect->ymin,
+ BLI_rcti_size_x(rect),
+ BLI_rcti_size_y(rect),
+ GL_DEPTH_COMPONENT,
+ GL_FLOAT,
+ data);
+
+ GPU_framebuffer_restore();
+ GPU_framebuffer_free(tmp_fb);
+}
+
+void ED_view3d_select_id_validate(ViewContext *vc)
+{
+ /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
+ * made on the backbuffer in this case. */
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact);
+ }
+}
+
+void ED_view3d_backbuf_depth_validate(ViewContext *vc)
+{
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ ARegion *ar = vc->ar;
+ Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
+
+ if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval);
+ }
+
+ vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
+ }
+}
+
+/**
+ * allow for small values [0.5 - 2.5],
+ * and large values, FLT_MAX by clamping by the area size
+ */
+int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+{
+ return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+}
+
+/* *********************** */
+
+void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
+{
+ /* clamp rect by region */
+ rcti r = {
+ .xmin = 0,
+ .xmax = ar->winx - 1,
+ .ymin = 0,
+ .ymax = ar->winy - 1,
+ };
+
+ /* Constrain rect to depth bounds */
+ BLI_rcti_isect(&r, rect, rect);
+
+ /* assign values to compare with the ViewDepths */
+ int x = rect->xmin;
+ int y = rect->ymin;
+
+ int w = BLI_rcti_size_x(rect);
+ int h = BLI_rcti_size_y(rect);
+
+ if (w <= 0 || h <= 0) {
+ if (d->depths) {
+ MEM_freeN(d->depths);
+ }
+ d->depths = NULL;
+
+ d->damaged = false;
+ }
+ else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) {
+ d->x = x;
+ d->y = y;
+ d->w = w;
+ d->h = h;
+
+ if (d->depths) {
+ MEM_freeN(d->depths);
+ }
+
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
+
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ view3d_opengl_read_Z_pixels(viewport, rect, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+ d->damaged = false;
+ }
+}
+
+/* Note, with nouveau drivers the glReadPixels() is very slow. [#24339]. */
+void ED_view3d_depth_update(ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* Create storage for, and, if necessary, copy depth buffer. */
+ if (!rv3d->depths) {
+ rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
+ }
+ if (rv3d->depths) {
+ ViewDepths *d = rv3d->depths;
+ if (d->w != ar->winx || d->h != ar->winy || !d->depths) {
+ d->w = ar->winx;
+ d->h = ar->winy;
+ if (d->depths) {
+ MEM_freeN(d->depths);
+ }
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ rcti r = {
+ .xmin = 0,
+ .xmax = d->w,
+ .ymin = 0,
+ .ymax = d->h,
+ };
+ view3d_opengl_read_Z_pixels(viewport, &r, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+ d->damaged = false;
+ }
+ }
+}
+
+/* Utility function to find the closest Z value, use for autodepth. */
+float view3d_depth_near(ViewDepths *d)
+{
+ /* Convert to float for comparisons. */
+ const float near = (float)d->depth_range[0];
+ const float far_real = (float)d->depth_range[1];
+ float far = far_real;
+
+ const float *depths = d->depths;
+ float depth = FLT_MAX;
+ int i = (int)d->w * (int)d->h; /* Cast to avoid short overflow. */
+
+ /* Far is both the starting 'far' value
+ * and the closest value found. */
+ while (i--) {
+ depth = *depths++;
+ if ((depth < far) && (depth > near)) {
+ far = depth;
+ }
+ }
+
+ return far == far_real ? FLT_MAX : far;
+}
+
+void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d)
+{
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
+
+ GPU_clear(GPU_DEPTH_BIT);
+
+ GPU_depth_test(true);
+
+ GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
+ DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport);
+
+ GPU_depth_test(false);
+}
+
+/* *********************** customdata **************** */
+
+void ED_view3d_datamask(const bContext *C,
+ const Scene *UNUSED(scene),
+ const View3D *v3d,
+ CustomData_MeshMasks *r_cddata_masks)
+{
+ if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+ r_cddata_masks->vmask |= CD_MASK_ORCO;
+ }
+ else if (v3d->shading.type == OB_SOLID) {
+ if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPUV;
+ }
+ if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) {
+ r_cddata_masks->lmask |= CD_MASK_MLOOPCOL;
+ }
+ }
+
+ if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) &&
+ (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) {
+ r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
+ }
+}
+
+/* Goes over all modes and view3d settings. */
+void ED_view3d_screen_datamask(const bContext *C,
+ const Scene *scene,
+ const bScreen *screen,
+ CustomData_MeshMasks *r_cddata_masks)
+{
+ CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH);
+
+ /* Check if we need tfaces & mcols due to view mode. */
+ for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks);
+ }
+ }
+}
+
+/**
+ * Store values from #RegionView3D, set when drawing.
+ * This is needed when we draw with to a viewport using a different matrix
+ * (offscreen drawing for example).
+ *
+ * Values set by #ED_view3d_update_viewmat should be handled here.
+ */
+struct RV3DMatrixStore {
+ float winmat[4][4];
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewcamtexcofac[4];
+ float pixsize;
+};
+
+struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
+{
+ struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
+ copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
+ copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
+ copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
+ copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
+ copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
+ copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
+ rv3dmat->pixsize = rv3d->pixsize;
+ return (void *)rv3dmat;
+}
+
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt)
+{
+ struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
+ copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
+ copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
+ copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
+ copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
+ copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
+ copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
+ rv3d->pixsize = rv3dmat->pixsize;
+}
+
+/**
+ * \note The info that this uses is updated in #ED_refresh_viewport_fps,
+ * which currently gets called during #SCREEN_OT_animation_step.
+ */
+void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset)
+{
+ ScreenFrameRateInfo *fpsi = scene->fps_info;
+ char printable[16];
+
+ if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) {
+ return;
+ }
+
+ printable[0] = '\0';
+
+ /* Doing an average for a more robust calculation. */
+ fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 /
+ (fpsi->lredrawtime - fpsi->redrawtime));
+
+ float fps = 0.0f;
+ int tot = 0;
+ for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) {
+ if (fpsi->redrawtimes_fps[i]) {
+ fps += fpsi->redrawtimes_fps[i];
+ tot++;
+ }
+ }
+ if (tot) {
+ fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
+ fps = fps / tot;
+ }
+
+ const int font_id = BLF_default();
+
+ /* Is this more than half a frame behind? */
+ if (fps + 0.5f < (float)(FPS)) {
+ UI_FontThemeColor(font_id, TH_REDALERT);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
+ }
+ else {
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
+ }
+
+ BLF_enable(font_id, BLF_SHADOW);
+ BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
+ BLF_shadow_offset(font_id, 1, -1);
+
+ *yoffset -= U.widget_unit;
+
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
+#else
+ BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
+#endif
+
+ BLF_disable(font_id, BLF_SHADOW);
+}
+
+static bool view3d_main_region_do_render_draw(const Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type && type->view_update && type->view_draw);
+}
+
+bool ED_view3d_calc_render_border(
+ const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ bool use_border;
+
+ /* Test if there is a 3d view rendering. */
+ if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) {
+ return false;
+ }
+
+ /* Test if there is a border render. */
+ if (rv3d->persp == RV3D_CAMOB) {
+ use_border = (scene->r.mode & R_BORDER) != 0;
+ }
+ else {
+ use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
+ }
+
+ if (!use_border) {
+ return false;
+ }
+
+ /* Compute border. */
+ if (rv3d->persp == RV3D_CAMOB) {
+ rctf viewborder;
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
+
+ rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
+ rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
+ rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
+ rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
+ }
+ else {
+ rect->xmin = v3d->render_border.xmin * ar->winx;
+ rect->xmax = v3d->render_border.xmax * ar->winx;
+ rect->ymin = v3d->render_border.ymin * ar->winy;
+ rect->ymax = v3d->render_border.ymax * ar->winy;
+ }
+
+ BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
+ BLI_rcti_isect(&ar->winrct, rect, rect);
+
+ return true;
+}
+
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
deleted file mode 100644
index 38cb5ad8651..00000000000
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2008 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup spview3d
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_customdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_key_types.h"
-#include "DNA_light_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_world_types.h"
-#include "DNA_brush_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_endian_switch.h"
-#include "BLI_threads.h"
-
-#include "BKE_anim.h"
-#include "BKE_camera.h"
-#include "BKE_context.h"
-#include "BKE_customdata.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_layer.h"
-#include "BKE_object.h"
-#include "BKE_global.h"
-#include "BKE_paint.h"
-#include "BKE_scene.h"
-#include "BKE_unit.h"
-#include "BKE_movieclip.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
-
-#include "BIF_glutil.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "BLF_api.h"
-#include "BLT_translation.h"
-
-#include "ED_armature.h"
-#include "ED_keyframing.h"
-#include "ED_gpencil.h"
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_space_api.h"
-#include "ED_screen_types.h"
-#include "ED_transform.h"
-#include "ED_view3d.h"
-
-#include "UI_interface.h"
-#include "UI_interface_icons.h"
-#include "UI_resources.h"
-
-#include "GPU_framebuffer.h"
-#include "GPU_immediate.h"
-#include "GPU_state.h"
-#include "GPU_viewport.h"
-
-#include "RE_engine.h"
-
-#include "DRW_engine.h"
-#include "DRW_select_buffer.h"
-
-#include "view3d_intern.h" /* own include */
-
-/* ********* custom clipping *********** */
-
-/* Legacy 2.7x, now use shaders that use clip distance instead.
- * Remove once clipping is working properly. */
-#define USE_CLIP_PLANES
-
-void ED_view3d_clipping_set(RegionView3D *rv3d)
-{
-#ifdef USE_CLIP_PLANES
- double plane[4];
- const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
-
- for (unsigned a = 0; a < tot; a++) {
- copy_v4db_v4fl(plane, rv3d->clip[a]);
- glClipPlane(GL_CLIP_PLANE0 + a, plane);
- glEnable(GL_CLIP_PLANE0 + a);
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
-#else
- for (unsigned a = 0; a < 6; a++) {
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
-#endif
-}
-
-/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
-void ED_view3d_clipping_disable(void)
-{
- for (unsigned a = 0; a < 6; a++) {
-#ifdef USE_CLIP_PLANES
- glDisable(GL_CLIP_PLANE0 + a);
-#endif
- glDisable(GL_CLIP_DISTANCE0 + a);
- }
-}
-void ED_view3d_clipping_enable(void)
-{
- for (unsigned a = 0; a < 6; a++) {
-#ifdef USE_CLIP_PLANES
- glEnable(GL_CLIP_PLANE0 + a);
-#endif
- glEnable(GL_CLIP_DISTANCE0 + a);
- }
-}
-
-/* *********************** backdraw for selection *************** */
-
-/**
- * \note Only use in object mode.
- */
-static void validate_object_select_id(
- struct Depsgraph *depsgraph, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Object *obact)
-{
- Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
-
- BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
- UNUSED_VARS_NDEBUG(ar);
-
- if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
- BKE_paint_select_face_test(obact_eval))) {
- /* do nothing */
- }
- /* texture paint mode sampling */
- else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) &&
- (v3d->shading.type > OB_WIRE)) {
- /* do nothing */
- }
- else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) {
- /* do nothing */
- }
- else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
-
- if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
- return;
- }
-
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
- Base *base = BKE_view_layer_base_find(view_layer, obact);
- DRW_select_buffer_context_create(&base, 1, -1);
- }
-
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the backbuffer in this case. */
- v3d->flag &= ~V3D_INVALID_BACKBUF;
-}
-
-/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
- * Calling this function should be avoided during interactive drawing. */
-static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data)
-{
- DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport);
-
- GPUFrameBuffer *tmp_fb = GPU_framebuffer_create();
- GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0);
- GPU_framebuffer_bind(tmp_fb);
-
- glReadPixels(rect->xmin,
- rect->ymin,
- BLI_rcti_size_x(rect),
- BLI_rcti_size_y(rect),
- GL_DEPTH_COMPONENT,
- GL_FLOAT,
- data);
-
- GPU_framebuffer_restore();
- GPU_framebuffer_free(tmp_fb);
-}
-
-void ED_view3d_select_id_validate(ViewContext *vc)
-{
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the backbuffer in this case. */
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- validate_object_select_id(vc->depsgraph, vc->view_layer, vc->ar, vc->v3d, vc->obact);
- }
-}
-
-void ED_view3d_backbuf_depth_validate(ViewContext *vc)
-{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- ARegion *ar = vc->ar;
- Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
-
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_object(vc->ar, vc->v3d, viewport, obact_eval);
- }
-
- vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
- }
-}
-
-/**
- * allow for small values [0.5 - 2.5],
- * and large values, FLT_MAX by clamping by the area size
- */
-int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
-{
- return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
-}
-
-/* *********************** */
-
-void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
-{
- /* clamp rect by region */
- rcti r = {
- .xmin = 0,
- .xmax = ar->winx - 1,
- .ymin = 0,
- .ymax = ar->winy - 1,
- };
-
- /* Constrain rect to depth bounds */
- BLI_rcti_isect(&r, rect, rect);
-
- /* assign values to compare with the ViewDepths */
- int x = rect->xmin;
- int y = rect->ymin;
-
- int w = BLI_rcti_size_x(rect);
- int h = BLI_rcti_size_y(rect);
-
- if (w <= 0 || h <= 0) {
- if (d->depths) {
- MEM_freeN(d->depths);
- }
- d->depths = NULL;
-
- d->damaged = false;
- }
- else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) {
- d->x = x;
- d->y = y;
- d->w = w;
- d->h = h;
-
- if (d->depths) {
- MEM_freeN(d->depths);
- }
-
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
-
- d->damaged = true;
- }
-
- if (d->damaged) {
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- view3d_opengl_read_Z_pixels(viewport, rect, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = false;
- }
-}
-
-/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
-void ED_view3d_depth_update(ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- /* Create storage for, and, if necessary, copy depth buffer */
- if (!rv3d->depths) {
- rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
- }
- if (rv3d->depths) {
- ViewDepths *d = rv3d->depths;
- if (d->w != ar->winx || d->h != ar->winy || !d->depths) {
- d->w = ar->winx;
- d->h = ar->winy;
- if (d->depths) {
- MEM_freeN(d->depths);
- }
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
- d->damaged = true;
- }
-
- if (d->damaged) {
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- rcti r = {
- .xmin = 0,
- .xmax = d->w,
- .ymin = 0,
- .ymax = d->h,
- };
- view3d_opengl_read_Z_pixels(viewport, &r, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = false;
- }
- }
-}
-
-/* utility function to find the closest Z value, use for autodepth */
-float view3d_depth_near(ViewDepths *d)
-{
- /* convert to float for comparisons */
- const float near = (float)d->depth_range[0];
- const float far_real = (float)d->depth_range[1];
- float far = far_real;
-
- const float *depths = d->depths;
- float depth = FLT_MAX;
- int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
-
- /* far is both the starting 'far' value
- * and the closest value found. */
- while (i--) {
- depth = *depths++;
- if ((depth < far) && (depth > near)) {
- far = depth;
- }
- }
-
- return far == far_real ? FLT_MAX : far;
-}
-
-void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d)
-{
- /* Setup view matrix. */
- ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
-
- GPU_clear(GPU_DEPTH_BIT);
-
- GPU_depth_test(true);
-
- GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport);
-
- GPU_depth_test(false);
-}
-
-/* *********************** customdata **************** */
-
-void ED_view3d_datamask(const bContext *C,
- const Scene *UNUSED(scene),
- const View3D *v3d,
- CustomData_MeshMasks *r_cddata_masks)
-{
- if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
- r_cddata_masks->vmask |= CD_MASK_ORCO;
- }
- else if (v3d->shading.type == OB_SOLID) {
- if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPUV;
- }
- if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) {
- r_cddata_masks->lmask |= CD_MASK_MLOOPCOL;
- }
- }
-
- if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) &&
- (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) {
- r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
- }
-}
-
-/* goes over all modes and view3d settings */
-void ED_view3d_screen_datamask(const bContext *C,
- const Scene *scene,
- const bScreen *screen,
- CustomData_MeshMasks *r_cddata_masks)
-{
- CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH);
-
- /* check if we need tfaces & mcols due to view mode */
- for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks);
- }
- }
-}
-
-/**
- * Store values from #RegionView3D, set when drawing.
- * This is needed when we draw with to a viewport using a different matrix
- * (offscreen drawing for example).
- *
- * Values set by #ED_view3d_update_viewmat should be handled here.
- */
-struct RV3DMatrixStore {
- float winmat[4][4];
- float viewmat[4][4];
- float viewinv[4][4];
- float persmat[4][4];
- float persinv[4][4];
- float viewcamtexcofac[4];
- float pixsize;
-};
-
-struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
-{
- struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
- copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
- copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
- copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
- copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
- copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
- copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
- rv3dmat->pixsize = rv3d->pixsize;
- return (void *)rv3dmat;
-}
-
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt)
-{
- struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
- copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
- copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
- copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
- copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
- copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
- copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
- rv3d->pixsize = rv3dmat->pixsize;
-}
-
-/**
- * \note The info that this uses is updated in #ED_refresh_viewport_fps,
- * which currently gets called during #SCREEN_OT_animation_step.
- */
-void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset)
-{
- ScreenFrameRateInfo *fpsi = scene->fps_info;
- char printable[16];
-
- if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) {
- return;
- }
-
- printable[0] = '\0';
-
-#if 0
- /* this is too simple, better do an average */
- fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
-#else
- fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 /
- (fpsi->lredrawtime - fpsi->redrawtime));
-
- float fps = 0.0f;
- int tot = 0;
- for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) {
- if (fpsi->redrawtimes_fps[i]) {
- fps += fpsi->redrawtimes_fps[i];
- tot++;
- }
- }
- if (tot) {
- fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
-
- // fpsi->redrawtime_index++;
- // if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) {
- // fpsi->redrawtime = 0;
- //}
-
- fps = fps / tot;
- }
-#endif
-
- const int font_id = BLF_default();
-
- /* is this more than half a frame behind? */
- if (fps + 0.5f < (float)(FPS)) {
- UI_FontThemeColor(font_id, TH_REDALERT);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
- }
- else {
- UI_FontThemeColor(font_id, TH_TEXT_HI);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
- }
-
- BLF_enable(font_id, BLF_SHADOW);
- BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
- BLF_shadow_offset(font_id, 1, -1);
-
- *yoffset -= U.widget_unit;
-
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
-#else
- BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
-#endif
-
- BLF_disable(font_id, BLF_SHADOW);
-}
-
-static bool view3d_main_region_do_render_draw(const Scene *scene)
-{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->view_update && type->view_draw);
-}
-
-bool ED_view3d_calc_render_border(
- const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- bool use_border;
-
- /* test if there is a 3d view rendering */
- if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) {
- return false;
- }
-
- /* test if there is a border render */
- if (rv3d->persp == RV3D_CAMOB) {
- use_border = (scene->r.mode & R_BORDER) != 0;
- }
- else {
- use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
- }
-
- if (!use_border) {
- return false;
- }
-
- /* compute border */
- if (rv3d->persp == RV3D_CAMOB) {
- rctf viewborder;
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
-
- rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
- rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
- rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
- rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
- }
- else {
- rect->xmin = v3d->render_border.xmin * ar->winx;
- rect->xmax = v3d->render_border.xmax * ar->winx;
- rect->ymin = v3d->render_border.ymin * ar->winy;
- rect->ymax = v3d->render_border.ymax * ar->winy;
- }
-
- BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
- BLI_rcti_isect(&ar->winrct, rect, rect);
-
- return true;
-}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 83fb87264e3..9a8e74385bb 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -48,7 +48,7 @@
#include "BKE_font.h"
#include "BKE_gpencil.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -700,9 +700,9 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
if (found) {
/* lock 'quat_best' to an axis view if we can */
- rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f);
+ ED_view3d_quat_to_axis_view(quat_best, 0.01f, &rv3d->view, &rv3d->view_axis_roll);
if (rv3d->view != RV3D_VIEW_USER) {
- ED_view3d_quat_from_axis_view(rv3d->view, quat_best);
+ ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, quat_best);
}
}
else {
@@ -3804,7 +3804,8 @@ static void axis_set_view(bContext *C,
View3D *v3d,
ARegion *ar,
const float quat_[4],
- short view,
+ char view,
+ char view_axis_roll,
int perspo,
const float *align_to_quat,
const int smooth_viewtx)
@@ -3818,10 +3819,12 @@ static void axis_set_view(bContext *C,
if (align_to_quat) {
mul_qt_qtqt(quat, quat, align_to_quat);
rv3d->view = view = RV3D_VIEW_USER;
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
}
if (align_to_quat == NULL) {
rv3d->view = view;
+ rv3d->view_axis_roll = view_axis_roll;
}
if (rv3d->viewlock & RV3D_LOCKED) {
@@ -3901,6 +3904,7 @@ static int view_axis_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d;
static int perspo = RV3D_PERSP;
int viewnum;
+ int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* no NULL check is needed, poll checks */
@@ -3928,58 +3932,73 @@ static int view_axis_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "relative")) {
- float z_rel[3];
+ float quat_rotate[4];
+ float quat_test[4];
- if (viewnum == RV3D_VIEW_RIGHT) {
- negate_v3_v3(z_rel, rv3d->viewinv[0]);
+ if (viewnum == RV3D_VIEW_LEFT) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f);
}
- else if (viewnum == RV3D_VIEW_LEFT) {
- copy_v3_v3(z_rel, rv3d->viewinv[0]);
+ else if (viewnum == RV3D_VIEW_RIGHT) {
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f);
}
else if (viewnum == RV3D_VIEW_TOP) {
- negate_v3_v3(z_rel, rv3d->viewinv[1]);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f);
}
else if (viewnum == RV3D_VIEW_BOTTOM) {
- copy_v3_v3(z_rel, rv3d->viewinv[1]);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f);
}
else if (viewnum == RV3D_VIEW_FRONT) {
- negate_v3_v3(z_rel, rv3d->viewinv[2]);
+ unit_qt(quat_rotate);
}
else if (viewnum == RV3D_VIEW_BACK) {
- copy_v3_v3(z_rel, rv3d->viewinv[2]);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI);
}
else {
BLI_assert(0);
}
- float angle_max = FLT_MAX;
- int view_closest = -1;
+ mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate);
+
+ float angle_best = FLT_MAX;
+ int view_best = -1;
+ int view_axis_roll_best = -1;
for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
- float quat[4];
- float mat[3][3];
- ED_view3d_quat_from_axis_view(i, quat);
- quat[0] *= -1.0f;
- quat_to_mat3(mat, quat);
- if (align_quat) {
- mul_qt_qtqt(quat, quat, align_quat);
- }
- const float angle_test = angle_normalized_v3v3(z_rel, mat[2]);
- if (angle_max > angle_test) {
- angle_max = angle_test;
- view_closest = i;
+ for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) {
+ float quat_axis[4];
+ ED_view3d_quat_from_axis_view(i, j, quat_axis);
+ if (align_quat) {
+ mul_qt_qtqt(quat_axis, quat_axis, align_quat);
+ }
+ const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test));
+ if (angle_best > angle_test) {
+ angle_best = angle_test;
+ view_best = i;
+ view_axis_roll_best = j;
+ }
}
}
- if (view_closest == -1) {
- view_closest = RV3D_VIEW_FRONT;
+ if (view_best == -1) {
+ view_best = RV3D_VIEW_FRONT;
+ view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
}
- viewnum = view_closest;
+
+ /* Disallow non-upright views in turn-table modes,
+ * it's too difficult to navigate out of them. */
+ if ((U.flag & USER_TRACKBALL) == 0) {
+ if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
+ }
+ }
+
+ viewnum = view_best;
+ view_axis_roll = view_axis_roll_best;
}
/* Use this to test if we started out with a camera */
const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
float quat[4];
- ED_view3d_quat_from_axis_view(viewnum, quat);
- axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_quat, smooth_viewtx);
+ ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
+ axis_set_view(C, v3d, ar, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
perspo = rv3d->persp;
@@ -4105,7 +4124,15 @@ static int view_camera_exec(bContext *C, wmOperator *op)
else {
/* return to settings of last view */
/* does view3d_smooth_view too */
- axis_set_view(C, v3d, ar, rv3d->lviewquat, rv3d->lview, rv3d->lpersp, NULL, smooth_viewtx);
+ axis_set_view(C,
+ v3d,
+ ar,
+ rv3d->lviewquat,
+ rv3d->lview,
+ rv3d->lview_axis_roll,
+ rv3d->lpersp,
+ NULL,
+ smooth_viewtx);
}
}
@@ -4217,7 +4244,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
if (view_opposite != RV3D_VIEW_USER) {
rv3d->view = view_opposite;
/* avoid float in-precision, just get a new orientation */
- ED_view3d_quat_from_axis_view(view_opposite, quat_new);
+ ED_view3d_quat_from_axis_view(view_opposite, rv3d->view_axis_roll, quat_new);
}
else {
rv3d->view = RV3D_VIEW_USER;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 33930efdd52..542d6dbea8b 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -709,7 +709,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
copy_m4_m4(cammat, ob->obmat);
- BKE_tracking_get_camera_object_matrix(scene, ob, mat);
+ BKE_tracking_get_camera_object_matrix(ob, mat);
INIT_MINMAX(min, max);
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 1af94e3ade5..08a4947dc18 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -408,6 +408,7 @@ void ED_view3d_lastview_store(RegionView3D *rv3d)
{
copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
rv3d->lview = rv3d->view;
+ rv3d->lview_axis_roll = rv3d->view_axis_roll;
if (rv3d->persp != RV3D_CAMOB) {
rv3d->lpersp = rv3d->persp;
}
@@ -781,14 +782,16 @@ static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_
int i;
/* we could use rv3d->viewinv, but better not depend on view matrix being updated */
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) {
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, rv3d_src->view_axis_roll, viewinv) ==
+ false)) {
return;
}
invert_qt_normalized(viewinv);
mul_qt_v3(viewinv, view_src_x);
mul_qt_v3(viewinv, view_src_y);
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) {
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, rv3d_dst->view_axis_roll, viewinv) ==
+ false)) {
return;
}
invert_qt_normalized(viewinv);
@@ -903,8 +906,9 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
if (ar->alignment == RGN_ALIGN_QSPLIT) {
rv3d = ar->regiondata;
if (rv3d->viewlock) {
- if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ if (!RV3D_VIEW_IS_AXIS(rv3d->view) || (rv3d->view_axis_roll != RV3D_VIEW_AXIS_ROLL_0)) {
rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
+ rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
rv3d->persp = RV3D_ORTHO;
ED_view3d_lock(rv3d);
}
@@ -1304,19 +1308,62 @@ bool ED_view3d_distance_set_from_location(RegionView3D *rv3d,
/* -------------------------------------------------------------------- */
/** \name View Axis Utilities
* \{ */
-static float view3d_quat_axis[6][4] = {
- {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */
- {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */
- {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */
- {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */
- {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */
- {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */
+
+/**
+ * Lookup by axis-view, axis-roll.
+ */
+static float view3d_quat_axis[6][4][4] = {
+ /* RV3D_VIEW_FRONT */
+ {
+ {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f},
+ {0.5f, -0.5f, -0.5f, 0.5f},
+ {0, 0, -M_SQRT1_2, M_SQRT1_2},
+ {-0.5f, 0.5f, -0.5f, 0.5f},
+ },
+ /* RV3D_VIEW_BACK */
+ {
+ {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2},
+ {0.5f, 0.5f, -0.5f, -0.5f},
+ {M_SQRT1_2, M_SQRT1_2, 0, 0},
+ {0.5f, 0.5f, 0.5f, 0.5f},
+ },
+ /* RV3D_VIEW_LEFT */
+ {
+ {0.5f, -0.5f, 0.5f, 0.5f},
+ {0, -M_SQRT1_2, 0.0f, M_SQRT1_2},
+ {-0.5f, -0.5f, -0.5f, 0.5f},
+ {-M_SQRT1_2, 0, -M_SQRT1_2, 0},
+ },
+
+ /* RV3D_VIEW_RIGHT */
+ {
+ {0.5f, -0.5f, -0.5f, -0.5f},
+ {M_SQRT1_2, 0, -M_SQRT1_2, 0},
+ {0.5f, 0.5f, -0.5f, 0.5f},
+ {0, M_SQRT1_2, 0, M_SQRT1_2},
+ },
+ /* RV3D_VIEW_TOP */
+ {
+ {1.0f, 0.0f, 0.0f, 0.0f},
+ {M_SQRT1_2, 0, 0, M_SQRT1_2},
+ {0, 0, 0, 1},
+ {-M_SQRT1_2, 0, 0, M_SQRT1_2},
+ },
+ /* RV3D_VIEW_BOTTOM */
+ {
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {0, -M_SQRT1_2, -M_SQRT1_2, 0},
+ {0, 0, -1, 0},
+ {0, M_SQRT1_2, -M_SQRT1_2, 0},
+ },
+
};
-bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
+bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float quat[4])
{
+ BLI_assert(view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270);
if (RV3D_VIEW_IS_AXIS(view)) {
- copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
+ copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll]);
return true;
}
else {
@@ -1324,19 +1371,28 @@ bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
}
}
-char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
+bool ED_view3d_quat_to_axis_view(const float quat[4],
+ const float epsilon,
+ char *r_view,
+ char *r_view_axis_roll)
{
- /* quat values are all unit length */
+ *r_view = RV3D_VIEW_USER;
+ *r_view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
- char view;
-
- for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
- if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) {
- return view;
+ /* quat values are all unit length */
+ for (int view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
+ for (int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270;
+ view_axis_roll++) {
+ if (fabsf(angle_signed_qtqt(
+ quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll])) < epsilon) {
+ *r_view = view;
+ *r_view_axis_roll = view_axis_roll;
+ return true;
+ }
}
}
- return RV3D_VIEW_USER;
+ return false;
}
char ED_view3d_lock_view_from_index(int index)
@@ -1375,7 +1431,7 @@ char ED_view3d_axis_view_opposite(char view)
bool ED_view3d_lock(RegionView3D *rv3d)
{
- return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
+ return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, rv3d->viewquat);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 53ff9952d05..e81a896e062 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -19,6 +19,7 @@
/** \file
* \ingroup edtransform
+ * \brief conversion and adaptation of different datablocks to a common struct.
*/
#ifndef __TRANSFORM_CONVERT_H__
@@ -60,28 +61,38 @@ void clipUVData(TransInfo *t);
/* transform_convert_action.c */
void flushTransIntFrameActionData(TransInfo *t);
+
/* transform_convert_armature.c */
void restoreMirrorPoseBones(TransDataContainer *tc);
void restoreBones(TransDataContainer *tc);
+
/* transform_convert_graph.c */
void flushTransGraphData(TransInfo *t);
+
/* transform_convert_mask.c */
void flushTransMasking(TransInfo *t);
+
/* transform_convert_mesh.c */
void flushTransUVs(TransInfo *t);
void trans_mesh_customdata_correction_init(TransInfo *t);
void trans_mesh_customdata_correction_apply(struct TransDataContainer *tc, bool is_final);
+
/* transform_convert_node.c */
void flushTransNodes(TransInfo *t);
+
/* transform_convert_object.c */
void trans_obdata_in_obmode_update_all(struct TransInfo *t);
void trans_obchild_in_obmode_update_all(struct TransInfo *t);
+
/* transform_convert_paintcurve.c */
void flushTransPaintCurve(TransInfo *t);
+
/* transform_convert_particle.c */
void flushTransParticles(TransInfo *t);
+
/* transform_convert_sequencer.c */
void flushTransSeq(TransInfo *t);
+
/* transform_convert_tracking.c */
void flushTransTracking(TransInfo *t);
@@ -96,45 +107,62 @@ bool FrameOnMouseSide(char side, float frame, float cframe);
/* transform_convert_action.c */
void createTransActionData(bContext *C, TransInfo *t);
+
/* transform_convert_armature.c */
struct bKinematicConstraint *has_targetless_ik(struct bPoseChannel *pchan);
void createTransPose(TransInfo *t);
void createTransArmatureVerts(TransInfo *t);
+
/* transform_convert_cursor.c */
void createTransCursor_image(TransInfo *t);
void createTransCursor_view3d(TransInfo *t);
+
/* transform_convert_curve.c */
void createTransCurveVerts(TransInfo *t);
+
/* transform_convert_graph.c */
void createTransGraphEditData(bContext *C, TransInfo *t);
+
/* transform_convert_gpencil.c */
void createTransGPencil(bContext *C, TransInfo *t);
+
/* transform_convert_lattice.c */
void createTransLatticeVerts(TransInfo *t);
+
/* transform_convert_mask.c */
void createTransMaskingData(bContext *C, TransInfo *t);
+
/* transform_convert_mball.c */
void createTransMBallVerts(TransInfo *t);
+
/* transform_convert_mesh.c */
void createTransEditVerts(TransInfo *t);
void createTransEdge(TransInfo *t);
void createTransUVs(bContext *C, TransInfo *t);
+
/* transform_convert_nla.c */
void createTransNlaData(bContext *C, TransInfo *t);
+
/* transform_convert_node.c */
void createTransNodeData(bContext *UNUSED(C), TransInfo *t);
+
/* transform_convert_object.c */
void clear_trans_object_base_flags(TransInfo *t);
void createTransObject(bContext *C, TransInfo *t);
void createTransTexspace(TransInfo *t);
+
/* transform_convert_paintcurve.c */
void createTransPaintCurveVerts(bContext *C, TransInfo *t);
+
/* transform_convert_particle.c */
void createTransParticleVerts(bContext *C, TransInfo *t);
+
/* transform_convert_sculpt.c */
void createTransSculpt(TransInfo *t);
+
/* transform_convert_sequence.c */
void createTransSeqData(bContext *C, TransInfo *t);
+
/* transform_convert_tracking.c */
void createTransTrackingData(bContext *C, TransInfo *t);
void cancelTransTracking(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 5595c3a0e38..db99971fa96 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -72,7 +72,7 @@
#include "BKE_gpencil.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mask.h"
#include "BKE_nla.h"
#include "BKE_paint.h"
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 63b9eb3937a..72076f64aa8 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -2055,7 +2055,7 @@ static short snapCamera(const SnapObjectContext *sctx,
tracking = &clip->tracking;
- BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
+ BKE_tracking_get_camera_object_matrix(object, orig_camera_mat);
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
index 8b125828fdc..7bdf607d981 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
@@ -48,7 +48,7 @@ extern "C" {
#include "render_types.h"
#include "BKE_customdata.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index bb9655fa59c..9073be55291 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -45,7 +45,7 @@ extern "C" {
#include "BKE_idprop.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h" /* free_libblock */
+#include "BKE_lib_id.h" /* free_libblock */
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 0567bd0df06..fdf9d4bac3d 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -46,7 +46,7 @@ extern "C" {
#include "BKE_context.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_linestyle.h"
#include "BKE_scene.h"
#include "BKE_text.h"
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
index 255a1b2a152..af4ab18d0e8 100644
--- a/source/blender/freestyle/intern/system/PythonInterpreter.h
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -39,7 +39,7 @@ extern "C" {
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_text.h"
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp
index 9acd730d062..c371eba4b94 100644
--- a/source/blender/freestyle/intern/view_map/ViewMap.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp
@@ -386,7 +386,7 @@ void TVertex::setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming)
if (!_sortedEdges.empty()) {
edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
for (; (dve != dveend) && ViewEdgeComp(**dve, _BackEdgeA); ++dve) {
- ;
+ /* pass */
}
_sortedEdges.insert(dve, &_BackEdgeA);
}
@@ -563,7 +563,7 @@ void NonTVertex::AddOutgoingViewEdge(ViewEdge *iVEdge)
if (!_ViewEdges.empty()) {
edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
for (; (dve != dveend) && ViewEdgeComp(*dve, idve); ++dve) {
- ;
+ /* pass */
}
_ViewEdges.insert(dve, idve);
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 27c8175af3f..eceb45780cf 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -39,7 +39,7 @@
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_modifier.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_scene.h"
#include "BKE_main.h"
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index bb70b548675..11ba639fa83 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -44,7 +44,7 @@
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_layer.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_collection.h"
#include "DEG_depsgraph.h"
@@ -228,24 +228,34 @@ static void generate_geometry(GpencilModifierData *md,
for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) {
/* check if stroke can be duplicated */
if (valid_strokes[idx]) {
- /* Duplicate stroke */
- bGPDstroke *gps_dst = MEM_dupallocN(gps);
- gps_dst->points = MEM_dupallocN(gps->points);
- if (gps->dvert) {
- gps_dst->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, gps_dst);
+ /* Calculate original stroke center (only first loop). */
+ float r_min[3], r_max[3], center[3];
+ if (x == 1) {
+ INIT_MINMAX(r_min, r_max);
+ BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
+ add_v3_v3v3(center, r_min, r_max);
+ mul_v3_fl(center, 0.5f);
+ sub_v3_v3v3(center, center, ob->obmat[3]);
}
- gps_dst->triangles = MEM_dupallocN(gps->triangles);
+
+ /* Duplicate stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
/* Move points */
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps_dst->points[i];
+ /* Apply object local transform (Rot/Scale). */
if (mmd->object) {
- /* apply local changes (rot/scale) */
mul_m4_v3(mat, &pt->x);
}
- /* global changes */
- mul_m4_v3(current_offset, &pt->x);
+ /* Translate to object origin. */
+ float fpt[3];
+ sub_v3_v3v3(fpt, &pt->x, center);
+ /* Global Rotate and scale. */
+ mul_mat3_m4_v3(current_offset, fpt);
+ /* Global translate. */
+ add_v3_v3(fpt, center);
+ add_v3_v3v3(&pt->x, fpt, current_offset[3]);
}
/* if replace material, use new one */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index bc62d0d69bb..132d86a87c8 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -40,7 +40,7 @@
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_modifier.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_scene.h"
#include "BKE_main.h"
#include "BKE_layer.h"
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index 9dbf7b35bc5..9286fcfff56 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -36,7 +36,7 @@
#include "BKE_gpencil_modifier.h"
#include "BKE_modifier.h"
#include "BKE_lattice.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_scene.h"
#include "BKE_main.h"
#include "BKE_layer.h"
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index ef06e14b3d7..42d45512dc5 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -38,7 +38,7 @@
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_modifier.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_scene.h"
#include "BKE_main.h"
#include "BKE_layer.h"
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
index bc545ce6ce8..919dbf91862 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
@@ -46,7 +46,7 @@
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_layer.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_collection.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index ab6c8c4e8a6..4e24a3172dc 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -31,12 +31,12 @@ extern "C" {
#endif
struct GPUVertBuf;
+struct ImBuf;
struct Image;
struct ImageUser;
struct MovieClip;
struct MovieClipUser;
struct PreviewImage;
-struct ImBuf;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 648389d610f..be904c5bf94 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -280,7 +280,7 @@ typedef struct MStringProperty {
*/
typedef struct MDeformWeight {
/** The index for the vertex group, must *always* be unique when in an array. */
- int def_nr;
+ unsigned int def_nr;
/** Weight between 0.0 and 1.0. */
float weight;
} MDeformWeight;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index fcf41481ade..2c0d34fdccf 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -24,6 +24,10 @@
#include "DNA_defs.h"
#include "DNA_listBase.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE!
* (ONLY ADD NEW ITEMS AT THE END)
*/
@@ -2042,4 +2046,8 @@ enum {
#define MOD_MESHSEQ_READ_ALL \
(MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __DNA_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index d741f22cc4f..cd67bb3d25b 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -724,6 +724,7 @@ typedef struct UserDef {
short vbotimeout, vbocollectrate;
short textimeout, texcollectrate;
int memcachelimit;
+ /** Unused. */
int prefetchframes;
/** Control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use. */
float pad_rot_angle;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 93b93bbdbf7..9a3bbee115b 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -104,10 +104,11 @@ typedef struct RegionView3D {
char is_persp;
char persp;
char view;
+ char view_axis_roll;
char viewlock;
/** Options for quadview (store while out of quad view). */
char viewlock_quad;
- char _pad[3];
+ char _pad[2];
/** Normalized offset for locked view: (-1, -1) bottom left, (1, 1) upper right. */
float ofs_lock[2];
@@ -118,7 +119,10 @@ typedef struct RegionView3D {
/** Last view (use when switching out of camera view). */
float lviewquat[4];
/** Lpersp can never be set to 'RV3D_CAMOB'. */
- short lpersp, lview;
+ char lpersp;
+ char lview;
+ char lview_axis_roll;
+ char _pad8[1];
/** Active rotation from NDOF or elsewhere. */
float rot_angle;
@@ -376,6 +380,19 @@ typedef struct View3D {
#define RV3D_VIEW_CAMERA 8
#define RV3D_VIEW_IS_AXIS(view) (((view) >= RV3D_VIEW_FRONT) && ((view) <= RV3D_VIEW_BOTTOM))
+
+/**
+ * #RegionView3D.view_axis_roll
+ *
+ * Clockwise rotation to use for axis-views, when #RV3D_VIEW_IS_AXIS is true.
+ */
+enum {
+ RV3D_VIEW_AXIS_ROLL_0 = 0,
+ RV3D_VIEW_AXIS_ROLL_90 = 1,
+ RV3D_VIEW_AXIS_ROLL_180 = 2,
+ RV3D_VIEW_AXIS_ROLL_270 = 3,
+};
+
#define RV3D_CLIPPING_ENABLED(v3d, rv3d) \
(rv3d && v3d && (rv3d->rflag & RV3D_CLIPPING) && ELEM(v3d->shading.type, OB_WIRE, OB_SOLID) && \
rv3d->clipbb)
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index e9c9b7e2815..54a2abdfa8c 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -260,7 +260,11 @@ extern StructRNA RNA_FileBrowserFSMenuEntry;
extern StructRNA RNA_FileSelectParams;
extern StructRNA RNA_FloatProperty;
extern StructRNA RNA_FloorConstraint;
+extern StructRNA RNA_FluidDomainSettings;
+extern StructRNA RNA_FluidEffectorSettings;
+extern StructRNA RNA_FluidFlowSettings;
extern StructRNA RNA_FluidFluidSettings;
+extern StructRNA RNA_FluidModifier;
extern StructRNA RNA_FluidSettings;
extern StructRNA RNA_FollowPathConstraint;
extern StructRNA RNA_FreestyleLineSet;
@@ -595,10 +599,6 @@ extern StructRNA RNA_ShrinkwrapModifier;
extern StructRNA RNA_SimpleDeformModifier;
extern StructRNA RNA_SimplifyGpencilModifier;
extern StructRNA RNA_SkinModifier;
-extern StructRNA RNA_FluidEffectorSettings;
-extern StructRNA RNA_FluidDomainSettings;
-extern StructRNA RNA_FluidFlowSettings;
-extern StructRNA RNA_FluidModifier;
extern StructRNA RNA_SmoothGpencilModifier;
extern StructRNA RNA_SmoothModifier;
extern StructRNA RNA_SoftBodyModifier;
@@ -736,11 +736,11 @@ extern StructRNA RNA_WalkNavigation;
extern StructRNA RNA_WarpModifier;
extern StructRNA RNA_WaveModifier;
extern StructRNA RNA_WeightedNormalModifier;
+extern StructRNA RNA_WeldModifier;
extern StructRNA RNA_Window;
extern StructRNA RNA_WindowManager;
extern StructRNA RNA_WipeSequence;
extern StructRNA RNA_WireframeModifier;
-extern StructRNA RNA_WeldModifier;
extern StructRNA RNA_WoodTexture;
extern StructRNA RNA_WorkSpace;
extern StructRNA RNA_World;
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 9b38ca8009c..2f5d9ae7a50 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4309,7 +4309,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
fprintf(f, "#include \"BLI_utildefines.h\"\n\n");
fprintf(f, "#include \"BKE_context.h\"\n");
- fprintf(f, "#include \"BKE_library.h\"\n");
+ fprintf(f, "#include \"BKE_lib_id.h\"\n");
fprintf(f, "#include \"BKE_main.h\"\n");
fprintf(f, "#include \"BKE_report.h\"\n");
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 0b4ac400152..12fa8150d5f 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -29,7 +29,7 @@
#include "BLI_utildefines.h"
#include "BKE_icons.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_object.h"
#include "RNA_access.h"
@@ -90,9 +90,10 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
# include "BKE_font.h"
# include "BKE_idprop.h"
-# include "BKE_library_query.h"
-# include "BKE_library_override.h"
-# include "BKE_library_remap.h"
+# include "BKE_lib_query.h"
+# include "BKE_lib_override.h"
+# include "BKE_lib_remap.h"
+# include "BKE_library.h"
# include "BKE_animsys.h"
# include "BKE_material.h"
# include "BKE_global.h" /* XXX, remove me */
@@ -493,7 +494,7 @@ static ID *rna_ID_copy(ID *id, Main *bmain)
static ID *rna_ID_override_create(ID *id, Main *bmain, bool remap_local_usages)
{
- if (!BKE_override_library_is_enabled() || !ID_IS_OVERRIDABLE_LIBRARY(id)) {
+ if (!BKE_lib_override_library_is_enabled() || !ID_IS_OVERRIDABLE_LIBRARY(id)) {
return NULL;
}
@@ -501,7 +502,7 @@ static ID *rna_ID_override_create(ID *id, Main *bmain, bool remap_local_usages)
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
}
- ID *local_id = BKE_override_library_create_from_id(bmain, id, remap_local_usages);
+ ID *local_id = BKE_lib_override_library_create_from_id(bmain, id, remap_local_usages);
if (remap_local_usages) {
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
index 7c9b4254e4d..053a0765546 100644
--- a/source/blender/makesrna/intern/rna_access_compare_override.c
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -34,7 +34,7 @@
#endif
#include "BKE_idprop.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "RNA_access.h"
@@ -109,7 +109,7 @@ bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop)
return false;
}
- return (BKE_override_library_property_find(id->override_library, rna_path) != NULL);
+ return (BKE_lib_override_library_property_find(id->override_library, rna_path) != NULL);
}
bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
@@ -691,7 +691,7 @@ bool RNA_struct_override_matches(Main *bmain,
// printf("Override Checking %s\n", rna_path);
- if (ignore_overridden && BKE_override_library_property_find(override, rna_path) != NULL) {
+ if (ignore_overridden && BKE_lib_override_library_property_find(override, rna_path) != NULL) {
RNA_PATH_FREE;
continue;
}
@@ -730,7 +730,7 @@ bool RNA_struct_override_matches(Main *bmain,
if (diff != 0) {
/* XXX TODO: refine this for per-item overriding of arrays... */
- IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path);
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(override, rna_path);
IDOverrideLibraryPropertyOperation *opop = op ? op->operations.first : NULL;
if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) {
@@ -1059,8 +1059,8 @@ IDOverrideLibraryProperty *RNA_property_override_property_find(PointerRNA *ptr,
char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
if (rna_path) {
- IDOverrideLibraryProperty *op = BKE_override_library_property_find(id->override_library,
- rna_path);
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(id->override_library,
+ rna_path);
MEM_freeN(rna_path);
return op;
}
@@ -1079,7 +1079,7 @@ IDOverrideLibraryProperty *RNA_property_override_property_get(PointerRNA *ptr,
char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
if (rna_path) {
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
id->override_library, rna_path, r_created);
MEM_freeN(rna_path);
return op;
@@ -1096,7 +1096,7 @@ IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_fin
return NULL;
}
- return BKE_override_library_property_operation_find(
+ return BKE_lib_override_library_property_operation_find(
op, NULL, NULL, index, index, strict, r_strict);
}
@@ -1115,7 +1115,7 @@ IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_get
return NULL;
}
- return BKE_override_library_property_operation_get(
+ return BKE_lib_override_library_property_operation_get(
op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
}
@@ -1125,7 +1125,7 @@ eRNAOverrideStatus RNA_property_override_library_status(PointerRNA *ptr,
{
int override_status = 0;
- if (!BKE_override_library_is_enabled()) {
+ if (!BKE_lib_override_library_is_enabled()) {
return override_status;
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index edbaa13f80c..3c9942f32c7 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -151,7 +151,11 @@ const EnumPropertyItem rna_enum_brush_gpencil_types_items[] = {
#ifndef RNA_RUNTIME
static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = {
- {GP_BRUSH_ERASER_SOFT, "SOFT", 0, "Dissolve,", "Erase strokes, fading their points strength and thickness"},
+ {GP_BRUSH_ERASER_SOFT,
+ "SOFT",
+ 0,
+ "Dissolve,",
+ "Erase strokes, fading their points strength and thickness"},
{GP_BRUSH_ERASER_HARD, "HARD", 0, "Point", "Erase stroke points"},
{GP_BRUSH_ERASER_STROKE, "STROKE", 0, "Stroke", "Erase entire strokes"},
{0, NULL, 0, NULL, NULL},
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index 40c6229f9b1..da882959ef2 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -88,11 +88,22 @@ static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr)
static void rna_LayerObjects_active_object_set(PointerRNA *ptr,
PointerRNA value,
- struct ReportList *UNUSED(reports))
+ struct ReportList *reports)
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
if (value.data) {
- view_layer->basact = BKE_view_layer_base_find(view_layer, (Object *)value.data);
+ Object *ob = value.data;
+ Base *basact_test = BKE_view_layer_base_find(view_layer, ob);
+ if (basact_test != NULL) {
+ view_layer->basact = basact_test;
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "ViewLayer '%s' does not contain object '%s'",
+ view_layer->name,
+ ob->id.name + 2);
+ }
}
else {
view_layer->basact = NULL;
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 31e696534fe..bb851365997 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -54,7 +54,7 @@
# include "BKE_image.h"
# include "BKE_light.h"
# include "BKE_lattice.h"
-# include "BKE_library_remap.h"
+# include "BKE_lib_remap.h"
# include "BKE_lightprobe.h"
# include "BKE_linestyle.h"
# include "BKE_mask.h"
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 85c4352d277..c6175f85bd8 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -1313,7 +1313,8 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_custom_shape_bone_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "drawflag", PCHAN_DRAW_NO_CUSTOM_BONE_SIZE);
- RNA_def_property_ui_text(prop, "Use Bone Size", "Scale the custom object by the bone length");
+ RNA_def_property_ui_text(
+ prop, "Scale to Bone Length", "Scale the custom object by the bone length");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
prop = RNA_def_property(srna, "custom_shape_transform", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 4db702b215f..484fac18c8e 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -127,7 +127,7 @@ const EnumPropertyItem rna_enum_property_unit_items[] = {
# include "BLI_ghash.h"
# include "BLI_string.h"
-# include "BKE_library_override.h"
+# include "BKE_lib_override.h"
/* Struct */
@@ -1290,21 +1290,21 @@ static int rna_property_override_diff_propptr(Main *bmain,
if (do_create && comp != 0) {
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
/* If not yet overridden, or if we are handling sub-items (inside a collection)... */
if (op != NULL && (created || rna_itemname_a != NULL || rna_itemname_b != NULL ||
rna_itemindex_a != -1 || rna_itemindex_b != -1)) {
- BKE_override_library_property_operation_get(op,
- IDOVERRIDE_LIBRARY_OP_REPLACE,
- rna_itemname_b,
- rna_itemname_a,
- rna_itemindex_b,
- rna_itemindex_a,
- true,
- NULL,
- &created);
+ BKE_lib_override_library_property_operation_get(op,
+ IDOVERRIDE_LIBRARY_OP_REPLACE,
+ rna_itemname_b,
+ rna_itemname_a,
+ rna_itemindex_b,
+ rna_itemindex_a,
+ true,
+ NULL,
+ &created);
if (r_override_changed) {
*r_override_changed = created;
}
@@ -1421,11 +1421,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
/* XXX TODO this will have to be refined to handle array items */
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) {
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1452,11 +1452,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) { /* If not yet overridden... */
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1486,11 +1486,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
/* XXX TODO this will have to be refined to handle array items */
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) {
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1517,11 +1517,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) { /* If not yet overridden... */
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1551,11 +1551,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
/* XXX TODO this will have to be refined to handle array items */
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) {
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1582,11 +1582,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) { /* If not yet overridden... */
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1605,11 +1605,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) { /* If not yet overridden... */
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1639,11 +1639,11 @@ int rna_property_override_diff_default(Main *bmain,
if (do_create && comp != 0) {
bool created = false;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (op != NULL && created) { /* If not yet overridden... */
- BKE_override_library_property_operation_get(
+ BKE_lib_override_library_property_operation_get(
op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@@ -1794,7 +1794,7 @@ int rna_property_override_diff_default(Main *bmain,
* also assume then that _a data is the one where things are inserted. */
if (is_valid_for_insertion && use_insertion) {
bool created;
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
override, rna_path, &created);
if (is_first_insert) {
@@ -1806,22 +1806,22 @@ int rna_property_override_diff_default(Main *bmain,
if (ELEM(opop->operation,
IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) {
- BKE_override_library_property_operation_delete(op, opop);
+ BKE_lib_override_library_property_operation_delete(op, opop);
}
opop = opop_next;
}
is_first_insert = false;
}
- BKE_override_library_property_operation_get(op,
- IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
- NULL,
- prev_propname_a,
- -1,
- idx_a - 1,
- true,
- NULL,
- NULL);
+ BKE_lib_override_library_property_operation_get(op,
+ IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
+ NULL,
+ prev_propname_a,
+ -1,
+ idx_a - 1,
+ true,
+ NULL,
+ NULL);
# if 0
printf("%s: Adding insertion op override after '%s'/%d\n",
rna_path,
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 3562569acec..ee697955ad4 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -365,7 +365,7 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_function_ui_description(func, "Clear sequence editor in this scene");
# ifdef WITH_ALEMBIC
- /* XXX Deprecated, will be removed in 2.8 in favour of calling the export operator. */
+ /* XXX Deprecated, will be removed in 2.8 in favor of calling the export operator. */
func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export");
RNA_def_function_ui_description(
func, "Export to Alembic file (deprecated, use the Alembic export operator)");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index b9fb8638c49..43a9bbd2e36 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -5074,14 +5074,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
/* Memory */
- prop = RNA_def_property(srna, "prefetch_frames", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "prefetchframes");
- RNA_def_property_range(prop, 0, INT_MAX);
- RNA_def_property_ui_range(prop, 0, 500, 1, -1);
- RNA_def_property_ui_text(prop,
- "Prefetch Frames",
- "Number of frames to render ahead during playback (sequencer only)");
-
prop = RNA_def_property(srna, "memory_cache_limit", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "memcachelimit");
RNA_def_property_range(prop, 0, max_memory_in_megabytes_int());
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 7dd1ce830aa..5dc4adf4393 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -23,6 +23,10 @@
#include "BKE_modifier.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* ****************** Type structures for all modifiers ****************** */
extern ModifierTypeInfo modifierType_None;
@@ -86,4 +90,8 @@ extern ModifierTypeInfo modifierType_WeightedNormal;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __MOD_MODIFIERTYPES_H__ */
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 9f3802a4fa1..38b66121cee 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -33,8 +33,8 @@
#include "BKE_action.h"
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 3b50cfe704a..f8f8ea49676 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -37,8 +37,8 @@
#include "BKE_displist.h"
#include "BKE_curve.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_object_deform.h"
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 9868395c0e8..20a4d8eef65 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -36,8 +36,8 @@
#include "DNA_object_types.h"
#include "BKE_global.h" /* only to check G.debug */
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index b070a3c7127..4cb73289636 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -31,8 +31,8 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index cc91e345c8f..953b1b460c8 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -39,8 +39,8 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 56e84423db4..2dec5963f3c 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -33,7 +33,7 @@
#include "BKE_collision.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index ff241550bdc..a746e265e39 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -37,7 +37,7 @@
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "MOD_modifiertypes.h"
#include "MOD_util.h"
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 7bfe63e562a..f1fa627df00 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -31,8 +31,8 @@
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
@@ -119,8 +119,14 @@ static void deformVerts(ModifierData *md,
/* silly that defaxis and curve_deform_verts are off by 1
* but leave for now to save having to call do_versions */
- curve_deform_verts(
- cmd->object, ctx->object, vertexCos, numVerts, dvert, defgrp_index, cmd->flag, cmd->defaxis - 1);
+ curve_deform_verts(cmd->object,
+ ctx->object,
+ vertexCos,
+ numVerts,
+ dvert,
+ defgrp_index,
+ cmd->flag,
+ cmd->defaxis - 1);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index bb032f9725c..5e6a5046a5b 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -32,8 +32,8 @@
#include "BKE_customdata.h"
#include "BKE_data_transfer.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 7f65b3bb5ae..196b0f5e126 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -32,8 +32,8 @@
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 83d8439f046..dc9b2f763e0 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -30,7 +30,7 @@
#include "BKE_dynamicpaint.h"
#include "BKE_layer.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 5f0bbc8ecf1..88e45f652a0 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -35,7 +35,7 @@
#include "BKE_deform.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c
index b48c80d8e32..9347c54b0ac 100644
--- a/source/blender/modifiers/intern/MOD_fluid.c
+++ b/source/blender/modifiers/intern/MOD_fluid.c
@@ -36,7 +36,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_layer.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_fluid.h"
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 1a62010abe7..b1a662c8667 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -31,8 +31,8 @@
#include "BKE_action.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 0fc2e0971da..866cf67bf79 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -34,7 +34,7 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_particle.h"
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 86d4124e5db..dbe776ed32a 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -33,7 +33,7 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 3128183060a..2b39f40a2b9 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -29,8 +29,8 @@
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
@@ -101,8 +101,14 @@ static void deformVerts(ModifierData *md,
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
- lattice_deform_verts(
- lmd->object, ctx->object, mesh_src, vertexCos, numVerts, lmd->flag, lmd->name, lmd->strength);
+ lattice_deform_verts(lmd->object,
+ ctx->object,
+ mesh_src,
+ vertexCos,
+ numVerts,
+ lmd->flag,
+ lmd->name,
+ lmd->strength);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index cf7d227e898..00b0068bd11 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -36,7 +36,7 @@
#include "BKE_action.h" /* BKE_pose_channel_find_name */
#include "BKE_customdata.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
@@ -131,7 +131,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
bDeformGroup *def;
bool *bone_select_array;
int bone_select_tot = 0;
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const uint defbase_tot = (uint)BLI_listbase_count(&ob->defbase);
/* check that there is armature object with bones to use, otherwise return original mesh */
if (ELEM(NULL, oba, oba->pose, ob->defbase.first)) {
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 21fdc010a1d..5be26e2a2dd 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -32,8 +32,8 @@
#include "DNA_scene_types.h"
#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 0f57b759e38..e0c81b005fd 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -31,7 +31,7 @@
#include "DNA_scene_types.h"
#include "BKE_cachefile.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_scene.h"
#include "DEG_depsgraph_build.h"
@@ -42,7 +42,7 @@
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
# include "BKE_global.h"
-# include "BKE_library.h"
+# include "BKE_lib_id.h"
#endif
static void initData(ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index fe3e608fcbe..45a2f619369 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -27,8 +27,8 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mirror.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 10852ed6148..b57fb7b398a 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -31,8 +31,8 @@
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_deform.h"
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 97be42367d4..62a5dd45e68 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -34,7 +34,7 @@
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_ocean.h"
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index f4c2e78d1ac..d4a8f50f03f 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -35,7 +35,7 @@
#include "BKE_effect.h"
#include "BKE_lattice.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 67a64921bbc..462f9a428f3 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -30,7 +30,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 773cbf72d5b..a50b703756e 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -33,7 +33,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "DEG_depsgraph_build.h"
@@ -1090,7 +1090,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
/* validate loop edges */
#if 0
{
- unsigned i = 0;
+ uint i = 0;
printf("\n");
for (; i < maxPolys * 4; i += 4) {
uint ii;
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 6e4b0edb004..e76731caae2 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -29,8 +29,8 @@
#include "DNA_object_types.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_shrinkwrap.h"
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index d10d74da453..18236973ea2 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -31,8 +31,8 @@
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 6e7a0b0dbae..4371de62fca 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -67,7 +67,7 @@
#include "DNA_modifier_types.h"
#include "BKE_deform.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index 59ed3b0b005..4dcd89c9709 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -31,7 +31,7 @@
#include "DNA_meshdata_types.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_particle.h"
#include "BKE_deform.h"
@@ -140,8 +140,9 @@ static void smoothModifier_do(
}
float *vco_new = accumulated_vecs[i];
- const float f_new = invert_vgroup ? (1.0f - defvert_find_weight(dv, defgrp_index)) * fac_new :
- defvert_find_weight(dv, defgrp_index) * fac_new;
+ const float f_new = invert_vgroup ?
+ (1.0f - defvert_find_weight(dv, defgrp_index)) * fac_new :
+ defvert_find_weight(dv, defgrp_index) * fac_new;
if (f_new <= 0.0f) {
continue;
}
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index 97e6bb9e804..a9c91e6188d 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -31,7 +31,7 @@
#include "DNA_meshdata_types.h"
#include "BKE_bvhutils.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 6ec7d1069de..605919662f7 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -32,8 +32,8 @@
#include "BKE_bvhutils.h"
#include "BKE_mesh_runtime.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 0b72c31ad7b..0fd4e6f9f72 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -40,7 +40,7 @@
#include "BKE_editmesh.h"
#include "BKE_image.h"
#include "BKE_lattice.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 9698e150850..b87bfa7190f 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -34,7 +34,7 @@
#include "DNA_object_types.h"
#include "BKE_camera.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 2c5f4b66c23..140da695ca7 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -31,7 +31,7 @@
#include "BKE_action.h" /* BKE_pose_channel_find_name */
#include "BKE_deform.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "DEG_depsgraph_query.h"
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index ba017577004..57094d71522 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -31,8 +31,8 @@
#include "DNA_object_types.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 908abeb6f76..ff5748b968c 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -32,8 +32,8 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 0accbe607eb..84ba6a7b148 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -29,7 +29,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 045ba78fab5..462830867cc 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -35,7 +35,7 @@
#include "BKE_colortools.h" /* CurveMapping. */
#include "BKE_deform.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 368a6b46c7e..774ce321358 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -33,7 +33,7 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 553743272a2..4f9719552fe 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -38,8 +38,8 @@
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c
index f96ec9a82e5..bd567c52d88 100644
--- a/source/blender/modifiers/intern/MOD_weld.c
+++ b/source/blender/modifiers/intern/MOD_weld.c
@@ -46,6 +46,8 @@
#include "DEG_depsgraph.h"
+#include "MOD_modifiertypes.h"
+
//#define USE_WELD_DEBUG
//#define USE_WELD_NORMALS
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 88765f1d165..e9a9aa37cfa 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -32,7 +32,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_scene.h"
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
index 07b339a5b78..8ad831dc1ae 100644
--- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
@@ -24,7 +24,7 @@
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{SOCK_RGBA, 0, N_("Image")},
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
index d218f7568eb..eee58bd354b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
+++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
@@ -24,7 +24,7 @@
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
/* **************** Translate ******************** */
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
index c13356f72b0..c57456adeb9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
+++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
@@ -24,7 +24,7 @@
#include "node_composite_util.h"
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
/* **************** Translate ******************** */
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
index cecd8204f4a..778be3db0f6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switchview.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -23,7 +23,7 @@
*/
#include "BKE_context.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "../node_composite_util.h"
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 3a51239306e..12763390506 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -44,7 +44,7 @@
#include "BKE_linestyle.h"
#include "BKE_node.h"
#include "BKE_scene.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "RNA_access.h"
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 73107ebc16c..ebfce204456 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -30,7 +30,7 @@
#include "BKE_customdata.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
index 77dd4891e17..0efafe4e022 100644
--- a/source/blender/python/gpu/gpu_py_offscreen.c
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -33,7 +33,7 @@
#include "BLI_utildefines.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_scene.h"
#include "DNA_screen_types.h"
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 678df0d8993..b6784f2cdc2 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -50,7 +50,7 @@
#include "BKE_appdir.h"
#include "BKE_blender_version.h"
#include "BKE_global.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_override.h"
#include "DNA_ID.h"
@@ -396,7 +396,7 @@ PyDoc_STRVAR(bpy_app_use_override_library_doc,
"Boolean, whether library override is exposed in UI or not.");
static PyObject *bpy_app_use_override_library_get(PyObject *UNUSED(self), void *UNUSED(closure))
{
- return PyBool_FromLong((long)BKE_override_library_is_enabled());
+ return PyBool_FromLong((long)BKE_lib_override_library_is_enabled());
}
static int bpy_app_use_override_library_set(PyObject *UNUSED(self),
@@ -410,7 +410,7 @@ static int bpy_app_use_override_library_set(PyObject *UNUSED(self),
return -1;
}
- BKE_override_library_enable((const bool)param);
+ BKE_lib_override_library_enable((const bool)param);
return 0;
}
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index b797624f23c..95f0daae862 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -36,7 +36,7 @@
#include "BKE_context.h"
#include "BKE_idcode.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 8aa6aa91fcf..bda7d342576 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -40,7 +40,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_report.h"
#include "RNA_access.h"
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 6ff1849f646..68e1678027e 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -29,8 +29,8 @@
#include "BLI_bitmap.h"
#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "DNA_ID.h"
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 82f1d17fe52..8af6e9a527e 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -47,7 +47,7 @@
# include "BKE_customdata.h"
# include "BKE_editmesh_bvh.h"
-# include "BKE_library.h"
+# include "BKE_lib_id.h"
# include "BKE_mesh.h"
# include "BKE_mesh_runtime.h"
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index e8c349f6c85..ca6ae3fb78c 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -73,7 +73,7 @@
#include "BKE_bvhutils.h"
#include "BKE_customdata.h"
#include "BKE_image.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_tangent.h"
#include "BKE_mesh_runtime.h"
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index c3125cb72a1..183ef89892e 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -59,8 +59,8 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_remap.h"
#include "BKE_mask.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
diff --git a/source/blender/shader_fx/intern/FX_shader_light.c b/source/blender/shader_fx/intern/FX_shader_light.c
index d3d5b9b69cb..5bcc130eb78 100644
--- a/source/blender/shader_fx/intern/FX_shader_light.c
+++ b/source/blender/shader_fx/intern/FX_shader_light.c
@@ -29,7 +29,7 @@
#include "BLI_utildefines.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_shader_fx.h"
diff --git a/source/blender/shader_fx/intern/FX_shader_shadow.c b/source/blender/shader_fx/intern/FX_shader_shadow.c
index 04160f618eb..0ee45a0bd51 100644
--- a/source/blender/shader_fx/intern/FX_shader_shadow.c
+++ b/source/blender/shader_fx/intern/FX_shader_shadow.c
@@ -29,7 +29,7 @@
#include "BLI_utildefines.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_shader_fx.h"
diff --git a/source/blender/shader_fx/intern/FX_shader_swirl.c b/source/blender/shader_fx/intern/FX_shader_swirl.c
index ee865e13764..6884694e057 100644
--- a/source/blender/shader_fx/intern/FX_shader_swirl.c
+++ b/source/blender/shader_fx/intern/FX_shader_swirl.c
@@ -30,7 +30,7 @@
#include "BLI_math_base.h"
#include "BLI_utildefines.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_shader_fx.h"
diff --git a/source/blender/usd/intern/usd_writer_mesh.cc b/source/blender/usd/intern/usd_writer_mesh.cc
index dc603f25b21..bc3bc06f8a6 100644
--- a/source/blender/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/usd/intern/usd_writer_mesh.cc
@@ -29,7 +29,7 @@ extern "C" {
#include "BKE_anim.h"
#include "BKE_customdata.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
@@ -59,7 +59,7 @@ bool USDGenericMeshWriter::is_supported(const HierarchyContext *context) const
if (is_dupli) {
/* Construct the object's base flags from its dupliparent, just like is done in
- * deg_objects_dupli_iterator_next(). Without this, the visiblity check below will fail. Doing
+ * deg_objects_dupli_iterator_next(). Without this, the visibility check below will fail. Doing
* this here, instead of a more suitable location in AbstractHierarchyIterator, prevents
* copying the Object for every dupli. */
base_flag = object->base_flag;
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 454239e5cf0..15e33734b62 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -40,7 +40,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_workspace.h"
@@ -344,7 +344,7 @@ void wm_add_default(Main *bmain, bContext *C)
wm_window_make_drawable(wm, win);
}
-/* context is allowed to be NULL, do not free wm itself (library.c) */
+/* context is allowed to be NULL, do not free wm itself (lib_id.c) */
void wm_close_and_free(bContext *C, wmWindowManager *wm)
{
wmWindow *win;
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index b82865a727d..e22863bc602 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -132,11 +132,8 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
}
}
-static void window_set_custom_cursor(wmWindow *win,
- unsigned const char mask[16][2],
- unsigned char bitmap[16][2],
- int hotx,
- int hoty)
+static void window_set_custom_cursor(
+ wmWindow *win, const uchar mask[16][2], uchar bitmap[16][2], int hotx, int hoty)
{
GHOST_SetCustomCursorShape(
win->ghostwin, (GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask, 16, 16, hotx, hoty, true);
@@ -380,8 +377,8 @@ void WM_cursor_time(wmWindow *win, int nr)
{0, 60, 66, 66, 60, 66, 66, 60},
{0, 56, 68, 68, 120, 64, 68, 56},
};
- unsigned char mask[16][2];
- unsigned char bitmap[16][2] = {{0}};
+ uchar mask[16][2];
+ uchar bitmap[16][2] = {{0}};
int i, idx;
if (win->lastcursor == 0) {
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 0835f128f51..ef31bcdb75e 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -77,7 +77,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
-#include "BKE_library_override.h"
+#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -1366,7 +1366,7 @@ static bool wm_file_write(bContext *C, const char *filepath, int fileflags, Repo
BKE_callback_exec_null(bmain, BKE_CB_EVT_SAVE_PRE);
/* Enforce full override check/generation on file save. */
- BKE_main_override_library_operations_create(bmain, true);
+ BKE_lib_override_library_main_operations_create(bmain, true);
/* blend file thumbnail */
/* Save before exit_editmode, otherwise derivedmeshes for shared data corrupt T27765. */
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index f0b186761ce..c6d4c13c411 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -51,8 +51,8 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_report.h"
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 32ef4ca8f95..b775b16c6df 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -58,7 +58,7 @@
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_icons.h"
-#include "BKE_library_remap.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_mball_tessellate.h"
#include "BKE_node.h"
@@ -249,13 +249,13 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_undosys_type_init();
- BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
+ BKE_library_callback_free_window_manager_set(wm_close_and_free); /* lib_id.c */
BKE_library_callback_free_notifier_reference_set(
- WM_main_remove_notifier_reference); /* library.c */
+ WM_main_remove_notifier_reference); /* lib_id.c */
BKE_region_callback_free_gizmomap_set(wm_gizmomap_remove); /* screen.c */
BKE_region_callback_refresh_tag_gizmomap_set(WM_gizmomap_tag_refresh);
BKE_library_callback_remap_editor_id_reference_set(
- WM_main_remap_editor_id_reference); /* library.c */
+ WM_main_remap_editor_id_reference); /* lib_id.c */
BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */
DEG_editors_set_update_cb(ED_render_id_flush_update, ED_render_scene_update);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 051d9959010..728bc32e144 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -65,8 +65,8 @@
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_report.h"
diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
index 8e49e47c492..616cb7613ba 100644
--- a/source/blender/windowmanager/intern/wm_toolsystem.c
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -40,7 +40,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
-#include "BKE_library.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_paint.h"
#include "BKE_workspace.h"
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 690c332c20e..c485caf2779 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -1058,7 +1058,7 @@ setup_liblinks(blender)
if(WITH_USD)
add_definitions(-DWITH_USD)
install(DIRECTORY
- ${LIBDIR}/usd/lib/usd
+ ${USD_LIBRARY_DIR}/usd
DESTINATION "${TARGETDIR_VER}/datafiles"
)
endif()
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index c7df4888c0d..f265112570f 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -50,8 +50,8 @@
# include "BKE_global.h"
# include "BKE_image.h"
-# include "BKE_library.h"
-# include "BKE_library_override.h"
+# include "BKE_lib_id.h"
+# include "BKE_lib_override.h"
# include "BKE_main.h"
# include "BKE_report.h"
# include "BKE_scene.h"
@@ -1115,7 +1115,7 @@ static int arg_handle_disable_override_library(int UNUSED(argc),
const char **UNUSED(argv),
void *UNUSED(data))
{
- BKE_override_library_enable(false);
+ BKE_lib_override_library_enable(false);
return 0;
}
diff --git a/tests/gtests/blenlib/BLI_array_ref_test.cc b/tests/gtests/blenlib/BLI_array_ref_test.cc
index 4507d9e6e84..538fadc1cf9 100644
--- a/tests/gtests/blenlib/BLI_array_ref_test.cc
+++ b/tests/gtests/blenlib/BLI_array_ref_test.cc
@@ -2,7 +2,8 @@
#include "BLI_array_ref.h"
#include "BLI_vector.h"
-using BLI::IndexRange;
+using namespace BLI;
+
using IntVector = BLI::Vector<int>;
using IntArrayRef = BLI::ArrayRef<int>;
using MutableIntArrayRef = BLI::MutableArrayRef<int>;
@@ -17,6 +18,15 @@ TEST(array_ref, FromSmallVector)
EXPECT_EQ(a_ref[2], 3);
}
+TEST(array_ref, AddConstToPointer)
+{
+ int a = 0;
+ std::vector<int *> vec = {&a};
+ ArrayRef<int *> ref = vec;
+ ArrayRef<const int *> const_ref = ref;
+ EXPECT_EQ(const_ref.size(), 1);
+}
+
TEST(array_ref, IsReferencing)
{
int array[] = {3, 5, 8};
@@ -264,3 +274,47 @@ TEST(array_ref, ContainsPtr)
EXPECT_FALSE(a_ref.contains_ptr(&a[0] - 1));
EXPECT_FALSE(a_ref.contains_ptr(&other));
}
+
+TEST(array_ref, FirstIndex)
+{
+ std::array<int, 5> a = {4, 5, 4, 2, 5};
+ IntArrayRef a_ref(a);
+
+ EXPECT_EQ(a_ref.first_index(4), 0);
+ EXPECT_EQ(a_ref.first_index(5), 1);
+ EXPECT_EQ(a_ref.first_index(2), 3);
+}
+
+TEST(array_ref, CastSameSize)
+{
+ int value = 0;
+ std::array<int *, 4> a = {&value, nullptr, nullptr, nullptr};
+ ArrayRef<int *> a_ref = a;
+ ArrayRef<float *> new_a_ref = a_ref.cast<float *>();
+
+ EXPECT_EQ(a_ref.size(), 4);
+ EXPECT_EQ(new_a_ref.size(), 4);
+
+ EXPECT_EQ(a_ref[0], &value);
+ EXPECT_EQ(new_a_ref[0], (float *)&value);
+}
+
+TEST(array_ref, CastSmallerSize)
+{
+ std::array<uint32_t, 4> a = {3, 4, 5, 6};
+ ArrayRef<uint32_t> a_ref = a;
+ ArrayRef<uint16_t> new_a_ref = a_ref.cast<uint16_t>();
+
+ EXPECT_EQ(a_ref.size(), 4);
+ EXPECT_EQ(new_a_ref.size(), 8);
+}
+
+TEST(array_ref, CastLargerSize)
+{
+ std::array<uint16_t, 4> a = {4, 5, 6, 7};
+ ArrayRef<uint16_t> a_ref = a;
+ ArrayRef<uint32_t> new_a_ref = a_ref.cast<uint32_t>();
+
+ EXPECT_EQ(a_ref.size(), 4);
+ EXPECT_EQ(new_a_ref.size(), 2);
+}
diff --git a/tests/gtests/blenlib/BLI_index_range_test.cc b/tests/gtests/blenlib/BLI_index_range_test.cc
index 1944279999d..c5c1f9a875b 100644
--- a/tests/gtests/blenlib/BLI_index_range_test.cc
+++ b/tests/gtests/blenlib/BLI_index_range_test.cc
@@ -119,6 +119,15 @@ TEST(index_range, Slice)
EXPECT_EQ(slice.last(), 12);
}
+TEST(index_range, SliceRange)
+{
+ IndexRange range = IndexRange(5, 15);
+ IndexRange slice = range.slice(IndexRange(3, 5));
+ EXPECT_EQ(slice.size(), 5);
+ EXPECT_EQ(slice.first(), 8);
+ EXPECT_EQ(slice.last(), 12);
+}
+
TEST(index_range, AsArrayRef)
{
IndexRange range = IndexRange(4, 6);
diff --git a/tests/gtests/blenlib/BLI_optional_test.cc b/tests/gtests/blenlib/BLI_optional_test.cc
new file mode 100644
index 00000000000..2e672967680
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_optional_test.cc
@@ -0,0 +1,74 @@
+#include "testing/testing.h"
+#include "BLI_optional.h"
+#include <string>
+
+using namespace BLI;
+
+TEST(optional, DefaultConstructor)
+{
+ Optional<int> a;
+ EXPECT_FALSE(a.has_value());
+}
+
+TEST(optional, ValueConstructor)
+{
+ Optional<int> a(5);
+ EXPECT_TRUE(a.has_value());
+ EXPECT_EQ(a.value(), 5);
+}
+
+TEST(optional, CopyConstructor)
+{
+ Optional<std::string> a("Hello");
+ Optional<std::string> b = a;
+ EXPECT_TRUE(a.has_value());
+ EXPECT_TRUE(b.has_value());
+ b.value()[0] = 'T';
+ EXPECT_EQ(a.value(), "Hello");
+ EXPECT_EQ(b.value(), "Tello");
+}
+
+TEST(optional, Reset)
+{
+ Optional<int> a(4);
+ EXPECT_TRUE(a.has_value());
+ a.reset();
+ EXPECT_FALSE(a.has_value());
+}
+
+TEST(optional, FromNullPointer)
+{
+ Optional<int> a = Optional<int>::FromPointer(nullptr);
+ EXPECT_FALSE(a.has_value());
+}
+
+TEST(optional, FromNonNullPointer)
+{
+ int value = 42;
+ Optional<int> a = Optional<int>::FromPointer(&value);
+ EXPECT_TRUE(a.has_value());
+ EXPECT_EQ(a.value(), 42);
+}
+
+TEST(optional, Extract)
+{
+ Optional<int> a(32);
+ EXPECT_TRUE(a.has_value());
+ EXPECT_EQ(a.extract(), 32);
+ EXPECT_FALSE(a.has_value());
+}
+
+TEST(optional, ArrowOperator)
+{
+ Optional<std::string> value = std::string("Hello");
+ EXPECT_TRUE(value.has_value());
+ EXPECT_EQ(value->size(), 5);
+}
+
+TEST(optional, StarOperator)
+{
+ Optional<std::string> value = std::string("Hello");
+ EXPECT_TRUE(value.has_value());
+ std::string &s = *value;
+ EXPECT_EQ(s.size(), 5);
+}
diff --git a/tests/gtests/blenlib/BLI_stack_cxx_test.cc b/tests/gtests/blenlib/BLI_stack_cxx_test.cc
index 436f1f307b9..272bba05cb8 100644
--- a/tests/gtests/blenlib/BLI_stack_cxx_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_cxx_test.cc
@@ -8,7 +8,7 @@ TEST(stack, DefaultConstructor)
{
IntStack stack;
EXPECT_EQ(stack.size(), 0);
- EXPECT_TRUE(stack.empty());
+ EXPECT_TRUE(stack.is_empty());
}
TEST(stack, ArrayRefConstructor)
@@ -19,7 +19,7 @@ TEST(stack, ArrayRefConstructor)
EXPECT_EQ(stack.pop(), 2);
EXPECT_EQ(stack.pop(), 7);
EXPECT_EQ(stack.pop(), 4);
- EXPECT_TRUE(stack.empty());
+ EXPECT_TRUE(stack.is_empty());
}
TEST(stack, Push)
@@ -32,6 +32,17 @@ TEST(stack, Push)
EXPECT_EQ(stack.size(), 2);
}
+TEST(stack, PushMultiple)
+{
+ IntStack stack;
+ EXPECT_EQ(stack.size(), 0);
+ stack.push_multiple({1, 2, 3});
+ EXPECT_EQ(stack.size(), 3);
+ EXPECT_EQ(stack.pop(), 3);
+ EXPECT_EQ(stack.pop(), 2);
+ EXPECT_EQ(stack.pop(), 1);
+}
+
TEST(stack, Pop)
{
IntStack stack;
diff --git a/tests/gtests/blenlib/BLI_string_map_test.cc b/tests/gtests/blenlib/BLI_string_map_test.cc
index cc02a54e0c8..dfe96d63297 100644
--- a/tests/gtests/blenlib/BLI_string_map_test.cc
+++ b/tests/gtests/blenlib/BLI_string_map_test.cc
@@ -43,6 +43,21 @@ TEST(string_map, MoveConstructor)
EXPECT_EQ(map2.lookup("B")[5], 6);
}
+TEST(string_map, Add)
+{
+ StringMap<int> map;
+ EXPECT_EQ(map.size(), 0);
+
+ map.add("test", 1);
+ EXPECT_EQ(map.lookup("test"), 1);
+
+ map.add("test", 2);
+ EXPECT_EQ(map.lookup("test"), 1);
+
+ map.add("test2", 2);
+ EXPECT_EQ(map.lookup("test2"), 2);
+}
+
TEST(string_map, AddNew)
{
StringMap<int> map;
@@ -128,6 +143,15 @@ TEST(string_map, LookupDefault)
EXPECT_EQ(map.lookup_default("test", 42), 5);
}
+TEST(string_map, TryLookup)
+{
+ StringMap<int> map;
+ map.add_new("test", 4);
+ EXPECT_TRUE(map.try_lookup("test").has_value());
+ EXPECT_FALSE(map.try_lookup("value").has_value());
+ EXPECT_EQ(map.try_lookup("test").value(), 4);
+}
+
TEST(string_map, FindKeyForValue)
{
StringMap<int> map;
@@ -179,7 +203,7 @@ TEST(string_map, ForeachKeyValuePair)
Vector<std::string> keys;
Vector<int> values;
- map.foreach_key_value_pair([&keys, &values](StringRefNull key, int value) {
+ map.foreach_item([&keys, &values](StringRefNull key, int value) {
keys.append(key);
values.append(value);
});
diff --git a/tests/gtests/blenlib/BLI_string_ref_test.cc b/tests/gtests/blenlib/BLI_string_ref_test.cc
index 5605e10ac86..38a970455c0 100644
--- a/tests/gtests/blenlib/BLI_string_ref_test.cc
+++ b/tests/gtests/blenlib/BLI_string_ref_test.cc
@@ -228,3 +228,12 @@ TEST(string_ref, DropPrefix)
EXPECT_EQ(ref2.size(), 1);
EXPECT_EQ(ref2, "t");
}
+
+TEST(string_ref, Substr)
+{
+ StringRef ref("hello world");
+ EXPECT_EQ(ref.substr(0, 5), "hello");
+ EXPECT_EQ(ref.substr(4, 0), "");
+ EXPECT_EQ(ref.substr(3, 4), "lo w");
+ EXPECT_EQ(ref.substr(6, 5), "world");
+}
diff --git a/tests/gtests/blenlib/BLI_vector_test.cc b/tests/gtests/blenlib/BLI_vector_test.cc
index f258e50a60c..6cf67fb2488 100644
--- a/tests/gtests/blenlib/BLI_vector_test.cc
+++ b/tests/gtests/blenlib/BLI_vector_test.cc
@@ -216,6 +216,38 @@ TEST(vector, Append)
EXPECT_EQ(vec[2], 7);
}
+TEST(vector, AppendAndGetIndex)
+{
+ IntVector vec;
+ EXPECT_EQ(vec.append_and_get_index(10), 0);
+ EXPECT_EQ(vec.append_and_get_index(10), 1);
+ EXPECT_EQ(vec.append_and_get_index(10), 2);
+ vec.append(10);
+ EXPECT_EQ(vec.append_and_get_index(10), 4);
+}
+
+TEST(vector, AppendNonDuplicates)
+{
+ IntVector vec;
+ vec.append_non_duplicates(4);
+ EXPECT_EQ(vec.size(), 1);
+ vec.append_non_duplicates(5);
+ EXPECT_EQ(vec.size(), 2);
+ vec.append_non_duplicates(4);
+ EXPECT_EQ(vec.size(), 2);
+}
+
+TEST(vector, ExtendNonDuplicates)
+{
+ IntVector vec;
+ vec.extend_non_duplicates({1, 2});
+ EXPECT_EQ(vec.size(), 2);
+ vec.extend_non_duplicates({3, 4});
+ EXPECT_EQ(vec.size(), 4);
+ vec.extend_non_duplicates({0, 1, 2, 3});
+ EXPECT_EQ(vec.size(), 5);
+}
+
TEST(vector, Fill)
{
IntVector vec(5);
@@ -339,6 +371,22 @@ TEST(vector, RemoveReorder)
EXPECT_TRUE(vec.empty());
}
+TEST(vector, RemoveFirstOccurrenceAndReorder)
+{
+ IntVector vec = {4, 5, 6, 7};
+ vec.remove_first_occurrence_and_reorder(5);
+ EXPECT_EQ(vec[0], 4);
+ EXPECT_EQ(vec[1], 7);
+ EXPECT_EQ(vec[2], 6);
+ vec.remove_first_occurrence_and_reorder(6);
+ EXPECT_EQ(vec[0], 4);
+ EXPECT_EQ(vec[1], 7);
+ vec.remove_first_occurrence_and_reorder(4);
+ EXPECT_EQ(vec[0], 7);
+ vec.remove_first_occurrence_and_reorder(7);
+ EXPECT_EQ(vec.size(), 0);
+}
+
TEST(vector, AllEqual_False)
{
IntVector a = {1, 2, 3};
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index c6b23615a5a..1a104fcb746 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -59,6 +59,7 @@ BLENDER_TEST(BLI_math_base "bf_blenlib")
BLENDER_TEST(BLI_math_color "bf_blenlib")
BLENDER_TEST(BLI_math_geom "bf_blenlib")
BLENDER_TEST(BLI_memiter "bf_blenlib")
+BLENDER_TEST(BLI_optional "bf_blenlib")
BLENDER_TEST(BLI_path_util "${BLI_path_util_extra_libs}")
BLENDER_TEST(BLI_polyfill_2d "bf_blenlib")
BLENDER_TEST(BLI_set "bf_blenlib")
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index b5af3e14237..f287ba5ed02 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -79,6 +79,11 @@ add_blender_test(
--python ${CMAKE_CURRENT_LIST_DIR}/bl_load_py_modules.py
)
+add_blender_test(
+ script_bundled_modules
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_bundled_modules.py
+)
+
# test running operators doesn't segfault under various conditions
if(USE_EXPERIMENTAL_TESTS)
add_blender_test(
diff --git a/tests/python/bl_bundled_modules.py b/tests/python/bl_bundled_modules.py
new file mode 100644
index 00000000000..6f757184e7b
--- /dev/null
+++ b/tests/python/bl_bundled_modules.py
@@ -0,0 +1,30 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# Test that modules we ship with our Python installation are available
+
+import bz2
+import cffi
+import lzma
+import numpy
+import sqlite3
+import ssl
+import zlib
+