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:
authorJulian Eisel <julian@blender.org>2022-11-02 13:58:03 +0300
committerJulian Eisel <julian@blender.org>2022-11-02 13:58:03 +0300
commit7158e0eb4cfa32f49527f660f73031207bc8f8be (patch)
treea7e692d87ad8bd0a4dcb074844b4d3bcb500f27b
parent75794f95c0d41fbc1d279058ec9293e69abdd5b2 (diff)
parent460c9d3d92e9f74254d58c6bb07d7e4fcb53e8b7 (diff)
Merge branch 'master' into blender-projects-basicsblender-projects-basics
-rw-r--r--CMakeLists.txt46
-rw-r--r--build_files/build_environment/CMakeLists.txt3
-rw-r--r--build_files/build_environment/cmake/aom.cmake6
-rw-r--r--build_files/build_environment/cmake/cve_check.cmake4
-rw-r--r--build_files/build_environment/cmake/cve_check.csv.in29
-rw-r--r--build_files/build_environment/cmake/download.cmake3
-rw-r--r--build_files/build_environment/cmake/ffmpeg.cmake6
-rw-r--r--build_files/build_environment/cmake/freetype.cmake4
-rw-r--r--build_files/build_environment/cmake/gmp.cmake1
-rw-r--r--build_files/build_environment/cmake/llvm.cmake1
-rw-r--r--build_files/build_environment/cmake/opencollada.cmake51
-rw-r--r--build_files/build_environment/cmake/options.cmake5
-rw-r--r--build_files/build_environment/cmake/osl.cmake3
-rw-r--r--build_files/build_environment/cmake/png.cmake8
-rw-r--r--build_files/build_environment/cmake/python.cmake17
-rw-r--r--build_files/build_environment/cmake/sndfile.cmake7
-rw-r--r--build_files/build_environment/cmake/sqlite.cmake1
-rw-r--r--build_files/build_environment/cmake/ssl.cmake1
-rw-r--r--build_files/build_environment/cmake/tiff.cmake1
-rw-r--r--build_files/build_environment/cmake/versions.cmake151
-rw-r--r--build_files/build_environment/cmake/wayland.cmake8
-rw-r--r--build_files/build_environment/cmake/xml2.cmake64
-rw-r--r--build_files/build_environment/dependencies.dot120
-rwxr-xr-xbuild_files/build_environment/install_deps.sh20
-rw-r--r--build_files/build_environment/patches/aom.diff18
-rw-r--r--build_files/build_environment/patches/ffmpeg.diff40
-rw-r--r--build_files/build_environment/patches/gmp.diff15
-rw-r--r--build_files/build_environment/patches/opencollada.diff25
-rw-r--r--build_files/build_environment/patches/osl.diff135
-rw-r--r--build_files/build_environment/patches/python_windows.diff24
-rw-r--r--build_files/build_environment/patches/sndfile.diff42
-rw-r--r--build_files/build_environment/patches/sqlite.diff14
-rw-r--r--build_files/build_environment/patches/ssl.diff10
-rw-r--r--build_files/cmake/Modules/FindOSL.cmake15
-rw-r--r--build_files/cmake/Modules/FindOpenSubdiv.cmake15
-rw-r--r--build_files/cmake/Modules/FindSYCL.cmake41
-rw-r--r--build_files/cmake/config/blender_developer.cmake6
-rw-r--r--build_files/cmake/config/blender_full.cmake4
-rw-r--r--build_files/cmake/config/blender_release.cmake4
-rw-r--r--build_files/cmake/macros.cmake18
-rw-r--r--build_files/cmake/platform/platform_apple.cmake100
-rw-r--r--build_files/cmake/platform/platform_unix.cmake211
-rw-r--r--build_files/cmake/platform/platform_win32.cmake88
-rw-r--r--build_files/config/pipeline_config.yaml2
-rwxr-xr-xbuild_files/utils/make_bpy_wheel.py11
-rwxr-xr-xbuild_files/utils/make_update.py86
-rwxr-xr-xbuild_files/utils/make_utils.py2
-rw-r--r--build_files/windows/parse_arguments.cmd2
-rw-r--r--build_files/windows/reset_variables.cmd1
-rw-r--r--build_files/windows/svn_update.cmd24
-rw-r--r--extern/hipew/src/hipew.c2
-rw-r--r--intern/cycles/CMakeLists.txt6
-rw-r--r--intern/cycles/app/CMakeLists.txt5
-rw-r--r--intern/cycles/blender/addon/engine.py15
-rw-r--r--intern/cycles/blender/addon/properties.py18
-rw-r--r--intern/cycles/blender/addon/ui.py14
-rw-r--r--intern/cycles/blender/session.cpp6
-rw-r--r--intern/cycles/blender/sync.cpp206
-rw-r--r--intern/cycles/cmake/external_libs.cmake56
-rw-r--r--intern/cycles/device/CMakeLists.txt22
-rw-r--r--intern/cycles/device/cuda/queue.cpp2
-rw-r--r--intern/cycles/device/cuda/queue.h2
-rw-r--r--intern/cycles/device/hip/queue.cpp2
-rw-r--r--intern/cycles/device/hip/queue.h2
-rw-r--r--intern/cycles/device/metal/device_impl.mm10
-rw-r--r--intern/cycles/device/metal/kernel.mm13
-rw-r--r--intern/cycles/device/metal/queue.h2
-rw-r--r--intern/cycles/device/metal/queue.mm51
-rw-r--r--intern/cycles/device/metal/util.mm6
-rw-r--r--intern/cycles/device/oneapi/device.cpp4
-rw-r--r--intern/cycles/device/oneapi/device_impl.cpp69
-rw-r--r--intern/cycles/device/oneapi/device_impl.h2
-rw-r--r--intern/cycles/device/oneapi/queue.cpp2
-rw-r--r--intern/cycles/device/oneapi/queue.h2
-rw-r--r--intern/cycles/device/queue.h2
-rw-r--r--intern/cycles/integrator/path_trace_work_gpu.cpp31
-rw-r--r--intern/cycles/kernel/CMakeLists.txt34
-rw-r--r--intern/cycles/kernel/bvh/shadow_all.h2
-rw-r--r--intern/cycles/kernel/bvh/util.h8
-rw-r--r--intern/cycles/kernel/camera/projection.h26
-rw-r--r--intern/cycles/kernel/device/cpu/bvh.h2
-rw-r--r--intern/cycles/kernel/device/gpu/parallel_active_index.h33
-rw-r--r--intern/cycles/kernel/device/metal/context_begin.h37
-rw-r--r--intern/cycles/kernel/device/metal/kernel.metal2
-rw-r--r--intern/cycles/kernel/device/oneapi/compat.h45
-rw-r--r--intern/cycles/kernel/device/oneapi/globals.h9
-rw-r--r--intern/cycles/kernel/device/oneapi/kernel.cpp17
-rw-r--r--intern/cycles/kernel/device/optix/bvh.h2
-rw-r--r--intern/cycles/kernel/types.h1
-rw-r--r--intern/cycles/scene/camera.cpp1
-rw-r--r--intern/cycles/util/transform_inverse.h2
-rw-r--r--intern/cycles/util/types_float3.h5
-rw-r--r--intern/ffmpeg/tests/ffmpeg_codecs.cc7
-rw-r--r--intern/ghost/CMakeLists.txt14
-rw-r--r--intern/ghost/GHOST_C-api.h2
-rw-r--r--intern/ghost/GHOST_ISystem.h6
-rw-r--r--intern/ghost/GHOST_Types.h12
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp4
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h3
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm4
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp2
-rw-r--r--intern/ghost/intern/GHOST_Debug.h34
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp8
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp385
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h53
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerUnix.cpp16
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerUnix.h2
-rw-r--r--intern/ghost/intern/GHOST_System.cpp2
-rw-r--r--intern/ghost/intern/GHOST_System.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm5
-rw-r--r--intern/ghost/intern/GHOST_SystemHeadless.h3
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp3
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h1
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp3212
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h19
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp3
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h2
-rw-r--r--intern/ghost/intern/GHOST_Window.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm4
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp84
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h4
-rw-r--r--intern/ghost/test/gears/GHOST_Test.cpp21
-rw-r--r--intern/guardedalloc/intern/leak_detector.cc2
-rw-r--r--intern/opensubdiv/CMakeLists.txt6
-rw-r--r--intern/wayland_dynload/extern/wayland_dynload_client.h1
-rw-r--r--make.bat12
-rw-r--r--release/scripts/modules/gpu_extras/batch.py4
-rw-r--r--release/scripts/modules/sys_info.py1
-rw-r--r--release/scripts/startup/bl_ui/node_add_menu.py8
-rw-r--r--release/scripts/startup/bl_ui/node_add_menu_geometry.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curves.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py16
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py19
-rw-r--r--source/blender/blenkernel/BKE_armature.h4
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog.hh11
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog_path.hh2
-rw-r--r--source/blender/blenkernel/BKE_asset_library.hh11
-rw-r--r--source/blender/blenkernel/BKE_attribute.hh2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_bpath.h33
-rw-r--r--source/blender/blenkernel/BKE_brush.h21
-rw-r--r--source/blender/blenkernel/BKE_context.h46
-rw-r--r--source/blender/blenkernel/BKE_duplilist.h12
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h6
-rw-r--r--source/blender/blenkernel/BKE_instances.hh2
-rw-r--r--source/blender/blenkernel/BKE_key.h4
-rw-r--r--source/blender/blenkernel/BKE_nla.h8
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h1
-rw-r--r--source/blender/blenkernel/BKE_screen.h1
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h2
-rw-r--r--source/blender/blenkernel/BKE_writeffmpeg.h2
-rw-r--r--source/blender/blenkernel/intern/action.c2
-rw-r--r--source/blender/blenkernel/intern/appdir.c22
-rw-r--r--source/blender/blenkernel/intern/armature.c10
-rw-r--r--source/blender/blenkernel/intern/armature_deform.c4
-rw-r--r--source/blender/blenkernel/intern/armature_update.c4
-rw-r--r--source/blender/blenkernel/intern/asset_catalog.cc36
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_path.cc2
-rw-r--r--source/blender/blenkernel/intern/asset_library.cc30
-rw-r--r--source/blender/blenkernel/intern/asset_library_service.cc38
-rw-r--r--source/blender/blenkernel/intern/asset_library_service.hh3
-rw-r--r--source/blender/blenkernel/intern/asset_library_service_test.cc2
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc17
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c6
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/brush.cc22
-rw-r--r--source/blender/blenkernel/intern/camera.c20
-rw-r--r--source/blender/blenkernel/intern/cloth.c10
-rw-r--r--source/blender/blenkernel/intern/constraint.c89
-rw-r--r--source/blender/blenkernel/intern/context.c60
-rw-r--r--source/blender/blenkernel/intern/crazyspace.cc35
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c4
-rw-r--r--source/blender/blenkernel/intern/curve_to_mesh_convert.cc10
-rw-r--r--source/blender/blenkernel/intern/curves.cc9
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc22
-rw-r--r--source/blender/blenkernel/intern/customdata.cc8
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c22
-rw-r--r--source/blender/blenkernel/intern/effect.c20
-rw-r--r--source/blender/blenkernel/intern/fcurve_driver.c14
-rw-r--r--source/blender/blenkernel/intern/fluid.c28
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc5
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc4
-rw-r--r--source/blender/blenkernel/intern/gpencil.c18
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc17
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c2
-rw-r--r--source/blender/blenkernel/intern/icons.cc2
-rw-r--r--source/blender/blenkernel/intern/image.cc23
-rw-r--r--source/blender/blenkernel/intern/image_format.cc7
-rw-r--r--source/blender/blenkernel/intern/image_save.cc2
-rw-r--r--source/blender/blenkernel/intern/instances.cc27
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/lattice.c6
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c6
-rw-r--r--source/blender/blenkernel/intern/layer.c2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c2
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c72
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c4
-rw-r--r--source/blender/blenkernel/intern/material.c65
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.cc11
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc10
-rw-r--r--source/blender/blenkernel/intern/mesh_mirror.c10
-rw-r--r--source/blender/blenkernel/intern/nla.c5
-rw-r--r--source/blender/blenkernel/intern/node.cc28
-rw-r--r--source/blender/blenkernel/intern/object.cc96
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc47
-rw-r--r--source/blender/blenkernel/intern/object_update.cc16
-rw-r--r--source/blender/blenkernel/intern/paint.cc13
-rw-r--r--source/blender/blenkernel/intern/particle.c22
-rw-r--r--source/blender/blenkernel/intern/particle_child.c4
-rw-r--r--source/blender/blenkernel/intern/particle_system.c36
-rw-r--r--source/blender/blenkernel/intern/pointcache.c10
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c24
-rw-r--r--source/blender/blenkernel/intern/scene.cc8
-rw-r--r--source/blender/blenkernel/intern/screen.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c22
-rw-r--r--source/blender/blenkernel/intern/sound.c8
-rw-r--r--source/blender/blenkernel/intern/unit.c2
-rw-r--r--source/blender/blenkernel/intern/vfont.c4
-rw-r--r--source/blender/blenkernel/intern/volume.cc4
-rw-r--r--source/blender/blenkernel/intern/writeavi.c3
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c238
-rw-r--r--source/blender/blenlib/BLI_array_utils.hh5
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h2
-rw-r--r--source/blender/blenlib/BLI_path_util.h15
-rw-r--r--source/blender/blenlib/BLI_string.h22
-rw-r--r--source/blender/blenlib/BLI_uvproject.h2
-rw-r--r--source/blender/blenlib/intern/array_utils.cc5
-rw-r--r--source/blender/blenlib/intern/fileops.c2
-rw-r--r--source/blender/blenlib/intern/kdtree_impl.h6
-rw-r--r--source/blender/blenlib/intern/list_sort_impl.h49
-rw-r--r--source/blender/blenlib/intern/path_util.c149
-rw-r--r--source/blender/blenlib/intern/string.c30
-rw-r--r--source/blender/blenlib/intern/uvproject.c2
-rw-r--r--source/blender/blenlib/tests/BLI_path_util_test.cc444
-rw-r--r--source/blender/blenlib/tests/BLI_string_test.cc97
-rw-r--r--source/blender/blenloader/intern/readfile.cc2
-rw-r--r--source/blender/blenloader/intern/versioning_300.cc23
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c2
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.h4
-rw-r--r--source/blender/compositor/realtime_compositor/CMakeLists.txt2
-rw-r--r--source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh45
-rw-r--r--source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc104
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc5
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc4
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc2
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c40
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_light.cc2
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_pipeline.cc4
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sync.cc6
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_velocity.cc6
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl36
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c10
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_data.c6
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c56
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c30
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_shared.h3
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl595
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl27
-rw-r--r--source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh8
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.cc55
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_text.cc6
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.cc84
-rw-r--r--source/blender/draw/engines/overlay/overlay_facing.cc2
-rw-r--r--source/blender/draw/engines/overlay/overlay_fade.cc2
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.cc6
-rw-r--r--source/blender/draw/engines/overlay/overlay_image.cc2
-rw-r--r--source/blender/draw/engines/overlay/overlay_lattice.cc2
-rw-r--r--source/blender/draw/engines/overlay/overlay_metaball.cc8
-rw-r--r--source/blender/draw/engines/overlay/overlay_mode_transfer.cc2
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.cc54
-rw-r--r--source/blender/draw/engines/overlay/overlay_sculpt.cc2
-rw-r--r--source/blender/draw/engines/overlay/overlay_sculpt_curves.cc4
-rw-r--r--source/blender/draw/engines/overlay/overlay_viewer_attribute.cc22
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.cc20
-rw-r--r--source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh2
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl15
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl2
-rw-r--r--source/blender/draw/engines/select/select_engine.c10
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c11
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h5
-rw-r--r--source/blender/draw/engines/workbench/workbench_shadow.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c4
-rw-r--r--source/blender/draw/intern/draw_cache.c29
-rw-r--r--source/blender/draw/intern/draw_cache.h18
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h12
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curves.cc58
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.cc (renamed from source/blender/draw/intern/draw_cache_impl_gpencil.c)261
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.cc8
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c43
-rw-r--r--source/blender/draw/intern/draw_cache_impl_pointcloud.cc403
-rw-r--r--source/blender/draw/intern/draw_command.cc10
-rw-r--r--source/blender/draw/intern/draw_command.hh34
-rw-r--r--source/blender/draw/intern/draw_common.h8
-rw-r--r--source/blender/draw/intern/draw_curves.cc57
-rw-r--r--source/blender/draw/intern/draw_curves_private.h7
-rw-r--r--source/blender/draw/intern/draw_hair.cc23
-rw-r--r--source/blender/draw/intern/draw_hair_private.h5
-rw-r--r--source/blender/draw/intern/draw_manager.c31
-rw-r--r--source/blender/draw/intern/draw_manager_data.cc26
-rw-r--r--source/blender/draw/intern/draw_manager_text.cc30
-rw-r--r--source/blender/draw/intern/draw_pass.hh14
-rw-r--r--source/blender/draw/intern/draw_pbvh.cc17
-rw-r--r--source/blender/draw/intern/draw_pointcloud.cc103
-rw-r--r--source/blender/draw/intern/draw_pointcloud_private.hh19
-rw-r--r--source/blender/draw/intern/draw_resource.hh2
-rw-r--r--source/blender/draw/intern/draw_volume.cc2
-rw-r--r--source/blender/draw/intern/shaders/common_gpencil_lib.glsl88
-rw-r--r--source/blender/draw/intern/shaders/common_pointcloud_lib.glsl78
-rw-r--r--source/blender/draw/intern/shaders/draw_view_info.hh21
-rw-r--r--source/blender/draw/tests/draw_pass_test.cc7
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c4
-rw-r--r--source/blender/editors/animation/keyframing.c4
-rw-r--r--source/blender/editors/armature/armature_add.c8
-rw-r--r--source/blender/editors/armature/armature_edit.c12
-rw-r--r--source/blender/editors/armature/armature_relations.c4
-rw-r--r--source/blender/editors/armature/armature_select.c8
-rw-r--r--source/blender/editors/armature/armature_skinning.c8
-rw-r--r--source/blender/editors/armature/armature_utils.c8
-rw-r--r--source/blender/editors/armature/meshlaplacian.c4
-rw-r--r--source/blender/editors/armature/pose_transform.c14
-rw-r--r--source/blender/editors/asset/ED_asset_list.h1
-rw-r--r--source/blender/editors/asset/intern/asset_list.cc14
-rw-r--r--source/blender/editors/curve/editcurve.c18
-rw-r--r--source/blender/editors/curve/editcurve_paint.c14
-rw-r--r--source/blender/editors/curve/editcurve_pen.c10
-rw-r--r--source/blender/editors/curve/editcurve_select.c4
-rw-r--r--source/blender/editors/curves/intern/curves_ops.cc4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_presets.c2
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_armature.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_bake_animation.cc4
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.cc2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c29
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c16
-rw-r--r--source/blender/editors/gpencil/gpencil_uv.c4
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/UI_interface.h11
-rw-r--r--source/blender/editors/include/UI_interface.hh1
-rw-r--r--source/blender/editors/include/UI_interface_icons.h12
-rw-r--r--source/blender/editors/interface/eyedroppers/eyedropper_depth.c2
-rw-r--r--source/blender/editors/interface/interface.cc20
-rw-r--r--source/blender/editors/interface/interface_context_path.cc14
-rw-r--r--source/blender/editors/interface/interface_handlers.c6
-rw-r--r--source/blender/editors/interface/interface_icons.c117
-rw-r--r--source/blender/editors/interface/interface_intern.h14
-rw-r--r--source/blender/editors/interface/interface_layout.c12
-rw-r--r--source/blender/editors/interface/interface_ops.cc3
-rw-r--r--source/blender/editors/interface/interface_panel.cc6
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.cc298
-rw-r--r--source/blender/editors/interface/interface_widgets.c15
-rw-r--r--source/blender/editors/interface/views/interface_view.cc2
-rw-r--r--source/blender/editors/mesh/editface.cc4
-rw-r--r--source/blender/editors/mesh/editmesh_add_gizmo.c2
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c2
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c12
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_screw.c8
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c2
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c18
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c2
-rw-r--r--source/blender/editors/mesh/editmesh_polybuild.c18
-rw-r--r--source/blender/editors/mesh/editmesh_preselect_elem.c4
-rw-r--r--source/blender/editors/mesh/editmesh_select.cc18
-rw-r--r--source/blender/editors/mesh/editmesh_select_similar.c22
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c6
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_data.cc4
-rw-r--r--source/blender/editors/mesh/meshtools.cc6
-rw-r--r--source/blender/editors/object/object_add.cc219
-rw-r--r--source/blender/editors/object/object_bake_api.c33
-rw-r--r--source/blender/editors/object/object_constraint.c6
-rw-r--r--source/blender/editors/object/object_hook.c18
-rw-r--r--source/blender/editors/object/object_relations.c22
-rw-r--r--source/blender/editors/object/object_remesh.cc10
-rw-r--r--source/blender/editors/object/object_transform.cc44
-rw-r--r--source/blender/editors/object/object_utils.c24
-rw-r--r--source/blender/editors/object/object_warp.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c14
-rw-r--r--source/blender/editors/physics/particle_object.c14
-rw-r--r--source/blender/editors/render/render_preview.cc2
-rw-r--r--source/blender/editors/screen/area.c5
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_brush.cc4
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_ops.cc19
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c20
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.cc19
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c95
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_expand.c7
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.cc31
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c6
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c4
-rw-r--r--source/blender/editors/space_file/file_draw.c65
-rw-r--r--source/blender/editors/space_file/file_ops.c28
-rw-r--r--source/blender/editors/space_file/filelist.cc12
-rw-r--r--source/blender/editors/space_file/filesel.c4
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_info/textview.c3
-rw-r--r--source/blender/editors/space_nla/nla_draw.c2
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_node/add_menu_assets.cc314
-rw-r--r--source/blender/editors/space_node/node_add.cc143
-rw-r--r--source/blender/editors/space_node/node_draw.cc3
-rw-r--r--source/blender/editors/space_node/node_intern.hh17
-rw-r--r--source/blender/editors/space_node/node_ops.cc1
-rw-r--r--source/blender/editors/space_node/node_relationships.cc3
-rw-r--r--source/blender/editors/space_node/space_node.cc3
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc152
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.cc10
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.cc2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_empty.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_forcefield.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_light.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc6
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.cc16
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_smoothview.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_walk.c16
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_select.cc14
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c47
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c6
-rw-r--r--source/blender/editors/transform/transform.c35
-rw-r--r--source/blender/editors/transform/transform.h12
-rw-r--r--source/blender/editors/transform/transform_constraints.c15
-rw-r--r--source/blender/editors/transform/transform_convert.c6
-rw-r--r--source/blender/editors/transform/transform_convert.h2
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c9
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c2
-rw-r--r--source/blender/editors/transform/transform_convert_lattice.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mball.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c4
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_edge.c4
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_skin.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_vert_cdata.c2
-rw-r--r--source/blender/editors/transform/transform_convert_nla.c6
-rw-r--r--source/blender/editors/transform/transform_convert_node.cc47
-rw-r--r--source/blender/editors/transform/transform_convert_object.c14
-rw-r--r--source/blender/editors/transform/transform_convert_object_texspace.c4
-rw-r--r--source/blender/editors/transform/transform_convert_particle.c2
-rw-r--r--source/blender/editors/transform/transform_convert_sculpt.c12
-rw-r--r--source/blender/editors/transform/transform_generics.c6
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c50
-rw-r--r--source/blender/editors/transform/transform_mode.c2
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c22
-rw-r--r--source/blender/editors/transform/transform_mode_edge_slide.c2
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c103
-rw-r--r--source/blender/editors/transform/transform_mode_vert_slide.c11
-rw-r--r--source/blender/editors/transform/transform_orientations.c16
-rw-r--r--source/blender/editors/transform/transform_snap.c140
-rw-r--r--source/blender/editors/transform/transform_snap.h3
-rw-r--r--source/blender/editors/transform/transform_snap_object.cc8
-rw-r--r--source/blender/editors/util/ed_viewer_path.cc3
-rw-r--r--source/blender/editors/uvedit/uvedit_islands.cc26
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c16
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c93
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.cpp1
-rw-r--r--source/blender/freestyle/intern/image/ImagePyramid.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp2
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Director.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeTransform.cpp1
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h2
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/Canvas.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/ContextFunctions.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/Operators.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/system/StringUtils.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/Functions0D.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/OccluderSource.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/SphericalGrid.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/SteerableViewMap.cpp4
-rw-r--r--source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapTesselator.h4
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.cpp2
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.cpp3
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp2
-rw-r--r--source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp2
-rw-r--r--source/blender/geometry/intern/fillet_curves.cc6
-rw-r--r--source/blender/geometry/intern/realize_instances.cc2
-rw-r--r--source/blender/geometry/intern/resample_curves.cc3
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc20
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c14
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c2
-rw-r--r--source/blender/gpu/CMakeLists.txt42
-rw-r--r--source/blender/gpu/GPU_context.h2
-rw-r--r--source/blender/gpu/GPU_framebuffer.h3
-rw-r--r--source/blender/gpu/GPU_platform.h1
-rw-r--r--source/blender/gpu/GPU_shader.h4
-rw-r--r--source/blender/gpu/intern/gpu_context.cc26
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.cc5
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer_private.hh10
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc11
-rw-r--r--source/blender/gpu/intern/gpu_immediate_private.hh8
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder.cc49
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder_stubs.cc9
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c5
-rw-r--r--source/blender/gpu/intern/gpu_texture_private.hh2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.cc8
-rw-r--r--source/blender/gpu/metal/mtl_batch.mm27
-rw-r--r--source/blender/gpu/metal/mtl_drawlist.mm14
-rw-r--r--source/blender/gpu/metal/mtl_shader_generator.hh2
-rw-r--r--source/blender/gpu/metal/mtl_texture.mm2
-rw-r--r--source/blender/gpu/metal/mtl_texture_util.mm2
-rw-r--r--source/blender/gpu/opengl/gl_batch.cc4
-rw-r--r--source/blender/gpu/opengl/gl_shader_interface.cc10
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_blur.glsl21
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl21
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_normalize.glsl10
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl22
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl26
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh12
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh81
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh16
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_icon_frag.glsl42
-rw-r--r--source/blender/gpu/shaders/gpu_shader_icon_vert.glsl37
-rw-r--r--source/blender/gpu/shaders/infos/gpu_interface_info.hh3
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh22
-rw-r--r--source/blender/gpu/vulkan/vk_backend.cc107
-rw-r--r--source/blender/gpu/vulkan/vk_backend.hh42
-rw-r--r--source/blender/gpu/vulkan/vk_batch.cc27
-rw-r--r--source/blender/gpu/vulkan/vk_batch.hh24
-rw-r--r--source/blender/gpu/vulkan/vk_context.cc48
-rw-r--r--source/blender/gpu/vulkan/vk_context.hh34
-rw-r--r--source/blender/gpu/vulkan/vk_drawlist.cc20
-rw-r--r--source/blender/gpu/vulkan/vk_drawlist.hh20
-rw-r--r--source/blender/gpu/vulkan/vk_framebuffer.cc62
-rw-r--r--source/blender/gpu/vulkan/vk_framebuffer.hh50
-rw-r--r--source/blender/gpu/vulkan/vk_index_buffer.cc33
-rw-r--r--source/blender/gpu/vulkan/vk_index_buffer.hh28
-rw-r--r--source/blender/gpu/vulkan/vk_query.cc28
-rw-r--r--source/blender/gpu/vulkan/vk_query.hh22
-rw-r--r--source/blender/gpu/vulkan/vk_shader.cc102
-rw-r--r--source/blender/gpu/vulkan/vk_shader.hh48
-rw-r--r--source/blender/gpu/vulkan/vk_storage_buffer.cc42
-rw-r--r--source/blender/gpu/vulkan/vk_storage_buffer.hh30
-rw-r--r--source/blender/gpu/vulkan/vk_texture.cc70
-rw-r--r--source/blender/gpu/vulkan/vk_texture.hh39
-rw-r--r--source/blender/gpu/vulkan/vk_uniform_buffer.cc24
-rw-r--r--source/blender/gpu/vulkan/vk_uniform_buffer.hh25
-rw-r--r--source/blender/gpu/vulkan/vk_vertex_buffer.cc58
-rw-r--r--source/blender/gpu/vulkan/vk_vertex_buffer.hh32
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c4
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp16
-rw-r--r--source/blender/imbuf/intern/anim_movie.c7
-rw-r--r--source/blender/imbuf/intern/indexer.c18
-rw-r--r--source/blender/imbuf/intern/util_gpu.c11
-rw-r--r--source/blender/imbuf/intern/webp.c2
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_hair.cc4
-rw-r--r--source/blender/io/alembic/intern/abc_axis_conversion.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.cc6
-rw-r--r--source/blender/io/alembic/intern/abc_reader_object.cc2
-rw-r--r--source/blender/io/collada/AnimationImporter.cpp6
-rw-r--r--source/blender/io/collada/ArmatureImporter.cpp4
-rw-r--r--source/blender/io/collada/ControllerExporter.cpp4
-rw-r--r--source/blender/io/collada/DocumentImporter.cpp4
-rw-r--r--source/blender/io/collada/SkinInfo.cpp6
-rw-r--r--source/blender/io/collada/collada_utils.cpp8
-rw-r--r--source/blender/io/common/intern/abstract_hierarchy_iterator.cc2
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_base.cc8
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc2
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_svg.cc2
-rw-r--r--source/blender/io/stl/CMakeLists.txt2
-rw-r--r--source/blender/io/usd/intern/usd_reader_mesh.cc21
-rw-r--r--source/blender/io/usd/intern/usd_writer_mesh.cc5
-rw-r--r--source/blender/io/usd/tests/usd_imaging_test.cc7
-rw-r--r--source/blender/io/wavefront_obj/CMakeLists.txt4
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc7
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc8
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h10
-rw-r--r--source/blender/makesdna/DNA_layer_types.h6
-rw-r--r--source/blender/makesdna/DNA_meta_types.h4
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h70
-rw-r--r--source/blender/makesdna/DNA_node_types.h10
-rw-r--r--source/blender/makesdna/DNA_object_defaults.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h4
-rw-r--r--source/blender/makesdna/DNA_particle_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h6
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h6
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesdna/intern/dna_rename_defs.h1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/rna_armature.c2
-rw-r--r--source/blender/makesrna/intern/rna_asset.c7
-rw-r--r--source/blender/makesrna/intern/rna_brush.c8
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c2
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c8
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c14
-rw-r--r--source/blender/makesrna/intern/rna_internal.h4
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c2
-rw-r--r--source/blender/makesrna/intern/rna_object.c7
-rw-r--r--source/blender/makesrna/intern/rna_particle.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c3
-rw-r--r--source/blender/makesrna/intern/rna_space.c10
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm.c22
-rw-r--r--source/blender/makesrna/intern/rna_xr.c2
-rw-r--r--source/blender/modifiers/intern/MOD_array.c6
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc34
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c16
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c4
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c2
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c4
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c6
-rw-r--r--source/blender/modifiers/intern/MOD_mesh_to_volume.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c4
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.cc8
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c4
-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.cc10
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.cc6
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_volume_displace.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_volume_to_mesh.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c6
-rw-r--r--source/blender/modifiers/intern/MOD_wave.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.cc6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normalize.cc47
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_tonemap.cc248
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_collection_info.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc40
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc46
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc25
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc77
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_object_info.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc6
-rw-r--r--source/blender/nodes/intern/geometry_nodes_lazy_function.cc9
-rw-r--r--source/blender/nodes/intern/node_exec.cc2
-rw-r--r--source/blender/nodes/intern/node_exec.h4
-rw-r--r--source/blender/nodes/shader/node_shader_tree.cc3
-rw-r--r--source/blender/nodes/texture/CMakeLists.txt2
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c3
-rw-r--r--source/blender/python/gpu/gpu_py_platform.c29
-rw-r--r--source/blender/python/intern/bpy_gizmo_wrap.h2
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.h5
-rw-r--r--source/blender/python/intern/bpy_rna.c4
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c4
-rw-r--r--source/blender/render/intern/bake.c2
-rw-r--r--source/blender/render/intern/engine.cc55
-rw-r--r--source/blender/render/intern/render_result.cc89
-rw-r--r--source/blender/render/intern/texture_pointdensity.c8
-rw-r--r--source/blender/sequencer/intern/disk_cache.c16
-rw-r--r--source/blender/sequencer/intern/proxy.c3
-rw-r--r--source/blender/sequencer/intern/render.c13
-rw-r--r--source/blender/windowmanager/WM_types.h2
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.cc3
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.cc2
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c5
-rw-r--r--source/blender/windowmanager/intern/wm_window.c30
-rw-r--r--source/blender/windowmanager/intern/wm_window_private.h5
-rw-r--r--source/blender/windowmanager/wm.h4
-rw-r--r--source/blender/windowmanager/wm_event_types.h55
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_session.c2
-rw-r--r--source/creator/CMakeLists.txt7
-rw-r--r--source/creator/creator_args.c52
761 files changed, 11927 insertions, 6194 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 408cf819ce8..7e89943714a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -336,11 +336,9 @@ if(APPLE)
else()
set(WITH_COREAUDIO OFF)
endif()
-if(NOT WIN32)
+if(UNIX AND NOT APPLE)
option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ON)
- if(UNIX AND NOT APPLE)
- option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF)
- endif()
+ option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF)
else()
set(WITH_JACK OFF)
endif()
@@ -489,13 +487,12 @@ endif()
if(NOT APPLE)
option(WITH_CYCLES_DEVICE_ONEAPI "Enable Cycles oneAPI compute support" OFF)
option(WITH_CYCLES_ONEAPI_BINARIES "Enable Ahead-Of-Time compilation for Cycles oneAPI device" OFF)
- option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF)
# https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html
- set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for")
+ # acm-g10 is the target for the first Intel Arc Alchemist GPUs.
+ set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "acm-g10" CACHE STRING "oneAPI Intel GPU architectures to build binaries for")
set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for")
- mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED)
mark_as_advanced(CYCLES_ONEAPI_SPIR64_GEN_DEVICES)
mark_as_advanced(CYCLES_ONEAPI_SYCL_TARGETS)
endif()
@@ -572,6 +569,12 @@ mark_as_advanced(
WITH_GPU_BUILDTIME_SHADER_BUILDER
)
+# Vulkan
+option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF)
+mark_as_advanced(
+ WITH_VULKAN_BACKEND
+)
+
# Metal
if(APPLE)
@@ -780,6 +783,8 @@ endif()
# -----------------------------------------------------------------------------
# Check for Conflicting/Unsupported Configurations
+option(WITH_STRICT_BUILD_OPTIONS "When requirements for a build option are not met, error instead of disabling the option" OFF)
+
if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE AND NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE)
message(FATAL_ERROR
"At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE "
@@ -895,10 +900,7 @@ endif()
if(WITH_BUILDINFO)
find_package(Git)
- if(NOT GIT_FOUND)
- message(WARNING "Git was not found, disabling WITH_BUILDINFO")
- set(WITH_BUILDINFO OFF)
- endif()
+ set_and_warn_library_found("Git" GIT_FOUND WITH_BUILDINFO)
endif()
if(WITH_AUDASPACE)
@@ -938,9 +940,10 @@ if(WITH_INTERNATIONAL)
WARNING
"Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, "
"This is a 'git submodule', which are known not to work with bridges to other version "
- "control systems, disabling 'WITH_INTERNATIONAL'."
+ "control systems."
)
- set(WITH_INTERNATIONAL OFF)
+ set(TRANSLATIONS_FOUND OFF)
+ set_and_warn_library_found("Translations" TRANSLATIONS_FOUND WITH_INTERNATIONAL)
endif()
endif()
@@ -1226,6 +1229,13 @@ endif()
# -----------------------------------------------------------------------------
+# Configure Vulkan.
+
+if(WITH_VULKAN_BACKEND)
+ add_definitions(-DWITH_VULKAN_BACKEND)
+endif()
+
+# -----------------------------------------------------------------------------
# Configure Metal
if(WITH_METAL_BACKEND)
@@ -1245,6 +1255,8 @@ if(WITH_OPENMP)
find_package(OpenMP)
endif()
+ set_and_warn_library_found("OpenMP" OPENMP_FOUND WITH_OPENMP)
+
if(OPENMP_FOUND)
if(NOT WITH_OPENMP_STATIC)
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
@@ -1260,9 +1272,6 @@ if(WITH_OPENMP)
find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
endif()
- else()
- message(STATUS "OpenMP not found, disabling WITH_OPENMP")
- set(WITH_OPENMP OFF)
endif()
mark_as_advanced(
@@ -1277,10 +1286,7 @@ endif()
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
find_package(Bullet)
- if(NOT BULLET_FOUND)
- message(STATUS "Bullet not found, disabling WITH_BULLET")
- set(WITH_BULLET OFF)
- endif()
+ set_and_warn_library_found("Bullet" BULLET_FOUND WITH_BULLET)
else()
set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src")
# set(BULLET_LIBRARIES "")
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index 4f40f44ad18..023d113b551 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -97,6 +97,8 @@ include(cmake/embree.cmake)
include(cmake/openpgl.cmake)
include(cmake/fmt.cmake)
include(cmake/robinmap.cmake)
+include(cmake/xml2.cmake)
+
if(NOT APPLE)
include(cmake/xr_openxr.cmake)
if(NOT WIN32 OR BUILD_MODE STREQUAL Release)
@@ -149,7 +151,6 @@ if(NOT WIN32 OR ENABLE_MINGW64)
endif()
if(UNIX)
include(cmake/flac.cmake)
- include(cmake/xml2.cmake)
if(NOT APPLE)
include(cmake/spnav.cmake)
include(cmake/jemalloc.cmake)
diff --git a/build_files/build_environment/cmake/aom.cmake b/build_files/build_environment/cmake/aom.cmake
index 9f64439771f..11c81c3f6e4 100644
--- a/build_files/build_environment/cmake/aom.cmake
+++ b/build_files/build_environment/cmake/aom.cmake
@@ -8,11 +8,6 @@ if(WIN32)
# building with mingw, it'll have an unhappy time with that and
# we need to clear them out.
set(AOM_CMAKE_FLAGS )
- # CMake will correctly identify phreads being available, however
- # we do not want to use them, as that gains a dependency on
- # libpthreadswin.dll which we do not want. when pthreads is not
- # available oam will use a pthreads emulation layer using win32 threads
- set(AOM_EXTRA_ARGS_WIN32 -DCMAKE_HAVE_PTHREAD_H=OFF)
else()
set(AOM_GENERATOR "Unix Makefiles")
set(AOM_CMAKE_FLAGS ${DEFAULT_CMAKE_FLAGS})
@@ -36,6 +31,7 @@ ExternalProject_Add(external_aom
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${AOM_HASH_TYPE}=${AOM_HASH}
PREFIX ${BUILD_DIR}/aom
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/aom/src/external_aom < ${PATCH_DIR}/aom.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
cd ${BUILD_DIR}/aom/src/external_aom-build/ &&
${CMAKE_COMMAND} -G "${AOM_GENERATOR}" -DCMAKE_INSTALL_PREFIX=${LIBDIR}/aom ${AOM_CMAKE_FLAGS} ${AOM_EXTRA_ARGS} ${BUILD_DIR}/aom/src/external_aom/
diff --git a/build_files/build_environment/cmake/cve_check.cmake b/build_files/build_environment/cmake/cve_check.cmake
index dfb190bcffa..ac42444aef1 100644
--- a/build_files/build_environment/cmake/cve_check.cmake
+++ b/build_files/build_environment/cmake/cve_check.cmake
@@ -27,10 +27,12 @@ get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if(_variableName MATCHES "CPE$")
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
+ string(REPLACE "_CPE" "_ID" CPE_DEPNAME ${_variableName})
list(GET CPE_LIST 3 CPE_VENDOR)
list(GET CPE_LIST 4 CPE_NAME)
list(GET CPE_LIST 5 CPE_VERSION)
- set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}\n")
+ set(${CPE_DEPNAME} "${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}")
+ set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION},,,\n")
endif()
endforeach()
configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY)
diff --git a/build_files/build_environment/cmake/cve_check.csv.in b/build_files/build_environment/cmake/cve_check.csv.in
index 6e7e8db5609..946dda5ab17 100644
--- a/build_files/build_environment/cmake/cve_check.csv.in
+++ b/build_files/build_environment/cmake/cve_check.csv.in
@@ -1,2 +1,29 @@
-vendor,product,version
+vendor,product,version,cve_number,remarks,comment
+@OPENJPEG_ID@,CVE-2016-9675,Ignored,issue in convert command line tool not used by blender
+@PYTHON_ID@,CVE-2009-2940,Ignored,issue in pygresql not used by blender
+@PYTHON_ID@,CVE-2020-29396,Ignored,issue in odoo not used by blender
+@PYTHON_ID@,CVE-2021-32052,Ignored,issue in django not used by blender
+@PYTHON_ID@,CVE-2009-3720,Ignored,already fixed in libexpat version used
+@SSL_ID@,CVE-2009-1390,Ignored,issue in mutt not used by blender
+@SSL_ID@,CVE-2009-3765,Ignored,issue in mutt not used by blender
+@SSL_ID@,CVE-2009-3766,Ignored,issue in mutt not used by blender
+@SSL_ID@,CVE-2009-3767,Ignored,issue in ldap not used by blender
+@SSL_ID@,CVE-2019-0190,Ignored,issue in apache not used by blender
+@TIFF_ID@,CVE-2022-2056,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2057,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2058,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2519,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2520,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2521,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2953,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-34526,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-3570,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-3597,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-3598,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-3599,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-3626,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-3627,Ignored,issue in tiff command line tool not used by blender
+@XML2_ID@,CVE-2016-3709,Ignored,not affecting blender and not considered a security issue upstream
+@GMP_ID@,CVE-2021-43618,Mitigated,patched using upstream commit 561a9c25298e
+@SQLITE_ID@,CVE-2022-35737,Ignored,only affects SQLITE_ENABLE_STAT4 compile option not used by blender or python
@SBOMCONTENTS@
diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake
index 35bc028a1e3..8d75f0ff0ed 100644
--- a/build_files/build_environment/cmake/download.cmake
+++ b/build_files/build_environment/cmake/download.cmake
@@ -62,7 +62,7 @@ function(download_source dep)
# since the actual build of the dep will notify the
# platform maintainer if there is a problem with the
# source package and refuse to build.
- if(NOT PACKAGE_USE_UPSTREAM_SOURCES)
+ if(NOT PACKAGE_USE_UPSTREAM_SOURCES OR FORCE_CHECK_HASH)
file(${TARGET_HASH_TYPE} ${TARGET_FILE} LOCAL_HASH)
if(NOT ${TARGET_HASH} STREQUAL ${LOCAL_HASH})
message(FATAL_ERROR "${TARGET_FILE} ${TARGET_HASH_TYPE} mismatch\nExpected\t: ${TARGET_HASH}\nActual\t: ${LOCAL_HASH}")
@@ -114,7 +114,6 @@ download_source(WEBP)
download_source(SPNAV)
download_source(JEMALLOC)
download_source(XML2)
-download_source(TINYXML)
download_source(YAMLCPP)
download_source(EXPAT)
download_source(PUGIXML)
diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake
index 7730607c514..e2b60e161f2 100644
--- a/build_files/build_environment/cmake/ffmpeg.cmake
+++ b/build_files/build_environment/cmake/ffmpeg.cmake
@@ -16,12 +16,6 @@ if(WIN32)
--enable-libopenjpeg
--disable-mediafoundation
)
- if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
- set(FFMPEG_EXTRA_FLAGS
- ${FFMPEG_EXTRA_FLAGS}
- --x86asmexe=yasm
- )
- endif()
else()
set(FFMPEG_EXTRA_FLAGS
${FFMPEG_EXTRA_FLAGS}
diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake
index b6f53ede2db..842e5c42e25 100644
--- a/build_files/build_environment/cmake/freetype.cmake
+++ b/build_files/build_environment/cmake/freetype.cmake
@@ -7,8 +7,11 @@ set(FREETYPE_EXTRA_ARGS
-DFT_DISABLE_HARFBUZZ=ON
-DFT_DISABLE_PNG=ON
-DFT_REQUIRE_BROTLI=ON
+ -DFT_REQUIRE_ZLIB=ON
-DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include
-DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include
)
ExternalProject_Add(external_freetype
@@ -23,6 +26,7 @@ ExternalProject_Add(external_freetype
add_dependencies(
external_freetype
external_brotli
+ external_zlib
)
if(BUILD_MODE STREQUAL Release AND WIN32)
diff --git a/build_files/build_environment/cmake/gmp.cmake b/build_files/build_environment/cmake/gmp.cmake
index e624778869e..ddfdba6662d 100644
--- a/build_files/build_environment/cmake/gmp.cmake
+++ b/build_files/build_environment/cmake/gmp.cmake
@@ -27,6 +27,7 @@ ExternalProject_Add(external_gmp
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${GMP_HASH_TYPE}=${GMP_HASH}
PREFIX ${BUILD_DIR}/gmp
+ PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/gmp/src/external_gmp < ${PATCH_DIR}/gmp.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/gmp ${GMP_OPTIONS} ${GMP_EXTRA_ARGS}
BUILD_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make install
diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake
index e4ddc7db846..11f6bf7c218 100644
--- a/build_files/build_environment/cmake/llvm.cmake
+++ b/build_files/build_environment/cmake/llvm.cmake
@@ -9,6 +9,7 @@ endif()
if(APPLE)
set(LLVM_XML2_ARGS
-DLIBXML2_LIBRARY=${LIBDIR}/xml2/lib/libxml2.a
+ -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
)
set(LLVM_BUILD_CLANG_TOOLS_EXTRA ^^clang-tools-extra)
set(BUILD_CLANG_TOOLS ON)
diff --git a/build_files/build_environment/cmake/opencollada.cmake b/build_files/build_environment/cmake/opencollada.cmake
index b2ae1a1a351..b1a3028debd 100644
--- a/build_files/build_environment/cmake/opencollada.cmake
+++ b/build_files/build_environment/cmake/opencollada.cmake
@@ -4,6 +4,29 @@ if(UNIX)
set(OPENCOLLADA_EXTRA_ARGS
-DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
-DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2.a)
+
+ # WARNING: the patch contains mixed UNIX and DOS line endings
+ # as does the OPENCOLLADA package, if this can be corrected upstream that would be better.
+ # For now use `sed` to force UNIX line endings so the patch applies.
+ # Needed as neither ignoring white-space or applying as a binary resolve this problem.
+ set(PATCH_MAYBE_DOS2UNIX_CMD
+ sed -i "s/\\r//"
+ ${PATCH_DIR}/opencollada.diff
+ ${BUILD_DIR}/opencollada/src/external_opencollada/CMakeLists.txt
+ ${BUILD_DIR}/opencollada/src/external_opencollada/Externals/LibXML/CMakeLists.txt &&
+ )
+
+else()
+ set(OPENCOLLADA_EXTRA_ARGS
+ -DCMAKE_DEBUG_POSTFIX=_d
+ -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
+ )
+ if(BUILD_MODE STREQUAL Release)
+ list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2s.lib)
+ else()
+ list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2sd.lib)
+ endif()
+ set(PATCH_MAYBE_DOS2UNIX_CMD)
endif()
ExternalProject_Add(external_opencollada
@@ -11,17 +34,19 @@ ExternalProject_Add(external_opencollada
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${OPENCOLLADA_HASH_TYPE}=${OPENCOLLADA_HASH}
PREFIX ${BUILD_DIR}/opencollada
- PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencollada/src/external_opencollada < ${PATCH_DIR}/opencollada.diff
+ PATCH_COMMAND
+ ${PATCH_MAYBE_DOS2UNIX_CMD}
+ ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencollada/src/external_opencollada < ${PATCH_DIR}/opencollada.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencollada ${DEFAULT_CMAKE_FLAGS} ${OPENCOLLADA_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/opencollada
)
-if(UNIX)
- add_dependencies(
- external_opencollada
- external_xml2
- )
-endif()
+unset(PATCH_MAYBE_DOS2UNIX_CMD)
+
+add_dependencies(
+ external_opencollada
+ external_xml2
+)
if(WIN32)
if(BUILD_MODE STREQUAL Release)
@@ -32,17 +57,7 @@ if(WIN32)
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_opencollada after_install
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/buffer.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/buffer_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/ftoa.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/ftoa_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/GeneratedSaxParser.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/GeneratedSaxParser_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/MathMLSolver.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/MathMLSolver_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADABaseUtils.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADABaseUtils_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAFramework.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAFramework_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/pcre.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/pcre_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/UTF.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/UTF_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/xml.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/xml_d.lib
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencollada/lib ${HARVEST_TARGET}/opencollada/lib
DEPENDEES install
)
endif()
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
index 6e5f9df20b4..13e7fb58be2 100644
--- a/build_files/build_environment/cmake/options.cmake
+++ b/build_files/build_environment/cmake/options.cmake
@@ -3,6 +3,7 @@
if(WIN32)
option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/fftw3 by installing mingw64" ON)
endif()
+option(FORCE_CHECK_HASH "Force a check of all hashses during CMake the configure phase" OFF)
option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES)
set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with")
@@ -20,8 +21,8 @@ else()
endif()
set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files")
-# This path must be hard-coded like this, so that the GNUmakefile knows where it is and can pass it to make_source_archive.py:
-set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages")
+
+set(PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/packages" CACHE PATH "default path for downloaded packages")
option(PACKAGE_USE_UPSTREAM_SOURCES "Use sources upstream to download the package sources, when OFF the blender mirror will be used" ON)
file(TO_CMAKE_PATH ${DOWNLOAD_DIR} DOWNLOAD_DIR)
diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake
index 9719de94d47..a5d000e4f44 100644
--- a/build_files/build_environment/cmake/osl.cmake
+++ b/build_files/build_environment/cmake/osl.cmake
@@ -32,6 +32,8 @@ set(OSL_EXTRA_ARGS
-DUSE_Qt5=OFF
-DINSTALL_DOCS=OFF
-Dpugixml_ROOT=${LIBDIR}/pugixml
+ -DTIFF_ROOT=${LIBDIR}/tiff
+ -DJPEG_ROOT=${LIBDIR}/jpeg
-DUSE_PYTHON=OFF
-DCMAKE_CXX_STANDARD=14
-DImath_ROOT=${LIBDIR}/imath
@@ -81,6 +83,7 @@ if(WIN32)
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslcomp.lib ${HARVEST_TARGET}/osl/lib/oslcomp_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslexec.lib ${HARVEST_TARGET}/osl/lib/oslexec_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslquery.lib ${HARVEST_TARGET}/osl/lib/oslquery_d.lib
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslnoise.lib ${HARVEST_TARGET}/osl/lib/oslnoise_d.lib
DEPENDEES install
)
endif()
diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake
index 890be673cb8..371f2608e2a 100644
--- a/build_files/build_environment/cmake/png.cmake
+++ b/build_files/build_environment/cmake/png.cmake
@@ -24,6 +24,14 @@ add_dependencies(
external_zlib
)
+if(WIN32 AND BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_png after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static${LIBEXT} ${HARVEST_TARGET}/png/lib/libpng${LIBEXT}
+ DEPENDEES install
+ )
+endif()
+
if(WIN32 AND BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_png after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_staticd${LIBEXT} ${LIBDIR}/png/lib/libpng16${LIBEXT}
diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake
index 8fed10e9d72..72ae27ddfdb 100644
--- a/build_files/build_environment/cmake/python.cmake
+++ b/build_files/build_environment/cmake/python.cmake
@@ -15,9 +15,11 @@ if(WIN32)
endmacro()
set(PYTHON_EXTERNALS_FOLDER ${BUILD_DIR}/python/src/external_python/externals)
+ set(ZLIB_SOURCE_FOLDER ${BUILD_DIR}/zlib/src/external_zlib)
set(DOWNLOADS_EXTERNALS_FOLDER ${DOWNLOAD_DIR}/externals)
cmake_to_dos_path(${PYTHON_EXTERNALS_FOLDER} PYTHON_EXTERNALS_FOLDER_DOS)
+ cmake_to_dos_path(${ZLIB_SOURCE_FOLDER} ZLIB_SOURCE_FOLDER_DOS)
cmake_to_dos_path(${DOWNLOADS_EXTERNALS_FOLDER} DOWNLOADS_EXTERNALS_FOLDER_DOS)
ExternalProject_Add(external_python
@@ -25,12 +27,21 @@ if(WIN32)
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${PYTHON_HASH_TYPE}=${PYTHON_HASH}
PREFIX ${BUILD_DIR}/python
- CONFIGURE_COMMAND ""
+ # Python will download its own deps and there's very little we can do about
+ # that beyond placing some code in their externals dir before it tries.
+ # the foldernames *HAVE* to match the ones inside pythons get_externals.cmd.
+ # python 3.10.8 still ships zlib 1.2.12, replace it with our 1.2.13
+ # copy until they update.
+ CONFIGURE_COMMAND mkdir ${PYTHON_EXTERNALS_FOLDER_DOS} &&
+ mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\zlib-1.2.12 ${ZLIB_SOURCE_FOLDER_DOS} &&
+ ${CMAKE_COMMAND} -E copy ${ZLIB_SOURCE_FOLDER}/../external_zlib-build/zconf.h ${PYTHON_EXTERNALS_FOLDER}/zlib-1.2.12/zconf.h
BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p x64 -c ${BUILD_MODE}
- PATCH_COMMAND ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_windows.diff
INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python
)
-
+ add_dependencies(
+ external_python
+ external_zlib
+ )
else()
if(APPLE)
# Disable functions that can be in 10.13 sdk but aren't available on 10.9 target.
diff --git a/build_files/build_environment/cmake/sndfile.cmake b/build_files/build_environment/cmake/sndfile.cmake
index 192c25f5ed1..a2ac2a33779 100644
--- a/build_files/build_environment/cmake/sndfile.cmake
+++ b/build_files/build_environment/cmake/sndfile.cmake
@@ -11,18 +11,11 @@ else()
set(SNDFILE_OPTIONS --enable-static --disable-shared )
endif()
-if(UNIX)
- set(SNDFILE_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/sndfile/src/external_sndfile < ${PATCH_DIR}/sndfile.diff)
-else()
- set(SNDFILE_PATCH_CMD)
-endif()
-
ExternalProject_Add(external_sndfile
URL file://${PACKAGE_DIR}/${SNDFILE_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${SNDFILE_HASH_TYPE}=${SNDFILE_HASH}
PREFIX ${BUILD_DIR}/sndfile
- PATCH_COMMAND ${SNDFILE_PATCH_CMD}
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && ${SNDFILE_ENV} ${CONFIGURE_COMMAND} ${SNDFILE_OPTIONS} --prefix=${mingw_LIBDIR}/sndfile
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make install
diff --git a/build_files/build_environment/cmake/sqlite.cmake b/build_files/build_environment/cmake/sqlite.cmake
index c82d832574a..c151a495ff1 100644
--- a/build_files/build_environment/cmake/sqlite.cmake
+++ b/build_files/build_environment/cmake/sqlite.cmake
@@ -48,7 +48,6 @@ ExternalProject_Add(external_sqlite
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${SQLITE_HASH_TYPE}=${SQLITE_HASH}
PREFIX ${BUILD_DIR}/sqlite
- PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/sqlite/src/external_sqlite < ${PATCH_DIR}/sqlite.diff
CONFIGURE_COMMAND ${SQLITE_CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/sqlite ${SQLITE_CONFIGURATION_ARGS}
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make install
diff --git a/build_files/build_environment/cmake/ssl.cmake b/build_files/build_environment/cmake/ssl.cmake
index 21c4d2418c3..628187dc0ac 100644
--- a/build_files/build_environment/cmake/ssl.cmake
+++ b/build_files/build_environment/cmake/ssl.cmake
@@ -5,6 +5,7 @@ set(SSL_PATCH_CMD echo .)
if(APPLE)
set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}")
+ set(SSL_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/ssl/src/external_ssl < ${PATCH_DIR}/ssl.diff)
else()
if(BLENDER_PLATFORM_ARM)
set(SSL_OS_COMPILER "blender-linux-aarch64")
diff --git a/build_files/build_environment/cmake/tiff.cmake b/build_files/build_environment/cmake/tiff.cmake
index 1f8e9442ae5..1ac2e4c6058 100644
--- a/build_files/build_environment/cmake/tiff.cmake
+++ b/build_files/build_environment/cmake/tiff.cmake
@@ -25,6 +25,7 @@ ExternalProject_Add(external_tiff
add_dependencies(
external_tiff
external_zlib
+ external_jpeg
)
if(WIN32)
if(BUILD_MODE STREQUAL Release)
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index bfc6d27f74d..328f5b8efc3 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -8,9 +8,9 @@
# Not all of our dependencies are currently in the nvd database so not all
# dependencies have one assigned.
-set(ZLIB_VERSION 1.2.12)
+set(ZLIB_VERSION 1.2.13)
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
-set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
+set(ZLIB_HASH 9b8aa094c4e5765dabf4da391f00d15c)
set(ZLIB_HASH_TYPE MD5)
set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*")
@@ -88,9 +88,9 @@ else()
set(OPENEXR_VERSION_POSTFIX)
endif()
-set(FREETYPE_VERSION 2.11.1)
+set(FREETYPE_VERSION 2.12.1)
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
-set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
+set(FREETYPE_HASH 8bc5c9c9df7ac12c504f8918552a7cf2)
set(FREETYPE_HASH_TYPE MD5)
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
@@ -159,9 +159,9 @@ set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${
set(OPENMP_HASH_TYPE MD5)
set(OPENMP_FILE openmp-${OPENMP_VERSION}.src.tar.xz)
-set(OPENIMAGEIO_VERSION v2.3.13.0)
+set(OPENIMAGEIO_VERSION v2.3.20.0)
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/refs/tags/${OPENIMAGEIO_VERSION}.tar.gz)
-set(OPENIMAGEIO_HASH de45fb38501c4581062b522b53b6141c)
+set(OPENIMAGEIO_HASH defb1fe7c8e64bac60eb3cacaf5c3736)
set(OPENIMAGEIO_HASH_TYPE MD5)
set(OPENIMAGEIO_FILE OpenImageIO-${OPENIMAGEIO_VERSION}.tar.gz)
@@ -189,17 +189,17 @@ set(TIFF_HASH_TYPE MD5)
set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*")
-set(OSL_VERSION 1.11.17.0)
-set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
-set(OSL_HASH 63265472ce14548839ace2e21e401544)
+set(OSL_VERSION 1.12.6.2)
+set(OSL_URI https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/archive/refs/tags/v${OSL_VERSION}.tar.gz)
+set(OSL_HASH 6fef11548adfdd3e5b25c49d2dae96ee)
set(OSL_HASH_TYPE MD5)
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
-set(PYTHON_VERSION 3.10.2)
+set(PYTHON_VERSION 3.10.8)
set(PYTHON_SHORT_VERSION 3.10)
set(PYTHON_SHORT_VERSION_NO_DOTS 310)
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
-set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9)
+set(PYTHON_HASH e92356b012ed4d0e09675131d39b1bde)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
@@ -298,17 +298,17 @@ set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce
set(XVIDCORE_HASH_TYPE SHA256)
set(XVIDCORE_FILE xvidcore-${XVIDCORE_VERSION}.tar.gz)
-set(OPENJPEG_VERSION 2.4.0)
-set(OPENJPEG_SHORT_VERSION 2.4)
+set(OPENJPEG_VERSION 2.5.0)
+set(OPENJPEG_SHORT_VERSION 2.5)
set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz)
-set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d)
+set(OPENJPEG_HASH 0333806d6adecc6f7a91243b2b839ff4d2053823634d4f6ed7a59bc87409122a)
set(OPENJPEG_HASH_TYPE SHA256)
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*")
-set(FFMPEG_VERSION 5.0)
+set(FFMPEG_VERSION 5.1.2)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
-set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
+set(FFMPEG_HASH 39a0bcc8d98549f16c570624678246a6ac736c066cebdb409f9502e915b22f2b)
set(FFMPEG_HASH_TYPE SHA256)
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
@@ -325,9 +325,9 @@ set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c)
set(ICONV_HASH_TYPE MD5)
set(ICONV_FILE libiconv-${ICONV_VERSION}.tar.gz)
-set(SNDFILE_VERSION 1.0.28)
-set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_VERSION}.tar.gz)
-set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c)
+set(SNDFILE_VERSION 1.1.0)
+set(SNDFILE_URI https://github.com/libsndfile/libsndfile/releases/download/1.1.0/libsndfile-${SNDFILE_VERSION}.tar.xz)
+set(SNDFILE_HASH e63dead2b4f0aaf323687619d007ee6a)
set(SNDFILE_HASH_TYPE MD5)
set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz)
set(SNDFILE_CPE "cpe:2.3:a:libsndfile_project:libsndfile:${SNDFILE_VERSION}:*:*:*:*:*:*:*")
@@ -351,21 +351,13 @@ set(JEMALLOC_HASH 3d41fbf006e6ebffd489bdb304d009ae)
set(JEMALLOC_HASH_TYPE MD5)
set(JEMALLOC_FILE jemalloc-${JEMALLOC_VERSION}.tar.bz2)
-set(XML2_VERSION 2.9.10)
-set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz)
-set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5)
+set(XML2_VERSION 2.10.3)
+set(XML2_URI https://download.gnome.org/sources/libxml2/2.10/libxml2-${XML2_VERSION}.tar.xz)
+set(XML2_HASH f9edac7fac232b3657a003fd9a5bbe42)
set(XML2_HASH_TYPE MD5)
-set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz)
+set(XML2_FILE libxml2-${XML2_VERSION}.tar.xz)
set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*")
-set(TINYXML_VERSION 2_6_2)
-set(TINYXML_VERSION_DOTS 2.6.2)
-set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXML_VERSION_DOTS}/tinyxml_${TINYXML_VERSION}.tar.gz)
-set(TINYXML_HASH c1b864c96804a10526540c664ade67f0)
-set(TINYXML_HASH_TYPE MD5)
-set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz)
-set(TINYXML_CPE "cpe:2.3:a:tinyxml_project:tinyxml:${TINYXML_VERSION_DOTS}:*:*:*:*:*:*:*")
-
set(YAMLCPP_VERSION 0.6.3)
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
@@ -379,10 +371,10 @@ set(PYSTRING_HASH f2c68786b359f5e4e62bed53bc4fb86d)
set(PYSTRING_HASH_TYPE MD5)
set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz)
-set(EXPAT_VERSION 2_4_4)
-set(EXPAT_VERSION_DOTS 2.4.4)
+set(EXPAT_VERSION 2_5_0)
+set(EXPAT_VERSION_DOTS 2.5.0)
set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
-set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
+set(EXPAT_HASH d375fa3571c0abb945873f5061a8f2e2)
set(EXPAT_HASH_TYPE MD5)
set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz)
set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*")
@@ -410,6 +402,10 @@ set(FLEX_FILE flex-${FLEX_VERSION}.tar.gz)
# NOTE: bzip.org domain does no longer belong to BZip 2 project, so we download
# sources from Debian packaging.
+#
+# NOTE 2: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there
+# can be no exceptions to this.
set(BZIP2_VERSION 1.0.8)
set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERSION}.orig.tar.gz)
set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
@@ -417,6 +413,9 @@ set(BZIP2_HASH_TYPE SHA256)
set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz)
set(BZIP2_CPE "cpe:2.3:a:bzip:bzip2:${BZIP2_VERSION}:*:*:*:*:*:*:*")
+# NOTE: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there
+# can be no exceptions to this.
set(FFI_VERSION 3.3)
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
@@ -430,27 +429,25 @@ set(LZMA_HASH 5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df)
set(LZMA_HASH_TYPE SHA256)
set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2)
-if(BLENDER_PLATFORM_ARM)
- # Need at least 1.1.1i for aarch64 support (https://github.com/openssl/openssl/pull/13218)
- set(SSL_VERSION 1.1.1i)
- set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
- set(SSL_HASH e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242)
- set(SSL_HASH_TYPE SHA256)
- set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
-else()
- set(SSL_VERSION 1.1.1g)
- set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
- set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46)
- set(SSL_HASH_TYPE SHA256)
- set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
-endif()
+# NOTE: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there
+# can be no exceptions to this.
+set(SSL_VERSION 1.1.1q)
+set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
+set(SSL_HASH d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca)
+set(SSL_HASH_TYPE SHA256)
+set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
-set(SQLITE_VERSION 3.31.1)
-set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
-set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
+# Note: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat for compliance reasons there
+# can be no exceptions to this.
+set(SQLITE_VERSION 3.37.2)
+set(SQLLITE_LONG_VERSION 3370200)
+set(SQLITE_URI https://www.sqlite.org/2022/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
+set(SQLITE_HASH e56faacadfb4154f8fbd0f2a3f827d13706b70a1)
set(SQLITE_HASH_TYPE SHA1)
-set(SQLITE_FILE sqlite-src-3240000.zip)
+set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
set(EMBREE_VERSION 3.13.4)
@@ -561,22 +558,22 @@ set(BROTLI_HASH_TYPE SHA256)
set(BROTLI_FILE brotli-v${BROTLI_VERSION}.tar.gz)
set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*")
-set(OPENPGL_VERSION v0.4.0-beta)
-set(OPENPGL_SHORT_VERSION 0.4.0)
+set(OPENPGL_VERSION v0.4.1-beta)
+set(OPENPGL_SHORT_VERSION 0.4.1)
set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz)
-set(OPENPGL_HASH 58d5b65c533ce6cac3f7e1d51cf169a5411adf356abcd85f04049bbcaecc2e77)
+set(OPENPGL_HASH db63f5dac5cfa8c110ede241f0c413f00db0c4748697381c4fa23e0f9e82a754)
set(OPENPGL_HASH_TYPE SHA256)
set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz)
-set(LEVEL_ZERO_VERSION v1.7.15)
+set(LEVEL_ZERO_VERSION v1.8.5)
set(LEVEL_ZERO_URI https://github.com/oneapi-src/level-zero/archive/refs/tags/${LEVEL_ZERO_VERSION}.tar.gz)
-set(LEVEL_ZERO_HASH c39bb05a8e5898aa6c444e1704105b93d3f1888b9c333f8e7e73825ffbfb2617)
+set(LEVEL_ZERO_HASH b6e9663bbcc53c148d32376998298bec6f7c434ef2218c61fa708963e3a09394)
set(LEVEL_ZERO_HASH_TYPE SHA256)
set(LEVEL_ZERO_FILE level-zero-${LEVEL_ZERO_VERSION}.tar.gz)
-set(DPCPP_VERSION 20220812)
+set(DPCPP_VERSION 20221019)
set(DPCPP_URI https://github.com/intel/llvm/archive/refs/tags/sycl-nightly/${DPCPP_VERSION}.tar.gz)
-set(DPCPP_HASH 0e3c95346c295f5cf80f3a42d80b1c49481955898530242636ddc002627248d6)
+set(DPCPP_HASH 2f533946e91ce3829431758ea17b0b834b960c1a796e9e4563c86e03eb9603a2)
set(DPCPP_HASH_TYPE SHA256)
set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz)
@@ -589,9 +586,9 @@ set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz)
# will take care of building them, unpack is being done in dpcpp_deps.cmake
# Source llvm/lib/SYCLLowerIR/CMakeLists.txt
-set(VCINTRINSICS_VERSION 984bb27baacce6ee5c716c2e64845f2a1928025b)
+set(VCINTRINSICS_VERSION abce9184b7a3a7fe1b02289b9285610d9dc45465)
set(VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/${VCINTRINSICS_VERSION}.tar.gz)
-set(VCINTRINSICS_HASH abea415a15a0dd11fdc94dee8fb462910f2548311b787e02f42509789e1b0d7b)
+set(VCINTRINSICS_HASH 3e9fd471246b87633b26f7e15e17ab7733d357458c53d5c5881c03929d6c551f)
set(VCINTRINSICS_HASH_TYPE SHA256)
set(VCINTRINSICS_FILE vc-intrinsics-${VCINTRINSICS_VERSION}.tar.gz)
@@ -603,9 +600,9 @@ set(OPENCLHEADERS_HASH_TYPE SHA256)
set(OPENCLHEADERS_FILE opencl_headers-${OPENCLHEADERS_VERSION}.tar.gz)
# Source opencl/CMakeLists.txt
-set(ICDLOADER_VERSION aec3952654832211636fc4af613710f80e203b0a)
+set(ICDLOADER_VERSION 792682ad3d877ab38573b997808bab3b43902b70)
set(ICDLOADER_URI https://github.com/KhronosGroup/OpenCL-ICD-Loader/archive/${ICDLOADER_VERSION}.tar.gz)
-set(ICDLOADER_HASH e1880551d67bd8dc31d13de63b94bbfd6b1f315b6145dad1ffcd159b89bda93c)
+set(ICDLOADER_HASH b33a0320d94bf300efa1da97931ded506d27813bd1148da6858fe79d412d1ea2)
set(ICDLOADER_HASH_TYPE SHA256)
set(ICDLOADER_FILE icdloader-${ICDLOADER_VERSION}.tar.gz)
@@ -620,9 +617,9 @@ set(MP11_FILE mp11-${MP11_VERSION}.tar.gz)
# Source llvm-spirv/CMakeLists.txt (repo)
# Source llvm-spirv/spirv-headers-tag.conf (hash)
-set(SPIRV_HEADERS_VERSION 36c0c1596225e728bd49abb7ef56a3953e7ed468)
+set(SPIRV_HEADERS_VERSION 5a121866927a16ab9d49bed4788b532c7fcea766)
set(SPIRV_HEADERS_URI https://github.com/KhronosGroup/SPIRV-Headers/archive/${SPIRV_HEADERS_VERSION}.tar.gz)
-set(SPIRV_HEADERS_HASH 7a5c89633f8740456fe8adee052033e134476d267411d1336c0cb1e587a9229a)
+set(SPIRV_HEADERS_HASH ec8ecb471a62672697846c436501638ab25447ae9d4a6761e0bfe8a9a839502a)
set(SPIRV_HEADERS_HASH_TYPE SHA256)
set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz)
@@ -637,9 +634,9 @@ set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz)
# compiler, the versions used are taken from the following location
# https://github.com/intel/intel-graphics-compiler/releases
-set(IGC_VERSION 1.0.11222)
+set(IGC_VERSION 1.0.12149.1)
set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz)
-set(IGC_HASH d92f0608dcbb52690855685f9447282e5c09c0ba98ae35fabf114fcf8b1e9fcf)
+set(IGC_HASH 44f67f24e3bc5130f9f062533abf8154782a9d0a992bc19b498639a8521ae836)
set(IGC_HASH_TYPE SHA256)
set(IGC_FILE igc-${IGC_VERSION}.tar.gz)
@@ -659,15 +656,15 @@ set(IGC_LLVM_FILE ${IGC_LLVM_VERSION}.tar.gz)
#
# WARNING WARNING WARNING
-set(IGC_OPENCL_CLANG_VERSION bbdd1587f577397a105c900be114b56755d1f7dc)
+set(IGC_OPENCL_CLANG_VERSION 363a5262d8c7cff3fb28f3bdb5d85c8d7e91c1bb)
set(IGC_OPENCL_CLANG_URI https://github.com/intel/opencl-clang/archive/${IGC_OPENCL_CLANG_VERSION}.tar.gz)
-set(IGC_OPENCL_CLANG_HASH d08315f1b0d8a6fef33de2b3e6aa7356534c324910634962c72523d970773efc)
+set(IGC_OPENCL_CLANG_HASH aa8cf72bb239722ce8ce44f79413c6887ecc8ca18477dd520aa5c4809756da9a)
set(IGC_OPENCL_CLANG_HASH_TYPE SHA256)
set(IGC_OPENCL_CLANG_FILE opencl-clang-${IGC_OPENCL_CLANG_VERSION}.tar.gz)
-set(IGC_VCINTRINSICS_VERSION v0.4.0)
+set(IGC_VCINTRINSICS_VERSION v0.5.0)
set(IGC_VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/refs/tags/${IGC_VCINTRINSICS_VERSION}.tar.gz)
-set(IGC_VCINTRINSICS_HASH c8b92682ad5031cf9d5b82a40e7d5c0e763cd9278660adbcaa69aab988e4b589)
+set(IGC_VCINTRINSICS_HASH 70bb47c5e32173cf61514941e83ae7c7eb4485e6d2fca60cfa1f50d4f42c41f2)
set(IGC_VCINTRINSICS_HASH_TYPE SHA256)
set(IGC_VCINTRINSICS_FILE vc-intrinsics-${IGC_VCINTRINSICS_VERSION}.tar.gz)
@@ -683,9 +680,9 @@ set(IGC_SPIRV_TOOLS_HASH 6e19900e948944243024aedd0a201baf3854b377b9cc7a386553bc1
set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256)
set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz)
-set(IGC_SPIRV_TRANSLATOR_VERSION 99420daab98998a7e36858befac9c5ed109d4920)
+set(IGC_SPIRV_TRANSLATOR_VERSION a31ffaeef77e23d500b3ea3d35e0c42ff5648ad9)
set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
-set(IGC_SPIRV_TRANSLATOR_HASH 77dfb4ddb6bfb993535562c02ddea23f0a0d1c5a0258c1afe7e27c894ff783a8)
+set(IGC_SPIRV_TRANSLATOR_HASH 9e26c96a45341b8f8af521bacea20e752623346340addd02af95d669f6e89252)
set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256)
set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
@@ -693,15 +690,15 @@ set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.
### Intel Graphics Compiler DEPS END ###
########################################
-set(GMMLIB_VERSION intel-gmmlib-22.1.2)
+set(GMMLIB_VERSION intel-gmmlib-22.1.8)
set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz)
-set(GMMLIB_HASH 3b9a6d5e7e3f5748b3d0a2fb0e980ae943907fece0980bd9c0508e71c838e334)
+set(GMMLIB_HASH bf23e9a3742b4fb98c7666c9e9b29f3219e4b2fb4d831aaf4eed71f5e2d17368)
set(GMMLIB_HASH_TYPE SHA256)
set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz)
-set(OCLOC_VERSION 22.20.23198)
+set(OCLOC_VERSION 22.38.24278)
set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz)
-set(OCLOC_HASH ab22b8bf2560a57fdd3def0e35a62ca75991406f959c0263abb00cd6cd9ae998)
+set(OCLOC_HASH db0c542fccd651e6404b15a74d46027f1ce0eda8dc9e25a40cbb6c0faef257ee)
set(OCLOC_HASH_TYPE SHA256)
set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz)
diff --git a/build_files/build_environment/cmake/wayland.cmake b/build_files/build_environment/cmake/wayland.cmake
index 799f2513da9..c73db1d10ff 100644
--- a/build_files/build_environment/cmake/wayland.cmake
+++ b/build_files/build_environment/cmake/wayland.cmake
@@ -7,10 +7,14 @@ ExternalProject_Add(external_wayland
PREFIX ${BUILD_DIR}/wayland
PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/wayland/src/external_wayland < ${PATCH_DIR}/wayland.diff
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT & LIBXML2.
- # Note that passing link args "ffi/lib" should not be needed, but
+ #
+ # NOTE: passing link args "ffi/lib" should not be needed, but
# `pkgconfig` would incorrectly look in "ffi/lib/../lib64" otherwise.
+ #
+ # NOTE: `-lm` is needed for `libxml2` which is a static library that uses `libm.so`,
+ # without this, math symbols such as `floor` aren't found.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:${LIBDIR}/ffi/lib/pkgconfig:$PKG_CONFIG_PATH
- meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dc_link_args=-L${LIBDIR}/ffi/lib . ../external_wayland
+ meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)
diff --git a/build_files/build_environment/cmake/xml2.cmake b/build_files/build_environment/cmake/xml2.cmake
index cd24fd836b0..3d31ec131bb 100644
--- a/build_files/build_environment/cmake/xml2.cmake
+++ b/build_files/build_environment/cmake/xml2.cmake
@@ -1,20 +1,48 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-ExternalProject_Add(external_xml2
- URL file://${PACKAGE_DIR}/${XML2_FILE}
- DOWNLOAD_DIR ${DOWNLOAD_DIR}
- URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH}
- PREFIX ${BUILD_DIR}/xml2
- CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND}
- --prefix=${LIBDIR}/xml2
- --disable-shared
- --enable-static
- --with-pic
- --with-python=no
- --with-lzma=no
- --with-zlib=no
- --with-iconv=no
- BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS}
- INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install
- INSTALL_DIR ${LIBDIR}/xml2
-)
+if(WIN32)
+ set(XML2_EXTRA_ARGS
+ -DLIBXML2_WITH_ZLIB=OFF
+ -DLIBXML2_WITH_LZMA=OFF
+ -DLIBXML2_WITH_PYTHON=OFF
+ -DLIBXML2_WITH_ICONV=OFF
+ -DLIBXML2_WITH_TESTS=OFF
+ -DLIBXML2_WITH_PROGRAMS=OFF
+ -DBUILD_SHARED_LIBS=OFF
+ )
+ ExternalProject_Add(external_xml2
+ URL file://${PACKAGE_DIR}/${XML2_FILE}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH}
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/xml2 ${DEFAULT_CMAKE_FLAGS} ${XML2_EXTRA_ARGS}
+ PREFIX ${BUILD_DIR}/xml2
+ INSTALL_DIR ${LIBDIR}/xml2
+ )
+else()
+ ExternalProject_Add(external_xml2
+ URL file://${PACKAGE_DIR}/${XML2_FILE}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH}
+ PREFIX ${BUILD_DIR}/xml2
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND}
+ --prefix=${LIBDIR}/xml2
+ --disable-shared
+ --enable-static
+ --with-pic
+ --with-python=no
+ --with-lzma=no
+ --with-zlib=no
+ --with-iconv=no
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install
+ INSTALL_DIR ${LIBDIR}/xml2
+ )
+endif()
+
+if(WIN32 AND BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_xml2 after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/xml2/include ${HARVEST_TARGET}/xml2/include
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/xml2/lib/libxml2s.lib ${HARVEST_TARGET}/xml2/lib/libxml2s.lib
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/dependencies.dot b/build_files/build_environment/dependencies.dot
index 7e8637fbced..bb42856c3ac 100644
--- a/build_files/build_environment/dependencies.dot
+++ b/build_files/build_environment/dependencies.dot
@@ -1,96 +1,114 @@
strict graph {
-graph[autosize = false, size = "25.7,8.3!", resolution = 300, overlap = false, splines = false, outputorder=edgesfirst ];
- node [style=filled fillcolor=white];
- external_alembic -- external_boost;
- external_alembic -- external_zlib;
+graph[autosize = false, size = "25.7,8.3!", resolution = 300];
external_alembic -- external_openexr;
+ external_alembic -- external_imath;
external_blosc -- external_zlib;
external_blosc -- external_pthreads;
- external_boost -- Make_Python_Environment;
- external_clang -- ll;
+ external_boost -- external_python;
+ external_boost -- external_numpy;
+ external_dpcpp -- external_python;
+ external_dpcpp -- external_python_site_packages;
+ external_dpcpp -- external_vcintrinsics;
+ external_dpcpp -- external_openclheaders;
+ external_dpcpp -- external_icdloader;
+ external_dpcpp -- external_mp11;
+ external_dpcpp -- external_level_zero;
+ external_dpcpp -- external_spirvheaders;
+ external_embree -- external_tbb;
external_ffmpeg -- external_zlib;
- external_ffmpeg -- external_faad;
external_ffmpeg -- external_openjpeg;
external_ffmpeg -- external_xvidcore;
external_ffmpeg -- external_x264;
+ external_ffmpeg -- external_opus;
external_ffmpeg -- external_vpx;
external_ffmpeg -- external_theora;
external_ffmpeg -- external_vorbis;
external_ffmpeg -- external_ogg;
external_ffmpeg -- external_lame;
+ external_ffmpeg -- external_aom;
external_ffmpeg -- external_zlib_mingw;
- external_numpy -- Make_Python_Environment;
+ external_ffmpeg -- external_nasm;
+ external_freetype -- external_brotli;
+ external_freetype -- external_zlib;
+ external_gmpxx -- external_gmp;
+ external_igc_llvm -- external_igc_opencl_clang;
+ external_igc_spirv_translator -- external_igc_opencl_clang;
+ external_igc -- external_igc_vcintrinsics;
+ external_igc -- external_igc_llvm;
+ external_igc -- external_igc_opencl_clang;
+ external_igc -- external_igc_vcintrinsics;
+ external_igc -- external_igc_spirv_headers;
+ external_igc -- external_igc_spirv_tools;
+ external_igc -- external_igc_spirv_translator;
+ external_igc -- external_flex;
+ external_ispc -- ll;
+ external_ispc -- external_python;
+ external_ispc -- external_flexbison;
+ external_ispc -- external_flex;
+ ll -- external_xml2;
+ ll -- external_python;
+ external_mesa -- ll;
+ external_numpy -- external_python;
+ external_numpy -- external_python_site_packages;
+ external_ocloc -- external_igc;
+ external_ocloc -- external_gmmlib;
external_opencollada -- external_xml2;
- external_opencolorio -- external_boost;
- external_opencolorio -- external_tinyxml;
external_opencolorio -- external_yamlcpp;
+ external_opencolorio -- external_expat;
+ external_opencolorio -- external_imath;
+ external_opencolorio -- external_pystring;
external_openexr -- external_zlib;
+ external_openimagedenoise -- external_tbb;
+ external_openimagedenoise -- external_ispc;
+ external_openimagedenoise -- external_python;
external_openimageio -- external_png;
external_openimageio -- external_zlib;
external_openimageio -- external_openexr;
- external_openimageio -- external_openexr;
+ external_openimageio -- external_imath;
external_openimageio -- external_jpeg;
external_openimageio -- external_boost;
external_openimageio -- external_tiff;
- external_openimageio -- external_opencolorio;
+ external_openimageio -- external_pugixml;
+ external_openimageio -- external_fmt;
+ external_openimageio -- external_robinmap;
external_openimageio -- external_openjpeg;
external_openimageio -- external_webp;
- external_openimageio -- external_opencolorio_extra;
- external_openmp -- external_clang;
+ external_openmp -- ll;
+ external_openpgl -- external_tbb;
external_opensubdiv -- external_tbb;
openvdb -- external_tbb;
openvdb -- external_boost;
- openvdb -- external_openexr;
- openvdb -- external_openexr;
openvdb -- external_zlib;
openvdb -- external_blosc;
external_osl -- external_boost;
external_osl -- ll;
- external_osl -- external_clang;
- external_osl -- external_openexr;
external_osl -- external_openexr;
external_osl -- external_zlib;
- external_osl -- external_flexbison;
external_osl -- external_openimageio;
external_osl -- external_pugixml;
+ external_osl -- external_flexbison;
+ external_osl -- external_flex;
external_png -- external_zlib;
- external_python_site_packages -- Make_Python_Environment;
+ external_python -- external_bzip2;
+ external_python -- external_ffi;
+ external_python -- external_lzma;
+ external_python -- external_ssl;
+ external_python -- external_sqlite;
+ external_python -- external_zlib;
+ external_python_site_packages -- external_python;
external_sndfile -- external_ogg;
external_sndfile -- external_vorbis;
external_sndfile -- external_flac;
external_theora -- external_vorbis;
external_theora -- external_ogg;
external_tiff -- external_zlib;
+ external_usd -- external_tbb;
+ external_usd -- external_boost;
+ external_usd -- external_opensubdiv;
external_vorbis -- external_ogg;
- blender-- external_ffmpeg;
- blender-- external_alembic;
- blender-- external_openjpeg;
- blender-- external_opencolorio;
- blender-- external_openexr;
- blender-- external_opensubdiv;
- blender-- openvdb;
- blender-- external_osl;
- blender-- external_boost;
- blender-- external_jpeg;
- blender-- external_png;
- blender-- external_python;
- blender-- external_sndfile;
- blender-- external_iconv;
- blender-- external_fftw3;
- external_python-- external_python_site_packages;
- external_python_site_packages-- requests;
- external_python_site_packages-- idna;
- external_python_site_packages-- chardet;
- external_python_site_packages-- urllib3;
- external_python_site_packages-- certifi;
- external_python-- external_numpy;
- external_usd-- external_boost;
- external_usd-- external_tbb;
- blender-- external_opencollada;
- blender-- external_sdl;
- blender-- external_freetype;
- blender-- external_pthreads;
- blender-- external_zlib;
- blender-- external_openal;
- blender-- external_usd;
+ external_wayland -- external_expat;
+ external_wayland -- external_xml2;
+ external_wayland -- external_ffi;
+ external_wayland_protocols -- external_wayland;
+ external_x264 -- external_nasm;
}
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index f913ac5e73c..5a191f7669b 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -394,7 +394,7 @@ CLANG_FORMAT_VERSION="10.0"
CLANG_FORMAT_VERSION_MIN="6.0"
CLANG_FORMAT_VERSION_MEX="14.0"
-PYTHON_VERSION="3.10.2"
+PYTHON_VERSION="3.10.8"
PYTHON_VERSION_SHORT="3.10"
PYTHON_VERSION_MIN="3.10"
PYTHON_VERSION_MEX="3.12"
@@ -505,7 +505,7 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="2.3.13.0"
+OIIO_VERSION="2.3.20.0"
OIIO_VERSION_SHORT="2.3"
OIIO_VERSION_MIN="2.1.12"
OIIO_VERSION_MEX="2.4.0"
@@ -523,8 +523,8 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.11.17.0"
-OSL_VERSION_SHORT="1.11"
+OSL_VERSION="1.12.6.2"
+OSL_VERSION_SHORT="1.12"
OSL_VERSION_MIN="1.11"
OSL_VERSION_MEX="2.0"
OSL_FORCE_BUILD=false
@@ -602,10 +602,10 @@ LEVEL_ZERO_FORCE_BUILD=false
LEVEL_ZERO_FORCE_REBUILD=false
LEVEL_ZERO_SKIP=false
-OPENPGL_VERSION="0.3.1"
-OPENPGL_VERSION_SHORT="0.3"
+OPENPGL_VERSION="0.4.0"
+OPENPGL_VERSION_SHORT="0.4"
OPENPGL_VERSION_MIN="0.3.1"
-OPENPGL_VERSION_MEX="0.3.2"
+OPENPGL_VERSION_MEX="0.5"
OPENPGL_FORCE_BUILD=false
OPENPGL_FORCE_REBUILD=false
OPENPGL_SKIP=false
@@ -618,8 +618,8 @@ XR_OPENXR_FORCE_BUILD=false
XR_OPENXR_FORCE_REBUILD=false
XR_OPENXR_SKIP=false
-FFMPEG_VERSION="5.0"
-FFMPEG_VERSION_SHORT="5.0"
+FFMPEG_VERSION="5.1.2"
+FFMPEG_VERSION_SHORT="5.1"
FFMPEG_VERSION_MIN="4.0"
FFMPEG_VERSION_MEX="6.0"
FFMPEG_FORCE_BUILD=false
@@ -1139,7 +1139,7 @@ LLVM_SOURCE=( "$_LLVM_SOURCE_ROOT/llvm-$LLVM_VERSION.src.tar.xz" )
LLVM_CLANG_SOURCE=( "$_LLVM_SOURCE_ROOT/clang-$LLVM_VERSION.src.tar.xz" "$_LLVM_SOURCE_ROOT/cfe-$LLVM_VERSION.src.tar.xz" )
OSL_USE_REPO=false
-OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" )
+OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/v$OSL_VERSION.tar.gz" )
#~ OSL_SOURCE_REPO=( "https://github.com/imageworks/OpenShadingLanguage.git" )
#~ OSL_SOURCE_REPO_BRANCH="master"
#~ OSL_SOURCE_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
diff --git a/build_files/build_environment/patches/aom.diff b/build_files/build_environment/patches/aom.diff
new file mode 100644
index 00000000000..1611cff5dca
--- /dev/null
+++ b/build_files/build_environment/patches/aom.diff
@@ -0,0 +1,18 @@
+diff -Naur libaom-3.4.0/build/cmake/aom_configure.cmake external_aom/build/cmake/aom_configure.cmake
+--- libaom-3.4.0/build/cmake/aom_configure.cmake 2022-06-17 11:46:18 -0600
++++ external_aom/build/cmake/aom_configure.cmake 2022-10-16 15:35:54 -0600
+@@ -15,8 +15,12 @@
+
+ include(FindGit)
+ include(FindPerl)
+-include(FindThreads)
+-
++# Blender: This will drag in a dep on libwinpthreads which we prefer
++# not to have, aom will fallback on a native win32 thread wrapper
++# if pthreads are not found.
++if(NOT WIN32)
++ include(FindThreads)
++endif()
+ include("${AOM_ROOT}/build/cmake/aom_config_defaults.cmake")
+ include("${AOM_ROOT}/build/cmake/aom_experiment_deps.cmake")
+ include("${AOM_ROOT}/build/cmake/aom_optimization.cmake")
diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff
index c255f7c37a3..ac104a20ffe 100644
--- a/build_files/build_environment/patches/ffmpeg.diff
+++ b/build_files/build_environment/patches/ffmpeg.diff
@@ -68,34 +68,18 @@
+
return ret;
}
---- a/libavcodec/rl.c
-+++ b/libavcodec/rl.c
-@@ -71,17 +71,19 @@
- av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
- {
- int i, q;
-- VLC_TYPE table[1500][2] = {{0}};
-+ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2);
- VLC vlc = { .table = table, .table_allocated = static_size };
-- av_assert0(static_size <= FF_ARRAY_ELEMS(table));
-+ av_assert0(static_size < 1500);
- init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC);
+diff --git a/libavcodec/x86/simple_idct.asm b/libavcodec/x86/simple_idct.asm
+index dcf0da6df121..982b2f0bbba1 100644
+--- a/libavcodec/x86/simple_idct.asm
++++ b/libavcodec/x86/simple_idct.asm
+@@ -25,9 +25,9 @@
- for (q = 0; q < 32; q++) {
- int qmul = q * 2;
- int qadd = (q - 1) | 1;
+ %include "libavutil/x86/x86util.asm"
-- if (!rl->rl_vlc[q])
-+ if (!rl->rl_vlc[q]){
-+ av_free(table);
- return;
-+ }
+-%if ARCH_X86_32
+ SECTION_RODATA
- if (q == 0) {
- qmul = 1;
-@@ -113,4 +115,5 @@
- rl->rl_vlc[q][i].run = run;
- }
- }
-+ av_free(table);
- }
++%if ARCH_X86_32
+ cextern pb_80
+
+ wm1010: dw 0, 0xffff, 0, 0xffff
diff --git a/build_files/build_environment/patches/gmp.diff b/build_files/build_environment/patches/gmp.diff
new file mode 100644
index 00000000000..bf22f93bc4f
--- /dev/null
+++ b/build_files/build_environment/patches/gmp.diff
@@ -0,0 +1,15 @@
+--- a/mpz/inp_raw.c Tue Dec 22 23:49:51 2020 +0100
++++ b/mpz/inp_raw.c Thu Oct 21 19:06:49 2021 +0200
+@@ -88,8 +88,11 @@
+
+ abs_csize = ABS (csize);
+
++ if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8))
++ return 0; /* Bit size overflows */
++
+ /* round up to a multiple of limbs */
+- abs_xsize = BITS_TO_LIMBS (abs_csize*8);
++ abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8);
+
+ if (abs_xsize != 0)
+ {
diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff
index e8efc1a6909..02eab251a13 100644
--- a/build_files/build_environment/patches/opencollada.diff
+++ b/build_files/build_environment/patches/opencollada.diff
@@ -130,3 +130,28 @@ index 715d903..24423ce 100644
{
string id = node.attribute("id").value();
size_t line = node.line();
+diff -Naur a/CMakeLists.txt b/CMakeLists.txt
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -274,7 +274,7 @@
+ add_subdirectory(${EXTERNAL_LIBRARIES}/UTF)
+ add_subdirectory(common/libBuffer)
+ add_subdirectory(${EXTERNAL_LIBRARIES}/MathMLSolver)
+-add_subdirectory(${EXTERNAL_LIBRARIES}/zlib)
++#add_subdirectory(${EXTERNAL_LIBRARIES}/zlib)
+
+ # building OpenCOLLADA libs
+ add_subdirectory(COLLADABaseUtils)
+@@ -284,10 +284,10 @@
+ add_subdirectory(COLLADAStreamWriter)
+
+ # building COLLADAValidator app
+-add_subdirectory(COLLADAValidator)
++#add_subdirectory(COLLADAValidator)
+
+ # DAE validator app
+-add_subdirectory(DAEValidator)
++#add_subdirectory(DAEValidator)
+
+ # Library export
+ install(EXPORT LibraryExport DESTINATION ${OPENCOLLADA_INST_CMAKECONFIG} FILE OpenCOLLADATargets.cmake)
diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff
index 28e1d6e101d..3f4a485b037 100644
--- a/build_files/build_environment/patches/osl.diff
+++ b/build_files/build_environment/patches/osl.diff
@@ -1,67 +1,53 @@
-diff -Naur OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h
---- OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h 2018-05-01 16:39:02 -0600
-+++ external_osl/src/include/OSL/llvm_util.h 2018-08-25 14:05:00 -0600
-@@ -33,6 +33,8 @@
-
- #include <vector>
-
-+#define OSL_HAS_BLENDER_CLEANUP_FIX
-+
- #ifdef LLVM_NAMESPACE
- namespace llvm = LLVM_NAMESPACE;
- #endif
-@@ -487,6 +489,7 @@
- std::string func_name (llvm::Function *f);
-
- static size_t total_jit_memory_held ();
-+ static void Cleanup ();
-
- private:
- class MemoryManager;
-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
-@@ -140,7 +140,10 @@
- };
-
-
--
-+void LLVM_Util::Cleanup ()
-+{
-+ if(jitmm_hold) jitmm_hold->clear();
-+}
-
- size_t
- LLVM_Util::total_jit_memory_held ()
-diff -Naur org/CMakeLists.txt external_osl/CMakeLists.txt
---- org/CMakeLists.txt 2020-12-01 12:37:15 -0700
-+++ external_osl/CMakeLists.txt 2021-01-20 13:26:50 -0700
-@@ -84,6 +84,11 @@
+diff -Naur OpenShadingLanguage-1.12.6.2/CMakeLists.txt external_osl/CMakeLists.txt
+--- OpenShadingLanguage-1.12.6.2/CMakeLists.txt 2022-09-30 17:43:53 -0600
++++ external_osl/CMakeLists.txt 2022-10-15 14:49:26 -0600
+@@ -101,6 +101,11 @@
CACHE STRING "Directory where OptiX PTX files will be installed")
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')")
-
+
+set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static")
+if (USE_OIIO_STATIC)
+ add_definitions ("-DOIIO_STATIC_BUILD=1")
+ add_definitions ("-DOIIO_STATIC_DEFINE=1")
+endif ()
-
+
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
if (OSL_NO_DEFAULT_TEXTURESYSTEM)
-diff -Naur external_osl_orig/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake
---- external_osl_orig/src/cmake/externalpackages.cmake 2021-06-01 13:44:18 -0600
-+++ external_osl/src/cmake/externalpackages.cmake 2021-06-28 07:44:32 -0600
-@@ -80,6 +80,7 @@
-
-
+diff -Naur OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake
+--- OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake 2022-09-30 17:43:53 -0600
++++ external_osl/src/cmake/externalpackages.cmake 2022-10-15 14:49:26 -0600
+@@ -77,6 +77,7 @@
+
+
checked_find_package (ZLIB REQUIRED) # Needed by several packages
+checked_find_package (PNG REQUIRED) # Needed since OIIO needs it
-
+
# IlmBase & OpenEXR
checked_find_package (OpenEXR REQUIRED
-diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp
---- external_osl_orig/src/liboslcomp/oslcomp.cpp 2021-06-01 13:44:18 -0600
-+++ external_osl/src/liboslcomp/oslcomp.cpp 2021-06-28 09:11:06 -0600
+diff -Naur OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h
+--- OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h 2022-09-30 17:43:53 -0600
++++ external_osl/src/include/OSL/llvm_util.h 2022-10-15 15:37:24 -0600
+@@ -9,6 +9,8 @@
+ #include <unordered_set>
+ #include <vector>
+
++#define OSL_HAS_BLENDER_CLEANUP_FIX
++
+ #ifdef LLVM_NAMESPACE
+ namespace llvm = LLVM_NAMESPACE;
+ #endif
+@@ -455,7 +457,7 @@
+ llvm::BasicBlock* masked_return_block() const;
+
+ bool is_masking_required() const { return m_is_masking_required; }
+-
++ static void Cleanup ();
+ struct ScopedMasking {
+ ScopedMasking() {}
+
+diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp
+--- OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp 2022-09-30 17:43:53 -0600
++++ external_osl/src/liboslcomp/oslcomp.cpp 2022-10-15 14:49:26 -0600
@@ -21,6 +21,13 @@
#if !defined(__STDC_CONSTANT_MACROS)
# define __STDC_CONSTANT_MACROS 1
@@ -76,3 +62,50 @@ diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslc
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
+diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp
+--- OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp 2022-09-30 17:43:53 -0600
++++ external_osl/src/liboslexec/llvm_util.cpp 2022-10-15 15:53:11 -0600
+@@ -116,8 +116,6 @@
+ return { A.data(), size_t(A.size()) };
+ }
+
+-
+-
+ namespace pvt {
+
+ typedef llvm::SectionMemoryManager LLVMMemoryManager;
+@@ -182,6 +180,13 @@
+ ++jit_mem_hold_users;
+ }
+
++void
++LLVM_Util::Cleanup()
++{
++ if (jitmm_hold)
++ jitmm_hold->clear();
++}
++
+
+ LLVM_Util::ScopedJitMemoryUser::~ScopedJitMemoryUser()
+ {
+diff --git a/src/include/OSL/mask.h b/src/include/OSL/mask.h
+index 24197af..b9275f6 100644
+--- a/src/include/OSL/mask.h
++++ b/src/include/OSL/mask.h
+@@ -4,7 +4,6 @@
+
+ #pragma once
+
+-#include <immintrin.h>
+ #include <type_traits>
+
+ #include <OSL/oslconfig.h>
+@@ -23,6 +22,8 @@ using std::countr_zero;
+
+ #elif OSL_INTEL_CLASSIC_COMPILER_VERSION
+
++#include <immintrin.h>
++
+ OSL_FORCEINLINE int popcount(uint32_t x) noexcept { return _mm_popcnt_u32(x);}
+ OSL_FORCEINLINE int popcount(uint64_t x) noexcept { return _mm_popcnt_u64(x); }
+ OSL_FORCEINLINE int countr_zero(uint32_t x) noexcept { return _bit_scan_forward(x); }
diff --git a/build_files/build_environment/patches/python_windows.diff b/build_files/build_environment/patches/python_windows.diff
deleted file mode 100644
index f9c89a90fde..00000000000
--- a/build_files/build_environment/patches/python_windows.diff
+++ /dev/null
@@ -1,24 +0,0 @@
-diff -Naur orig/PCbuild/get_externals.bat Python-3.10.2/PCbuild/get_externals.bat
---- orig/PCbuild/get_externals.bat 2022-01-13 11:52:14 -0700
-+++ Python-3.10.2/PCbuild/get_externals.bat 2022-08-17 11:24:42 -0600
-@@ -51,7 +51,7 @@
- echo.Fetching external libraries...
-
- set libraries=
--set libraries=%libraries% bzip2-1.0.6
-+set libraries=%libraries% bzip2-1.0.8
- if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0
- if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m
- set libraries=%libraries% sqlite-3.35.5.0
- diff -Naur orig/PCbuild/python.props external_python/PCbuild/python.props
---- orig/PCbuild/python.props 2022-01-13 11:52:14 -0700
-+++ external_python/PCbuild/python.props 2022-08-17 11:38:38 -0600
-@@ -58,7 +58,7 @@
- <ExternalsDir Condition="$(ExternalsDir) == ''">$([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`))</ExternalsDir>
- <ExternalsDir Condition="!HasTrailingSlash($(ExternalsDir))">$(ExternalsDir)\</ExternalsDir>
- <sqlite3Dir>$(ExternalsDir)sqlite-3.35.5.0\</sqlite3Dir>
-- <bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir>
-+ <bz2Dir>$(ExternalsDir)bzip2-1.0.8\</bz2Dir>
- <lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir>
- <libffiDir>$(ExternalsDir)libffi-3.3.0\</libffiDir>
- <libffiOutDir>$(ExternalsDir)libffi-3.3.0\$(ArchName)\</libffiOutDir>
diff --git a/build_files/build_environment/patches/sndfile.diff b/build_files/build_environment/patches/sndfile.diff
deleted file mode 100644
index ab43baa78df..00000000000
--- a/build_files/build_environment/patches/sndfile.diff
+++ /dev/null
@@ -1,42 +0,0 @@
---- src/Makefile.in 2017-09-26 01:28:47.000000000 +0300
-+++ src/Makefile.in 2017-09-26 01:19:06.000000000 +0300
-@@ -513,7 +513,7 @@
- libcommon_la_SOURCES = common.c file_io.c command.c pcm.c ulaw.c alaw.c \
- float32.c double64.c ima_adpcm.c ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c \
- interleave.c strings.c dither.c cart.c broadcast.c audio_detect.c \
-- ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \
-+ ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \
- windows.c id3.c $(WIN_VERSION_FILE)
-
-
-@@ -719,10 +719,10 @@
- $(AM_V_CCLD)$(LINK) $(GSM610_libgsm_la_OBJECTS) $(GSM610_libgsm_la_LIBADD) $(LIBS)
-
- libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS)
-+ $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS)
-
- libsndfile.la: $(libsndfile_la_OBJECTS) $(libsndfile_la_DEPENDENCIES) $(EXTRA_libsndfile_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS)
-+ $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS)
-
- clean-checkPROGRAMS:
- @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
-@@ -924,7 +924,7 @@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-dwd.lo `test -f 'dwd.c' || echo '$(srcdir)/'`dwd.c
-
- libsndfile_la-flac.lo: flac.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-flac.Tpo $(DEPDIR)/libsndfile_la-flac.Plo
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='flac.c' object='libsndfile_la-flac.lo' libtool=yes @AMDEPBACKSLASH@
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@@ -1092,7 +1092,7 @@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-rf64.lo `test -f 'rf64.c' || echo '$(srcdir)/'`rf64.c
-
- libsndfile_la-ogg_vorbis.lo: ogg_vorbis.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo $(DEPDIR)/libsndfile_la-ogg_vorbis.Plo
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ogg_vorbis.c' object='libsndfile_la-ogg_vorbis.lo' libtool=yes @AMDEPBACKSLASH@
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
diff --git a/build_files/build_environment/patches/sqlite.diff b/build_files/build_environment/patches/sqlite.diff
deleted file mode 100644
index 80f1384f9cf..00000000000
--- a/build_files/build_environment/patches/sqlite.diff
+++ /dev/null
@@ -1,14 +0,0 @@
-Only in external_sqlite_orig: config.log
-diff -ru external_sqlite_orig/config.sub external_sqlite/config.sub
---- external_sqlite_orig/config.sub 2020-07-10 14:06:42.000000000 +0200
-+++ external_sqlite/config.sub 2020-07-10 14:10:24.000000000 +0200
-@@ -314,6 +314,7 @@
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
-+ | aarch64-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
-Only in external_sqlite: mksourceid
-Only in external_sqlite: sqlite3session.h
diff --git a/build_files/build_environment/patches/ssl.diff b/build_files/build_environment/patches/ssl.diff
new file mode 100644
index 00000000000..7bb4413952c
--- /dev/null
+++ b/build_files/build_environment/patches/ssl.diff
@@ -0,0 +1,10 @@
+--- ./test/v3ext.c 2022-07-05 11:08:33.000000000 +0200
++++ ./test/v3ext.c 2022-10-18 13:58:05.000000000 +0200
+@@ -8,6 +8,7 @@
+ */
+
+ #include <stdio.h>
++#include <string.h>
+ #include <openssl/x509.h>
+ #include <openssl/x509v3.h>
+ #include <openssl/pem.h>
diff --git a/build_files/cmake/Modules/FindOSL.cmake b/build_files/cmake/Modules/FindOSL.cmake
index ab5de53d3c9..a8d8344ae66 100644
--- a/build_files/cmake/Modules/FindOSL.cmake
+++ b/build_files/cmake/Modules/FindOSL.cmake
@@ -20,6 +20,7 @@ IF(NOT OSL_ROOT_DIR AND NOT $ENV{OSL_ROOT_DIR} STREQUAL "")
ENDIF()
SET(_osl_FIND_COMPONENTS
+ oslnoise
oslcomp
oslexec
oslquery
@@ -39,7 +40,6 @@ FIND_PATH(OSL_INCLUDE_DIR
include
)
-SET(_osl_LIBRARIES)
FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
@@ -51,9 +51,20 @@ FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
PATH_SUFFIXES
lib64 lib
)
- LIST(APPEND _osl_LIBRARIES "${OSL_${UPPERCOMPONENT}_LIBRARY}")
ENDFOREACH()
+# Note linking order matters, and oslnoise existence depends on version.
+SET(_osl_LIBRARIES ${OSL_OSLCOMP_LIBRARY})
+IF(APPLE)
+ list(APPEND _osl_LIBRARIES -force_load ${OSL_OSLEXEC_LIBRARY})
+ELSE()
+ list(APPEND _osl_LIBRARIES ${OSL_OSLEXEC_LIBRARY})
+ENDIF()
+list(APPEND _osl_LIBRARIES ${OSL_OSLQUERY_LIBRARY})
+IF(OSL_OSLNOISE_LIBRARY)
+ list(APPEND _osl_LIBRARIES ${OSL_OSLNOISE_LIBRARY})
+ENDIF()
+
FIND_PROGRAM(OSL_COMPILER oslc
HINTS ${_osl_SEARCH_DIRS}
PATH_SUFFIXES bin)
diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake
index 37a2cddf3de..66d3b435c46 100644
--- a/build_files/cmake/Modules/FindOpenSubdiv.cmake
+++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake
@@ -71,21 +71,6 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenSubdiv DEFAULT_MSG
IF(OPENSUBDIV_FOUND)
SET(OPENSUBDIV_LIBRARIES ${_opensubdiv_LIBRARIES})
SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR})
-
- # Find available compute controllers.
-
- FIND_PACKAGE(OpenMP)
- IF(OPENMP_FOUND)
- SET(OPENSUBDIV_HAS_OPENMP TRUE)
- ELSE()
- SET(OPENSUBDIV_HAS_OPENMP FALSE)
- ENDIF()
-
- OPENSUBDIV_CHECK_CONTROLLER("tbbEvaluator.h" OPENSUBDIV_HAS_TBB)
- OPENSUBDIV_CHECK_CONTROLLER("clEvaluator.h" OPENSUBDIV_HAS_OPENCL)
- OPENSUBDIV_CHECK_CONTROLLER("cudaEvaluator.h" OPENSUBDIV_HAS_CUDA)
- OPENSUBDIV_CHECK_CONTROLLER("glXFBEvaluator.h" OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
- OPENSUBDIV_CHECK_CONTROLLER("glComputeEvaluator.h" OPENSUBDIV_HAS_GLSL_COMPUTE)
ENDIF()
MARK_AS_ADVANCED(
diff --git a/build_files/cmake/Modules/FindSYCL.cmake b/build_files/cmake/Modules/FindSYCL.cmake
index 139ebad46b1..1ccbee179fb 100644
--- a/build_files/cmake/Modules/FindSYCL.cmake
+++ b/build_files/cmake/Modules/FindSYCL.cmake
@@ -30,6 +30,7 @@ SET(_sycl_search_dirs
# dpcpp binary.
FIND_PROGRAM(SYCL_COMPILER
NAMES
+ icpx
dpcpp
clang++
HINTS
@@ -45,6 +46,7 @@ FIND_PROGRAM(SYCL_COMPILER
if(NOT SYCL_COMPILER)
FIND_PROGRAM(SYCL_COMPILER
NAMES
+ icpx
dpcpp
HINTS
${_sycl_search_dirs}
@@ -55,6 +57,8 @@ endif()
FIND_LIBRARY(SYCL_LIBRARY
NAMES
+ sycl7
+ sycl6
sycl
HINTS
${_sycl_search_dirs}
@@ -63,34 +67,51 @@ FIND_LIBRARY(SYCL_LIBRARY
)
if(WIN32)
- string(REPLACE ".lib" "d.lib" SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY})
- set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY_DEBUG} CACHE FILEPATH "Path to SYCL debug library")
-else()
- set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY} CACHE FILEPATH "Path to SYCL debug library")
+ FIND_LIBRARY(SYCL_LIBRARY_DEBUG
+ NAMES
+ sycl7d
+ sycl6d
+ sycld
+ HINTS
+ ${_sycl_search_dirs}
+ PATH_SUFFIXES
+ lib64 lib
+ )
endif()
FIND_PATH(SYCL_INCLUDE_DIR
NAMES
- CL/sycl.hpp
+ sycl/sycl.hpp
HINTS
${_sycl_search_dirs}
PATH_SUFFIXES
include
- include/sycl
)
+IF(EXISTS "${SYCL_INCLUDE_DIR}/sycl/version.hpp")
+ FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_major_version REGEX "^#define __LIBSYCL_MAJOR_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _libsycl_major_version ${_libsycl_major_version})
+ FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_minor_version REGEX "^#define __LIBSYCL_MINOR_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _libsycl_minor_version ${_libsycl_minor_version})
+ FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_patch_version REGEX "^#define __LIBSYCL_PATCH_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _libsycl_patch_version ${_libsycl_patch_version})
+
+ SET(SYCL_VERSION "${_libsycl_major_version}.${_libsycl_minor_version}.${_libsycl_patch_version}")
+ENDIF()
+
INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL
+ REQUIRED_VARS SYCL_LIBRARY SYCL_INCLUDE_DIR
+ VERSION_VAR SYCL_VERSION
+)
IF(SYCL_FOUND)
- get_filename_component(_SYCL_INCLUDE_PARENT_DIR ${SYCL_INCLUDE_DIR} DIRECTORY)
- SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${_SYCL_INCLUDE_PARENT_DIR})
+ SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl)
ELSE()
SET(SYCL_SYCL_FOUND FALSE)
ENDIF()
MARK_AS_ADVANCED(
_SYCL_INCLUDE_PARENT_DIR
- SYCL_LIBRARY_DEBUG
)
diff --git a/build_files/cmake/config/blender_developer.cmake b/build_files/cmake/config/blender_developer.cmake
index 1f1a100d958..ebc5727a79c 100644
--- a/build_files/cmake/config/blender_developer.cmake
+++ b/build_files/cmake/config/blender_developer.cmake
@@ -8,7 +8,11 @@
set(WITH_ASSERT_ABORT ON CACHE BOOL "" FORCE)
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
-set(WITH_COMPILER_ASAN ON CACHE BOOL "" FORCE)
+# Sadly ASAN is more often broken than working with MSVC do not enable it in the
+# developer profile for now.
+if(NOT WIN32)
+ set(WITH_COMPILER_ASAN ON CACHE BOOL "" FORCE)
+endif()
set(WITH_CYCLES_NATIVE_ONLY ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE)
set(WITH_GTESTS ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 958eb17522b..95304bd64c7 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -66,13 +66,11 @@ set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
if(APPLE)
set(WITH_COREAUDIO ON CACHE BOOL "" FORCE)
endif()
-if(NOT WIN32)
- set(WITH_JACK ON CACHE BOOL "" FORCE)
-endif()
if(WIN32)
set(WITH_WASAPI ON CACHE BOOL "" FORCE)
endif()
if(UNIX AND NOT APPLE)
+ set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index d5f5230862b..74bbcb223c3 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -67,13 +67,11 @@ if(APPLE)
set(WITH_COREAUDIO ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_METAL ON CACHE BOOL "" FORCE)
endif()
-if(NOT WIN32)
- set(WITH_JACK ON CACHE BOOL "" FORCE)
-endif()
if(WIN32)
set(WITH_WASAPI ON CACHE BOOL "" FORCE)
endif()
if(UNIX AND NOT APPLE)
+ set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 3acea19079b..8af45690862 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -1205,11 +1205,27 @@ 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})'")
+ if(WITH_STRICT_BUILD_OPTIONS)
+ message(SEND_ERROR "${_dependency} disabled but required by ${_setting}")
+ else()
+ message(STATUS "${_dependency} is disabled, setting ${_setting}=${_val}")
+ endif()
set(${_setting} ${_val})
endif()
endmacro()
+macro(set_and_warn_library_found
+ _library_name _library_found _setting)
+ if(NOT ${${_library_found}} AND ${${_setting}})
+ if(WITH_STRICT_BUILD_OPTIONS)
+ message(SEND_ERROR "${_library_name} required but not found")
+ else()
+ message(STATUS "${_library_name} not found, disabling ${_setting}")
+ endif()
+ set(${_setting} OFF)
+ endif()
+endmacro()
+
macro(without_system_libs_begin)
set(CMAKE_IGNORE_PATH "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES};${CMAKE_SYSTEM_INCLUDE_PATH};${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES};${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}")
endmacro()
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 04f5a312030..c5fe3c908de 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -43,22 +43,18 @@ find_package(BZip2 REQUIRED)
list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES})
if(WITH_OPENAL)
- find_package(OpenAL)
- if(NOT OPENAL_FOUND)
- message(WARNING "OpenAL not found, disabling WITH_OPENAL")
- set(WITH_OPENAL OFF)
- endif()
+ find_package(OpenAL REQUIRED)
endif()
if(WITH_JACK)
find_library(JACK_FRAMEWORK
NAMES jackmp
)
- if(NOT JACK_FRAMEWORK)
- message(STATUS "JACK not found, disabling WITH_JACK")
- set(WITH_JACK OFF)
- else()
+
+ if(JACK_FRAMEWORK)
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
+ else()
+ set_and_warn_library_found("JACK" JACK_FRAMEWORK WITH_JACK)
endif()
endif()
@@ -101,11 +97,7 @@ if(WITH_ALEMBIC)
endif()
if(WITH_USD)
- find_package(USD)
- if(NOT USD_FOUND)
- message(STATUS "USD not found, disabling WITH_USD")
- set(WITH_USD OFF)
- endif()
+ find_package(USD REQUIRED)
endif()
if(WITH_OPENSUBDIV)
@@ -227,20 +219,12 @@ find_package(JPEG REQUIRED)
if(WITH_IMAGE_TIFF)
set(TIFF_ROOT ${LIBDIR}/tiff)
- find_package(TIFF)
- if(NOT TIFF_FOUND)
- message(WARNING "TIFF not found, disabling WITH_IMAGE_TIFF")
- set(WITH_IMAGE_TIFF OFF)
- endif()
+ find_package(TIFF REQUIRED)
endif()
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
- find_package(WebP)
- if(NOT WEBP_FOUND)
- message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP")
- set(WITH_IMAGE_WEBP OFF)
- endif()
+ find_package(WebP REQUIRED)
endif()
if(WITH_BOOST)
@@ -270,11 +254,7 @@ if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG)
endif()
if(WITH_PUGIXML)
- find_package(PugiXML)
- if(NOT PUGIXML_FOUND)
- message(WARNING "PugiXML not found, disabling WITH_PUGIXML")
- set(WITH_PUGIXML OFF)
- endif()
+ find_package(PugiXML REQUIRED)
endif()
if(WITH_OPENIMAGEIO)
@@ -292,12 +272,7 @@ if(WITH_OPENIMAGEIO)
endif()
if(WITH_OPENCOLORIO)
- find_package(OpenColorIO 2.0.0)
-
- if(NOT OPENCOLORIO_FOUND)
- set(WITH_OPENCOLORIO OFF)
- message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO")
- endif()
+ find_package(OpenColorIO 2.0.0 REQUIRED)
endif()
if(WITH_OPENVDB)
@@ -331,23 +306,7 @@ if(WITH_LLVM)
endif()
if(WITH_CYCLES AND WITH_CYCLES_OSL)
- set(CYCLES_OSL ${LIBDIR}/osl)
-
- find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
- find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
- find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
- # WARNING! depends on correct order of OSL libs linking
- list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
- find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
- find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- find_path(OSL_SHADER_DIR NAMES stdosl.h PATHS ${CYCLES_OSL}/share/OSL/shaders)
-
- if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR)
- set(OSL_FOUND TRUE)
- else()
- message(WARNING "OSL not found, disabling WITH_CYCLES_OSL")
- set(WITH_CYCLES_OSL OFF)
- endif()
+ find_package(OSL REQUIRED)
endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
@@ -365,28 +324,15 @@ if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
endif()
if(WITH_OPENIMAGEDENOISE)
- find_package(OpenImageDenoise)
-
- if(NOT OPENIMAGEDENOISE_FOUND)
- set(WITH_OPENIMAGEDENOISE OFF)
- message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE")
- endif()
+ find_package(OpenImageDenoise REQUIRED)
endif()
if(WITH_TBB)
- find_package(TBB)
- if(NOT TBB_FOUND)
- message(WARNING "TBB not found, disabling WITH_TBB")
- set(WITH_TBB OFF)
- endif()
+ find_package(TBB REQUIRED)
endif()
if(WITH_POTRACE)
- find_package(Potrace)
- if(NOT POTRACE_FOUND)
- message(WARNING "potrace not found, disabling WITH_POTRACE")
- set(WITH_POTRACE OFF)
- endif()
+ find_package(Potrace REQUIRED)
endif()
# CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags.
@@ -406,27 +352,15 @@ if(WITH_OPENMP)
endif()
if(WITH_XR_OPENXR)
- find_package(XR_OpenXR_SDK)
- if(NOT XR_OPENXR_SDK_FOUND)
- message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR")
- set(WITH_XR_OPENXR OFF)
- endif()
+ find_package(XR_OpenXR_SDK REQUIRED)
endif()
if(WITH_GMP)
- find_package(GMP)
- if(NOT GMP_FOUND)
- message(WARNING "GMP not found, disabling WITH_GMP")
- set(WITH_GMP OFF)
- endif()
+ find_package(GMP REQUIRED)
endif()
if(WITH_HARU)
- find_package(Haru)
- if(NOT HARU_FOUND)
- message(WARNING "Haru not found, disabling WITH_HARU")
- set(WITH_HARU OFF)
- endif()
+ find_package(Haru REQUIRED)
endif()
if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 695ea3d773e..343ed6d8ef4 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -174,32 +174,24 @@ endif()
if(WITH_IMAGE_OPENEXR)
find_package_wrapper(OpenEXR) # our own module
- if(NOT OPENEXR_FOUND)
- set(WITH_IMAGE_OPENEXR OFF)
- endif()
+ set_and_warn_library_found("OpenEXR" OPENEXR_FOUND WITH_IMAGE_OPENEXR)
endif()
if(WITH_IMAGE_OPENJPEG)
find_package_wrapper(OpenJPEG)
- if(NOT OPENJPEG_FOUND)
- set(WITH_IMAGE_OPENJPEG OFF)
- endif()
+ set_and_warn_library_found("OpenJPEG" OPENJPEG_FOUND WITH_IMAGE_OPENJPEG)
endif()
if(WITH_IMAGE_TIFF)
# XXX Linking errors with debian static tiff :/
# find_package_wrapper(TIFF)
find_package(TIFF)
- if(NOT TIFF_FOUND)
- set(WITH_IMAGE_TIFF OFF)
- endif()
+ set_and_warn_library_found("TIFF" TIFF_FOUND WITH_IMAGE_TIFF)
endif()
if(WITH_OPENAL)
find_package_wrapper(OpenAL)
- if(NOT OPENAL_FOUND)
- set(WITH_OPENAL OFF)
- endif()
+ set_and_warn_library_found("OpenAL" OPENAL_FOUND WITH_OPENAL)
endif()
if(WITH_SDL)
@@ -221,18 +213,14 @@ if(WITH_SDL)
SDL_LIBRARY
)
# unset(SDLMAIN_LIBRARY CACHE)
- if(NOT SDL_FOUND)
- set(WITH_SDL OFF)
- endif()
+ set_and_warn_library_found("SDL" SDL_FOUND WITH_SDL)
endif()
endif()
# Codecs
if(WITH_CODEC_SNDFILE)
find_package_wrapper(SndFile)
- if(NOT SNDFILE_FOUND)
- set(WITH_CODEC_SNDFILE OFF)
- endif()
+ set_and_warn_library_found("libsndfile" SNDFILE_FOUND WITH_CODEC_SNDFILE)
endif()
if(WITH_CODEC_FFMPEG)
@@ -260,17 +248,12 @@ if(WITH_CODEC_FFMPEG)
endif()
find_package(FFmpeg)
- if(NOT FFMPEG_FOUND)
- set(WITH_CODEC_FFMPEG OFF)
- message(STATUS "FFmpeg not found, disabling it")
- endif()
+ set_and_warn_library_found("FFmpeg" FFMPEG_FOUND WITH_CODEC_FFMPEG)
endif()
if(WITH_FFTW3)
find_package_wrapper(Fftw3)
- if(NOT FFTW3_FOUND)
- set(WITH_FFTW3 OFF)
- endif()
+ set_and_warn_library_found("fftw3" FFTW3_FOUND WITH_FFTW3)
endif()
if(WITH_OPENCOLLADA)
@@ -285,25 +268,23 @@ if(WITH_OPENCOLLADA)
endif()
find_package_wrapper(XML2)
else()
- set(WITH_OPENCOLLADA OFF)
+ set_and_warn_library_found("OpenCollada" OPENCOLLADA_FOUND WITH_OPENCOLLADA)
endif()
endif()
if(WITH_MEM_JEMALLOC)
find_package_wrapper(JeMalloc)
- if(NOT JEMALLOC_FOUND)
- set(WITH_MEM_JEMALLOC OFF)
- endif()
+ set_and_warn_library_found("JeMalloc" JEMALLOC_FOUND WITH_MEM_JEMALLOC)
endif()
if(WITH_INPUT_NDOF)
find_package_wrapper(Spacenav)
+ set_and_warn_library_found("SpaceNav" SPACENAV_FOUND WITH_INPUT_NDOF)
+
if(SPACENAV_FOUND)
# use generic names within blenders buildsystem.
set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS})
set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES})
- else()
- set(WITH_INPUT_NDOF OFF)
endif()
endif()
@@ -313,6 +294,8 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
set(OSL_ROOT ${CYCLES_OSL})
endif()
find_package_wrapper(OSL)
+ set_and_warn_library_found("OSL" OSL_FOUND WITH_CYCLES_OSL)
+
if(OSL_FOUND)
if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")
# Note: --whole-archive is needed to force loading of all symbols in liboslexec,
@@ -323,9 +306,6 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
-Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY}
)
endif()
- else()
- message(STATUS "OSL not found, disabling it from Cycles")
- set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -341,35 +321,27 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
endif()
file(GLOB _sycl_runtime_libraries
${SYCL_ROOT_DIR}/lib/libsycl.so
- ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9]
- ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9].[0-9].[0-9]-[0-9]
+ ${SYCL_ROOT_DIR}/lib/libsycl.so.*
${SYCL_ROOT_DIR}/lib/libpi_level_zero.so
)
+ list(FILTER _sycl_runtime_libraries EXCLUDE REGEX ".*\.py")
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries})
unset(_sycl_runtime_libraries)
endif()
if(WITH_OPENVDB)
find_package_wrapper(OpenVDB)
- find_package_wrapper(Blosc)
-
- if(NOT OPENVDB_FOUND)
- set(WITH_OPENVDB OFF)
- set(WITH_OPENVDB_BLOSC OFF)
- message(STATUS "OpenVDB not found, disabling it")
- elseif(NOT BLOSC_FOUND)
- set(WITH_OPENVDB_BLOSC OFF)
- message(STATUS "Blosc not found, disabling it for OpenVBD")
+ set_and_warn_library_found("OpenVDB" OPENVDB_FOUND WITH_OPENVDB)
+
+ if(OPENVDB_FOUND)
+ find_package_wrapper(Blosc)
+ set_and_warn_library_found("Blosc" BLOSC_FOUND WITH_OPENVDB_BLOSC)
endif()
endif()
if(WITH_NANOVDB)
find_package_wrapper(NanoVDB)
-
- if(NOT NANOVDB_FOUND)
- set(WITH_NANOVDB OFF)
- message(STATUS "NanoVDB not found, disabling it")
- endif()
+ set_and_warn_library_found("NanoVDB" NANOVDB_FOUND WITH_NANOVDB)
endif()
if(WITH_CPU_SIMD AND SUPPORT_NEON_BUILD)
@@ -378,18 +350,12 @@ endif()
if(WITH_ALEMBIC)
find_package_wrapper(Alembic)
-
- if(NOT ALEMBIC_FOUND)
- set(WITH_ALEMBIC OFF)
- endif()
+ set_and_warn_library_found("Alembic" ALEMBIC_FOUND WITH_ALEMBIC)
endif()
if(WITH_USD)
find_package_wrapper(USD)
-
- if(NOT USD_FOUND)
- set(WITH_USD OFF)
- endif()
+ set_and_warn_library_found("USD" USD_FOUND WITH_USD)
endif()
if(WITH_BOOST)
@@ -442,20 +408,13 @@ endif()
if(WITH_PUGIXML)
find_package_wrapper(PugiXML)
-
- if(NOT PUGIXML_FOUND)
- set(WITH_PUGIXML OFF)
- message(STATUS "PugiXML not found, disabling WITH_PUGIXML")
- endif()
+ set_and_warn_library_found("PugiXML" PUGIXML_FOUND WITH_PUGIXML)
endif()
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
find_package_wrapper(WebP)
- if(NOT WEBP_FOUND)
- set(WITH_IMAGE_WEBP OFF)
- message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP")
- endif()
+ set_and_warn_library_found("WebP" WEBP_FOUND WITH_IMAGE_WEBP)
endif()
if(WITH_OPENIMAGEIO)
@@ -480,10 +439,7 @@ if(WITH_OPENIMAGEIO)
list(APPEND OPENIMAGEIO_LIBRARIES "${WEBP_LIBRARIES}")
endif()
- if(NOT OPENIMAGEIO_FOUND)
- set(WITH_OPENIMAGEIO OFF)
- message(STATUS "OpenImageIO not found, disabling WITH_CYCLES")
- endif()
+ set_and_warn_library_found("OPENIMAGEIO" OPENIMAGEIO_FOUND WITH_OPENIMAGEIO)
endif()
if(WITH_OPENCOLORIO)
@@ -493,10 +449,7 @@ if(WITH_OPENCOLORIO)
set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
set(OPENCOLORIO_DEFINITIONS)
- if(NOT OPENCOLORIO_FOUND)
- set(WITH_OPENCOLORIO OFF)
- message(STATUS "OpenColorIO not found")
- endif()
+ set_and_warn_library_found("OpenColorIO" OPENCOLORIO_FOUND WITH_OPENCOLORIO)
endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
@@ -505,11 +458,7 @@ endif()
if(WITH_OPENIMAGEDENOISE)
find_package_wrapper(OpenImageDenoise)
-
- if(NOT OPENIMAGEDENOISE_FOUND)
- set(WITH_OPENIMAGEDENOISE OFF)
- message(STATUS "OpenImageDenoise not found")
- endif()
+ set_and_warn_library_found("OpenImageDenoise" OPENIMAGEDENOISE_FOUND WITH_OPENIMAGEDENOISE)
endif()
if(WITH_LLVM)
@@ -518,24 +467,19 @@ if(WITH_LLVM)
endif()
find_package_wrapper(LLVM)
- if(WITH_CLANG)
- find_package_wrapper(Clang)
- endif()
- # Symbol conflicts with same UTF library used by OpenCollada
- if(EXISTS ${LIBDIR})
- if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0"))
- list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY})
+ set_and_warn_library_found("LLVM" LLVM_FOUND WITH_LLVM)
+
+ if(LLVM_FOUND)
+ if(WITH_CLANG)
+ find_package_wrapper(Clang)
+ set_and_warn_library_found("Clang" CLANG_FOUND WITH_CLANG)
endif()
- endif()
- if(NOT LLVM_FOUND)
- set(WITH_LLVM OFF)
- set(WITH_CLANG OFF)
- message(STATUS "LLVM not found")
- else()
- if(NOT CLANG_FOUND)
- set(WITH_CLANG OFF)
- message(STATUS "Clang not found")
+ # Symbol conflicts with same UTF library used by OpenCollada
+ if(EXISTS ${LIBDIR})
+ if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0"))
+ list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY})
+ endif()
endif()
endif()
endif()
@@ -546,50 +490,32 @@ if(WITH_OPENSUBDIV)
set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES})
set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere
- if(NOT OPENSUBDIV_FOUND)
- set(WITH_OPENSUBDIV OFF)
- message(STATUS "OpenSubdiv not found")
- endif()
+ set_and_warn_library_found("OpenSubdiv" OPENSUBDIV_FOUND WITH_OPENSUBDIV)
endif()
if(WITH_TBB)
find_package_wrapper(TBB)
- if(NOT TBB_FOUND)
- message(WARNING "TBB not found, disabling WITH_TBB")
- set(WITH_TBB OFF)
- endif()
+ set_and_warn_library_found("TBB" TBB_FOUND WITH_TBB)
endif()
if(WITH_XR_OPENXR)
find_package(XR_OpenXR_SDK)
- if(NOT XR_OPENXR_SDK_FOUND)
- message(WARNING "OpenXR-SDK not found, disabling WITH_XR_OPENXR")
- set(WITH_XR_OPENXR OFF)
- endif()
+ set_and_warn_library_found("OpenXR-SDK" XR_OPENXR_SDK_FOUND WITH_XR_OPENXR)
endif()
if(WITH_GMP)
find_package_wrapper(GMP)
- if(NOT GMP_FOUND)
- message(WARNING "GMP not found, disabling WITH_GMP")
- set(WITH_GMP OFF)
- endif()
+ set_and_warn_library_found("GMP" GMP_FOUND WITH_GMP)
endif()
if(WITH_POTRACE)
find_package_wrapper(Potrace)
- if(NOT POTRACE_FOUND)
- message(WARNING "potrace not found, disabling WITH_POTRACE")
- set(WITH_POTRACE OFF)
- endif()
+ set_and_warn_library_found("Potrace" POTRACE_FOUND WITH_POTRACE)
endif()
if(WITH_HARU)
find_package_wrapper(Haru)
- if(NOT HARU_FOUND)
- message(WARNING "Haru not found, disabling WITH_HARU")
- set(WITH_HARU OFF)
- endif()
+ set_and_warn_library_found("Haru" HARU_FOUND WITH_HARU)
endif()
if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
@@ -676,25 +602,20 @@ endif()
# Jack is intended to use the system library.
if(WITH_JACK)
find_package_wrapper(Jack)
- if(NOT JACK_FOUND)
- set(WITH_JACK OFF)
- endif()
+ set_and_warn_library_found("JACK" JACK_FOUND WITH_JACK)
endif()
# Pulse is intended to use the system library.
if(WITH_PULSEAUDIO)
find_package_wrapper(Pulse)
- if(NOT PULSE_FOUND)
- set(WITH_PULSEAUDIO OFF)
- endif()
+ set_and_warn_library_found("PulseAudio" PULSE_FOUND WITH_PULSEAUDIO)
endif()
# Audio IO
if(WITH_SYSTEM_AUDASPACE)
find_package_wrapper(Audaspace)
- if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND)
- message(FATAL_ERROR "Audaspace external library not found!")
- endif()
+ set(AUDASPACE_FOUND ${AUDASPACE_FOUND} AND ${AUDASPACE_C_FOUND})
+ set_and_warn_library_found("External Audaspace" AUDASPACE_FOUND WITH_SYSTEM_AUDASPACE)
endif()
if(WITH_GHOST_WAYLAND)
@@ -739,31 +660,14 @@ if(WITH_GHOST_WAYLAND)
set(wayland-scanner_FOUND ON)
set(wayland-cursor_FOUND ON)
endif()
+ mark_as_advanced(WAYLAND_PROTOCOLS_DIR)
- if (NOT wayland-client_FOUND)
- message(STATUS "wayland-client not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-egl_FOUND)
- message(STATUS "wayland-egl not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-scanner_FOUND)
- message(STATUS "wayland-scanner not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-cursor_FOUND)
- message(STATUS "wayland-cursor not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-protocols_FOUND)
- message(STATUS "wayland-protocols not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT xkbcommon_FOUND)
- message(STATUS "xkbcommon not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
+ set_and_warn_library_found("wayland-client" wayland-client_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-egl" wayland-egl_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-scanner" wayland-scanner_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-cursor" wayland-cursor_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-protocols" wayland-protocols_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("xkbcommon" xkbcommon_FOUND WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND_DBUS)
@@ -791,6 +695,7 @@ if(WITH_GHOST_WAYLAND)
else()
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
endif()
+ mark_as_advanced(WAYLAND_SCANNER)
# When using dynamic loading, headers generated
# from older versions of `wayland-scanner` aren't compatible.
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index cfb8bf34b81..3818076634a 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -326,18 +326,10 @@ if(WITH_FFTW3)
endif()
if(WITH_IMAGE_WEBP)
- windows_find_package(WebP)
- if(NOT WEBP_FOUND)
- if(EXISTS ${LIBDIR}/webp)
- set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
- set(WEBP_ROOT_DIR ${LIBDIR}/webp)
- set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
- set(WEBP_FOUND ON)
- else()
- message(STATUS "WITH_IMAGE_WEBP is ON but WEBP libraries are not found, setting WITH_IMAGE_WEBP=OFF")
- set(WITH_IMAGE_WEBP OFF)
- endif()
- endif()
+ set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
+ set(WEBP_ROOT_DIR ${LIBDIR}/webp)
+ set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
+ set(WEBP_FOUND ON)
endif()
if(WITH_OPENCOLLADA)
@@ -358,7 +350,6 @@ if(WITH_OPENCOLLADA)
optimized ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib
optimized ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib
optimized ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib
- optimized ${OPENCOLLADA}/lib/opencollada/xml.lib
optimized ${OPENCOLLADA}/lib/opencollada/buffer.lib
optimized ${OPENCOLLADA}/lib/opencollada/ftoa.lib
@@ -368,10 +359,14 @@ if(WITH_OPENCOLLADA)
debug ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter_d.lib
debug ${OPENCOLLADA}/lib/opencollada/MathMLSolver_d.lib
debug ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser_d.lib
- debug ${OPENCOLLADA}/lib/opencollada/xml_d.lib
debug ${OPENCOLLADA}/lib/opencollada/buffer_d.lib
debug ${OPENCOLLADA}/lib/opencollada/ftoa_d.lib
)
+ if(EXISTS ${LIBDIR}/xml2/lib/libxml2s.lib) # 3.4 libraries
+ list(APPEND OPENCOLLADA_LIBRARIES ${LIBDIR}/xml2/lib/libxml2s.lib)
+ else()
+ list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/xml.lib)
+ endif()
list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib)
@@ -679,11 +674,11 @@ endif()
if(WITH_IMAGE_OPENJPEG)
set(OPENJPEG ${LIBDIR}/openjpeg)
- set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4)
+ set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.5)
if(NOT EXISTS "${OPENJPEG_INCLUDE_DIRS}")
- # when not found, could be an older lib folder with openjpeg 2.3
- # to ease the transition period, fall back if 2.4 is not found.
- set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.3)
+ # when not found, could be an older lib folder with openjpeg 2.4
+ # to ease the transition period, fall back if 2.5 is not found.
+ set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4)
endif()
set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/openjp2.lib)
endif()
@@ -700,12 +695,6 @@ if(WITH_OPENSUBDIV)
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
)
- set(OPENSUBDIV_HAS_OPENMP TRUE)
- set(OPENSUBDIV_HAS_TBB FALSE)
- set(OPENSUBDIV_HAS_OPENCL TRUE)
- set(OPENSUBDIV_HAS_CUDA FALSE)
- set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
- set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
endif()
endif()
@@ -773,9 +762,11 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
+ find_library(OSL_LIB_NOISE NAMES oslnoise PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib)
+ find_library(OSL_LIB_NOISE_DEBUG NAMES oslnoise_d PATHS ${CYCLES_OSL}/lib)
list(APPEND OSL_LIBRARIES
optimized ${OSL_LIB_COMP}
optimized ${OSL_LIB_EXEC}
@@ -785,15 +776,14 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
debug ${OSL_LIB_QUERY_DEBUG}
${PUGIXML_LIBRARIES}
)
+ if(OSL_LIB_NOISE)
+ list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_NOISE})
+ endif()
+ if(OSL_LIB_NOISE_DEBUG)
+ list(APPEND OSL_LIBRARIES debug ${OSL_LIB_NOISE_DEBUG})
+ endif()
find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
-
- if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
- set(OSL_FOUND TRUE)
- else()
- message(STATUS "OSL not found")
- set(WITH_CYCLES_OSL OFF)
- endif()
endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
@@ -893,21 +883,16 @@ if(WINDOWS_PYTHON_DEBUG)
endif()
if(WITH_XR_OPENXR)
- if(EXISTS ${LIBDIR}/xr_openxr_sdk)
- set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk)
- set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib)
- set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include)
- # This is the old name of this library, it is checked to
- # support the transition between the old and new lib versions
- # this can be removed after the next lib update.
- if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
- set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
- else()
- set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib)
- endif()
+ set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk)
+ set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib)
+ set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include)
+ # This is the old name of this library, it is checked to
+ # support the transition between the old and new lib versions
+ # this can be removed after the next lib update.
+ if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
+ set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
else()
- message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR")
- set(WITH_XR_OPENXR OFF)
+ set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib)
endif()
endif()
@@ -925,15 +910,10 @@ if(WITH_POTRACE)
endif()
if(WITH_HARU)
- if(EXISTS ${LIBDIR}/haru)
- set(HARU_FOUND ON)
- set(HARU_ROOT_DIR ${LIBDIR}/haru)
- set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include)
- set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib)
- else()
- message(WARNING "Haru was not found, disabling WITH_HARU")
- set(WITH_HARU OFF)
- endif()
+ set(HARU_FOUND ON)
+ set(HARU_ROOT_DIR ${LIBDIR}/haru)
+ set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include)
+ set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib)
endif()
if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
diff --git a/build_files/config/pipeline_config.yaml b/build_files/config/pipeline_config.yaml
index 82cd009ea95..3359f89c41e 100644
--- a/build_files/config/pipeline_config.yaml
+++ b/build_files/config/pipeline_config.yaml
@@ -58,6 +58,8 @@ buildbot:
version: '5.2.21440'
optix:
version: '7.3.0'
+ ocloc:
+ version: '101.3430'
cmake:
default:
version: any
diff --git a/build_files/utils/make_bpy_wheel.py b/build_files/utils/make_bpy_wheel.py
index ba1d0f21937..81d267c6e10 100755
--- a/build_files/utils/make_bpy_wheel.py
+++ b/build_files/utils/make_bpy_wheel.py
@@ -208,12 +208,15 @@ def main() -> None:
dist_dir = os.path.join(install_dir, "dist")
for f in os.listdir(dist_dir):
if f.endswith(".whl"):
- # No apparent way to override this ABI version with setuptools, so rename.
- sys_py = "cp%d%d" % (sys.version_info.major, sys.version_info.minor)
- sys_py_abi = sys_py + sys.abiflags
blender_py = "cp%d%d" % (python_version_number[0], python_version_number[1])
- renamed_f = f.replace(sys_py_abi, blender_py).replace(sys_py, blender_py)
+ # No apparent way to override this ABI version with setuptools, so rename.
+ sys_py = "cp%d%d" % (sys.version_info.major, sys.version_info.minor)
+ if hasattr(sys, "abiflags"):
+ sys_py_abi = sys_py + sys.abiflags
+ renamed_f = f.replace(sys_py_abi, blender_py).replace(sys_py, blender_py)
+ else:
+ renamed_f = f.replace(sys_py, blender_py)
os.rename(os.path.join(dist_dir, f), os.path.join(output_dir, renamed_f))
diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py
index 254cccda301..a0b61b18e60 100755
--- a/build_files/utils/make_update.py
+++ b/build_files/utils/make_update.py
@@ -18,8 +18,13 @@ import sys
import make_utils
from make_utils import call, check_output
+from typing import (
+ List,
+ Optional,
+)
-def print_stage(text):
+
+def print_stage(text: str) -> None:
print("")
print(text)
print("")
@@ -27,7 +32,7 @@ def print_stage(text):
# Parse arguments
-def parse_arguments():
+def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--no-libraries", action="store_true")
parser.add_argument("--no-blender", action="store_true")
@@ -40,13 +45,13 @@ def parse_arguments():
return parser.parse_args()
-def get_blender_git_root():
+def get_blender_git_root() -> str:
return check_output([args.git_command, "rev-parse", "--show-toplevel"])
# Setup for precompiled libraries and tests from svn.
-def svn_update(args, release_version):
+def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None:
svn_non_interactive = [args.svn_command, '--non-interactive']
lib_dirpath = os.path.join(get_blender_git_root(), '..', 'lib')
@@ -99,42 +104,42 @@ def svn_update(args, release_version):
call(svn_non_interactive + ["checkout", svn_url_tests, lib_tests_dirpath])
# Update precompiled libraries and tests
- print_stage("Updating Precompiled Libraries and Tests")
-
- if os.path.isdir(lib_dirpath):
- for dirname in os.listdir(lib_dirpath):
- dirpath = os.path.join(lib_dirpath, dirname)
-
- if dirname == ".svn":
- # Cleanup must be run from svn root directory if it exists.
- if not make_utils.command_missing(args.svn_command):
- call(svn_non_interactive + ["cleanup", lib_dirpath])
- continue
- elif dirname.startswith("."):
- # Temporary paths such as ".mypy_cache" will report a warning, skip hidden directories.
- continue
-
- svn_dirpath = os.path.join(dirpath, ".svn")
- svn_root_dirpath = os.path.join(lib_dirpath, ".svn")
-
- if (
- os.path.isdir(dirpath) and
- (os.path.exists(svn_dirpath) or os.path.exists(svn_root_dirpath))
- ):
- if make_utils.command_missing(args.svn_command):
- sys.stderr.write("svn not found, can't update libraries\n")
- sys.exit(1)
-
- # Cleanup to continue with interrupted downloads.
- if os.path.exists(svn_dirpath):
- call(svn_non_interactive + ["cleanup", dirpath])
+
+ if not os.path.isdir(lib_dirpath):
+ print("Library path: %r, not found, skipping" % lib_dirpath)
+ else:
+ paths_local_and_remote = []
+ if os.path.exists(os.path.join(lib_dirpath, ".svn")):
+ print_stage("Updating Precompiled Libraries and Tests (one repository)")
+ paths_local_and_remote.append((lib_dirpath, svn_url))
+ else:
+ print_stage("Updating Precompiled Libraries and Tests (multiple repositories)")
+ # Separate paths checked out.
+ for dirname in os.listdir(lib_dirpath):
+ if dirname.startswith("."):
+ # Temporary paths such as ".mypy_cache" will report a warning, skip hidden directories.
+ continue
+
+ dirpath = os.path.join(lib_dirpath, dirname)
+ if not (os.path.isdir(dirpath) and os.path.exists(os.path.join(dirpath, ".svn"))):
+ continue
+
+ paths_local_and_remote.append((dirpath, svn_url + dirname))
+
+ if paths_local_and_remote:
+ if make_utils.command_missing(args.svn_command):
+ sys.stderr.write("svn not found, can't update libraries\n")
+ sys.exit(1)
+
+ for dirpath, svn_url_full in paths_local_and_remote:
+ call(svn_non_interactive + ["cleanup", dirpath])
# Switch to appropriate branch and update.
- call(svn_non_interactive + ["switch", svn_url + dirname, dirpath], exit_on_error=False)
+ call(svn_non_interactive + ["switch", svn_url_full, dirpath], exit_on_error=False)
call(svn_non_interactive + ["update", dirpath])
# Test if git repo can be updated.
-def git_update_skip(args, check_remote_exists=True):
+def git_update_skip(args: argparse.Namespace, check_remote_exists: bool = True) -> str:
if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update code\n")
sys.exit(1)
@@ -166,13 +171,17 @@ def git_update_skip(args, check_remote_exists=True):
# Update blender repository.
-def blender_update(args):
+def blender_update(args: argparse.Namespace) -> None:
print_stage("Updating Blender Git Repository")
call([args.git_command, "pull", "--rebase"])
# Update submodules.
-def submodules_update(args, release_version, branch):
+def submodules_update(
+ args: argparse.Namespace,
+ release_version: Optional[str],
+ branch: Optional[str],
+) -> str:
print_stage("Updating Submodules")
if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update code\n")
@@ -214,7 +223,8 @@ def submodules_update(args, release_version, branch):
elif make_utils.git_branch_exists(args.git_command, submodule_branch_fallback):
submodule_branch = submodule_branch_fallback
else:
- submodule_branch = None
+ # Skip.
+ submodule_branch = ""
# Switch to branch and pull.
if submodule_branch:
diff --git a/build_files/utils/make_utils.py b/build_files/utils/make_utils.py
index 564930617ff..9b15eb363bc 100755
--- a/build_files/utils/make_utils.py
+++ b/build_files/utils/make_utils.py
@@ -80,7 +80,7 @@ def git_tag(git_command: str) -> Optional[str]:
return tag.strip().decode('utf8')
-def git_branch_release_version(branch: str, tag: str) -> Optional[str]:
+def git_branch_release_version(branch: str, tag: Optional[str]) -> Optional[str]:
re_match = re.search("^blender-v(.*)-release$", branch)
release_version = None
if re_match:
diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd
index eaf4a85f7ac..a2ff4c1ff95 100644
--- a/build_files/windows/parse_arguments.cmd
+++ b/build_files/windows/parse_arguments.cmd
@@ -80,9 +80,11 @@ if NOT "%1" == "" (
REM Non-Build Commands
) else if "%1" == "update" (
SET BUILD_UPDATE=1
+ SET BUILD_UPDATE_SVN=1
set BUILD_UPDATE_ARGS=
) else if "%1" == "code_update" (
SET BUILD_UPDATE=1
+ SET BUILD_UPDATE_SVN=0
set BUILD_UPDATE_ARGS="--no-libraries"
) else if "%1" == "ninja" (
SET BUILD_WITH_NINJA=1
diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd
index 8ba7b4d3307..37c5d1034ea 100644
--- a/build_files/windows/reset_variables.cmd
+++ b/build_files/windows/reset_variables.cmd
@@ -34,3 +34,4 @@ set BUILD_WITH_SCCACHE=
set ICONS=
set ICONS_GEOM=
set DOC_PY=
+SET BUILD_UPDATE_SVN= \ No newline at end of file
diff --git a/build_files/windows/svn_update.cmd b/build_files/windows/svn_update.cmd
new file mode 100644
index 00000000000..f91f03f15b3
--- /dev/null
+++ b/build_files/windows/svn_update.cmd
@@ -0,0 +1,24 @@
+if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
+if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
+
+set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
+set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
+
+cd %BUILD_VS_LIBDIR%
+:RETRY
+"%SVN%" update
+if errorlevel 1 (
+ set /p LibRetry= "Error during update, retry? y/n"
+ if /I "!LibRetry!"=="Y" (
+ "%SVN%" cleanup
+ goto RETRY
+ )
+ echo.
+ echo Error: Download of external libraries failed.
+ echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
+ echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
+ echo.
+ exit /b 1
+)
+
+cd %BLENDER_DIR% \ No newline at end of file
diff --git a/extern/hipew/src/hipew.c b/extern/hipew/src/hipew.c
index ecf952e266f..7cafe7727f5 100644
--- a/extern/hipew/src/hipew.c
+++ b/extern/hipew/src/hipew.c
@@ -253,7 +253,7 @@ static int hipewHipInit(void) {
/* Default installation path. */
const char *hip_paths[] = {"", NULL};
#else
- const char *hip_paths[] = {"/opt/rocm/hip/lib/libamdhip64.so", NULL};
+ const char *hip_paths[] = {"libamdhip64.so", "/opt/rocm/hip/lib/libamdhip64.so", NULL};
#endif
static int initialized = 0;
static int result = 0;
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index f619e6b104e..329aa3990f6 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -263,8 +263,7 @@ if(WITH_CYCLES_DEVICE_OPTIX)
${OPTIX_INCLUDE_DIR}
)
else()
- message(STATUS "OptiX not found, disabling it from Cycles")
- set(WITH_CYCLES_DEVICE_OPTIX OFF)
+ set_and_warn_library_found("OptiX" OPTIX_FOUND WITH_CYCLES_DEVICE_OPTIX)
endif()
endif()
@@ -387,8 +386,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_USD))
- message(STATUS "USD not found, disabling WITH_CYCLES_HYDRA_RENDER_DELEGATE")
- set(WITH_CYCLES_HYDRA_RENDER_DELEGATE OFF)
+ set_and_warn_library_found("USD" WITH_USD WITH_CYCLES_HYDRA_RENDER_DELEGATE)
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_BLENDER) AND (NOT WITH_CYCLES_STANDALONE))
set(CYCLES_INSTALL_PATH ${CYCLES_INSTALL_PATH}/hdCycles/resources)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 0988b1c0ac4..1c7a861ea93 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -43,7 +43,10 @@ else()
endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
- list(APPEND INC_SYS ${Epoxy_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
+ list(APPEND INC_SYS
+ ${Epoxy_INCLUDE_DIRS}
+ ${SDL2_INCLUDE_DIRS}
+ )
list(APPEND LIB ${Epoxy_LIBRARIES} ${SDL2_LIBRARIES})
endif()
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 794338fe78e..e33891fa7a2 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -209,22 +209,25 @@ def list_render_passes(scene, srl):
yield ("Debug Sample Count", "X", 'VALUE')
# Cryptomatte passes.
- crypto_depth = (srl.pass_cryptomatte_depth + 1) // 2
+ # NOTE: Name channels are lowercase RGBA so that compression rules check in OpenEXR DWA code
+ # uses lossless compression. Reportedly this naming is the only one which works good from the
+ # interoperability point of view. Using XYZW naming is not portable.
+ crypto_depth = (min(16, srl.pass_cryptomatte_depth) + 1) // 2
if srl.use_pass_cryptomatte_object:
for i in range(0, crypto_depth):
- yield ("CryptoObject" + '{:02d}'.format(i), "RGBA", 'COLOR')
+ yield ("CryptoObject" + '{:02d}'.format(i), "rgba", 'COLOR')
if srl.use_pass_cryptomatte_material:
for i in range(0, crypto_depth):
- yield ("CryptoMaterial" + '{:02d}'.format(i), "RGBA", 'COLOR')
+ yield ("CryptoMaterial" + '{:02d}'.format(i), "rgba", 'COLOR')
if srl.use_pass_cryptomatte_asset:
for i in range(0, crypto_depth):
- yield ("CryptoAsset" + '{:02d}'.format(i), "RGBA", 'COLOR')
+ yield ("CryptoAsset" + '{:02d}'.format(i), "rgba", 'COLOR')
# Denoising passes.
if scene.cycles.use_denoising and crl.use_denoising:
yield ("Noisy Image", "RGBA", 'COLOR')
if crl.use_pass_shadow_catcher:
- yield ("Noisy Shadow Catcher", "RGBA", 'COLOR')
+ yield ("Noisy Shadow Catcher", "RGB", 'COLOR')
if crl.denoising_store_passes:
yield ("Denoising Normal", "XYZ", 'VECTOR')
yield ("Denoising Albedo", "RGB", 'COLOR')
@@ -232,6 +235,8 @@ def list_render_passes(scene, srl):
# Custom AOV passes.
for aov in srl.aovs:
+ if not aov.is_valid:
+ continue
if aov.type == 'VALUE':
yield (aov.name, "X", 'VALUE')
else:
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index b7ce76d8f44..f5cd88f6b6a 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -60,13 +60,14 @@ enum_filter_types = (
)
enum_panorama_types = (
- ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
- ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
+ ('EQUIRECTANGULAR', "Equirectangular", "Spherical camera for environment maps, also known as Lat Long panorama", 0),
+ ('EQUIANGULAR_CUBEMAP_FACE', "Equiangular Cubemap Face", "Single face of an equiangular cubemap", 5),
+ ('MIRRORBALL', "Mirror Ball", "Mirror ball mapping for environment maps", 3),
+ ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions", 1),
('FISHEYE_EQUISOLID', "Fisheye Equisolid",
- "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
- ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
+ "Similar to most fisheye modern lens, takes sensor dimensions into consideration", 2),
('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial",
- "Defines the lens projection as polynomial to allow real world camera lenses to be mimicked"),
+ "Defines the lens projection as polynomial to allow real world camera lenses to be mimicked", 4),
)
enum_curve_shape = (
@@ -1636,11 +1637,13 @@ class CyclesPreferences(bpy.types.AddonPreferences):
col.label(text="and AMD driver version 22.10 or newer", icon='BLANK1')
elif device_type == 'ONEAPI':
import sys
- col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
if sys.platform.startswith("win"):
+ col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
col.label(text="and Windows driver version 101.3430 or newer", icon='BLANK1')
elif sys.platform.startswith("linux"):
- col.label(text="and Linux driver version xx.xx.23904 or newer", icon='BLANK1')
+ col.label(text="Requires Intel GPU with Xe-HPG architecture and", icon='BLANK1')
+ col.label(text=" - Linux driver version xx.xx.23904 or newer", icon='BLANK1')
+ col.label(text=" - oneAPI Level-Zero Loader", icon='BLANK1')
elif device_type == 'METAL':
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
@@ -1651,6 +1654,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
box.prop(
device, "use", text=device.name
.replace('(TM)', unicodedata.lookup('TRADE MARK SIGN'))
+ .replace('(tm)', unicodedata.lookup('TRADE MARK SIGN'))
.replace('(R)', unicodedata.lookup('REGISTERED SIGN'))
.replace('(C)', unicodedata.lookup('COPYRIGHT SIGN'))
)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index f763fe0eb0b..305accc8f1a 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -150,6 +150,16 @@ def get_effective_preview_denoiser(context):
return 'OIDN'
+def use_mnee(context):
+ # The MNEE kernel doesn't compile on macOS < 13.
+ if use_metal(context):
+ import platform
+ v, _, _ = platform.mac_ver()
+ if float(v) < 13.0:
+ return False
+ return True
+
+
class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
bl_label = "Sampling"
@@ -1235,7 +1245,7 @@ class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return CyclesButtonsPanel.poll(context) and not use_metal(context) and context.object.type != 'LIGHT'
+ return CyclesButtonsPanel.poll(context) and use_mnee(context) and context.object.type != 'LIGHT'
def draw(self, context):
layout = self.layout
@@ -1449,7 +1459,7 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
sub.active = not (light.type == 'AREA' and clamp.is_portal)
sub.prop(clamp, "cast_shadow")
sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
- if not use_metal(context):
+ if use_mnee(context):
sub.prop(clamp, "is_caustics_light", text="Shadow Caustics")
if light.type == 'AREA':
diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp
index f9a83b2dc4b..6641e2b8ac5 100644
--- a/intern/cycles/blender/session.cpp
+++ b/intern/cycles/blender/session.cpp
@@ -497,9 +497,9 @@ void BlenderSession::render_frame_finish()
session->full_buffer_written_cb = function_null;
/* The display driver is the source of drawing context for both drawing and possible graphics
- * interop objects in the path trace. Once the frame is finished the OpenGL context might be
- * freed form Blender side. Need to ensure that all GPU resources are freed prior to that
- * point.
+ * interoperability objects in the path trace. Once the frame is finished the OpenGL context
+ * might be freed form Blender side. Need to ensure that all GPU resources are freed prior to
+ * that point.
* Ideally would only do this when OpenGL context is actually destroyed, but there is no way to
* know when this happens (at least in the code at the time when this comment was written).
* The penalty of re-creating resources on every frame is unlikely to be noticed. */
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index a69a94614d3..5251f0fee9c 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -575,68 +575,72 @@ void BlenderSync::sync_images()
/* Passes */
-static PassType get_blender_pass_type(BL::RenderPass &b_pass)
+static bool get_known_pass_type(BL::RenderPass &b_pass, PassType &type, PassMode &mode)
{
string name = b_pass.name();
-#define MAP_PASS(passname, passtype) \
+#define MAP_PASS(passname, passtype, noisy) \
if (name == passname) { \
- return passtype; \
+ type = passtype; \
+ mode = (noisy) ? PassMode::NOISY : PassMode::DENOISED; \
+ return true; \
} \
((void)0)
- /* NOTE: Keep in sync with defined names from DNA_scene_types.h */
+ /* NOTE: Keep in sync with defined names from engine.py */
- MAP_PASS("Combined", PASS_COMBINED);
- MAP_PASS("Noisy Image", PASS_COMBINED);
+ MAP_PASS("Combined", PASS_COMBINED, false);
+ MAP_PASS("Noisy Image", PASS_COMBINED, true);
- MAP_PASS("Depth", PASS_DEPTH);
- MAP_PASS("Mist", PASS_MIST);
- MAP_PASS("Position", PASS_POSITION);
- MAP_PASS("Normal", PASS_NORMAL);
- MAP_PASS("IndexOB", PASS_OBJECT_ID);
- MAP_PASS("UV", PASS_UV);
- MAP_PASS("Vector", PASS_MOTION);
- MAP_PASS("IndexMA", PASS_MATERIAL_ID);
+ MAP_PASS("Depth", PASS_DEPTH, false);
+ MAP_PASS("Mist", PASS_MIST, false);
+ MAP_PASS("Position", PASS_POSITION, false);
+ MAP_PASS("Normal", PASS_NORMAL, false);
+ MAP_PASS("IndexOB", PASS_OBJECT_ID, false);
+ MAP_PASS("UV", PASS_UV, false);
+ MAP_PASS("Vector", PASS_MOTION, false);
+ MAP_PASS("IndexMA", PASS_MATERIAL_ID, false);
- MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT);
- MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
- MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
- MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT);
+ MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT, false);
+ MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT, false);
+ MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT, false);
+ MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT, false);
- MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
- MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
- MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
- MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT);
+ MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT, false);
+ MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT, false);
+ MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT, false);
+ MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT, false);
- MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
- MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
- MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR);
+ MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR, false);
+ MAP_PASS("GlossCol", PASS_GLOSSY_COLOR, false);
+ MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR, false);
- MAP_PASS("Emit", PASS_EMISSION);
- MAP_PASS("Env", PASS_BACKGROUND);
- MAP_PASS("AO", PASS_AO);
- MAP_PASS("Shadow", PASS_SHADOW);
+ MAP_PASS("Emit", PASS_EMISSION, false);
+ MAP_PASS("Env", PASS_BACKGROUND, false);
+ MAP_PASS("AO", PASS_AO, false);
+ MAP_PASS("Shadow", PASS_SHADOW, false);
- MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE);
- MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL);
+ MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE, false);
+ MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL, false);
- MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL);
- MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO);
- MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH);
+ MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL, true);
+ MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO, true);
+ MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH, true);
- MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER);
- MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER);
+ MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER, false);
+ MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER, true);
- MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER);
- MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT);
+ MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER, false);
+ MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT, false);
if (string_startswith(name, cryptomatte_prefix)) {
- return PASS_CRYPTOMATTE;
+ type = PASS_CRYPTOMATTE;
+ mode = PassMode::DENOISED;
+ return true;
}
#undef MAP_PASS
- return PASS_NONE;
+ return false;
}
static Pass *pass_add(Scene *scene,
@@ -655,8 +659,6 @@ static Pass *pass_add(Scene *scene,
void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer)
{
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
/* Delete all existing passes. */
set<Pass *> clear_passes(scene->passes.begin(), scene->passes.end());
scene->delete_nodes(clear_passes);
@@ -664,103 +666,23 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
/* Always add combined pass. */
pass_add(scene, PASS_COMBINED, "Combined");
- /* Blender built-in data and light passes. */
- for (BL::RenderPass &b_pass : b_rlay.passes) {
- const PassType pass_type = get_blender_pass_type(b_pass);
-
- if (pass_type == PASS_NONE) {
- LOG(ERROR) << "Unknown pass " << b_pass.name();
- continue;
- }
-
- if (pass_type == PASS_MOTION &&
- (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) {
- continue;
- }
-
- pass_add(scene, pass_type, b_pass.name().c_str());
- }
-
- PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
-
- /* Debug passes. */
- if (get_boolean(crl, "pass_debug_sample_count")) {
- b_engine.add_pass("Debug Sample Count", 1, "X", b_view_layer.name().c_str());
- pass_add(scene, PASS_SAMPLE_COUNT, "Debug Sample Count");
- }
-
- /* Cycles specific passes. */
- if (get_boolean(crl, "use_pass_volume_direct")) {
- b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_VOLUME_DIRECT, "VolumeDir");
- }
- if (get_boolean(crl, "use_pass_volume_indirect")) {
- b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_VOLUME_INDIRECT, "VolumeInd");
- }
- if (get_boolean(crl, "use_pass_shadow_catcher")) {
- b_engine.add_pass("Shadow Catcher", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_SHADOW_CATCHER, "Shadow Catcher");
- }
-
/* Cryptomatte stores two ID/weight pairs per RGBA layer.
- * User facing parameter is the number of pairs.
- *
- * NOTE: Name channels lowercase RGBA so that compression rules check in OpenEXR DWA code uses
- * lossless compression. Reportedly this naming is the only one which works good from the
- * interoperability point of view. Using XYZW naming is not portable. */
+ * User facing parameter is the number of pairs. */
int crypto_depth = divide_up(min(16, b_view_layer.pass_cryptomatte_depth()), 2);
scene->film->set_cryptomatte_depth(crypto_depth);
CryptomatteType cryptomatte_passes = CRYPT_NONE;
if (b_view_layer.use_pass_cryptomatte_object()) {
- for (int i = 0; i < crypto_depth; i++) {
- string passname = cryptomatte_prefix + string_printf("Object%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str());
- pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
- }
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT);
}
if (b_view_layer.use_pass_cryptomatte_material()) {
- for (int i = 0; i < crypto_depth; i++) {
- string passname = cryptomatte_prefix + string_printf("Material%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str());
- pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
- }
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL);
}
if (b_view_layer.use_pass_cryptomatte_asset()) {
- for (int i = 0; i < crypto_depth; i++) {
- string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str());
- pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
- }
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET);
}
scene->film->set_cryptomatte_passes(cryptomatte_passes);
- /* Denoising passes. */
- const bool use_denoising = get_boolean(cscene, "use_denoising") &&
- get_boolean(crl, "use_denoising");
- const bool store_denoising_passes = get_boolean(crl, "denoising_store_passes");
- if (use_denoising) {
- b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
- pass_add(scene, PASS_COMBINED, "Noisy Image", PassMode::NOISY);
- if (get_boolean(crl, "use_pass_shadow_catcher")) {
- b_engine.add_pass("Noisy Shadow Catcher", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_SHADOW_CATCHER, "Noisy Shadow Catcher", PassMode::NOISY);
- }
- }
- if (store_denoising_passes) {
- b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
- pass_add(scene, PASS_DENOISING_NORMAL, "Denoising Normal", PassMode::NOISY);
-
- b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_DENOISING_ALBEDO, "Denoising Albedo", PassMode::NOISY);
-
- b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str());
- pass_add(scene, PASS_DENOISING_DEPTH, "Denoising Depth", PassMode::NOISY);
- }
-
+ /* Path guiding debug passes. */
#ifdef WITH_CYCLES_DEBUG
b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY);
@@ -772,6 +694,8 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY);
#endif
+ unordered_set<string> expected_passes;
+
/* Custom AOV passes. */
BL::ViewLayer::aovs_iterator b_aov_iter;
for (b_view_layer.aovs.begin(b_aov_iter); b_aov_iter != b_view_layer.aovs.end(); ++b_aov_iter) {
@@ -781,16 +705,10 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
}
string name = b_aov.name();
- bool is_color = b_aov.type() == BL::AOV::type_COLOR;
+ PassType type = (b_aov.type() == BL::AOV::type_COLOR) ? PASS_AOV_COLOR : PASS_AOV_VALUE;
- if (is_color) {
- b_engine.add_pass(name.c_str(), 4, "RGBA", b_view_layer.name().c_str());
- pass_add(scene, PASS_AOV_COLOR, name.c_str());
- }
- else {
- b_engine.add_pass(name.c_str(), 1, "X", b_view_layer.name().c_str());
- pass_add(scene, PASS_AOV_VALUE, name.c_str());
- }
+ pass_add(scene, type, name.c_str());
+ expected_passes.insert(name);
}
/* Light Group passes. */
@@ -802,9 +720,29 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
string name = string_printf("Combined_%s", b_lightgroup.name().c_str());
- b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str());
Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY);
pass->set_lightgroup(ustring(b_lightgroup.name()));
+ expected_passes.insert(name);
+ }
+
+ /* Sync the passes that were defined in engine.py. */
+ for (BL::RenderPass &b_pass : b_rlay.passes) {
+ PassType pass_type = PASS_NONE;
+ PassMode pass_mode = PassMode::DENOISED;
+
+ if (!get_known_pass_type(b_pass, pass_type, pass_mode)) {
+ if (!expected_passes.count(b_pass.name())) {
+ LOG(ERROR) << "Unknown pass " << b_pass.name();
+ }
+ continue;
+ }
+
+ if (pass_type == PASS_MOTION &&
+ (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) {
+ continue;
+ }
+
+ pass_add(scene, pass_type, b_pass.name().c_str(), pass_mode);
}
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index 9524cda54f5..44542a08156 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -289,8 +289,7 @@ if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_PATH_GUIDING)
endif()
get_target_property(OPENPGL_INCLUDE_DIR openpgl::openpgl INTERFACE_INCLUDE_DIRECTORIES)
else()
- set(WITH_CYCLES_PATH_GUIDING OFF)
- message(STATUS "OpenPGL not found, disabling WITH_CYCLES_PATH_GUIDING")
+ set_and_warn_library_found("OpenPGL" openpgl_FOUND WITH_CYCLES_PATH_GUIDING)
endif()
endif()
@@ -588,16 +587,14 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
# We can't use the version from the Blender precompiled libraries because
# it does not include the video subsystem.
find_package(SDL2 REQUIRED)
+ set_and_warn_library_found("SDL" SDL2_FOUND WITH_CYCLES_STANDALONE_GUI)
- if(NOT SDL2_FOUND)
- set(WITH_CYCLES_STANDALONE_GUI OFF)
- message(STATUS "SDL not found, disabling Cycles standalone GUI")
+ if(SDL2_FOUND)
+ include_directories(
+ SYSTEM
+ ${SDL2_INCLUDE_DIRS}
+ )
endif()
-
- include_directories(
- SYSTEM
- ${SDL2_INCLUDE_DIRS}
- )
endif()
###########################################################################
@@ -606,11 +603,11 @@ endif()
if(WITH_CYCLES_DEVICE_CUDA AND (WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD))
find_package(CUDA) # Try to auto locate CUDA toolkit
+ set_and_warn_library_found("CUDA compiler" CUDA_FOUND WITH_CYCLES_CUDA_BINARIES)
+
if(CUDA_FOUND)
message(STATUS "Found CUDA ${CUDA_NVCC_EXECUTABLE} (${CUDA_VERSION})")
else()
- message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES")
- set(WITH_CYCLES_CUDA_BINARIES OFF)
if(NOT WITH_CUDA_DYNLOAD)
message(STATUS "Additionally falling back to dynamic CUDA load")
set(WITH_CUDA_DYNLOAD ON)
@@ -624,11 +621,10 @@ endif()
if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
find_package(HIP)
+ set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
+
if(HIP_FOUND)
message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
- else()
- message(STATUS "HIP compiler not found, disabling WITH_CYCLES_HIP_BINARIES")
- set(WITH_CYCLES_HIP_BINARIES OFF)
endif()
endif()
@@ -644,13 +640,17 @@ if(WITH_CYCLES_DEVICE_METAL)
find_library(METAL_LIBRARY Metal)
# This file was added in the 12.0 SDK, use it as a way to detect the version.
- if(METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
- message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL")
- set(WITH_CYCLES_DEVICE_METAL OFF)
- elseif(NOT METAL_LIBRARY)
- message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL")
- set(WITH_CYCLES_DEVICE_METAL OFF)
- else()
+ if(METAL_LIBRARY)
+ if(EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
+ set(METAL_FOUND ON)
+ else()
+ message(STATUS "Metal version too old, must be SDK 12.0 or newer")
+ set(METAL_FOUND OFF)
+ endif()
+ endif()
+
+ set_and_warn_library_found("Metal" METAL_FOUND WITH_CYCLES_DEVICE_METAL)
+ if(METAL_FOUND)
message(STATUS "Found Metal: ${METAL_LIBRARY}")
endif()
endif()
@@ -662,9 +662,10 @@ endif()
if(WITH_CYCLES_DEVICE_ONEAPI)
find_package(SYCL)
find_package(LevelZero)
+ set_and_warn_library_found("oneAPI" SYCL_FOUND WITH_CYCLES_DEVICE_ONEAPI)
+ set_and_warn_library_found("Level Zero" LEVEL_ZERO_FOUND WITH_CYCLES_DEVICE_ONEAPI)
- if(SYCL_FOUND AND LEVEL_ZERO_FOUND)
- message(STATUS "Found oneAPI: ${SYCL_LIBRARY}")
+ if(SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND)
message(STATUS "Found Level Zero: ${LEVEL_ZERO_LIBRARY}")
if(WITH_CYCLES_ONEAPI_BINARIES)
@@ -675,13 +676,14 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
endif()
if(NOT EXISTS ${OCLOC_INSTALL_DIR})
- message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}, disabling WITH_CYCLES_ONEAPI_BINARIES."
+ set(OCLOC_FOUND OFF)
+ message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}."
" A different ocloc directory can be set using OCLOC_INSTALL_DIR cmake variable.")
- set(WITH_CYCLES_ONEAPI_BINARIES OFF)
+ set_and_warn_library_found("ocloc" OCLOC_FOUND WITH_CYCLES_ONEAPI_BINARIES)
endif()
endif()
else()
- message(STATUS "oneAPI or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI")
+ message(STATUS "SYCL 6.0+ or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI")
set(WITH_CYCLES_DEVICE_ONEAPI OFF)
endif()
endif()
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 5516e97f34f..5296d819e42 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -187,18 +187,22 @@ if(WITH_CYCLES_DEVICE_METAL)
)
endif()
if (WITH_CYCLES_DEVICE_ONEAPI)
+ if(WITH_CYCLES_ONEAPI_BINARIES)
+ set(cycles_kernel_oneapi_lib_suffix "_aot")
+ else()
+ set(cycles_kernel_oneapi_lib_suffix "_jit")
+ endif()
if(WIN32)
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi.lib)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib)
else()
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so)
+ endif()
+ list(APPEND LIB ${cycles_kernel_oneapi_lib})
+ if(WIN32)
+ list(APPEND LIB debug ${SYCL_LIBRARY_DEBUG} optimized ${SYCL_LIBRARY})
+ else()
+ list(APPEND LIB ${SYCL_LIBRARY})
endif()
- list(APPEND LIB
- ${cycles_kernel_oneapi_lib}
- "$<$<CONFIG:Debug>:${SYCL_LIBRARY_DEBUG}>"
- "$<$<CONFIG:Release>:${SYCL_LIBRARY}>"
- "$<$<CONFIG:RelWithDebInfo>:${SYCL_LIBRARY}>"
- "$<$<CONFIG:MinSizeRel>:${SYCL_LIBRARY}>"
- )
add_definitions(-DWITH_ONEAPI)
list(APPEND SRC
${SRC_ONEAPI}
diff --git a/intern/cycles/device/cuda/queue.cpp b/intern/cycles/device/cuda/queue.cpp
index 84b0a1e0dd6..69fae03e32c 100644
--- a/intern/cycles/device/cuda/queue.cpp
+++ b/intern/cycles/device/cuda/queue.cpp
@@ -49,7 +49,7 @@ int CUDADeviceQueue::num_concurrent_states(const size_t state_size) const
return num_states;
}
-int CUDADeviceQueue::num_concurrent_busy_states() const
+int CUDADeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const
{
const int max_num_threads = cuda_device_->get_num_multiprocessors() *
cuda_device_->get_max_num_threads_per_multiprocessor();
diff --git a/intern/cycles/device/cuda/queue.h b/intern/cycles/device/cuda/queue.h
index b450f5b3592..7107afe70c9 100644
--- a/intern/cycles/device/cuda/queue.h
+++ b/intern/cycles/device/cuda/queue.h
@@ -23,7 +23,7 @@ class CUDADeviceQueue : public DeviceQueue {
~CUDADeviceQueue();
virtual int num_concurrent_states(const size_t state_size) const override;
- virtual int num_concurrent_busy_states() const override;
+ virtual int num_concurrent_busy_states(const size_t state_size) const override;
virtual void init_execution() override;
diff --git a/intern/cycles/device/hip/queue.cpp b/intern/cycles/device/hip/queue.cpp
index 3f8b6267100..e93a9b4df3a 100644
--- a/intern/cycles/device/hip/queue.cpp
+++ b/intern/cycles/device/hip/queue.cpp
@@ -49,7 +49,7 @@ int HIPDeviceQueue::num_concurrent_states(const size_t state_size) const
return num_states;
}
-int HIPDeviceQueue::num_concurrent_busy_states() const
+int HIPDeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const
{
const int max_num_threads = hip_device_->get_num_multiprocessors() *
hip_device_->get_max_num_threads_per_multiprocessor();
diff --git a/intern/cycles/device/hip/queue.h b/intern/cycles/device/hip/queue.h
index 729d8a19acb..df0678108af 100644
--- a/intern/cycles/device/hip/queue.h
+++ b/intern/cycles/device/hip/queue.h
@@ -23,7 +23,7 @@ class HIPDeviceQueue : public DeviceQueue {
~HIPDeviceQueue();
virtual int num_concurrent_states(const size_t state_size) const override;
- virtual int num_concurrent_busy_states() const override;
+ virtual int num_concurrent_busy_states(const size_t state_size) const override;
virtual void init_execution() override;
diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm
index 6a16d4bb3b4..6f1042b1e55 100644
--- a/intern/cycles/device/metal/device_impl.mm
+++ b/intern/cycles/device/metal/device_impl.mm
@@ -296,9 +296,11 @@ void MetalDevice::make_source(MetalPipelineType pso_type, const uint kernel_feat
}
source = global_defines + source;
+# if 0
metal_printf("================\n%s================\n\%s================\n",
global_defines.c_str(),
baked_constants.c_str());
+# endif
/* Generate an MD5 from the source and include any baked constants. This is used when caching
* PSOs. */
@@ -339,6 +341,14 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type)
MTLCompileOptions *options = [[MTLCompileOptions alloc] init];
+# if defined(MAC_OS_VERSION_13_0)
+ if (@available(macos 13.0, *)) {
+ if (device_vendor == METAL_GPU_INTEL) {
+ [options setOptimizationLevel:MTLLibraryOptimizationLevelSize];
+ }
+ }
+# endif
+
options.fastMathEnabled = YES;
if (@available(macOS 12.0, *)) {
options.languageVersion = MTLLanguageVersion2_4;
diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm
index 5e0cb6d18f4..55938d1a03a 100644
--- a/intern/cycles/device/metal/kernel.mm
+++ b/intern/cycles/device/metal/kernel.mm
@@ -162,6 +162,13 @@ bool ShaderCache::should_load_kernel(DeviceKernel device_kernel,
}
}
+ if (device_kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE) {
+ if ((device->kernel_features & KERNEL_FEATURE_MNEE) == 0) {
+ /* Skip shade_surface_mnee kernel if the scene doesn't require it. */
+ return false;
+ }
+ }
+
if (pso_type != PSO_GENERIC) {
/* Only specialize kernels where it can make an impact. */
if (device_kernel < DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST ||
@@ -317,6 +324,12 @@ bool MetalKernelPipeline::should_use_binary_archive() const
}
}
+ /* Workaround for Intel GPU having issue using Binary Archives */
+ MetalGPUVendor gpu_vendor = MetalInfo::get_device_vendor(mtlDevice);
+ if (gpu_vendor == METAL_GPU_INTEL) {
+ return false;
+ }
+
if (pso_type == PSO_GENERIC) {
/* Archive the generic kernels. */
return true;
diff --git a/intern/cycles/device/metal/queue.h b/intern/cycles/device/metal/queue.h
index fc32740f3e1..2a6c12e2a60 100644
--- a/intern/cycles/device/metal/queue.h
+++ b/intern/cycles/device/metal/queue.h
@@ -23,7 +23,7 @@ class MetalDeviceQueue : public DeviceQueue {
~MetalDeviceQueue();
virtual int num_concurrent_states(const size_t) const override;
- virtual int num_concurrent_busy_states() const override;
+ virtual int num_concurrent_busy_states(const size_t) const override;
virtual int num_sort_partition_elements() const override;
virtual void init_execution() override;
diff --git a/intern/cycles/device/metal/queue.mm b/intern/cycles/device/metal/queue.mm
index 5ac63a16c61..c0df2c8553f 100644
--- a/intern/cycles/device/metal/queue.mm
+++ b/intern/cycles/device/metal/queue.mm
@@ -264,33 +264,46 @@ MetalDeviceQueue::~MetalDeviceQueue()
}
}
-int MetalDeviceQueue::num_concurrent_states(const size_t /*state_size*/) const
+int MetalDeviceQueue::num_concurrent_states(const size_t state_size) const
{
- /* METAL_WIP */
- /* TODO: compute automatically. */
- /* TODO: must have at least num_threads_per_block. */
- int result = 1048576;
- if (metal_device_->device_vendor == METAL_GPU_AMD) {
- result *= 2;
+ static int result = 0;
+ if (result) {
+ return result;
}
- else if (metal_device_->device_vendor == METAL_GPU_APPLE) {
+
+ result = 1048576;
+ if (metal_device_->device_vendor == METAL_GPU_APPLE) {
result *= 4;
+
+ if (MetalInfo::get_apple_gpu_architecture(metal_device_->mtlDevice) == APPLE_M2) {
+ size_t system_ram = system_physical_ram();
+ size_t allocated_so_far = [metal_device_->mtlDevice currentAllocatedSize];
+ size_t max_recommended_working_set = [metal_device_->mtlDevice recommendedMaxWorkingSetSize];
+
+ /* Determine whether we can double the state count, and leave enough GPU-available memory
+ * (1/8 the system RAM or 1GB - whichever is largest). Enlarging the state size allows us to
+ * keep dispatch sizes high and minimize work submission overheads. */
+ size_t min_headroom = std::max(system_ram / 8, size_t(1024 * 1024 * 1024));
+ size_t total_state_size = result * state_size;
+ if (max_recommended_working_set - allocated_so_far - total_state_size * 2 >= min_headroom) {
+ result *= 2;
+ metal_printf("Doubling state count to exploit available RAM (new size = %d)\n", result);
+ }
+ }
+ }
+ else if (metal_device_->device_vendor == METAL_GPU_AMD) {
+ /* METAL_WIP */
+ /* TODO: compute automatically. */
+ /* TODO: must have at least num_threads_per_block. */
+ result *= 2;
}
return result;
}
-int MetalDeviceQueue::num_concurrent_busy_states() const
+int MetalDeviceQueue::num_concurrent_busy_states(const size_t state_size) const
{
- /* METAL_WIP */
- /* TODO: compute automatically. */
- int result = 65536;
- if (metal_device_->device_vendor == METAL_GPU_AMD) {
- result *= 2;
- }
- else if (metal_device_->device_vendor == METAL_GPU_APPLE) {
- result *= 4;
- }
- return result;
+ /* A 1:4 busy:total ratio gives best rendering performance, independent of total state count. */
+ return num_concurrent_states(state_size) / 4;
}
int MetalDeviceQueue::num_sort_partition_elements() const
diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm
index 65c67c400fe..f47638fac15 100644
--- a/intern/cycles/device/metal/util.mm
+++ b/intern/cycles/device/metal/util.mm
@@ -110,6 +110,12 @@ vector<id<MTLDevice>> const &MetalInfo::get_usable_devices()
usable |= (vendor == METAL_GPU_AMD);
}
+# if defined(MAC_OS_VERSION_13_0)
+ if (@available(macos 13.0, *)) {
+ usable |= (vendor == METAL_GPU_INTEL);
+ }
+# endif
+
if (usable) {
metal_printf("- %s\n", device_name.c_str());
[device retain];
diff --git a/intern/cycles/device/oneapi/device.cpp b/intern/cycles/device/oneapi/device.cpp
index f303ab41627..66d6f749e30 100644
--- a/intern/cycles/device/oneapi/device.cpp
+++ b/intern/cycles/device/oneapi/device.cpp
@@ -39,7 +39,7 @@ bool device_oneapi_init()
_putenv_s("SYCL_CACHE_THRESHOLD", "0");
}
if (getenv("SYCL_DEVICE_FILTER") == nullptr) {
- _putenv_s("SYCL_DEVICE_FILTER", "host,level_zero");
+ _putenv_s("SYCL_DEVICE_FILTER", "level_zero");
}
if (getenv("SYCL_ENABLE_PCI") == nullptr) {
_putenv_s("SYCL_ENABLE_PCI", "1");
@@ -50,7 +50,7 @@ bool device_oneapi_init()
# elif __linux__
setenv("SYCL_CACHE_PERSISTENT", "1", false);
setenv("SYCL_CACHE_THRESHOLD", "0", false);
- setenv("SYCL_DEVICE_FILTER", "host,level_zero", false);
+ setenv("SYCL_DEVICE_FILTER", "level_zero", false);
setenv("SYCL_ENABLE_PCI", "1", false);
setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0", false);
# endif
diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp
index 91f53fd1eae..d0ddd69289c 100644
--- a/intern/cycles/device/oneapi/device_impl.cpp
+++ b/intern/cycles/device/oneapi/device_impl.cpp
@@ -430,9 +430,9 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_
sycl::usm::alloc usm_type = get_pointer_type(usm_ptr, queue->get_context());
(void)usm_type;
assert(usm_type == sycl::usm::alloc::device ||
- ((device_type == sycl::info::device_type::host ||
- device_type == sycl::info::device_type::cpu || allow_host) &&
- usm_type == sycl::usm::alloc::host));
+ ((device_type == sycl::info::device_type::cpu || allow_host) &&
+ usm_type == sycl::usm::alloc::host ||
+ usm_type == sycl::usm::alloc::unknown));
# else
/* Silence warning about unused arguments. */
(void)queue_;
@@ -668,16 +668,9 @@ int OneapiDevice::parse_driver_build_version(const sycl::device &device)
std::vector<sycl::device> OneapiDevice::available_devices()
{
bool allow_all_devices = false;
- if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr)
+ if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr) {
allow_all_devices = true;
-
- /* Host device is useful only for debugging at the moment
- * so we hide this device with default build settings. */
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
- bool allow_host = true;
-# else
- bool allow_host = false;
-# endif
+ }
const std::vector<sycl::platform> &oneapi_platforms = sycl::platform::get_platforms();
@@ -690,33 +683,28 @@ std::vector<sycl::device> OneapiDevice::available_devices()
}
const std::vector<sycl::device> &oneapi_devices =
- (allow_all_devices || allow_host) ? platform.get_devices(sycl::info::device_type::all) :
- platform.get_devices(sycl::info::device_type::gpu);
+ (allow_all_devices) ? platform.get_devices(sycl::info::device_type::all) :
+ platform.get_devices(sycl::info::device_type::gpu);
for (const sycl::device &device : oneapi_devices) {
- if (allow_all_devices) {
- /* still filter out host device if build doesn't support it. */
- if (allow_host || !device.is_host()) {
- available_devices.push_back(device);
- }
- }
- else {
- bool filter_out = false;
-
+ bool filter_out = false;
+ if (!allow_all_devices) {
/* For now we support all Intel(R) Arc(TM) devices and likely any future GPU,
* assuming they have either more than 96 Execution Units or not 7 threads per EU.
* Official support can be broaden to older and smaller GPUs once ready. */
- if (device.is_gpu() && platform.get_backend() == sycl::backend::ext_oneapi_level_zero) {
- /* Filtered-out defaults in-case these values aren't available through too old L0
- * runtime. */
+ if (!device.is_gpu() || platform.get_backend() != sycl::backend::ext_oneapi_level_zero) {
+ filter_out = true;
+ }
+ else {
+ /* Filtered-out defaults in-case these values aren't available. */
int number_of_eus = 96;
int threads_per_eu = 7;
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
- number_of_eus = device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
+ number_of_eus = device.get_info<sycl::ext::intel::info::device::gpu_eu_count>();
}
if (device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
threads_per_eu =
- device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
+ device.get_info<sycl::ext::intel::info::device::gpu_hw_threads_per_eu>();
}
/* This filters out all Level-Zero supported GPUs from older generation than Arc. */
if (number_of_eus <= 96 && threads_per_eu == 7) {
@@ -732,16 +720,9 @@ std::vector<sycl::device> OneapiDevice::available_devices()
}
}
}
- else if (!allow_host && device.is_host()) {
- filter_out = true;
- }
- else if (!allow_all_devices) {
- filter_out = true;
- }
-
- if (!filter_out) {
- available_devices.push_back(device);
- }
+ }
+ if (!filter_out) {
+ available_devices.push_back(device);
}
}
}
@@ -797,9 +778,7 @@ char *OneapiDevice::device_capabilities()
GET_NUM_ATTR(native_vector_width_double)
GET_NUM_ATTR(native_vector_width_half)
- size_t max_clock_frequency =
- (size_t)(device.is_host() ? (size_t)0 :
- device.get_info<sycl::info::device::max_clock_frequency>());
+ size_t max_clock_frequency = device.get_info<sycl::info::device::max_clock_frequency>();
WRITE_ATTR("max_clock_frequency", max_clock_frequency)
GET_NUM_ATTR(address_bits)
@@ -837,7 +816,7 @@ void OneapiDevice::iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_p
std::string name = device.get_info<sycl::info::device::name>();
std::string id = "ONEAPI_" + platform_name + "_" + name;
if (device.has(sycl::aspect::ext_intel_pci_address)) {
- id.append("_" + device.get_info<sycl::info::device::ext_intel_pci_address>());
+ id.append("_" + device.get_info<sycl::ext::intel::info::device::pci_address>());
}
(cb)(id.c_str(), name.c_str(), num, user_ptr);
num++;
@@ -855,7 +834,7 @@ int OneapiDevice::get_num_multiprocessors()
{
const sycl::device &device = reinterpret_cast<sycl::queue *>(device_queue_)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
- return device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
+ return device.get_info<sycl::ext::intel::info::device::gpu_eu_count>();
}
else
return 0;
@@ -866,8 +845,8 @@ int OneapiDevice::get_max_num_threads_per_multiprocessor()
const sycl::device &device = reinterpret_cast<sycl::queue *>(device_queue_)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) &&
device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
- return device.get_info<sycl::info::device::ext_intel_gpu_eu_simd_width>() *
- device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
+ return device.get_info<sycl::ext::intel::info::device::gpu_eu_simd_width>() *
+ device.get_info<sycl::ext::intel::info::device::gpu_hw_threads_per_eu>();
}
else
return 0;
diff --git a/intern/cycles/device/oneapi/device_impl.h b/intern/cycles/device/oneapi/device_impl.h
index 62034150eac..197cf03d60d 100644
--- a/intern/cycles/device/oneapi/device_impl.h
+++ b/intern/cycles/device/oneapi/device_impl.h
@@ -3,7 +3,7 @@
#ifdef WITH_ONEAPI
-# include <CL/sycl.hpp>
+# include <sycl/sycl.hpp>
# include "device/device.h"
# include "device/oneapi/device.h"
diff --git a/intern/cycles/device/oneapi/queue.cpp b/intern/cycles/device/oneapi/queue.cpp
index 9632b14d485..3d019661aa8 100644
--- a/intern/cycles/device/oneapi/queue.cpp
+++ b/intern/cycles/device/oneapi/queue.cpp
@@ -43,7 +43,7 @@ int OneapiDeviceQueue::num_concurrent_states(const size_t state_size) const
return num_states;
}
-int OneapiDeviceQueue::num_concurrent_busy_states() const
+int OneapiDeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const
{
const int max_num_threads = oneapi_device_->get_num_multiprocessors() *
oneapi_device_->get_max_num_threads_per_multiprocessor();
diff --git a/intern/cycles/device/oneapi/queue.h b/intern/cycles/device/oneapi/queue.h
index 32363bf2a6e..bbd947b49cb 100644
--- a/intern/cycles/device/oneapi/queue.h
+++ b/intern/cycles/device/oneapi/queue.h
@@ -25,7 +25,7 @@ class OneapiDeviceQueue : public DeviceQueue {
virtual int num_concurrent_states(const size_t state_size) const override;
- virtual int num_concurrent_busy_states() const override;
+ virtual int num_concurrent_busy_states(const size_t state_size) const override;
virtual void init_execution() override;
diff --git a/intern/cycles/device/queue.h b/intern/cycles/device/queue.h
index 1d6a8d736b7..e27e081a407 100644
--- a/intern/cycles/device/queue.h
+++ b/intern/cycles/device/queue.h
@@ -103,7 +103,7 @@ class DeviceQueue {
/* Number of states which keeps the device occupied with work without losing performance.
* The renderer will add more work (when available) when number of active paths falls below this
* value. */
- virtual int num_concurrent_busy_states() const = 0;
+ virtual int num_concurrent_busy_states(const size_t state_size) const = 0;
/* Number of elements in a partition of sorted shaders, that improves memory locality of
* integrator state fetch at the cost of decreased coherence for shader kernel execution. */
diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp
index ee250a6916b..547e8d50a22 100644
--- a/intern/cycles/integrator/path_trace_work_gpu.cpp
+++ b/intern/cycles/integrator/path_trace_work_gpu.cpp
@@ -18,13 +18,15 @@
CCL_NAMESPACE_BEGIN
-static size_t estimate_single_state_size()
+static size_t estimate_single_state_size(const uint kernel_features)
{
size_t state_size = 0;
#define KERNEL_STRUCT_BEGIN(name) for (int array_index = 0;; array_index++) {
-#define KERNEL_STRUCT_MEMBER(parent_struct, type, name, feature) state_size += sizeof(type);
-#define KERNEL_STRUCT_ARRAY_MEMBER(parent_struct, type, name, feature) state_size += sizeof(type);
+#define KERNEL_STRUCT_MEMBER(parent_struct, type, name, feature) \
+ state_size += (kernel_features & (feature)) ? sizeof(type) : 0;
+#define KERNEL_STRUCT_ARRAY_MEMBER(parent_struct, type, name, feature) \
+ state_size += (kernel_features & (feature)) ? sizeof(type) : 0;
#define KERNEL_STRUCT_END(name) \
break; \
}
@@ -76,16 +78,11 @@ PathTraceWorkGPU::PathTraceWorkGPU(Device *device,
num_queued_paths_(device, "num_queued_paths", MEM_READ_WRITE),
work_tiles_(device, "work_tiles", MEM_READ_WRITE),
display_rgba_half_(device, "display buffer half", MEM_READ_WRITE),
- max_num_paths_(queue_->num_concurrent_states(estimate_single_state_size())),
- min_num_active_main_paths_(queue_->num_concurrent_busy_states()),
+ max_num_paths_(0),
+ min_num_active_main_paths_(0),
max_active_main_path_index_(0)
{
memset(&integrator_state_gpu_, 0, sizeof(integrator_state_gpu_));
-
- /* Limit number of active paths to the half of the overall state. This is due to the logic in the
- * path compaction which relies on the fact that regeneration does not happen sooner than half of
- * the states are available again. */
- min_num_active_main_paths_ = min(min_num_active_main_paths_, max_num_paths_ / 2);
}
void PathTraceWorkGPU::alloc_integrator_soa()
@@ -103,6 +100,20 @@ void PathTraceWorkGPU::alloc_integrator_soa()
integrator_state_soa_volume_stack_size_ = max(integrator_state_soa_volume_stack_size_,
requested_volume_stack_size);
+ /* Determine the number of path states. Deferring this for as long as possible allows the
+ * back-end to make better decisions about memory availability. */
+ if (max_num_paths_ == 0) {
+ size_t single_state_size = estimate_single_state_size(kernel_features);
+
+ max_num_paths_ = queue_->num_concurrent_states(single_state_size);
+ min_num_active_main_paths_ = queue_->num_concurrent_busy_states(single_state_size);
+
+ /* Limit number of active paths to the half of the overall state. This is due to the logic in
+ * the path compaction which relies on the fact that regeneration does not happen sooner than
+ * half of the states are available again. */
+ min_num_active_main_paths_ = min(min_num_active_main_paths_, max_num_paths_ / 2);
+ }
+
/* Allocate a device only memory buffer before for each struct member, and then
* write the pointers into a struct that resides in constant memory.
*
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 36c8b23d983..81c5f593974 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -713,10 +713,17 @@ endif()
# oneAPI module
if(WITH_CYCLES_DEVICE_ONEAPI)
+ if(WITH_CYCLES_ONEAPI_BINARIES)
+ set(cycles_kernel_oneapi_lib_suffix "_aot")
+ else()
+ set(cycles_kernel_oneapi_lib_suffix "_jit")
+ endif()
+
if(WIN32)
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.dll)
+ set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib)
else()
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so)
endif()
set(cycles_oneapi_kernel_sources
@@ -751,10 +758,6 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
${SYCL_CPP_FLAGS}
)
- if (WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED)
- list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_ENABLED)
- endif()
-
# Set defaults for spir64 and spir64_gen options
if (NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64)
set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64 "-options '-ze-opt-large-register-file -ze-opt-regular-grf-kernel integrator_intersect'")
@@ -767,6 +770,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
string(PREPEND CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "-device ${CYCLES_ONEAPI_SPIR64_GEN_DEVICES} ")
if (WITH_CYCLES_ONEAPI_BINARIES)
+ # AoT binaries aren't currently reused when calling sycl::build.
+ list (APPEND sycl_compiler_flags -DSYCL_SKIP_KERNELS_PRELOAD)
# Iterate over all targest and their options
list (JOIN CYCLES_ONEAPI_SYCL_TARGETS "," targets_string)
list (APPEND sycl_compiler_flags -fsycl-targets=${targets_string})
@@ -819,12 +824,17 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
-DONEAPI_EXPORT)
string(REPLACE /Redist/ /Tools/ MSVC_TOOLS_DIR ${MSVC_REDIST_DIR})
- if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) # case for Ninja on Windows
+ # Version Folder between Redist and Tools can mismatch sometimes
+ if(NOT EXISTS ${MSVC_TOOLS_DIR})
+ get_filename_component(cmake_ar_dir ${CMAKE_AR} DIRECTORY)
+ get_filename_component(MSVC_TOOLS_DIR "${cmake_ar_dir}/../../../" ABSOLUTE)
+ endif()
+ if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
+ set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION})
+ else() # case for Ninja on Windows
get_filename_component(cmake_mt_dir ${CMAKE_MT} DIRECTORY)
string(REPLACE /bin/ /Lib/ WINDOWS_KIT_DIR ${cmake_mt_dir})
get_filename_component(WINDOWS_KIT_DIR "${WINDOWS_KIT_DIR}/../" ABSOLUTE)
- else()
- set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION})
endif()
list(APPEND sycl_compiler_flags
-L "${MSVC_TOOLS_DIR}/lib/x64"
@@ -836,15 +846,13 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
set(sycl_compiler_flags_RelWithDebInfo ${sycl_compiler_flags})
set(sycl_compiler_flags_MinSizeRel ${sycl_compiler_flags})
list(APPEND sycl_compiler_flags_RelWithDebInfo -g)
- get_filename_component(sycl_library_debug_name ${SYCL_LIBRARY_DEBUG} NAME_WE)
list(APPEND sycl_compiler_flags_Debug
-g
-D_DEBUG
- -nostdlib -Xclang --dependent-lib=msvcrtd
- -Xclang --dependent-lib=${sycl_library_debug_name})
+ -nostdlib -Xclang --dependent-lib=msvcrtd)
add_custom_command(
- OUTPUT ${cycles_kernel_oneapi_lib}
+ OUTPUT ${cycles_kernel_oneapi_lib} ${cycles_kernel_oneapi_linker_lib}
COMMAND ${CMAKE_COMMAND} -E env
"LIB=${sycl_compiler_root}/../lib" # for compiler to find sycl.lib
"PATH=${OCLOC_INSTALL_DIR}\;${sycl_compiler_root}"
diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h
index 2ffe1496c72..b31ba479e4f 100644
--- a/intern/cycles/kernel/bvh/shadow_all.h
+++ b/intern/cycles/kernel/bvh/shadow_all.h
@@ -229,7 +229,7 @@ ccl_device_inline
/* Always use baked shadow transparency for curves. */
if (isect.type & PRIMITIVE_CURVE) {
*r_throughput *= intersection_curve_shadow_transparency(
- kg, isect.object, isect.prim, isect.u);
+ kg, isect.object, isect.prim, isect.type, isect.u);
if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
return true;
diff --git a/intern/cycles/kernel/bvh/util.h b/intern/cycles/kernel/bvh/util.h
index a57703a8b8c..9ba787550c5 100644
--- a/intern/cycles/kernel/bvh/util.h
+++ b/intern/cycles/kernel/bvh/util.h
@@ -190,10 +190,8 @@ ccl_device_inline int intersection_find_attribute(KernelGlobals kg,
/* Cut-off value to stop transparent shadow tracing when practically opaque. */
#define CURVE_SHADOW_TRANSPARENCY_CUTOFF 0.001f
-ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg,
- const int object,
- const int prim,
- const float u)
+ccl_device_inline float intersection_curve_shadow_transparency(
+ KernelGlobals kg, const int object, const int prim, const int type, const float u)
{
/* Find attribute. */
const int offset = intersection_find_attribute(kg, object, ATTR_STD_SHADOW_TRANSPARENCY);
@@ -204,7 +202,7 @@ ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg,
/* Interpolate transparency between curve keys. */
const KernelCurve kcurve = kernel_data_fetch(curves, prim);
- const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(kcurve.type);
+ const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
const int k1 = k0 + 1;
const float f0 = kernel_data_fetch(attributes_float, offset + k0);
diff --git a/intern/cycles/kernel/camera/projection.h b/intern/cycles/kernel/camera/projection.h
index c9fe3a6c7fb..1d16aa35abe 100644
--- a/intern/cycles/kernel/camera/projection.h
+++ b/intern/cycles/kernel/camera/projection.h
@@ -201,11 +201,35 @@ ccl_device float2 direction_to_mirrorball(float3 dir)
return make_float2(u, v);
}
+/* Single face of a equiangular cube map projection as described in
+ https://blog.google/products/google-ar-vr/bringing-pixels-front-and-center-vr-video/ */
+ccl_device float3 equiangular_cubemap_face_to_direction(float u, float v)
+{
+ u = (1.0f - u);
+
+ u = tanf(u * M_PI_2_F - M_PI_4_F);
+ v = tanf(v * M_PI_2_F - M_PI_4_F);
+
+ return make_float3(1.0f, u, v);
+}
+
+ccl_device float2 direction_to_equiangular_cubemap_face(float3 dir)
+{
+ float u = atan2f(dir.y, dir.x) * 2.0f / M_PI_F + 0.5f;
+ float v = atan2f(dir.z, dir.x) * 2.0f / M_PI_F + 0.5f;
+
+ u = 1.0f - u;
+
+ return make_float2(u, v);
+}
+
ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, float u, float v)
{
switch (cam->panorama_type) {
case PANORAMA_EQUIRECTANGULAR:
return equirectangular_range_to_direction(u, v, cam->equirectangular_range);
+ case PANORAMA_EQUIANGULAR_CUBEMAP_FACE:
+ return equiangular_cubemap_face_to_direction(u, v);
case PANORAMA_MIRRORBALL:
return mirrorball_to_direction(u, v);
case PANORAMA_FISHEYE_EQUIDISTANT:
@@ -230,6 +254,8 @@ ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, f
switch (cam->panorama_type) {
case PANORAMA_EQUIRECTANGULAR:
return direction_to_equirectangular_range(dir, cam->equirectangular_range);
+ case PANORAMA_EQUIANGULAR_CUBEMAP_FACE:
+ return direction_to_equiangular_cubemap_face(dir);
case PANORAMA_MIRRORBALL:
return direction_to_mirrorball(dir);
case PANORAMA_FISHEYE_EQUIDISTANT:
diff --git a/intern/cycles/kernel/device/cpu/bvh.h b/intern/cycles/kernel/device/cpu/bvh.h
index d9267e1cd6d..2d7d8c2d704 100644
--- a/intern/cycles/kernel/device/cpu/bvh.h
+++ b/intern/cycles/kernel/device/cpu/bvh.h
@@ -252,7 +252,7 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
/* Always use baked shadow transparency for curves. */
if (current_isect.type & PRIMITIVE_CURVE) {
ctx->throughput *= intersection_curve_shadow_transparency(
- kg, current_isect.object, current_isect.prim, current_isect.u);
+ kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u);
if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
ctx->opaque_hit = true;
diff --git a/intern/cycles/kernel/device/gpu/parallel_active_index.h b/intern/cycles/kernel/device/gpu/parallel_active_index.h
index c1df49c4f49..38cdcb572eb 100644
--- a/intern/cycles/kernel/device/gpu/parallel_active_index.h
+++ b/intern/cycles/kernel/device/gpu/parallel_active_index.h
@@ -23,22 +23,6 @@ CCL_NAMESPACE_BEGIN
* and keep device specific code in compat.h */
#ifdef __KERNEL_ONEAPI__
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
-template<typename IsActiveOp>
-void cpu_serial_active_index_array_impl(const uint num_states,
- ccl_global int *ccl_restrict indices,
- ccl_global int *ccl_restrict num_indices,
- IsActiveOp is_active_op)
-{
- int write_index = 0;
- for (int state_index = 0; state_index < num_states; state_index++) {
- if (is_active_op(state_index))
- indices[write_index++] = state_index;
- }
- *num_indices = write_index;
- return;
-}
-# endif /* WITH_ONEAPI_SYCL_HOST_ENABLED */
template<typename IsActiveOp>
void gpu_parallel_active_index_array_impl(const uint num_states,
@@ -182,18 +166,11 @@ __device__
num_simd_groups, \
simdgroup_offset)
#elif defined(__KERNEL_ONEAPI__)
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
-# define gpu_parallel_active_index_array( \
- blocksize, num_states, indices, num_indices, is_active_op) \
- if (ccl_gpu_global_size_x() == 1) \
- cpu_serial_active_index_array_impl(num_states, indices, num_indices, is_active_op); \
- else \
- gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op);
-# else
-# define gpu_parallel_active_index_array( \
- blocksize, num_states, indices, num_indices, is_active_op) \
- gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op)
-# endif
+
+# define gpu_parallel_active_index_array( \
+ blocksize, num_states, indices, num_indices, is_active_op) \
+ gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op)
+
#else
# define gpu_parallel_active_index_array( \
diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h
index 99cb1e3826e..e75ec9cadec 100644
--- a/intern/cycles/kernel/device/metal/context_begin.h
+++ b/intern/cycles/kernel/device/metal/context_begin.h
@@ -34,21 +34,48 @@ class MetalKernelContext {
kernel_assert(0);
return 0;
}
-
+
+#ifdef __KERNEL_METAL_INTEL__
+ template<typename TextureType, typename CoordsType>
+ inline __attribute__((__always_inline__))
+ auto ccl_gpu_tex_object_read_intel_workaround(TextureType texture_array,
+ const uint tid, const uint sid,
+ CoordsType coords) const
+ {
+ switch(sid) {
+ default:
+ case 0: return texture_array[tid].tex.sample(sampler(address::repeat, filter::nearest), coords);
+ case 1: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::nearest), coords);
+ case 2: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::nearest), coords);
+ case 3: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords);
+ case 4: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords);
+ case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords);
+ }
+ }
+#endif
+
// texture2d
template<>
inline __attribute__((__always_inline__))
float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y));
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y));
+#endif
}
template<>
inline __attribute__((__always_inline__))
float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x;
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y)).x;
+#endif
}
// texture3d
@@ -57,14 +84,22 @@ class MetalKernelContext {
float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z));
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z));
+#endif
}
template<>
inline __attribute__((__always_inline__))
float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x;
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z)).x;
+#endif
}
# include "kernel/device/gpu/image.h"
diff --git a/intern/cycles/kernel/device/metal/kernel.metal b/intern/cycles/kernel/device/metal/kernel.metal
index 5646c7446db..8b69ee025cd 100644
--- a/intern/cycles/kernel/device/metal/kernel.metal
+++ b/intern/cycles/kernel/device/metal/kernel.metal
@@ -228,7 +228,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
/* Always use baked shadow transparency for curves. */
if (type & PRIMITIVE_CURVE) {
float throughput = payload.throughput;
- throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, u);
+ throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, type, u);
payload.throughput = throughput;
payload.num_hits += 1;
diff --git a/intern/cycles/kernel/device/oneapi/compat.h b/intern/cycles/kernel/device/oneapi/compat.h
index 8ae40b0612e..dfaec65130c 100644
--- a/intern/cycles/kernel/device/oneapi/compat.h
+++ b/intern/cycles/kernel/device/oneapi/compat.h
@@ -55,18 +55,6 @@
#define ccl_gpu_kernel(block_num_threads, thread_num_registers)
#define ccl_gpu_kernel_threads(block_num_threads)
-#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
-# define KG_ND_ITEMS \
- kg->nd_item_local_id_0 = item.get_local_id(0); \
- kg->nd_item_local_range_0 = item.get_local_range(0); \
- kg->nd_item_group_0 = item.get_group(0); \
- kg->nd_item_group_range_0 = item.get_group_range(0); \
- kg->nd_item_global_id_0 = item.get_global_id(0); \
- kg->nd_item_global_range_0 = item.get_global_range(0);
-#else
-# define KG_ND_ITEMS
-#endif
-
#define ccl_gpu_kernel_signature(name, ...) \
void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
size_t kernel_global_size, \
@@ -76,8 +64,7 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
(kg); \
cgh.parallel_for<class kernel_##name>( \
sycl::nd_range<1>(kernel_global_size, kernel_local_size), \
- [=](sycl::nd_item<1> item) { \
- KG_ND_ITEMS
+ [=](sycl::nd_item<1> item) {
#define ccl_gpu_kernel_postfix \
}); \
@@ -95,31 +82,17 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
} ccl_gpu_kernel_lambda_pass((ONEAPIKernelContext *)kg)
/* GPU thread, block, grid size and index */
-#ifndef WITH_ONEAPI_SYCL_HOST_ENABLED
-# define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0))
-# define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0))
-# define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0))
-# define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0))
-# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0])
-# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
-
-# define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0))
-# define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0))
-#else
-# define ccl_gpu_thread_idx_x (kg->nd_item_local_id_0)
-# define ccl_gpu_block_dim_x (kg->nd_item_local_range_0)
-# define ccl_gpu_block_idx_x (kg->nd_item_group_0)
-# define ccl_gpu_grid_dim_x (kg->nd_item_group_range_0)
-# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0])
-# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
-
-# define ccl_gpu_global_id_x() (kg->nd_item_global_id_0)
-# define ccl_gpu_global_size_x() (kg->nd_item_global_range_0)
-#endif
+#define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0))
+#define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0))
+#define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0))
+#define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0))
+#define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0])
+#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
+#define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0))
+#define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0))
/* GPU warp synchronization */
-
#define ccl_gpu_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier()
#define ccl_gpu_local_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier(sycl::access::fence_space::local_space)
#ifdef __SYCL_DEVICE_ONLY__
diff --git a/intern/cycles/kernel/device/oneapi/globals.h b/intern/cycles/kernel/device/oneapi/globals.h
index d60f4f135ba..116620eb725 100644
--- a/intern/cycles/kernel/device/oneapi/globals.h
+++ b/intern/cycles/kernel/device/oneapi/globals.h
@@ -23,15 +23,6 @@ typedef struct KernelGlobalsGPU {
#undef KERNEL_DATA_ARRAY
IntegratorStateGPU *integrator_state;
const KernelData *__data;
-#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
- size_t nd_item_local_id_0;
- size_t nd_item_local_range_0;
- size_t nd_item_group_0;
- size_t nd_item_group_range_0;
-
- size_t nd_item_global_id_0;
- size_t nd_item_global_range_0;
-#endif
} KernelGlobalsGPU;
typedef ccl_global KernelGlobalsGPU *ccl_restrict KernelGlobals;
diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp
index 40e0b1f0b2b..525ae288f0c 100644
--- a/intern/cycles/kernel/device/oneapi/kernel.cpp
+++ b/intern/cycles/kernel/device/oneapi/kernel.cpp
@@ -8,7 +8,7 @@
# include <map>
# include <set>
-# include <CL/sycl.hpp>
+# include <sycl/sycl.hpp>
# include "kernel/device/oneapi/compat.h"
# include "kernel/device/oneapi/globals.h"
@@ -144,6 +144,10 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
{
+# ifdef SYCL_SKIP_KERNELS_PRELOAD
+ (void)queue_;
+ (void)requested_features;
+# else
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
@@ -175,7 +179,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
sycl::kernel_bundle<sycl::bundle_state::input> one_kernel_bundle =
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(), {kernel_id});
- sycl::build(one_kernel_bundle, {queue->get_device()}, sycl::property::queue::in_order());
+ sycl::build(one_kernel_bundle);
}
}
catch (sycl::exception const &e) {
@@ -184,7 +188,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
}
return false;
}
-
+# endif
return true;
}
@@ -226,13 +230,6 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
/* NOTE(@nsirgien): As for now non-uniform work-groups don't work on most oneAPI devices,
* we extend work size to fit uniformity requirements. */
global_size = groups_count * local_size;
-
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
- if (queue->get_device().is_host()) {
- global_size = 1;
- local_size = 1;
- }
-# endif
}
/* Let the compiler throw an error if there are any kernels missing in this implementation. */
diff --git a/intern/cycles/kernel/device/optix/bvh.h b/intern/cycles/kernel/device/optix/bvh.h
index fb9907709ce..6d81b44660c 100644
--- a/intern/cycles/kernel/device/optix/bvh.h
+++ b/intern/cycles/kernel/device/optix/bvh.h
@@ -202,7 +202,7 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit()
/* Always use baked shadow transparency for curves. */
if (type & PRIMITIVE_CURVE) {
float throughput = __uint_as_float(optixGetPayload_1());
- throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, u);
+ throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, type, u);
optixSetPayload_1(__float_as_uint(throughput));
optixSetPayload_2(uint16_pack_to_uint(num_recorded_hits, num_hits + 1));
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 8f7cfd19169..24c5a6a4540 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -490,6 +490,7 @@ enum PanoramaType {
PANORAMA_FISHEYE_EQUISOLID = 2,
PANORAMA_MIRRORBALL = 3,
PANORAMA_FISHEYE_LENS_POLYNOMIAL = 4,
+ PANORAMA_EQUIANGULAR_CUBEMAP_FACE = 5,
PANORAMA_NUM_TYPES,
};
diff --git a/intern/cycles/scene/camera.cpp b/intern/cycles/scene/camera.cpp
index 240e5d9c128..255dd320ec7 100644
--- a/intern/cycles/scene/camera.cpp
+++ b/intern/cycles/scene/camera.cpp
@@ -84,6 +84,7 @@ NODE_DEFINE(Camera)
static NodeEnum panorama_type_enum;
panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
+ panorama_type_enum.insert("equiangular_cubemap_face", PANORAMA_EQUIANGULAR_CUBEMAP_FACE);
panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL);
panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT);
panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID);
diff --git a/intern/cycles/util/transform_inverse.h b/intern/cycles/util/transform_inverse.h
index b72bbc5f680..bb410a6daef 100644
--- a/intern/cycles/util/transform_inverse.h
+++ b/intern/cycles/util/transform_inverse.h
@@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_forceinline float3 transform_inverse_cross(const float3 a, const float3 b)
{
-#ifdef __AVX2__
+#if defined(__AVX2__) && defined(__KERNEL_SSE2__)
const ssef sse_a = (const __m128 &)a;
const ssef sse_b = (const __m128 &)b;
const ssef r = shuffle<1, 2, 0, 3>(
diff --git a/intern/cycles/util/types_float3.h b/intern/cycles/util/types_float3.h
index 87c6b1d3654..34430945c38 100644
--- a/intern/cycles/util/types_float3.h
+++ b/intern/cycles/util/types_float3.h
@@ -10,7 +10,12 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_NATIVE_VECTOR_TYPES__
+# ifdef __KERNEL_ONEAPI__
+/* Define float3 as packed for oneAPI. */
+struct float3
+# else
struct ccl_try_align(16) float3
+# endif
{
# ifdef __KERNEL_GPU__
/* Compact structure for GPU. */
diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc
index d0c40736884..e5c33202417 100644
--- a/intern/ffmpeg/tests/ffmpeg_codecs.cc
+++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc
@@ -130,6 +130,7 @@ FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_DVVIDEO, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG1VIDEO, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG2VIDEO, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_FLV1, AV_PIX_FMT_YUV420P)
+FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_AV1, AV_PIX_FMT_YUV420P)
/* Audio codecs */
@@ -149,6 +150,12 @@ FFMPEG_TEST_VCODEC_NAME(libx264, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_NAME(libvpx, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_NAME(libopenjpeg, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_NAME(libxvid, AV_PIX_FMT_YUV420P)
+/* aom's AV1 encoder is "libaom-av1". FFMPEG_TEST_VCODEC_NAME(libaom-av1, ...)
+ * will not work because the dash will not work with the test macro. */
+TEST(ffmpeg, libaom_av1_AV_PIX_FMT_YUV420P)
+{
+ EXPECT_TRUE(test_codec_video_by_name("libaom-av1", AV_PIX_FMT_YUV420P));
+}
FFMPEG_TEST_ACODEC_NAME(libvorbis, AV_SAMPLE_FMT_FLTP)
FFMPEG_TEST_ACODEC_NAME(libopus, AV_SAMPLE_FMT_FLT)
FFMPEG_TEST_ACODEC_NAME(libmp3lame, AV_SAMPLE_FMT_FLTP)
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 2f8ea1f9065..ea21d831b0c 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -268,7 +268,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND_DYNLOAD)
list(APPEND INC_SYS
- ../../intern/wayland_dynload/extern
+ ../wayland_dynload/extern
)
list(APPEND LIB
bf_intern_wayland_dynload
@@ -372,14 +372,22 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
)
+ # Pointer-gestures (multi-touch).
+ generate_protocol_bindings(
+ "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml"
+ )
# Tablet.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml"
)
-
- add_definitions(-DWITH_GHOST_WAYLAND)
+ # Primary-selection.
+ generate_protocol_bindings(
+ "${WAYLAND_PROTOCOLS_DIR}/unstable/primary-selection/primary-selection-unstable-v1.xml"
+ )
unset(INC_DST)
+
+ add_definitions(-DWITH_GHOST_WAYLAND)
endif()
if(WITH_INPUT_NDOF)
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 7fda535a7ac..62984c762c1 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -162,7 +162,6 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL options.
* \return A handle to the new window ( == NULL if creation failed).
*/
@@ -175,7 +174,6 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
/**
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 9fb94ed1525..edaeca1e159 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -118,9 +118,11 @@ class GHOST_ISystem {
/**
* Creates the one and only system.
* \param verbose: report back-ends that were attempted no back-end could be loaded.
+ * \param background: loading the system for background rendering (no visible windows).
* \return An indication of success.
*/
- static GHOST_TSuccess createSystem(bool verbose);
+
+ static GHOST_TSuccess createSystem(bool verbose, bool background);
static GHOST_TSuccess createSystemBackground();
/**
@@ -232,7 +234,6 @@ class GHOST_ISystem {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
@@ -245,7 +246,6 @@ class GHOST_ISystem {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 2645ce448b0..db4eeff3122 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -60,10 +60,6 @@ typedef struct {
int hot_spot[2];
} GHOST_CursorBitmapRef;
-typedef struct {
- int flags;
-} GHOST_GLSettings;
-
typedef enum {
GHOST_glStereoVisual = (1 << 0),
GHOST_glDebugContext = (1 << 1),
@@ -157,6 +153,9 @@ typedef enum {
#ifdef WIN32
GHOST_kDrawingContextTypeD3D,
#endif
+#ifdef __APPLE__
+ GHOST_kDrawingContextTypeMetal,
+#endif
} GHOST_TDrawingContextType;
typedef enum {
@@ -598,6 +597,11 @@ typedef struct {
uint32_t frequency;
} GHOST_DisplaySetting;
+typedef struct {
+ int flags;
+ GHOST_TDrawingContextType context_type;
+} GHOST_GLSettings;
+
typedef enum {
/** Axis that cursor grab will wrap. */
GHOST_kDebugDefault = (1 << 1),
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 158e979cdf2..0c595b27148 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -24,7 +24,7 @@
GHOST_SystemHandle GHOST_CreateSystem(void)
{
- GHOST_ISystem::createSystem(true);
+ GHOST_ISystem::createSystem(true, false);
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return (GHOST_SystemHandle)system;
@@ -161,7 +161,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -172,7 +171,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
width,
height,
state,
- type,
glSettings,
false,
is_dialog,
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index 130b926f25c..d19fffffb43 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -30,7 +30,8 @@ class GHOST_ContextCGL : public GHOST_Context {
GHOST_ContextCGL(bool stereoVisual,
NSView *metalView,
CAMetalLayer *metalLayer,
- NSOpenGLView *openglView);
+ NSOpenGLView *openglView,
+ GHOST_TDrawingContextType type);
/**
* Destructor.
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index ff53ecdbbba..9dad337a5d6 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -46,8 +46,10 @@ int GHOST_ContextCGL::s_sharedCount = 0;
GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
NSView *metalView,
CAMetalLayer *metalLayer,
- NSOpenGLView *openGLView)
+ NSOpenGLView *openGLView,
+ GHOST_TDrawingContextType type)
: GHOST_Context(stereoVisual),
+ m_useMetalForRendering(type == GHOST_kDrawingContextTypeMetal),
m_metalView(metalView),
m_metalLayer(metalLayer),
m_metalCmdQueue(nil),
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
index 93708983f37..d9f2df21ee0 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.cpp
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -140,7 +140,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
/* End Inline GLEW. */
/* -------------------------------------------------------------------- */
#else
- /* Important to initialize only glxew (_not_ GLEW),
+ /* Important to initialize only GLXEW (_not_ GLEW),
* since this breaks w/ Mesa's `swrast`, see: T46431. */
glxewInit();
#endif /* USE_GLXEW_INIT_WORKAROUND */
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index ec1a0b34be6..64eff7f9aed 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -15,29 +15,41 @@
# endif
#endif
-#if defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))
-# include <iostream>
-# include <stdio.h> //for printf()
-#endif // WITH_GHOST_DEBUG
+#include <iostream>
+#include <stdio.h> /* For `printf()`. */
#if defined(WITH_GHOST_DEBUG)
# define GHOST_PRINT(x) \
{ \
std::cout << x; \
} \
- (void)0
+ ((void)0)
# define GHOST_PRINTF(x, ...) \
{ \
printf(x, __VA_ARGS__); \
} \
- (void)0
+ ((void)0)
#else
-# define GHOST_PRINT(x)
-# define GHOST_PRINTF(x, ...)
+/* Expand even when `WITH_GHOST_DEBUG` is disabled to prevent expressions
+ * becoming invalid even when the option is disable. */
+# define GHOST_PRINT(x) \
+ { \
+ if (false) { \
+ std::cout << x; \
+ } \
+ } \
+ ((void)0)
+# define GHOST_PRINTF(x, ...) \
+ { \
+ if (false) { \
+ printf(x, __VA_ARGS__); \
+ } \
+ } \
+ ((void)0)
+
#endif /* `!defined(WITH_GHOST_DEBUG)` */
#ifdef WITH_ASSERT_ABORT
-# include <stdio.h> //for fprintf()
# include <stdlib.h> //for abort()
# define GHOST_ASSERT(x, info) \
{ \
@@ -48,7 +60,7 @@
abort(); \
} \
} \
- (void)0
+ ((void)0)
/* Assert in non-release builds too. */
#elif defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))
# define GHOST_ASSERT(x, info) \
@@ -59,7 +71,7 @@
GHOST_PRINT("\n"); \
} \
} \
- (void)0
+ ((void)0)
#else /* `defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))` */
# define GHOST_ASSERT(x, info) ((void)0)
#endif /* `defined(WITH_GHOST_DEBUG) || (!defined(NDEBUG))` */
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 8e2859ca1e1..696848ce623 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -34,7 +34,7 @@ const char *GHOST_ISystem::m_system_backend_id = nullptr;
GHOST_TBacktraceFn GHOST_ISystem::m_backtrace_fn = nullptr;
-GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
+GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose, [[maybe_unused]] bool background)
{
/* When GHOST fails to start, report the back-ends that were attempted.
* A Verbose argument could be supported in printing isn't always desired. */
@@ -61,7 +61,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
if (has_wayland_libraries) {
backends_attempted[backends_attempted_num++] = "WAYLAND";
try {
- m_system = new GHOST_SystemWayland();
+ m_system = new GHOST_SystemWayland(background);
}
catch (const std::runtime_error &) {
delete m_system;
@@ -99,7 +99,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
if (has_wayland_libraries) {
backends_attempted[backends_attempted_num++] = "WAYLAND";
try {
- m_system = new GHOST_SystemWayland();
+ m_system = new GHOST_SystemWayland(background);
}
catch (const std::runtime_error &) {
delete m_system;
@@ -160,7 +160,7 @@ GHOST_TSuccess GHOST_ISystem::createSystemBackground()
if (!m_system) {
#if !defined(WITH_HEADLESS)
/* Try to create a off-screen render surface with the graphical systems. */
- success = createSystem(false);
+ success = createSystem(false, true);
if (success) {
return success;
}
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index 85c8ed7b4bd..cb6d8a770cf 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -266,7 +266,7 @@ class GHOST_ImeWin32 {
* Parameters
* * window_handle [in] (HWND)
* Represents the window handle of the caller.
- * * caret_rect [in] (const gfx::Rect&)
+ * * caret_rect [in] (`const gfx::Rect&`)
* Represent the rectangle of the input caret.
* This rectangle is used for controlling the positions of IME windows.
* * complete [in] (bool)
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index f4c726c7450..5484da82a18 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -12,11 +12,14 @@
#include <climits>
#include <cmath>
-#include <cstdio> /* For error/info reporting. */
#include <cstring> /* For memory functions. */
-/* Printable version of each GHOST_TProgress value. */
-static const char *progress_string[] = {
+/* -------------------------------------------------------------------- */
+/** \name NDOF Enum Strings
+ * \{ */
+
+/* Printable values for #GHOST_TProgress enum (keep aligned). */
+static const char *ndof_progress_string[] = {
"not started",
"starting",
"in progress",
@@ -24,41 +27,30 @@ static const char *progress_string[] = {
"finished",
};
+/* Printable values for #NDOF_ButtonT enum (keep aligned) */
static const char *ndof_button_names[] = {
- /* used internally, never sent */
- "NDOF_BUTTON_NONE",
- /* these two are available from any 3Dconnexion device */
+ /* Exclude `NDOF_BUTTON_NONE` (-1). */
"NDOF_BUTTON_MENU",
"NDOF_BUTTON_FIT",
- /* standard views */
"NDOF_BUTTON_TOP",
"NDOF_BUTTON_BOTTOM",
"NDOF_BUTTON_LEFT",
"NDOF_BUTTON_RIGHT",
"NDOF_BUTTON_FRONT",
"NDOF_BUTTON_BACK",
- /* more views */
"NDOF_BUTTON_ISO1",
"NDOF_BUTTON_ISO2",
- /* 90 degree rotations */
"NDOF_BUTTON_ROLL_CW",
"NDOF_BUTTON_ROLL_CCW",
"NDOF_BUTTON_SPIN_CW",
"NDOF_BUTTON_SPIN_CCW",
"NDOF_BUTTON_TILT_CW",
"NDOF_BUTTON_TILT_CCW",
- /* device control */
"NDOF_BUTTON_ROTATE",
"NDOF_BUTTON_PANZOOM",
"NDOF_BUTTON_DOMINANT",
"NDOF_BUTTON_PLUS",
"NDOF_BUTTON_MINUS",
- /* keyboard emulation */
- "NDOF_BUTTON_ESC",
- "NDOF_BUTTON_ALT",
- "NDOF_BUTTON_SHIFT",
- "NDOF_BUTTON_CTRL",
- /* general-purpose buttons */
"NDOF_BUTTON_1",
"NDOF_BUTTON_2",
"NDOF_BUTTON_3",
@@ -69,18 +61,47 @@ static const char *ndof_button_names[] = {
"NDOF_BUTTON_8",
"NDOF_BUTTON_9",
"NDOF_BUTTON_10",
- /* more general-purpose buttons */
"NDOF_BUTTON_A",
"NDOF_BUTTON_B",
"NDOF_BUTTON_C",
- /* the end */
- "NDOF_BUTTON_LAST",
+ "NDOF_BUTTON_V1",
+ "NDOF_BUTTON_V2",
+ "NDOF_BUTTON_V3",
+ /* Keyboard emulation. */
+ "NDOF_BUTTON_ESC",
+ "NDOF_BUTTON_ENTER",
+ "NDOF_BUTTON_DELETE",
+ "NDOF_BUTTON_TAB",
+ "NDOF_BUTTON_SPACE",
+ "NDOF_BUTTON_ALT",
+ "NDOF_BUTTON_SHIFT",
+ "NDOF_BUTTON_CTRL",
};
+static const char *ndof_device_names[] = {
+ "UnknownDevice",
+ "SpaceNavigator",
+ "SpaceExplorer",
+ "SpacePilotPro",
+ "SpaceMousePro",
+ "SpaceMouseWireless",
+ "SpaceMouseProWireless",
+ "SpaceMouseEnterprise",
+ "SpacePilot",
+ "Spaceball5000",
+ "SpaceTraveler",
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Button Maps
+ * \{ */
+
/* Shared by the latest 3Dconnexion hardware
* SpacePilotPro uses all of these
* smaller devices use only some, based on button mask. */
-static const NDOF_ButtonT Modern3Dx_HID_map[] = {
+static const NDOF_ButtonT ndof_HID_map_Modern3Dx[] = {
NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_BOTTOM, NDOF_BUTTON_BACK,
NDOF_BUTTON_ROLL_CW, NDOF_BUTTON_ROLL_CCW, NDOF_BUTTON_ISO1, NDOF_BUTTON_ISO2,
@@ -90,7 +111,7 @@ static const NDOF_ButtonT Modern3Dx_HID_map[] = {
NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, NDOF_BUTTON_ROTATE, NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS};
-static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
+static const NDOF_ButtonT ndof_HID_map_SpaceExplorer[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_TOP,
@@ -108,9 +129,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
NDOF_BUTTON_ROTATE,
};
-/* This is the older SpacePilot (sans Pro)
- * thanks to polosson for info about this device. */
-static const NDOF_ButtonT SpacePilot_HID_map[] = {
+/* This is the older SpacePilot (sans Pro). */
+static const NDOF_ButtonT ndof_HID_map_SpacePilot[] = {
NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, NDOF_BUTTON_4,
NDOF_BUTTON_5, NDOF_BUTTON_6, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_ESC, NDOF_BUTTON_ALT,
@@ -119,7 +139,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_NONE /* the CONFIG button -- what does it do? */
};
-static const NDOF_ButtonT Generic_HID_map[] = {
+static const NDOF_ButtonT ndof_HID_map_Generic[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
@@ -134,27 +154,70 @@ static const NDOF_ButtonT Generic_HID_map[] = {
NDOF_BUTTON_C,
};
-static const int genericButtonCount = ARRAY_SIZE(Generic_HID_map);
+/* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */
+static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = {
+ NDOF_BUTTON_1, /* (0) */
+ NDOF_BUTTON_2, /* (1) */
+ NDOF_BUTTON_3, /* (2) */
+ NDOF_BUTTON_4, /* (3) */
+ NDOF_BUTTON_5, /* (4) */
+ NDOF_BUTTON_6, /* (5) */
+ NDOF_BUTTON_7, /* (6) */
+ NDOF_BUTTON_8, /* (7) */
+ NDOF_BUTTON_9, /* (8) */
+ NDOF_BUTTON_A, /* Labeled "10" (9). */
+ NDOF_BUTTON_B, /* Labeled "11" (10). */
+ NDOF_BUTTON_C, /* Labeled "12" (11). */
+ NDOF_BUTTON_MENU, /* (12). */
+ NDOF_BUTTON_FIT, /* (13). */
+ NDOF_BUTTON_TOP, /* (14). */
+ NDOF_BUTTON_RIGHT, /* (15). */
+ NDOF_BUTTON_FRONT, /* (16). */
+ NDOF_BUTTON_ROLL_CW, /* (17). */
+ NDOF_BUTTON_ESC, /* (18). */
+ NDOF_BUTTON_ALT, /* (19). */
+ NDOF_BUTTON_SHIFT, /* (20). */
+ NDOF_BUTTON_CTRL, /* (21). */
+ NDOF_BUTTON_ROTATE, /* Labeled "Lock Rotate" (22). */
+ NDOF_BUTTON_ENTER, /* Labeled "Enter" (23). */
+ NDOF_BUTTON_DELETE, /* (24). */
+ NDOF_BUTTON_TAB, /* (25). */
+ NDOF_BUTTON_SPACE, /* (26). */
+ NDOF_BUTTON_V1, /* Labeled "V1" (27). */
+ NDOF_BUTTON_V2, /* Labeled "V2" (28). */
+ NDOF_BUTTON_V3, /* Labeled "V3" (29). */
+ NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Manager Class
+ * \{ */
+
+static const int genericButtonCount = ARRAY_SIZE(ndof_HID_map_Generic);
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys)
- : m_system(sys),
- m_deviceType(NDOF_UnknownDevice), /* Each platform has its own device detection code. */
- m_buttonCount(genericButtonCount),
- m_buttonMask(0),
- m_hidMap(Generic_HID_map),
- m_buttons(0),
- m_motionTime(0),
- m_prevMotionTime(0),
- m_motionState(GHOST_kNotStarted),
- m_motionEventPending(false),
- m_deadZone(0.0f)
+ : system_(sys),
+ device_type_(NDOF_UnknownDevice), /* Each platform has its own device detection code. */
+ hid_map_button_num_(genericButtonCount),
+ hid_map_button_mask_(0),
+ hid_map_(ndof_HID_map_Generic),
+ button_depressed_(0),
+ motion_time_(0),
+ motion_time_prev_(0),
+ motion_state_(GHOST_kNotStarted),
+ motion_event_pending_(false),
+ motion_dead_zone_(0.0f)
{
/* To avoid the rare situation where one triple is updated and
* the other is not, initialize them both here: */
- memset(m_translation, 0, sizeof(m_translation));
- memset(m_rotation, 0, sizeof(m_rotation));
+ memset(translation_, 0, sizeof(translation_));
+ memset(rotation_, 0, sizeof(rotation_));
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name NDOF Device Setup
* \{ */
@@ -166,16 +229,16 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
{
/* Call this function until it returns true
* it's a good idea to stop calling it after that, as it will "forget"
- * whichever device it already found */
+ * whichever device it already found. */
/* Default to safe generic behavior for "unknown" devices
* unidentified devices will emit motion events like normal
* rogue buttons do nothing by default, but can be customized by the user. */
- m_deviceType = NDOF_UnknownDevice;
- m_hidMap = Generic_HID_map;
- m_buttonCount = genericButtonCount;
- m_buttonMask = 0;
+ device_type_ = NDOF_UnknownDevice;
+ hid_map_ = ndof_HID_map_Generic;
+ hid_map_button_num_ = genericButtonCount;
+ hid_map_button_mask_ = 0;
/* "mystery device" owners can help build a HID_map for their hardware
* A few users have already contributed information about several older devices
@@ -185,96 +248,102 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
case 0x046D: /* Logitech (3Dconnexion was a subsidiary). */
switch (product_id) {
/* -- current devices -- */
- case 0xC626: /* full-size SpaceNavigator */
- case 0xC628: /* the "for Notebooks" one */
- puts("ndof: using SpaceNavigator");
- m_deviceType = NDOF_SpaceNavigator;
- m_buttonCount = 2;
- m_hidMap = Modern3Dx_HID_map;
+ case 0xC626: /* Full-size SpaceNavigator. */
+ case 0xC628: /* The "for Notebooks" one. */
+ {
+ device_type_ = NDOF_SpaceNavigator;
+ hid_map_button_num_ = 2;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
- case 0xC627:
- puts("ndof: using SpaceExplorer");
- m_deviceType = NDOF_SpaceExplorer;
- m_buttonCount = 15;
- m_hidMap = SpaceExplorer_HID_map;
+ }
+ case 0xC627: {
+ device_type_ = NDOF_SpaceExplorer;
+ hid_map_button_num_ = 15;
+ hid_map_ = ndof_HID_map_SpaceExplorer;
break;
- case 0xC629:
- puts("ndof: using SpacePilot Pro");
- m_deviceType = NDOF_SpacePilotPro;
- m_buttonCount = 31;
- m_hidMap = Modern3Dx_HID_map;
+ }
+ case 0xC629: {
+ device_type_ = NDOF_SpacePilotPro;
+ hid_map_button_num_ = 31;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
- case 0xC62B:
- puts("ndof: using SpaceMouse Pro");
- m_deviceType = NDOF_SpaceMousePro;
- m_buttonCount = 27;
- /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26 */
- m_buttonMask = 0x07C0F137;
- m_hidMap = Modern3Dx_HID_map;
+ }
+ case 0xC62B: {
+ device_type_ = NDOF_SpaceMousePro;
+ hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */
+ hid_map_button_mask_ = 0x07C0F137;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
+ }
/* -- older devices -- */
- case 0xC625:
- puts("ndof: using SpacePilot");
- m_deviceType = NDOF_SpacePilot;
- m_buttonCount = 21;
- m_hidMap = SpacePilot_HID_map;
+ case 0xC625: {
+ device_type_ = NDOF_SpacePilot;
+ hid_map_button_num_ = 21;
+ hid_map_ = ndof_HID_map_SpacePilot;
break;
- case 0xC621:
- puts("ndof: using Spaceball 5000");
- m_deviceType = NDOF_Spaceball5000;
- m_buttonCount = 12;
+ }
+ case 0xC621: {
+ device_type_ = NDOF_Spaceball5000;
+ hid_map_button_num_ = 12;
break;
- case 0xC623:
- puts("ndof: using SpaceTraveler");
- m_deviceType = NDOF_SpaceTraveler;
- m_buttonCount = 8;
+ }
+ case 0xC623: {
+ device_type_ = NDOF_SpaceTraveler;
+ hid_map_button_num_ = 8;
break;
-
- default:
- printf("ndof: unknown Logitech product %04hx\n", product_id);
+ }
+ default: {
+ CLOG_INFO(LOG, 2, "unknown Logitech product %04hx", product_id);
+ }
}
break;
- case 0x256F: /* 3Dconnexion */
+ case 0x256F: /* 3Dconnexion. */
switch (product_id) {
case 0xC62E: /* Plugged in. */
case 0xC62F: /* Wireless. */
- puts("ndof: using SpaceMouse Wireless");
- m_deviceType = NDOF_SpaceMouseWireless;
- m_buttonCount = 2;
- m_hidMap = Modern3Dx_HID_map;
+ case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see T82412. */
+ {
+ device_type_ = NDOF_SpaceMouseWireless;
+ hid_map_button_num_ = 2;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
+ }
case 0xC631: /* Plugged in. */
case 0xC632: /* Wireless. */
- puts("ndof: using SpaceMouse Pro Wireless");
- m_deviceType = NDOF_SpaceMouseProWireless;
- m_buttonCount = 27;
- /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26. */
- m_buttonMask = 0x07C0F137;
- m_hidMap = Modern3Dx_HID_map;
+ {
+ device_type_ = NDOF_SpaceMouseProWireless;
+ hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */
+ hid_map_button_mask_ = 0x07C0F137;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
- case 0xC633:
- puts("ndof: using SpaceMouse Enterprise");
- m_deviceType = NDOF_SpaceMouseEnterprise;
- m_buttonCount = 31;
- m_hidMap = Modern3Dx_HID_map;
+ }
+ case 0xC633: {
+ device_type_ = NDOF_SpaceMouseEnterprise;
+ hid_map_button_num_ = 31;
+ hid_map_ = ndof_HID_map_SpaceMouseEnterprise;
break;
-
- default:
- printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
+ }
+ default: {
+ CLOG_INFO(LOG, 2, "unknown 3Dconnexion product %04hx", product_id);
+ }
}
break;
default:
- printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id);
+ CLOG_INFO(LOG, 2, "unknown device %04hx:%04hx", vendor_id, product_id);
+ }
+
+ if (device_type_ != NDOF_UnknownDevice) {
+ CLOG_INFO(LOG, 2, "using %s", ndof_device_names[device_type_]);
}
- if (m_buttonMask == 0) {
- m_buttonMask = int(~(UINT_MAX << m_buttonCount));
+ if (hid_map_button_mask_ == 0) {
+ hid_map_button_mask_ = int(~(UINT_MAX << hid_map_button_num_));
}
- CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", m_buttonCount, (uint)m_buttonMask);
+ CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, (uint)hid_map_button_mask_);
- return m_deviceType != NDOF_UnknownDevice;
+ return device_type_ != NDOF_UnknownDevice;
}
#undef LOG
@@ -287,16 +356,16 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time)
{
- memcpy(m_translation, t, sizeof(m_translation));
- m_motionTime = time;
- m_motionEventPending = true;
+ memcpy(translation_, t, sizeof(translation_));
+ motion_time_ = time;
+ motion_event_pending_ = true;
}
void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time)
{
- memcpy(m_rotation, r, sizeof(m_rotation));
- m_motionTime = time;
- m_motionEventPending = true;
+ memcpy(rotation_, r, sizeof(rotation_));
+ motion_time_ = time;
+ motion_event_pending_ = true;
}
/** \} */
@@ -314,6 +383,18 @@ static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const NDOF_ButtonT button)
case NDOF_BUTTON_ESC: {
return GHOST_kKeyEsc;
}
+ case NDOF_BUTTON_ENTER: {
+ return GHOST_kKeyEnter;
+ }
+ case NDOF_BUTTON_DELETE: {
+ return GHOST_kKeyDelete;
+ }
+ case NDOF_BUTTON_TAB: {
+ return GHOST_kKeyTab;
+ }
+ case NDOF_BUTTON_SPACE: {
+ return GHOST_kKeySpace;
+ }
case NDOF_BUTTON_ALT: {
return GHOST_kKeyLeftAlt;
}
@@ -334,7 +415,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
uint64_t time,
GHOST_IWindow *window)
{
- GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_LAST,
+ GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM,
"rogue button trying to escape NDOF manager");
GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
@@ -343,7 +424,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
data->action = press ? GHOST_kPress : GHOST_kRelease;
data->button = button;
- m_system.pushEvent(event);
+ system_.pushEvent(event);
}
void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
@@ -354,21 +435,21 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
- m_system.pushEvent(event);
+ system_.pushEvent(event);
}
void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time)
{
- if (button_number >= m_buttonCount) {
+ if (button_number >= hid_map_button_num_) {
CLOG_INFO(LOG,
2,
"button=%d, press=%d (out of range %d, ignoring!)",
button_number,
(int)press,
- m_buttonCount);
+ hid_map_button_num_);
return;
}
- const NDOF_ButtonT button = m_hidMap[button_number];
+ const NDOF_ButtonT button = hid_map_[button_number];
if (button == NDOF_BUTTON_NONE) {
CLOG_INFO(
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press);
@@ -382,7 +463,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
(int)press,
ndof_button_names[button]);
- GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow();
+ GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();
const GHOST_TKey key = ghost_map_keyboard_from_ndof_buttom(button);
if (key != GHOST_kKeyUnknown) {
sendKeyEvent(key, press, time, window);
@@ -393,20 +474,20 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
int mask = 1 << button_number;
if (press) {
- m_buttons |= mask; /* Set this button's bit. */
+ button_depressed_ |= mask; /* Set this button's bit. */
}
else {
- m_buttons &= ~mask; /* Clear this button's bit. */
+ button_depressed_ &= ~mask; /* Clear this button's bit. */
}
}
void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time)
{
- button_bits &= m_buttonMask; /* Discard any "garbage" bits. */
+ button_bits &= hid_map_button_mask_; /* Discard any "garbage" bits. */
- int diff = m_buttons ^ button_bits;
+ int diff = button_depressed_ ^ button_bits;
- for (int button_number = 0; button_number < m_buttonCount; ++button_number) {
+ for (int button_number = 0; button_number < hid_map_button_num_; ++button_number) {
int mask = 1 << button_number;
if (diff & mask) {
@@ -433,7 +514,7 @@ void GHOST_NDOFManager::setDeadZone(float dz)
/* Negative values don't make sense, so clamp at zero. */
dz = 0.0f;
}
- m_deadZone = dz;
+ motion_dead_zone_ = dz;
/* Warn the rogue user/developer about high dead-zone, but allow it. */
CLOG_INFO(LOG, 2, "dead zone set to %.2f%s", dz, (dz > 0.5f) ? " (unexpectedly high)" : "");
@@ -458,20 +539,20 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold)
bool GHOST_NDOFManager::sendMotionEvent()
{
- if (!m_motionEventPending) {
+ if (!motion_event_pending_) {
return false;
}
- m_motionEventPending = false; /* Any pending motion is handled right now. */
+ motion_event_pending_ = false; /* Any pending motion is handled right now. */
- GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow();
+ GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();
if (window == nullptr) {
- m_motionState = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */
+ motion_state_ = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */
return false; /* Delivery will fail, so don't bother sending. */
}
- GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(m_motionTime, window);
+ GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window);
GHOST_TEventNDOFMotionData *data = (GHOST_TEventNDOFMotionData *)event->getData();
/* Scale axis values here to normalize them to around +/- 1
@@ -479,26 +560,26 @@ bool GHOST_NDOFManager::sendMotionEvent()
const float scale = 1.0f / 350.0f; /* 3Dconnexion devices send +/- 350 usually */
- data->tx = scale * m_translation[0];
- data->ty = scale * m_translation[1];
- data->tz = scale * m_translation[2];
+ data->tx = scale * translation_[0];
+ data->ty = scale * translation_[1];
+ data->tz = scale * translation_[2];
- data->rx = scale * m_rotation[0];
- data->ry = scale * m_rotation[1];
- data->rz = scale * m_rotation[2];
- data->dt = 0.001f * (m_motionTime - m_prevMotionTime); /* In seconds. */
- m_prevMotionTime = m_motionTime;
+ data->rx = scale * rotation_[0];
+ data->ry = scale * rotation_[1];
+ data->rz = scale * rotation_[2];
+ data->dt = 0.001f * (motion_time_ - motion_time_prev_); /* In seconds. */
+ motion_time_prev_ = motion_time_;
- bool weHaveMotion = !nearHomePosition(data, m_deadZone);
+ bool weHaveMotion = !nearHomePosition(data, motion_dead_zone_);
/* Determine what kind of motion event to send `(Starting, InProgress, Finishing)`
* and where that leaves this NDOF manager `(NotStarted, InProgress, Finished)`. */
- switch (m_motionState) {
+ switch (motion_state_) {
case GHOST_kNotStarted:
case GHOST_kFinished: {
if (weHaveMotion) {
data->progress = GHOST_kStarting;
- m_motionState = GHOST_kInProgress;
+ motion_state_ = GHOST_kInProgress;
/* Previous motion time will be ancient, so just make up a reasonable time delta. */
data->dt = 0.0125f;
}
@@ -517,7 +598,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
}
else {
data->progress = GHOST_kFinishing;
- m_motionState = GHOST_kFinished;
+ motion_state_ = GHOST_kFinished;
}
break;
}
@@ -538,21 +619,21 @@ bool GHOST_NDOFManager::sendMotionEvent()
data->ry,
data->rz,
data->dt,
- progress_string[data->progress]);
+ ndof_progress_string[data->progress]);
#else
/* Raw values, may be useful for debugging. */
CLOG_INFO(LOG,
2,
"motion sent, T=(%d,%d,%d) R=(%d,%d,%d) status=%s",
- m_translation[0],
- m_translation[1],
- m_translation[2],
- m_rotation[0],
- m_rotation[1],
- m_rotation[2],
- progress_string[data->progress]);
+ translation_[0],
+ translation_[1],
+ translation_[2],
+ rotation_[0],
+ rotation_[1],
+ rotation_[2],
+ ndof_progress_string[data->progress]);
#endif
- m_system.pushEvent(event);
+ system_.pushEvent(event);
return true;
}
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 73c1b17f891..2d5bba14aa4 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -9,7 +9,7 @@
#include "GHOST_System.h"
typedef enum {
- NDOF_UnknownDevice,
+ NDOF_UnknownDevice = 0,
/* Current devices. */
NDOF_SpaceNavigator,
@@ -29,8 +29,8 @@ typedef enum {
/* NDOF device button event types */
typedef enum {
- /* Used internally, never sent. */
- NDOF_BUTTON_NONE = 0,
+ /* Used internally, never sent or used as an index. */
+ NDOF_BUTTON_NONE = -1,
/* These two are available from any 3Dconnexion device. */
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT,
@@ -58,11 +58,6 @@ typedef enum {
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
- /* Keyboard emulation. */
- NDOF_BUTTON_ESC,
- NDOF_BUTTON_ALT,
- NDOF_BUTTON_SHIFT,
- NDOF_BUTTON_CTRL,
/* General-purpose buttons.
* Users can assign functions via keymap editor. */
NDOF_BUTTON_1,
@@ -79,8 +74,20 @@ typedef enum {
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
- /* The end. */
- NDOF_BUTTON_LAST
+ /* Store Views. */
+ NDOF_BUTTON_V1,
+ NDOF_BUTTON_V2,
+ NDOF_BUTTON_V3,
+ /* Keyboard emulation. */
+ NDOF_BUTTON_ESC,
+ NDOF_BUTTON_ENTER,
+ NDOF_BUTTON_DELETE,
+ NDOF_BUTTON_TAB,
+ NDOF_BUTTON_SPACE,
+ NDOF_BUTTON_ALT,
+ NDOF_BUTTON_SHIFT,
+ NDOF_BUTTON_CTRL,
+#define NDOF_BUTTON_NUM (NDOF_BUTTON_CTRL + 1)
} NDOF_ButtonT;
class GHOST_NDOFManager {
@@ -140,25 +147,25 @@ class GHOST_NDOFManager {
bool sendMotionEvent();
protected:
- GHOST_System &m_system;
+ GHOST_System &system_;
private:
void sendButtonEvent(NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *);
void sendKeyEvent(GHOST_TKey, bool press, uint64_t time, GHOST_IWindow *);
- NDOF_DeviceT m_deviceType;
- int m_buttonCount;
- int m_buttonMask;
- const NDOF_ButtonT *m_hidMap;
+ NDOF_DeviceT device_type_;
+ int hid_map_button_num_;
+ int hid_map_button_mask_;
+ const NDOF_ButtonT *hid_map_;
- int m_translation[3];
- int m_rotation[3];
- int m_buttons; /* Bit field. */
+ int translation_[3];
+ int rotation_[3];
+ int button_depressed_; /* Bit field. */
- uint64_t m_motionTime; /* In milliseconds. */
- uint64_t m_prevMotionTime; /* Time of most recent motion event sent. */
+ uint64_t motion_time_; /* In milliseconds. */
+ uint64_t motion_time_prev_; /* Time of most recent motion event sent. */
- GHOST_TProgress m_motionState;
- bool m_motionEventPending;
- float m_deadZone; /* Discard motion with each component < this. */
+ GHOST_TProgress motion_state_;
+ bool motion_event_pending_;
+ float motion_dead_zone_; /* Discard motion with each component < this. */
};
diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
index 94bf0337371..0ccf4dc9bfb 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
@@ -10,7 +10,7 @@
#define SPNAV_SOCK_PATH "/var/run/spnav.sock"
GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
- : GHOST_NDOFManager(sys), m_available(false)
+ : GHOST_NDOFManager(sys), available_(false)
{
if (access(SPNAV_SOCK_PATH, F_OK) != 0) {
#ifdef DEBUG
@@ -20,7 +20,7 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
#endif
}
else if (spnav_open() != -1) {
- m_available = true;
+ available_ = true;
/* determine exactly which device (if any) is plugged in */
@@ -45,14 +45,14 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
GHOST_NDOFManagerUnix::~GHOST_NDOFManagerUnix()
{
- if (m_available) {
+ if (available_) {
spnav_close();
}
}
bool GHOST_NDOFManagerUnix::available()
{
- return m_available;
+ return available_;
}
/*
@@ -74,7 +74,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
{
bool anyProcessed = false;
- if (m_available) {
+ if (available_) {
spnav_event e;
#ifdef USE_FINISH_GLITCH_WORKAROUND
@@ -85,7 +85,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
switch (e.type) {
case SPNAV_EVENT_MOTION: {
/* convert to blender view coords */
- uint64_t now = m_system.getMilliSeconds();
+ uint64_t now = system_.getMilliSeconds();
const int t[3] = {int(e.motion.x), int(e.motion.y), int(-e.motion.z)};
const int r[3] = {int(-e.motion.rx), int(-e.motion.ry), int(e.motion.rz)};
@@ -97,7 +97,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
break;
}
case SPNAV_EVENT_BUTTON:
- uint64_t now = m_system.getMilliSeconds();
+ uint64_t now = system_.getMilliSeconds();
updateButton(e.button.bnum, e.button.press, now);
break;
}
@@ -106,7 +106,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
#ifdef USE_FINISH_GLITCH_WORKAROUND
if (motion_test_prev == true && motion_test == false) {
- uint64_t now = m_system.getMilliSeconds();
+ uint64_t now = system_.getMilliSeconds();
const int v[3] = {0, 0, 0};
updateTranslation(v, now);
diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h
index fd603e3cb54..2b98fad974f 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h
+++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h
@@ -15,5 +15,5 @@ class GHOST_NDOFManagerUnix : public GHOST_NDOFManager {
bool processEvents();
private:
- bool m_available;
+ bool available_;
};
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 94d021fd822..670ede35989 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -384,6 +384,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
if (stereoVisual) {
glSettings.flags |= GHOST_glStereoVisual;
}
+ glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger than the viewport. */
GHOST_ASSERT(m_displayManager,
@@ -395,7 +396,6 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
settings.xPixels,
settings.yPixels,
GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
glSettings,
true /* exclusive */);
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 810f828a8a1..924a4bff790 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -76,7 +76,7 @@ class GHOST_System : public GHOST_ISystem {
GHOST_ITimerTask *installTimer(uint64_t delay,
uint64_t interval,
GHOST_TimerProcPtr timerProc,
- GHOST_TUserDataPtr userData = NULL);
+ GHOST_TUserDataPtr userData = nullptr);
/**
* Removes a timer.
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index dbb41c7fddf..0211694aad4 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -77,7 +77,6 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
@@ -89,7 +88,6 @@ class GHOST_SystemCocoa : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index bfa90114e4c..a1016dd4843 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -689,7 +689,6 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -719,7 +718,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
width,
height,
state,
- type,
+ glSettings.context_type,
glSettings.flags & GHOST_glStereoVisual,
glSettings.flags & GHOST_glDebugContext,
is_dialog,
@@ -751,7 +750,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
{
- GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL);
+ GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type);
if (context->initializeDrawingContext())
return context;
else
diff --git a/intern/ghost/intern/GHOST_SystemHeadless.h b/intern/ghost/intern/GHOST_SystemHeadless.h
index b02a82fc9eb..66af65f763d 100644
--- a/intern/ghost/intern/GHOST_SystemHeadless.h
+++ b/intern/ghost/intern/GHOST_SystemHeadless.h
@@ -142,7 +142,6 @@ class GHOST_SystemHeadless : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool /*exclusive*/,
const bool /*is_dialog*/,
@@ -155,7 +154,7 @@ class GHOST_SystemHeadless : public GHOST_System {
height,
state,
parentWindow,
- type,
+ glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0));
}
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index ad5c4dc85fb..9174664adc4 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -42,7 +42,6 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool /* is_dialog */,
@@ -57,7 +56,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
width,
height,
state,
- type,
+ glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
parentWindow);
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index bee277ba674..385bfb841e3 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -71,7 +71,6 @@ class GHOST_SystemSDL : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 04c7e103bde..67270d26ed3 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -10,6 +10,7 @@
#include "GHOST_EventCursor.h"
#include "GHOST_EventDragnDrop.h"
#include "GHOST_EventKey.h"
+#include "GHOST_EventTrackpad.h"
#include "GHOST_EventWheel.h"
#include "GHOST_PathUtils.h"
#include "GHOST_TimerManager.h"
@@ -50,6 +51,8 @@
/* Generated by `wayland-scanner`. */
#include <pointer-constraints-unstable-v1-client-protocol.h>
+#include <pointer-gestures-unstable-v1-client-protocol.h>
+#include <primary-selection-unstable-v1-client-protocol.h>
#include <relative-pointer-unstable-v1-client-protocol.h>
#include <tablet-unstable-v2-client-protocol.h>
#include <xdg-output-unstable-v1-client-protocol.h>
@@ -82,10 +85,23 @@ static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
static void output_handle_done(void *data, struct wl_output *wl_output);
+static void gwl_seat_capability_pointer_disable(GWL_Seat *seat);
+static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat);
+static void gwl_seat_capability_touch_disable(GWL_Seat *seat);
+
+static bool gwl_registry_entry_remove_by_name(GWL_Display *display,
+ uint32_t name,
+ int *r_interface_slot);
+static void gwl_registry_entry_remove_all(GWL_Display *display);
+
+struct GWL_RegistryHandler;
+static int gwl_registry_handler_interface_slot_max();
+static int gwl_registry_handler_interface_slot_from_string(const char *interface);
+static const struct GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(
+ int interface_slot);
+
/* -------------------------------------------------------------------- */
-/** \name Local Defines
- *
- * Control local functionality, compositors specific workarounds.
+/** \name Workaround Compositor Specific Bugs
* \{ */
/**
@@ -116,11 +132,20 @@ static bool use_gnome_confine_hack = false;
* This define could be removed without changing any functionality,
* it just means GNOME users will see verbose warning messages that alert them about
* a known problem that needs to be fixed up-stream.
+ *
+ * This has been fixed for GNOME 43. Keep the workaround until support for gnome 42 is dropped.
* See: https://gitlab.gnome.org/GNOME/mutter/-/issues/2457
*/
#define USE_GNOME_KEYBOARD_SUPPRESS_WARNING
/**
+ * KDE (plasma 5.26.1) has a bug where the cursor surface needs to be committed
+ * (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: T102048.
+ * See: https://bugs.kde.org/show_bug.cgi?id=461001
+ */
+#define USE_KDE_TABLET_HIDDEN_CURSOR_HACK
+
+/**
* When GNOME is found, require `libdecor`.
* This is a hack because it seems there is no way to check if the compositor supports
* server side decorations when initializing WAYLAND.
@@ -129,6 +154,20 @@ static bool use_gnome_confine_hack = false;
# define USE_GNOME_NEEDS_LIBDECOR_HACK
#endif
+/* -------------------------------------------------------------------- */
+/** \name Local Defines
+ *
+ * Control local functionality, compositors specific workarounds.
+ * \{ */
+
+/**
+ * Fix short-cut part of keyboard reading code not properly handling some keys, see: T102194.
+ * \note This is similar to X11 workaround by the same name, see: T47228.
+ */
+#define USE_NON_LATIN_KB_WORKAROUND
+
+#define WL_NAME_UNSET uint32_t(-1)
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -140,8 +179,7 @@ static bool use_gnome_confine_hack = false;
* \{ */
/**
- * The event codes are used to
- * to differentiate from which mouse button an event comes from.
+ * The event codes are used to differentiate from which mouse button an event comes from.
*/
#define BTN_LEFT 0x110
#define BTN_RIGHT 0x111
@@ -154,9 +192,14 @@ static bool use_gnome_confine_hack = false;
/**
* Tablet events.
+ *
+ * \note Gnome/GTK swap middle/right, where the same application in X11 will swap the middle/right
+ * mouse button when running under WAYLAND. KDE doesn't do this, and according to artists
+ * at the Blender studio, having the button closest to the nib be MMB is preferable,
+ * so use this as a default. If needs be - swapping these could be a preference.
*/
-#define BTN_STYLUS 0x14b /* Use as right-mouse. */
-#define BTN_STYLUS2 0x14c /* Use as middle-mouse. */
+#define BTN_STYLUS 0x14b /* Use as middle-mouse. */
+#define BTN_STYLUS2 0x14c /* Use as right-mouse. */
/* NOTE(@campbellbarton): Map to an additional button (not sure which hardware uses this). */
#define BTN_STYLUS3 0x149
@@ -165,6 +208,19 @@ static bool use_gnome_confine_hack = false;
*/
#define KEY_GRAVE 41
+#ifdef USE_NON_LATIN_KB_WORKAROUND
+# define KEY_1 2
+# define KEY_2 3
+# define KEY_3 4
+# define KEY_4 5
+# define KEY_5 6
+# define KEY_6 7
+# define KEY_7 8
+# define KEY_8 9
+# define KEY_9 10
+# define KEY_0 11
+#endif
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -190,48 +246,76 @@ struct GWL_ModifierInfo {
};
static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = {
- [MOD_INDEX_SHIFT] =
- {
- .display_name = "Shift",
- .xkb_id = XKB_MOD_NAME_SHIFT,
- .key_l = GHOST_kKeyLeftShift,
- .key_r = GHOST_kKeyRightShift,
- .mod_l = GHOST_kModifierKeyLeftShift,
- .mod_r = GHOST_kModifierKeyRightShift,
- },
- [MOD_INDEX_ALT] =
- {
- .display_name = "Alt",
- .xkb_id = XKB_MOD_NAME_ALT,
- .key_l = GHOST_kKeyLeftAlt,
- .key_r = GHOST_kKeyRightAlt,
- .mod_l = GHOST_kModifierKeyLeftAlt,
- .mod_r = GHOST_kModifierKeyRightAlt,
- },
- [MOD_INDEX_CTRL] =
- {
- .display_name = "Control",
- .xkb_id = XKB_MOD_NAME_CTRL,
- .key_l = GHOST_kKeyLeftControl,
- .key_r = GHOST_kKeyRightControl,
- .mod_l = GHOST_kModifierKeyLeftControl,
- .mod_r = GHOST_kModifierKeyRightControl,
- },
- [MOD_INDEX_OS] =
- {
- .display_name = "OS",
- .xkb_id = XKB_MOD_NAME_LOGO,
- .key_l = GHOST_kKeyLeftOS,
- .key_r = GHOST_kKeyRightOS,
- .mod_l = GHOST_kModifierKeyLeftOS,
- .mod_r = GHOST_kModifierKeyRightOS,
- },
+ /* MOD_INDEX_SHIFT */
+ {
+ /* display_name */ "Shift",
+ /* xkb_id */ XKB_MOD_NAME_SHIFT,
+ /* key_l */ GHOST_kKeyLeftShift,
+ /* key_r */ GHOST_kKeyRightShift,
+ /* mod_l */ GHOST_kModifierKeyLeftShift,
+ /* mod_r */ GHOST_kModifierKeyRightShift,
+ },
+ /* MOD_INDEX_ALT */
+ {
+ /* display_name */ "Alt",
+ /* xkb_id */ XKB_MOD_NAME_ALT,
+ /* key_l */ GHOST_kKeyLeftAlt,
+ /* key_r */ GHOST_kKeyRightAlt,
+ /* mod_l */ GHOST_kModifierKeyLeftAlt,
+ /* mod_r */ GHOST_kModifierKeyRightAlt,
+ },
+ /* MOD_INDEX_CTRL */
+ {
+ /* display_name */ "Control",
+ /* xkb_id */ XKB_MOD_NAME_CTRL,
+ /* key_l */ GHOST_kKeyLeftControl,
+ /* key_r */ GHOST_kKeyRightControl,
+ /* mod_l */ GHOST_kModifierKeyLeftControl,
+ /* mod_r */ GHOST_kModifierKeyRightControl,
+ },
+ /* MOD_INDEX_OS */
+ {
+ /* display_name */ "OS",
+ /* xkb_id */ XKB_MOD_NAME_LOGO,
+ /* key_l */ GHOST_kKeyLeftOS,
+ /* key_r */ GHOST_kKeyRightOS,
+ /* mod_l */ GHOST_kModifierKeyLeftOS,
+ /* mod_r */ GHOST_kModifierKeyRightOS,
+ },
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_SimpleBuffer Type
+ * \{ */
+
+struct GWL_SimpleBuffer {
+ /** Constant data, but may be freed. */
+ const char *data = nullptr;
+ size_t data_size = 0;
};
+static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer)
+{
+ free(const_cast<char *>(buffer->data));
+ buffer->data = nullptr;
+ buffer->data_size = 0;
+}
+
+static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const char *str)
+{
+ free(const_cast<char *>(buffer->data));
+ buffer->data_size = strlen(str);
+ char *data = static_cast<char *>(malloc(buffer->data_size));
+ std::memcpy(data, str, buffer->data_size);
+ buffer->data = data;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Private Types & Defines
+/** \name Internal #GWL_Cursor Type
* \{ */
/**
@@ -249,16 +333,26 @@ struct GWL_Cursor {
* the hardware cursor is used.
*/
bool is_hardware = true;
+ /** When true, a custom image is used to display the cursor (stored in `wl_image`). */
bool is_custom = false;
- struct wl_surface *wl_surface = nullptr;
+ struct wl_surface *wl_surface_cursor = nullptr;
struct wl_buffer *wl_buffer = nullptr;
struct wl_cursor_image wl_image = {0};
struct wl_cursor_theme *wl_theme = nullptr;
void *custom_data = nullptr;
+ /** The size of `custom_data` in bytes. */
size_t custom_data_size = 0;
- int size = 0;
+ /**
+ * The name of the theme (loaded by DBUS, depends on #WITH_GHOST_WAYLAND_DBUS).
+ * When disabled, leave as an empty string and the default theme will be used.
+ */
std::string theme_name;
-
+ /**
+ * The size of the cursor (when looking up a cursor theme).
+ * This must be scaled by the maximum output scale when passing to wl_cursor_theme_load.
+ * See #update_cursor_scale.
+ * */
+ int theme_size = 0;
int custom_scale = 1;
};
@@ -269,6 +363,7 @@ struct GWL_Cursor {
*/
struct GWL_TabletTool {
struct GWL_Seat *seat = nullptr;
+ /** Tablets have a separate cursor to the 'pointer', this surface is used for cursor drawing. */
struct wl_surface *wl_surface_cursor = nullptr;
/** Used to delay clearing tablet focused wl_surface until the frame is handled. */
bool proximity = false;
@@ -276,23 +371,55 @@ struct GWL_TabletTool {
GHOST_TabletData data = GHOST_TABLET_DATA_NONE;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_DataOffer Type
+ * \{ */
+
+/**
+ * Data storage used for clipboard paste & drag-and-drop.
+ */
struct GWL_DataOffer {
- std::unordered_set<std::string> types;
- uint32_t source_actions = 0;
- uint32_t dnd_action = 0;
struct wl_data_offer *id = nullptr;
- std::atomic<bool> in_use = false;
+ std::unordered_set<std::string> types;
+
struct {
+ /**
+ * Prevents freeing after #wl_data_device_listener.leave,
+ * before #wl_data_device_listener.drop.
+ */
+ bool in_use = false;
+ /**
+ * Bit-mask with available drop options.
+ * #WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, #WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE.. etc.
+ * The application that initializes the drag may set these depending on modifiers held
+ * \note when dragging begins. Currently ghost doesn't make use of these.
+ */
+ enum wl_data_device_manager_dnd_action source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+ enum wl_data_device_manager_dnd_action action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
/** Compatible with #GWL_Seat.xy coordinates. */
wl_fixed_t xy[2] = {0, 0};
} dnd;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_DataSource Type
+ * \{ */
+
struct GWL_DataSource {
- struct wl_data_source *data_source = nullptr;
- char *buffer_out = nullptr;
+ struct wl_data_source *wl_source = nullptr;
+ GWL_SimpleBuffer buffer_out;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Seat Type (#wl_seat wrapper & associated types)
+ * \{ */
+
/**
* Data used to implement client-side key-repeat.
*
@@ -352,12 +479,58 @@ struct GWL_SeatStatePointer {
* The wl_surface last used with this pointing device
* (events with this pointing device will be sent here).
*/
- struct wl_surface *wl_surface = nullptr;
+ struct wl_surface *wl_surface_window = nullptr;
GHOST_Buttons buttons = GHOST_Buttons();
};
/**
+ * Scroll state, applying to pointer (not tablet) events.
+ * Otherwise this would be part of #GWL_SeatStatePointer.
+ */
+struct GWL_SeatStatePointerScroll {
+ /** Smooth scrolling (handled & reset with pointer "frame" callback). */
+ wl_fixed_t smooth_xy[2] = {0, 0};
+ /** Discrete scrolling (handled & reset with pointer "frame" callback). */
+ int32_t discrete_xy[2] = {0, 0};
+ /** The source of scroll event. */
+ enum wl_pointer_axis_source axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
+};
+
+/**
+ * Utility struct to access rounded values from a scaled `wl_fixed_t`,
+ * without loosing information.
+ *
+ * As the rounded result is rounded to a lower precision integer,
+ * the high precision value is accumulated and converted to an integer to
+ * prevent the accumulation of rounded values giving an inaccurate result.
+ *
+ * \note This is simple but doesn't read well when expanded multiple times inline.
+ */
+struct GWL_ScaledFixedT {
+ wl_fixed_t value = 0;
+ wl_fixed_t factor = 1;
+};
+
+static int gwl_scaled_fixed_t_add_and_calc_rounded_delta(GWL_ScaledFixedT *sf,
+ const wl_fixed_t add)
+{
+ const int result_prev = wl_fixed_to_int(sf->value * sf->factor);
+ sf->value += add;
+ const int result_curr = wl_fixed_to_int(sf->value * sf->factor);
+ return result_curr - result_prev;
+}
+
+/**
+ * Gesture state.
+ * This is needed so the gesture values can be converted to deltas.
+ */
+struct GWL_SeatStatePointerGesture_Pinch {
+ GWL_ScaledFixedT scale;
+ GWL_ScaledFixedT rotation;
+};
+
+/**
* State of the keyboard (in #GWL_Seat).
*/
struct GWL_SeatStateKeyboard {
@@ -368,7 +541,7 @@ struct GWL_SeatStateKeyboard {
* The wl_surface last used with this pointing device
* (events with this pointing device will be sent here).
*/
- struct wl_surface *wl_surface = nullptr;
+ struct wl_surface *wl_surface_window = nullptr;
};
/**
@@ -376,48 +549,110 @@ struct GWL_SeatStateKeyboard {
*
* Needed as #GWL_Seat.xkb_state doesn't store which modifier keys are held.
*/
-struct WGL_KeyboardDepressedState {
+struct GWL_KeyboardDepressedState {
int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0};
};
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
-struct WGL_LibDecor_System {
+struct GWL_LibDecor_System {
struct libdecor *context = nullptr;
};
-static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor)
+static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor)
{
if (decor->context) {
libdecor_unref(decor->context);
+ decor->context = nullptr;
}
delete decor;
}
#endif
-struct WGL_XDG_Decor_System {
+struct GWL_XDG_Decor_System {
struct xdg_wm_base *shell = nullptr;
+ uint32_t shell_name = WL_NAME_UNSET;
+
struct zxdg_decoration_manager_v1 *manager = nullptr;
+ uint32_t manager_name = WL_NAME_UNSET;
};
-static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor)
+static void gwl_xdg_decor_system_destroy(struct GWL_Display *display, GWL_XDG_Decor_System *decor)
{
if (decor->manager) {
- zxdg_decoration_manager_v1_destroy(decor->manager);
+ gwl_registry_entry_remove_by_name(display, decor->manager_name, nullptr);
+ GHOST_ASSERT(decor->manager == nullptr, "Internal registry error");
}
if (decor->shell) {
- xdg_wm_base_destroy(decor->shell);
+ gwl_registry_entry_remove_by_name(display, decor->shell_name, nullptr);
+ GHOST_ASSERT(decor->shell == nullptr, "Internal registry error");
}
delete decor;
}
+struct GWL_PrimarySelection_DataOffer {
+ struct zwp_primary_selection_offer_v1 *id = nullptr;
+
+ std::unordered_set<std::string> types;
+};
+
+struct GWL_PrimarySelection_DataSource {
+ struct zwp_primary_selection_source_v1 *wp_source = nullptr;
+ GWL_SimpleBuffer buffer_out;
+};
+
+/** Primary selection support. */
+struct GWL_PrimarySelection {
+
+ GWL_PrimarySelection_DataSource *data_source = nullptr;
+ std::mutex data_source_mutex;
+
+ GWL_PrimarySelection_DataOffer *data_offer = nullptr;
+ std::mutex data_offer_mutex;
+};
+
+static void gwl_primary_selection_discard_offer(GWL_PrimarySelection *primary)
+{
+ if (primary->data_offer == nullptr) {
+ return;
+ }
+ zwp_primary_selection_offer_v1_destroy(primary->data_offer->id);
+ delete primary->data_offer;
+ primary->data_offer = nullptr;
+}
+
+static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary)
+{
+ GWL_PrimarySelection_DataSource *data_source = primary->data_source;
+ if (data_source == nullptr) {
+ return;
+ }
+ gwl_simple_buffer_free_data(&data_source->buffer_out);
+ if (data_source->wp_source) {
+ zwp_primary_selection_source_v1_destroy(data_source->wp_source);
+ }
+ delete primary->data_source;
+ primary->data_source = nullptr;
+}
+
struct GWL_Seat {
GHOST_SystemWayland *system = nullptr;
std::string name;
struct wl_seat *wl_seat = nullptr;
struct wl_pointer *wl_pointer = nullptr;
+ struct wl_touch *wl_touch = nullptr;
struct wl_keyboard *wl_keyboard = nullptr;
- struct zwp_tablet_seat_v2 *tablet_seat = nullptr;
+ struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr;
+
+#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
+ struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold = nullptr;
+#endif
+#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
+ struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch = nullptr;
+#endif
+#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
+ struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe = nullptr;
+#endif
/** All currently active tablet tools (needed for changing the cursor). */
std::unordered_set<zwp_tablet_tool_v2 *> tablet_tools;
@@ -426,6 +661,8 @@ struct GWL_Seat {
uint32_t cursor_source_serial = 0;
GWL_SeatStatePointer pointer;
+ GWL_SeatStatePointerScroll pointer_scroll;
+ GWL_SeatStatePointerGesture_Pinch pointer_gesture_pinch;
/** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */
GWL_SeatStatePointer tablet;
@@ -440,9 +677,9 @@ struct GWL_Seat {
struct GWL_Cursor cursor;
- struct zwp_relative_pointer_v1 *relative_pointer = nullptr;
- struct zwp_locked_pointer_v1 *locked_pointer = nullptr;
- struct zwp_confined_pointer_v1 *confined_pointer = nullptr;
+ struct zwp_relative_pointer_v1 *wp_relative_pointer = nullptr;
+ struct zwp_locked_pointer_v1 *wp_locked_pointer = nullptr;
+ struct zwp_confined_pointer_v1 *wp_confined_pointer = nullptr;
struct xkb_context *xkb_context = nullptr;
@@ -451,14 +688,24 @@ struct GWL_Seat {
* Keep a state with no modifiers active, use for symbol lookups.
*/
struct xkb_state *xkb_state_empty = nullptr;
+
+ /**
+ * Keep a state with shift enabled, use to access predictable number access for AZERTY keymaps.
+ * If shift is not supported by the key-map, this is set to NULL.
+ */
+ struct xkb_state *xkb_state_empty_with_shift = nullptr;
/**
* Keep a state with number-lock enabled, use to access predictable key-pad symbols.
* If number-lock is not supported by the key-map, this is set to NULL.
*/
struct xkb_state *xkb_state_empty_with_numlock = nullptr;
+#ifdef USE_NON_LATIN_KB_WORKAROUND
+ bool xkb_use_non_latin_workaround = false;
+#endif
+
/** Keys held matching `xkb_state`. */
- struct WGL_KeyboardDepressedState key_depressed;
+ struct GWL_KeyboardDepressedState key_depressed;
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
struct {
@@ -483,9 +730,9 @@ struct GWL_Seat {
GHOST_ITimerTask *timer = nullptr;
} key_repeat;
- struct wl_surface *wl_surface_focus_dnd = nullptr;
+ struct wl_surface *wl_surface_window_focus_dnd = nullptr;
- struct wl_data_device *data_device = nullptr;
+ struct wl_data_device *wl_data_device = nullptr;
/** Drag & Drop. */
struct GWL_DataOffer *data_offer_dnd = nullptr;
std::mutex data_offer_dnd_mutex;
@@ -497,209 +744,434 @@ struct GWL_Seat {
struct GWL_DataSource *data_source = nullptr;
std::mutex data_source_mutex;
+ struct zwp_primary_selection_device_v1 *wp_primary_selection_device = nullptr;
+ struct GWL_PrimarySelection primary_selection;
+
/** Last device that was active. */
uint32_t data_source_serial = 0;
};
+static GWL_SeatStatePointer *gwl_seat_state_pointer_active(GWL_Seat *seat)
+{
+ if (seat->pointer.serial == seat->cursor_source_serial) {
+ return &seat->pointer;
+ }
+ if (seat->tablet.serial == seat->cursor_source_serial) {
+ return &seat->tablet;
+ }
+ return nullptr;
+}
+
+static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface(
+ GWL_Seat *seat, const wl_surface *wl_surface)
+{
+ if (ghost_wl_surface_own_cursor_pointer(wl_surface)) {
+ return &seat->pointer;
+ }
+ if (ghost_wl_surface_own_cursor_tablet(wl_surface)) {
+ return &seat->tablet;
+ }
+ GHOST_ASSERT(0, "Surface found without pointer/tablet tag");
+ return nullptr;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Display Type (#wl_display & #wl_compositor wrapper)
+ * \{ */
+
+struct GWL_RegistryEntry;
+
struct GWL_Display {
GHOST_SystemWayland *system = nullptr;
+ /**
+ * True when initializing registration, while updating all other entries wont cause problems,
+ * it will preform many redundant update calls.
+ */
+ bool registry_skip_update_all = false;
+
+ /** Registry entries, kept to allow updating & removal at run-time. */
+ struct GWL_RegistryEntry *registry_entry = nullptr;
+
+ struct wl_registry *wl_registry = nullptr;
struct wl_display *wl_display = nullptr;
struct wl_compositor *wl_compositor = nullptr;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- WGL_LibDecor_System *libdecor = nullptr;
+ GWL_LibDecor_System *libdecor = nullptr;
bool libdecor_required = false;
#endif
- WGL_XDG_Decor_System *xdg_decor = nullptr;
+ GWL_XDG_Decor_System *xdg_decor = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct wl_shm *wl_shm = nullptr;
std::vector<GWL_Output *> outputs;
std::vector<GWL_Seat *> seats;
+ /**
+ * Support a single active seat at once, this isn't an exact or correct mapping from WAYLAND.
+ * Only allow input from different seats, not full concurrent multi-seat support.
+ *
+ * The main purpose of having an active seat is an alternative from always using the first
+ * seat which prevents events from any other seat.
+ *
+ * NOTE(@campbellbarton): This could be extended and developed further extended to support
+ * an active seat per window (for e.g.), basic support is sufficient for now as currently isn't
+ * a widely used feature.
+ */
+ int seats_active_index = 0;
- struct wl_data_device_manager *data_device_manager = nullptr;
- struct zwp_tablet_manager_v2 *tablet_manager = nullptr;
- struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
- struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
-};
-
-#undef LOG
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Private Utility Functions
- * \{ */
-
-static GHOST_WindowManager *window_manager = nullptr;
+ /* Managers. */
+ struct wl_data_device_manager *wl_data_device_manager = nullptr;
+ struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr;
+ struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr;
+ struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr;
-/** Check this lock before accessing #GHOST_SystemWayland::clipboard_ from a thread. */
-static std::mutex system_clipboard_mutex;
+ struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr;
+ struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr;
+};
/**
- * Callback for WAYLAND to run when there is an error.
+ * Free the #GWL_Display and it's related members.
*
- * \note It's useful to set a break-point on this function as some errors are fatal
- * (for all intents and purposes) but don't crash the process.
+ * \note This may run on a partially initialized struct,
+ * so it can't be assumed all members are set.
*/
-static void ghost_wayland_log_handler(const char *msg, va_list arg)
+static void gwl_display_destroy(GWL_Display *display)
{
- fprintf(stderr, "GHOST/Wayland: ");
- vfprintf(stderr, msg, arg); /* Includes newline. */
+ /* For typical WAYLAND use this will always be set.
+ * However when WAYLAND isn't running, this will early-exit and be null. */
+ if (display->wl_registry) {
+ wl_registry_destroy(display->wl_registry);
+ display->wl_registry = nullptr;
+ }
- GHOST_TBacktraceFn backtrace_fn = GHOST_ISystem::getBacktraceFn();
- if (backtrace_fn) {
- backtrace_fn(stderr); /* Includes newline. */
+ /* Unregister items in reverse order. */
+ gwl_registry_entry_remove_all(display);
+
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ if (display->libdecor) {
+ gwl_libdecor_system_destroy(display->libdecor);
+ display->libdecor = nullptr;
+ }
+ }
+ else
+#endif
+ {
+ if (display->xdg_decor) {
+ gwl_xdg_decor_system_destroy(display, display->xdg_decor);
+ display->xdg_decor = nullptr;
+ }
}
-}
-static GWL_SeatStatePointer *seat_state_pointer_active(GWL_Seat *seat)
-{
- if (seat->pointer.serial == seat->cursor_source_serial) {
- return &seat->pointer;
+ if (eglGetDisplay) {
+ ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->wl_display)));
}
- if (seat->tablet.serial == seat->cursor_source_serial) {
- return &seat->tablet;
+
+ if (display->wl_display) {
+ wl_display_disconnect(display->wl_display);
}
- return nullptr;
+
+ delete display;
}
-static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *seat,
- const wl_surface *wl_surface)
+static int gwl_display_seat_index(GWL_Display *display, const GWL_Seat *seat)
{
- if (ghost_wl_surface_own_cursor_pointer(wl_surface)) {
- return &seat->pointer;
- }
- if (ghost_wl_surface_own_cursor_tablet(wl_surface)) {
- return &seat->tablet;
- }
- GHOST_ASSERT(0, "Surface found without pointer/tablet tag");
- return nullptr;
+ std::vector<GWL_Seat *>::iterator iter = std::find(
+ display->seats.begin(), display->seats.end(), seat);
+ const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) :
+ -1;
+ GHOST_ASSERT(index != -1, "invalid internal state");
+ return index;
}
-static void display_destroy(GWL_Display *display)
+static GWL_Seat *gwl_display_seat_active_get(const GWL_Display *display)
{
- if (display->data_device_manager) {
- wl_data_device_manager_destroy(display->data_device_manager);
+ if (UNLIKELY(display->seats.empty())) {
+ return nullptr;
}
+ return display->seats[display->seats_active_index];
+}
- if (display->tablet_manager) {
- zwp_tablet_manager_v2_destroy(display->tablet_manager);
+static bool gwl_display_seat_active_set(GWL_Display *display, const GWL_Seat *seat)
+{
+ if (UNLIKELY(display->seats.empty())) {
+ return false;
}
-
- for (GWL_Output *output : display->outputs) {
- wl_output_destroy(output->wl_output);
- delete output;
+ const int index = gwl_display_seat_index(display, seat);
+ if (index == display->seats_active_index) {
+ return false;
}
+ display->seats_active_index = index;
+ return true;
+}
- for (GWL_Seat *seat : display->seats) {
+/** \} */
- /* First handle members that require locking.
- * While highly unlikely, it's possible they are being used while this function runs. */
- {
- std::lock_guard lock{seat->data_source_mutex};
- if (seat->data_source) {
- free(seat->data_source->buffer_out);
- if (seat->data_source->data_source) {
- wl_data_source_destroy(seat->data_source->data_source);
- }
- delete seat->data_source;
- }
- }
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_RegistryHandler
+ * \{ */
- {
- std::lock_guard lock{seat->data_offer_dnd_mutex};
- if (seat->data_offer_dnd) {
- wl_data_offer_destroy(seat->data_offer_dnd->id);
- delete seat->data_offer_dnd;
- }
- }
+struct GWL_RegisteryAdd_Params {
+ uint32_t name = 0;
+ /** Index within `gwl_registry_handlers`. */
+ int interface_slot = 0;
+ uint32_t version = 0;
+};
- {
- std::lock_guard lock{seat->data_offer_copy_paste_mutex};
- if (seat->data_offer_copy_paste) {
- wl_data_offer_destroy(seat->data_offer_copy_paste->id);
- delete seat->data_offer_copy_paste;
- }
- }
+/**
+ * Add callback for object registry.
+ * \note Any operations that depend on other interfaces being registered must be performed in the
+ * #GWL_RegistryHandler_UpdateFn callback as the order interfaces are added is out of our control.
+ *
+ * \param display: The display which holes a reference to the global object.
+ * \param params: Various arguments needed for registration.
+ */
+using GWL_RegistryHandler_AddFn = void (*)(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params);
- if (seat->data_device) {
- wl_data_device_release(seat->data_device);
- }
+struct GWL_RegisteryUpdate_Params {
+ uint32_t name = 0;
+ /** Index within `gwl_registry_handlers`. */
+ int interface_slot = 0;
+ uint32_t version = 0;
- if (seat->cursor.custom_data) {
- munmap(seat->cursor.custom_data, seat->cursor.custom_data_size);
- }
+ /** Set to #GWL_RegistryEntry.user_data. */
+ void *user_data = nullptr;
+};
- if (seat->wl_pointer) {
- if (seat->cursor.wl_surface) {
- wl_surface_destroy(seat->cursor.wl_surface);
- }
- if (seat->cursor.wl_theme) {
- wl_cursor_theme_destroy(seat->cursor.wl_theme);
- }
- if (seat->wl_pointer) {
- wl_pointer_destroy(seat->wl_pointer);
- }
- }
- if (seat->wl_keyboard) {
- if (seat->key_repeat.timer) {
- keyboard_handle_key_repeat_cancel(seat);
- }
- wl_keyboard_destroy(seat->wl_keyboard);
- }
+/**
+ * Optional update callback to refresh internal data when another interface has been added/removed.
+ *
+ * \param display: The display which holes a reference to the global object.
+ * \param params: Various arguments needed for updating.
+ */
+using GWL_RegistryHandler_UpdateFn = void (*)(GWL_Display *display,
+ const GWL_RegisteryUpdate_Params *params);
- /* Un-referencing checks for NULL case. */
- xkb_state_unref(seat->xkb_state);
- xkb_state_unref(seat->xkb_state_empty);
- xkb_state_unref(seat->xkb_state_empty_with_numlock);
+/**
+ * Remove callback for object registry.
+ * \param display: The display which holes a reference to the global object.
+ * \param user_data: Optional reference to a sub element of `display`,
+ * use for outputs or seats for e.g. when the display may hold multiple references.
+ * \param on_exit: Enabled when freeing on exit.
+ * When true the consistency of references between objects should be kept valid.
+ * Otherwise it can be assumed that all objects will be freed and none will be used again,
+ * so there is no need to ensure a valid state.
+ */
+using GWL_RegistryEntry_RemoveFn = void (*)(GWL_Display *display, void *user_data, bool on_exit);
+
+struct GWL_RegistryHandler {
+ /** Pointer to the name (not the name it's self), needed as the values aren't set on startup. */
+ const char *const *interface_p = nullptr;
+
+ /** Add the interface. */
+ GWL_RegistryHandler_AddFn add_fn = nullptr;
+ /** Optional update the interface (when other interfaces have been added/removed). */
+ GWL_RegistryHandler_UpdateFn update_fn = nullptr;
+ /** Remove the interface. */
+ GWL_RegistryEntry_RemoveFn remove_fn = nullptr;
+};
- xkb_context_unref(seat->xkb_context);
+/** \} */
- wl_seat_destroy(seat->wl_seat);
- delete seat;
- }
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_RegistryEntry
+ * \{ */
- if (display->wl_shm) {
- wl_shm_destroy(display->wl_shm);
- }
+/**
+ * Registered global objects can be removed by the compositor,
+ * these entries are a registry of objects and callbacks to properly remove them.
+ * These are also used to remove all registered objects before exiting.
+ */
+struct GWL_RegistryEntry {
+ GWL_RegistryEntry *next = nullptr;
+ /**
+ * Optional pointer passed to `remove_fn`, typically the container in #GWL_Display
+ * in cases multiple instances of the same interface are supported.
+ */
+ void *user_data = nullptr;
+ /**
+ * A unique identifier used as a handle by `wl_registry_listener.global_remove`.
+ */
+ uint32_t name = WL_NAME_UNSET;
+ /**
+ * Version passed by the add callback.
+ */
+ uint32_t version;
+ /**
+ * The index in `gwl_registry_handlers`,
+ * useful for accessing the interface name (for logging for example).
+ */
+ int interface_slot = 0;
+};
- if (display->relative_pointer_manager) {
- zwp_relative_pointer_manager_v1_destroy(display->relative_pointer_manager);
- }
+static void gwl_registry_entry_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params,
+ void *user_data)
+{
+ GWL_RegistryEntry *reg = new GWL_RegistryEntry;
- if (display->pointer_constraints) {
- zwp_pointer_constraints_v1_destroy(display->pointer_constraints);
- }
+ reg->interface_slot = params->interface_slot;
+ reg->name = params->name;
+ reg->version = params->version;
+ reg->user_data = user_data;
+
+ reg->next = display->registry_entry;
+ display->registry_entry = reg;
+}
+
+static bool gwl_registry_entry_remove_by_name(GWL_Display *display,
+ uint32_t name,
+ int *r_interface_slot)
+{
+ GWL_RegistryEntry *reg = display->registry_entry;
+ GWL_RegistryEntry **reg_link_p = &display->registry_entry;
+ bool found = false;
- if (display->wl_compositor) {
- wl_compositor_destroy(display->wl_compositor);
+ if (r_interface_slot) {
+ *r_interface_slot = -1;
}
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- if (display->libdecor) {
- wgl_libdecor_system_destroy(display->libdecor);
+ while (reg) {
+ if (reg->name == name) {
+ GWL_RegistryEntry *reg_next = reg->next;
+ const GWL_RegistryHandler *handler = gwl_registry_handler_from_interface_slot(
+ reg->interface_slot);
+ handler->remove_fn(display, reg->user_data, false);
+ if (r_interface_slot) {
+ *r_interface_slot = reg->interface_slot;
+ }
+ delete reg;
+ *reg_link_p = reg_next;
+ found = true;
+ break;
}
- }
- else
-#endif
- {
- if (display->xdg_decor) {
- wgl_xdg_decor_system_destroy(display->xdg_decor);
+ reg_link_p = &reg->next;
+ reg = reg->next;
+ }
+ return found;
+}
+
+static bool gwl_registry_entry_remove_by_interface_slot(GWL_Display *display,
+ int interface_slot,
+ bool on_exit)
+{
+ GWL_RegistryEntry *reg = display->registry_entry;
+ GWL_RegistryEntry **reg_link_p = &display->registry_entry;
+ bool found = false;
+
+ while (reg) {
+ if (reg->interface_slot == interface_slot) {
+ GWL_RegistryEntry *reg_next = reg->next;
+ const GWL_RegistryHandler *handler = gwl_registry_handler_from_interface_slot(
+ interface_slot);
+ handler->remove_fn(display, reg->user_data, on_exit);
+ delete reg;
+ *reg_link_p = reg_next;
+ reg = reg_next;
+ found = true;
+ continue;
}
+ reg_link_p = &reg->next;
+ reg = reg->next;
}
+ return found;
+}
- if (eglGetDisplay) {
- ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->wl_display)));
+/**
+ * Remove all global objects (on exit).
+ */
+static void gwl_registry_entry_remove_all(GWL_Display *display)
+{
+ const bool on_exit = true;
+
+ /* NOTE(@campbellbarton): Free by slot instead of simply looping over
+ * `display->registry_entry` so the order of freeing is always predictable.
+ * Otherwise global objects would be feed in the order they are registered.
+ * While this works in my tests, it could cause difficult to reproduce bugs
+ * where lesser used compositors or changes to existing compositors could
+ * crash on exit based on the order of freeing objects is out of our control.
+ *
+ * To give a concrete example of how this could fail, it's possible removing
+ * a tablet interface could reference the pointer interface, or the output interface.
+ * Even though references between interfaces shouldn't be necessary in most cases
+ * when `on_exit` is enabled. */
+ int interface_slot = gwl_registry_handler_interface_slot_max();
+ while (interface_slot--) {
+ gwl_registry_entry_remove_by_interface_slot(display, interface_slot, on_exit);
}
- if (display->wl_display) {
- wl_display_disconnect(display->wl_display);
+ GHOST_ASSERT(display->registry_entry == nullptr, "Failed to remove all entries!");
+ display->registry_entry = nullptr;
+}
+
+/**
+ * Run GWL_RegistryHandler.update_fn an all registered interface instances.
+ * This is needed to refresh the state of interfaces that may reference other interfaces.
+ * Called when interfaces are added/removed.
+ *
+ * \param interface_slot_exclude: Skip updating slots of this type.
+ * Note that while harmless dependencies only exist between different types,
+ * so there is no reason to update all other outputs that an output was removed (for e.g.).
+ * Pass as -1 to update all slots.
+ *
+ * NOTE(@campbellbarton): Updating all other items on a single change is typically worth avoiding.
+ * In practice this isn't a problem as so there are so few elements in `display->registry_entry`,
+ * so few use update functions and adding/removal at runtime is rarely called (plugging/unplugging)
+ * hardware for e.g. So while it's possible to store dependency links to avoid unnecessary
+ * looping over data - it ends up being a non issue.
+ */
+static void gwl_registry_entry_update_all(GWL_Display *display, const int interface_slot_exclude)
+{
+ GHOST_ASSERT(interface_slot_exclude == -1 || (uint(interface_slot_exclude) <
+ uint(gwl_registry_handler_interface_slot_max())),
+ "Invalid exclude slot");
+
+ for (GWL_RegistryEntry *reg = display->registry_entry; reg; reg = reg->next) {
+ if (reg->interface_slot == interface_slot_exclude) {
+ continue;
+ }
+ const GWL_RegistryHandler *handler = gwl_registry_handler_from_interface_slot(
+ reg->interface_slot);
+ if (handler->update_fn == nullptr) {
+ continue;
+ }
+
+ GWL_RegisteryUpdate_Params params = {
+ .name = reg->name,
+ .interface_slot = reg->interface_slot,
+ .version = reg->version,
+
+ .user_data = reg->user_data,
+ };
+ handler->update_fn(display, &params);
}
+}
- delete display;
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Private Utility Functions
+ * \{ */
+
+/**
+ * Callback for WAYLAND to run when there is an error.
+ *
+ * \note It's useful to set a break-point on this function as some errors are fatal
+ * (for all intents and purposes) but don't crash the process.
+ */
+static void ghost_wayland_log_handler(const char *msg, va_list arg)
+{
+ fprintf(stderr, "GHOST/Wayland: ");
+ vfprintf(stderr, msg, arg); /* Includes newline. */
+
+ GHOST_TBacktraceFn backtrace_fn = GHOST_ISystem::getBacktraceFn();
+ if (backtrace_fn) {
+ backtrace_fn(stderr); /* Includes newline. */
+ }
}
static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym)
@@ -837,9 +1309,24 @@ static GHOST_TKey xkb_map_gkey_or_scan_code(const xkb_keysym_t sym, const uint32
return gkey;
}
-static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type)
+static int pointer_axis_as_index(const uint32_t axis)
+{
+ switch (axis) {
+ case WL_POINTER_AXIS_HORIZONTAL_SCROLL: {
+ return 0;
+ }
+ case WL_POINTER_AXIS_VERTICAL_SCROLL: {
+ return 1;
+ }
+ default: {
+ return -1;
+ }
+ }
+}
+
+static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_tablet_tool_type)
{
- switch (wl_tablet_tool_type) {
+ switch (wp_tablet_tool_type) {
case ZWP_TABLET_TOOL_V2_TYPE_ERASER: {
return GHOST_kTabletModeEraser;
}
@@ -854,13 +1341,13 @@ static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_ta
}
}
- GHOST_PRINT("unknown tablet tool: " << wl_tablet_tool_type << std::endl);
+ GHOST_PRINT("unknown tablet tool: " << wp_tablet_tool_type << std::endl);
return GHOST_kTabletModeStylus;
}
static const int default_cursor_size = 24;
-static const std::unordered_map<GHOST_TStandardCursor, const char *> cursors = {
+static const std::unordered_map<GHOST_TStandardCursor, const char *> ghost_wl_cursors = {
{GHOST_kStandardCursorDefault, "left_ptr"},
{GHOST_kStandardCursorRightArrow, "right_ptr"},
{GHOST_kStandardCursorLeftArrow, "left_ptr"},
@@ -901,23 +1388,23 @@ static const std::unordered_map<GHOST_TStandardCursor, const char *> cursors = {
{GHOST_kStandardCursorCopy, "copy"},
};
-static constexpr const char *mime_text_plain = "text/plain";
-static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8";
-static constexpr const char *mime_text_uri = "text/uri-list";
+static constexpr const char *ghost_wl_mime_text_plain = "text/plain";
+static constexpr const char *ghost_wl_mime_text_utf8 = "text/plain;charset=utf-8";
+static constexpr const char *ghost_wl_mime_text_uri = "text/uri-list";
-static const std::unordered_map<std::string, GHOST_TDragnDropTypes> mime_dnd = {
- {mime_text_plain, GHOST_kDragnDropTypeString},
- {mime_text_utf8, GHOST_kDragnDropTypeString},
- {mime_text_uri, GHOST_kDragnDropTypeFilenames},
+static const char *ghost_wl_mime_preference_order[] = {
+ ghost_wl_mime_text_uri,
+ ghost_wl_mime_text_utf8,
+ ghost_wl_mime_text_plain,
};
-
-static const std::vector<std::string> mime_preference_order = {
- mime_text_uri,
- mime_text_utf8,
- mime_text_plain,
+/* Aligned to `ghost_wl_mime_preference_order`. */
+static const GHOST_TDragnDropTypes ghost_wl_mime_preference_order_type[] = {
+ GHOST_kDragnDropTypeString,
+ GHOST_kDragnDropTypeString,
+ GHOST_kDragnDropTypeFilenames,
};
-static const std::vector<std::string> mime_send = {
+static const char *ghost_wl_mime_send[] = {
"UTF8_STRING",
"COMPOUND_TEXT",
"TEXT",
@@ -1045,9 +1532,9 @@ static void keyboard_depressed_state_key_event(GWL_Seat *seat,
}
static void keyboard_depressed_state_push_events_from_change(
- GWL_Seat *seat, const WGL_KeyboardDepressedState &key_depressed_prev)
+ GWL_Seat *seat, const GWL_KeyboardDepressedState &key_depressed_prev)
{
- GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface);
+ GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface_window);
GHOST_SystemWayland *system = seat->system;
/* Separate key up and down into separate passes so key down events always come after key up.
@@ -1134,7 +1621,7 @@ static void relative_pointer_handle_relative_motion(
const wl_fixed_t /*dy_unaccel*/)
{
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
CLOG_INFO(LOG, 2, "relative_motion");
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
@@ -1167,7 +1654,7 @@ static CLG_LogRef LOG_WL_DATA_SOURCE = {"ghost.wl.handle.data_source"};
static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event)
{
/* NOTE: `seat->data_offer_dnd_mutex` must already be locked. */
- if (wl_surface *wl_surface_focus = seat->wl_surface_focus_dnd) {
+ if (wl_surface *wl_surface_focus = seat->wl_surface_window_focus_dnd) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
const int event_xy[2] = {
@@ -1176,40 +1663,144 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event)
};
const uint64_t time = seat->system->getMilliSeconds();
- for (const std::string &type : mime_preference_order) {
- seat->system->pushEvent(new GHOST_EventDragnDrop(
- time, event, mime_dnd.at(type), win, UNPACK2(event_xy), nullptr));
+ for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order_type); i++) {
+ const GHOST_TDragnDropTypes type = ghost_wl_mime_preference_order_type[i];
+ seat->system->pushEvent(
+ new GHOST_EventDragnDrop(time, event, type, win, UNPACK2(event_xy), nullptr));
}
}
}
-static std::string read_pipe(GWL_DataOffer *data_offer,
- const std::string mime_receive,
- std::mutex *mutex)
+/**
+ * Read from `fd` into a buffer which is returned.
+ * \return the buffer or null on failure.
+ */
+static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t *r_len)
+{
+ struct ByteChunk {
+ ByteChunk *next;
+ char data[4096 - sizeof(ByteChunk *)];
+ };
+ ByteChunk *chunk_first = nullptr, **chunk_link_p = &chunk_first;
+ bool ok = true;
+ size_t len = 0;
+ while (true) {
+ ByteChunk *chunk = static_cast<typeof(chunk)>(malloc(sizeof(*chunk)));
+ if (UNLIKELY(chunk == nullptr)) {
+ CLOG_WARN(LOG, "unable to allocate chunk for file buffer");
+ ok = false;
+ break;
+ }
+ chunk->next = nullptr;
+ const ssize_t len_chunk = read(fd, chunk->data, sizeof(chunk->data));
+ if (len_chunk <= 0) {
+ if (UNLIKELY(len_chunk < 0)) {
+ CLOG_WARN(LOG, "error reading from pipe: %s", std::strerror(errno));
+ ok = false;
+ }
+ free(chunk);
+ break;
+ }
+ if (chunk_first == nullptr) {
+ chunk_first = chunk;
+ }
+ *chunk_link_p = chunk;
+ chunk_link_p = &chunk->next;
+ len += len_chunk;
+ }
+
+ char *buf = nullptr;
+ if (ok) {
+ buf = static_cast<char *>(malloc(len + (nil_terminate ? 1 : 0)));
+ if (UNLIKELY(buf == nullptr)) {
+ CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len);
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ *r_len = len;
+ if (nil_terminate) {
+ buf[len] = '\0';
+ }
+ }
+ else {
+ *r_len = 0;
+ }
+
+ char *buf_stride = buf;
+ while (chunk_first) {
+ if (ok) {
+ const size_t len_chunk = std::min(len, sizeof(chunk_first->data));
+ memcpy(buf_stride, chunk_first->data, len_chunk);
+ buf_stride += len_chunk;
+ len -= len_chunk;
+ }
+ ByteChunk *chunk = chunk_first->next;
+ free(chunk_first);
+ chunk_first = chunk;
+ }
+
+ return buf;
+}
+
+static char *read_buffer_from_data_offer(GWL_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ const bool nil_terminate,
+ size_t *r_len)
{
int pipefd[2];
- if (UNLIKELY(pipe(pipefd) != 0)) {
- return {};
+ const bool pipefd_ok = pipe(pipefd) == 0;
+ if (pipefd_ok) {
+ wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]);
+ close(pipefd[1]);
+ }
+ else {
+ CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno));
}
- wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
- close(pipefd[1]);
- data_offer->in_use.store(false);
+ /* Only for DND (A no-op to disable for clipboard data-offer). */
+ data_offer->dnd.in_use = false;
if (mutex) {
mutex->unlock();
}
/* WARNING: `data_offer` may be freed from now on. */
+ char *buf = nullptr;
+ if (pipefd_ok) {
+ buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len);
+ close(pipefd[0]);
+ }
+ return buf;
+}
- std::string data;
- ssize_t len;
- char buffer[4096];
- while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
- data.insert(data.end(), buffer, buffer + len);
+static char *read_buffer_from_primary_selection_offer(GWL_PrimarySelection_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ const bool nil_terminate,
+ size_t *r_len)
+{
+ int pipefd[2];
+ const bool pipefd_ok = pipe(pipefd) == 0;
+ if (pipefd_ok) {
+ zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]);
+ close(pipefd[1]);
+ }
+ else {
+ CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno));
}
- close(pipefd[0]);
- return data;
+ if (mutex) {
+ mutex->unlock();
+ }
+ /* WARNING: `data_offer` may be freed from now on. */
+ char *buf = nullptr;
+ if (pipefd_ok) {
+ buf = read_file_as_buffer(pipefd[0], nil_terminate, r_len);
+ close(pipefd[0]);
+ }
+ return buf;
}
/**
@@ -1231,20 +1822,33 @@ static void data_source_handle_send(void *data,
const int32_t fd)
{
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- std::lock_guard lock{seat->data_source_mutex};
CLOG_INFO(LOG, 2, "send");
- const char *const buffer = seat->data_source->buffer_out;
- if (write(fd, buffer, strlen(buffer)) < 0) {
- GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl);
- }
- close(fd);
+ auto write_file_fn = [](GWL_Seat *seat, const int fd) {
+ if (UNLIKELY(write(fd,
+ seat->data_source->buffer_out.data,
+ seat->data_source->buffer_out.data_size) < 0)) {
+ CLOG_WARN(LOG, "error writing to clipboard: %s", std::strerror(errno));
+ }
+ close(fd);
+ seat->data_source_mutex.unlock();
+ };
+
+ seat->data_source_mutex.lock();
+ std::thread write_thread(write_file_fn, seat, fd);
+ write_thread.detach();
}
-static void data_source_handle_cancelled(void * /*data*/, struct wl_data_source *wl_data_source)
+static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source)
{
CLOG_INFO(LOG, 2, "cancelled");
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ GWL_DataSource *data_source = seat->data_source;
+ if (seat->data_source->wl_source == wl_data_source) {
+ data_source->wl_source = nullptr;
+ }
+
wl_data_source_destroy(wl_data_source);
}
@@ -1313,7 +1917,8 @@ static void data_offer_handle_offer(void *data,
const char *mime_type)
{
CLOG_INFO(LOG, 2, "offer (mime_type=%s)", mime_type);
- static_cast<GWL_DataOffer *>(data)->types.insert(mime_type);
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->types.insert(mime_type);
}
static void data_offer_handle_source_actions(void *data,
@@ -1321,7 +1926,8 @@ static void data_offer_handle_source_actions(void *data,
const uint32_t source_actions)
{
CLOG_INFO(LOG, 2, "source_actions (%u)", source_actions);
- static_cast<GWL_DataOffer *>(data)->source_actions = source_actions;
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->dnd.source_actions = (enum wl_data_device_manager_dnd_action)source_actions;
}
static void data_offer_handle_action(void *data,
@@ -1329,7 +1935,8 @@ static void data_offer_handle_action(void *data,
const uint32_t dnd_action)
{
CLOG_INFO(LOG, 2, "actions (%u)", dnd_action);
- static_cast<GWL_DataOffer *>(data)->dnd_action = dnd_action;
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->dnd.action = (enum wl_data_device_manager_dnd_action)dnd_action;
}
static const struct wl_data_offer_listener data_offer_listener = {
@@ -1381,7 +1988,7 @@ static void data_device_handle_enter(void *data,
seat->data_offer_dnd = static_cast<GWL_DataOffer *>(wl_data_offer_get_user_data(id));
GWL_DataOffer *data_offer = seat->data_offer_dnd;
- data_offer->in_use.store(true);
+ data_offer->dnd.in_use = true;
data_offer->dnd.xy[0] = x;
data_offer->dnd.xy[1] = y;
@@ -1390,11 +1997,15 @@ static void data_device_handle_enter(void *data,
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
- for (const std::string &type : mime_preference_order) {
- wl_data_offer_accept(id, serial, type.c_str());
+ for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order); i++) {
+ const char *type = ghost_wl_mime_preference_order[i];
+ wl_data_offer_accept(id, serial, type);
}
- seat->wl_surface_focus_dnd = wl_surface;
+ seat->wl_surface_window_focus_dnd = wl_surface;
+
+ seat->system->seat_active_set(seat);
+
dnd_events(seat, GHOST_kEventDraggingEntered);
}
@@ -1406,9 +2017,9 @@ static void data_device_handle_leave(void *data, struct wl_data_device * /*wl_da
CLOG_INFO(LOG, 2, "leave");
dnd_events(seat, GHOST_kEventDraggingExited);
- seat->wl_surface_focus_dnd = nullptr;
+ seat->wl_surface_window_focus_dnd = nullptr;
- if (seat->data_offer_dnd && !seat->data_offer_dnd->in_use.load()) {
+ if (seat->data_offer_dnd && !seat->data_offer_dnd->dnd.in_use) {
wl_data_offer_destroy(seat->data_offer_dnd->id);
delete seat->data_offer_dnd;
seat->data_offer_dnd = nullptr;
@@ -1439,23 +2050,35 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
GWL_DataOffer *data_offer = seat->data_offer_dnd;
- const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(),
- mime_preference_order.end(),
- data_offer->types.begin(),
- data_offer->types.end());
+ /* Use a blank string for `mime_receive` to prevent crashes, although could also be `nullptr`.
+ * Failure to set this to a known type just means the file won't have any special handling.
+ * GHOST still generates a dropped file event.
+ * NOTE: this string can be compared with `mime_text_plain`, `mime_text_uri` etc...
+ * as the this always points to the same values. */
+ const char *mime_receive = "";
+ for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order); i++) {
+ const char *type = ghost_wl_mime_preference_order[i];
+ if (data_offer->types.count(type)) {
+ mime_receive = type;
+ break;
+ }
+ }
- CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive.c_str());
+ CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive);
auto read_uris_fn = [](GWL_Seat *const seat,
GWL_DataOffer *data_offer,
- wl_surface *wl_surface,
- const std::string mime_receive) {
+ wl_surface *wl_surface_window,
+ const char *mime_receive) {
const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)};
- const std::string data = read_pipe(data_offer, mime_receive, nullptr);
+ size_t data_buf_len = 0;
+ const char *data_buf = read_buffer_from_data_offer(
+ data_offer, mime_receive, nullptr, false, &data_buf_len);
+ std::string data = data_buf ? std::string(data_buf, data_buf_len) : "";
+ free(const_cast<char *>(data_buf));
- CLOG_INFO(
- LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str());
+ CLOG_INFO(LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive, data.c_str());
wl_data_offer_finish(data_offer->id);
wl_data_offer_destroy(data_offer->id);
@@ -1468,13 +2091,13 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
GHOST_SystemWayland *const system = seat->system;
- if (mime_receive == mime_text_uri) {
+ if (mime_receive == ghost_wl_mime_text_uri) {
static constexpr const char *file_proto = "file://";
/* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`.
* So support both, once `\n` is found, strip the preceding `\r` if found. */
static constexpr const char *lf = "\n";
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_window);
std::vector<std::string> uris;
size_t pos = 0;
@@ -1513,7 +2136,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
wl_fixed_to_int(scale * xy[1]),
flist));
}
- else if (ELEM(mime_receive, mime_text_plain, mime_text_utf8)) {
+ else if (ELEM(mime_receive, ghost_wl_mime_text_plain, ghost_wl_mime_text_utf8)) {
/* TODO: enable use of internal functions 'txt_insert_buf' and
* 'text_update_edited' to behave like dropped text was pasted. */
CLOG_INFO(LOG, 2, "drop_read_uris_fn (text_plain, text_utf8), unhandled!");
@@ -1521,10 +2144,10 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
wl_display_roundtrip(system->wl_display());
};
- /* Pass in `seat->wl_surface_focus_dnd` instead of accessing it from `seat` since the leave
- * callback (#data_device_handle_leave) will clear the value once this function starts. */
+ /* Pass in `seat->wl_surface_window_focus_dnd` instead of accessing it from `seat` since the
+ * leave callback (#data_device_handle_leave) will clear the value once this function starts. */
std::thread read_thread(
- read_uris_fn, seat, data_offer, seat->wl_surface_focus_dnd, mime_receive);
+ read_uris_fn, seat, data_offer, seat->wl_surface_window_focus_dnd, mime_receive);
read_thread.detach();
}
@@ -1554,30 +2177,6 @@ static void data_device_handle_selection(void *data,
/* Get new data offer. */
data_offer = static_cast<GWL_DataOffer *>(wl_data_offer_get_user_data(id));
seat->data_offer_copy_paste = data_offer;
-
- auto read_selection_fn = [](GWL_Seat *seat) {
- GHOST_SystemWayland *const system = seat->system;
- seat->data_offer_copy_paste_mutex.lock();
-
- GWL_DataOffer *data_offer = seat->data_offer_copy_paste;
- std::string mime_receive;
- for (const std::string type : {mime_text_utf8, mime_text_plain}) {
- if (data_offer->types.count(type)) {
- mime_receive = type;
- break;
- }
- }
- const std::string data = read_pipe(
- data_offer, mime_receive, &seat->data_offer_copy_paste_mutex);
-
- {
- std::lock_guard lock{system_clipboard_mutex};
- system->clipboard_set(data);
- }
- };
-
- std::thread read_thread(read_selection_fn, seat);
- read_thread.detach();
}
static const struct wl_data_device_listener data_device_listener = {
@@ -1631,7 +2230,7 @@ static CLG_LogRef LOG_WL_CURSOR_SURFACE = {"ghost.wl.handle.cursor_surface"};
static bool update_cursor_scale(GWL_Cursor &cursor,
wl_shm *shm,
GWL_SeatStatePointer *seat_state_pointer,
- wl_surface *wl_cursor_surface)
+ wl_surface *wl_surface_cursor)
{
int scale = 0;
for (const GWL_Output *output : seat_state_pointer->outputs) {
@@ -1643,10 +2242,11 @@ static bool update_cursor_scale(GWL_Cursor &cursor,
if (scale > 0 && seat_state_pointer->theme_scale != scale) {
seat_state_pointer->theme_scale = scale;
if (!cursor.is_custom) {
- wl_surface_set_buffer_scale(wl_cursor_surface, scale);
+ wl_surface_set_buffer_scale(wl_surface_cursor, scale);
}
wl_cursor_theme_destroy(cursor.wl_theme);
- cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm);
+ cursor.wl_theme = wl_cursor_theme_load(
+ cursor.theme_name.c_str(), scale * cursor.theme_size, shm);
return true;
}
return false;
@@ -1663,8 +2263,8 @@ static void cursor_surface_handle_enter(void *data,
CLOG_INFO(LOG, 2, "handle_enter");
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_from_cursor_surface(seat,
- wl_surface);
+ GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_from_cursor_surface(
+ seat, wl_surface);
const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output);
seat_state_pointer->outputs.insert(reg_output);
update_cursor_scale(seat->cursor, seat->system->wl_shm(), seat_state_pointer, wl_surface);
@@ -1681,8 +2281,8 @@ static void cursor_surface_handle_leave(void *data,
CLOG_INFO(LOG, 2, "handle_leave");
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_from_cursor_surface(seat,
- wl_surface);
+ GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_from_cursor_surface(
+ seat, wl_surface);
const GWL_Output *reg_output = ghost_wl_output_user_data(wl_output);
seat_state_pointer->outputs.erase(reg_output);
update_cursor_scale(seat->cursor, seat->system->wl_shm(), seat_state_pointer, wl_surface);
@@ -1726,7 +2326,18 @@ static void pointer_handle_enter(void *data,
seat->pointer.serial = serial;
seat->pointer.xy[0] = surface_x;
seat->pointer.xy[1] = surface_y;
- seat->pointer.wl_surface = wl_surface;
+
+ /* Resetting scroll events is likely unnecessary,
+ * do this to avoid any possible problems as it's harmless. */
+ seat->pointer_scroll.smooth_xy[0] = 0;
+ seat->pointer_scroll.smooth_xy[1] = 0;
+ seat->pointer_scroll.discrete_xy[0] = 0;
+ seat->pointer_scroll.discrete_xy[1] = 0;
+ seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
+
+ seat->pointer.wl_surface_window = wl_surface;
+
+ seat->system->seat_active_set(seat);
win->setCursorShape(win->getCursorShape());
@@ -1745,7 +2356,7 @@ static void pointer_handle_leave(void *data,
struct wl_surface *wl_surface)
{
/* First clear the `pointer.wl_surface`, since the window won't exist when closing the window. */
- static_cast<GWL_Seat *>(data)->pointer.wl_surface = nullptr;
+ static_cast<GWL_Seat *>(data)->pointer.wl_surface_window = nullptr;
if (wl_surface && ghost_wl_surface_own(wl_surface)) {
CLOG_INFO(LOG, 2, "leave");
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface);
@@ -1766,7 +2377,7 @@ static void pointer_handle_motion(void *data,
seat->pointer.xy[0] = surface_x;
seat->pointer.xy[1] = surface_y;
- if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
CLOG_INFO(LOG, 2, "motion");
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
@@ -1830,31 +2441,99 @@ static void pointer_handle_button(void *data,
seat->data_source_serial = serial;
seat->pointer.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
- if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
seat->system->pushEvent(new GHOST_EventButton(
seat->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
}
}
-static void pointer_handle_axis(void * /*data*/,
+static void pointer_handle_axis(void *data,
struct wl_pointer * /*wl_pointer*/,
const uint32_t /*time*/,
const uint32_t axis,
const wl_fixed_t value)
{
+ /* NOTE: this is used for touch based scrolling - or other input that doesn't scroll with
+ * discrete "steps". This allows supporting smooth-scrolling without "touch" gesture support. */
CLOG_INFO(LOG, 2, "axis (axis=%u, value=%d)", axis, value);
+ const int index = pointer_axis_as_index(axis);
+ if (UNLIKELY(index == -1)) {
+ return;
+ }
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer_scroll.smooth_xy[index] = value;
}
-static void pointer_handle_frame(void * /*data*/, struct wl_pointer * /*wl_pointer*/)
+static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/)
{
CLOG_INFO(LOG, 2, "frame");
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+
+ /* Both discrete and smooth events may be set at once, never generate events for both
+ * as this will be handling the same event in to different ways.
+ * Prioritize discrete axis events for the mouse wheel, otherwise smooth scroll. */
+ if (seat->pointer_scroll.axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
+ if (seat->pointer_scroll.discrete_xy[0]) {
+ seat->pointer_scroll.smooth_xy[0] = 0;
+ }
+ if (seat->pointer_scroll.discrete_xy[1]) {
+ seat->pointer_scroll.smooth_xy[1] = 0;
+ }
+ }
+ else {
+ if (seat->pointer_scroll.smooth_xy[0]) {
+ seat->pointer_scroll.discrete_xy[0] = 0;
+ }
+ if (seat->pointer_scroll.smooth_xy[1]) {
+ seat->pointer_scroll.discrete_xy[1] = 0;
+ }
+ }
+
+ /* Discrete X axis currently unsupported. */
+ if (seat->pointer_scroll.discrete_xy[1]) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ const int32_t discrete = seat->pointer_scroll.discrete_xy[1];
+ seat->system->pushEvent(new GHOST_EventWheel(
+ seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1));
+ }
+ seat->pointer_scroll.discrete_xy[0] = 0;
+ seat->pointer_scroll.discrete_xy[1] = 0;
+ }
+
+ if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ const wl_fixed_t scale = win->scale();
+ seat->system->pushEvent(new GHOST_EventTrackpad(
+ seat->system->getMilliSeconds(),
+ win,
+ GHOST_kTrackpadEventScroll,
+ wl_fixed_to_int(scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(scale * seat->pointer.xy[1]),
+ /* NOTE: scaling the delta doesn't seem necessary.
+ * NOTE: inverting delta gives correct results, see: QTBUG-85767.
+ * NOTE: the preference to invert scrolling (in GNOME at least)
+ * has already been applied so there is no need to read this preference. */
+ -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]),
+ -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]),
+ false));
+ }
+
+ seat->pointer_scroll.smooth_xy[0] = 0;
+ seat->pointer_scroll.smooth_xy[1] = 0;
+ }
+
+ seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
}
-static void pointer_handle_axis_source(void * /*data*/,
+static void pointer_handle_axis_source(void *data,
struct wl_pointer * /*wl_pointer*/,
uint32_t axis_source)
{
CLOG_INFO(LOG, 2, "axis_source (axis_source=%u)", axis_source);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer_scroll.axis_source = (enum wl_pointer_axis_source)axis_source;
}
static void pointer_handle_axis_stop(void * /*data*/,
struct wl_pointer * /*wl_pointer*/,
@@ -1868,18 +2547,15 @@ static void pointer_handle_axis_discrete(void *data,
uint32_t axis,
int32_t discrete)
{
+ /* NOTE: a discrete axis are typically mouse wheel events.
+ * The non-discrete version of this function is used for touch-pad. */
CLOG_INFO(LOG, 2, "axis_discrete (axis=%u, discrete=%d)", axis, discrete);
-
- GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
+ const int index = pointer_axis_as_index(axis);
+ if (UNLIKELY(index == -1)) {
return;
}
-
- if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
- seat->system->pushEvent(new GHOST_EventWheel(
- seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1));
- }
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer_scroll.discrete_xy[index] = discrete;
}
static const struct wl_pointer_listener pointer_listener = {
@@ -1899,6 +2575,325 @@ static const struct wl_pointer_listener pointer_listener = {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Listener (Pointer Gesture: Hold), #zwp_pointer_gesture_hold_v1_listener
+ * \{ */
+
+#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
+static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {"ghost.wl.handle.pointer_gesture.hold"};
+# define LOG (&LOG_WL_POINTER_GESTURE_HOLD)
+
+static void gesture_hold_handle_begin(
+ void * /*data*/,
+ struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*surface*/,
+ uint32_t fingers)
+{
+ CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers);
+}
+
+static void gesture_hold_handle_end(
+ void * /*data*/,
+ struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t cancelled)
+{
+ CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled);
+}
+
+static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = {
+ gesture_hold_handle_begin,
+ gesture_hold_handle_end,
+};
+
+# undef LOG
+#endif /* ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Pointer Gesture: Pinch), #zwp_pointer_gesture_pinch_v1_listener
+ * \{ */
+
+#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
+static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {"ghost.wl.handle.pointer_gesture.pinch"};
+# define LOG (&LOG_WL_POINTER_GESTURE_PINCH)
+
+static void gesture_pinch_handle_begin(void *data,
+ struct zwp_pointer_gesture_pinch_v1 * /*pinch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*surface*/,
+ uint32_t fingers)
+{
+ CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ /* Reset defaults. */
+ seat->pointer_gesture_pinch = GWL_SeatStatePointerGesture_Pinch{};
+
+ GHOST_WindowWayland *win = nullptr;
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
+ win = ghost_wl_surface_user_data(wl_surface_focus);
+ }
+ /* NOTE(@campbellbarton): Blender's use of track-pad coordinates is inconsistent and needs work.
+ * This isn't specific to WAYLAND, in practice they tend to work well enough in most cases.
+ * Some operators scale by the UI scale, some don't.
+ * Even this window scale is not correct because it doesn't account for:
+ * 1) Fractional window scale.
+ * 2) Blender's UI scale preference (which GHOST doesn't know about).
+ *
+ * If support for this were all that was needed it could be handled in GHOST,
+ * however as the operators are not even using coordinates compatible with each other,
+ * it would be better to resolve this by passing rotation & zoom levels directly,
+ * instead of attempting to handle them as cursor coordinates.
+ */
+ const wl_fixed_t win_scale = win ? win->scale() : 1;
+
+ /* NOTE(@campbellbarton): Scale factors match Blender's operators & default preferences.
+ * For these values to work correctly, operator logic will need to be changed not to scale input
+ * by the region size (as with 3D view zoom) or preference for 3D view orbit sensitivity.
+ *
+ * By working "correctly" I mean that a rotation action where the users fingers rotate to
+ * opposite locations should always rotate the viewport 180d, since users will expect the
+ * physical location of their fingers to match the viewport.
+ * Similarly with zoom, the scale value from the pinch action can be mapped to a zoom level
+ * although unlike rotation, an inexact mapping is less noticeable.
+ * Users may even prefer the zoom level to be scaled - which could be a preference. */
+ seat->pointer_gesture_pinch.scale.value = wl_fixed_from_int(1);
+ /* The value 300 matches a value used in clip & image zoom operators.
+ * It seems OK for the 3D view too. */
+ seat->pointer_gesture_pinch.scale.factor = 300 * win_scale;
+ /* The value 5 is used on macOS and roughly maps 1:1 with turntable rotation,
+ * although preferences can scale the sensitivity (which would be skipped ideally). */
+ seat->pointer_gesture_pinch.rotation.factor = 5 * win_scale;
+}
+
+static void gesture_pinch_handle_update(void *data,
+ struct zwp_pointer_gesture_pinch_v1 * /*pinch*/,
+ uint32_t /*time*/,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t scale,
+ wl_fixed_t rotation)
+{
+ CLOG_INFO(LOG,
+ 2,
+ "update (dx=%.3f, dy=%.3f, scale=%.3f, rotation=%.3f)",
+ wl_fixed_to_double(dx),
+ wl_fixed_to_double(dy),
+ wl_fixed_to_double(scale),
+ wl_fixed_to_double(rotation));
+
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+
+ GHOST_WindowWayland *win = nullptr;
+
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
+ win = ghost_wl_surface_user_data(wl_surface_focus);
+ }
+
+ /* Scale defaults to `wl_fixed_from_int(1)` which may change while pinching.
+ * This needs to be converted to a delta. */
+ const wl_fixed_t scale_delta = scale - seat->pointer_gesture_pinch.scale.value;
+ const int scale_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta(
+ &seat->pointer_gesture_pinch.scale, scale_delta);
+
+ /* Rotation in degrees, unlike scale this is a delta. */
+ const int rotation_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta(
+ &seat->pointer_gesture_pinch.rotation, rotation);
+
+ if (win) {
+ const wl_fixed_t win_scale = win->scale();
+ const int32_t event_xy[2] = {
+ wl_fixed_to_int(win_scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(win_scale * seat->pointer.xy[1]),
+ };
+ if (scale_as_delta_px) {
+ seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(),
+ win,
+ GHOST_kTrackpadEventMagnify,
+ event_xy[0],
+ event_xy[1],
+ scale_as_delta_px,
+ 0,
+ false));
+ }
+
+ if (rotation_as_delta_px) {
+ seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(),
+ win,
+ GHOST_kTrackpadEventRotate,
+ event_xy[0],
+ event_xy[1],
+ rotation_as_delta_px,
+ 0,
+ false));
+ }
+ }
+}
+
+static void gesture_pinch_handle_end(void * /*data*/,
+ struct zwp_pointer_gesture_pinch_v1 * /*pinch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t cancelled)
+{
+ CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled);
+}
+
+static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = {
+ gesture_pinch_handle_begin,
+ gesture_pinch_handle_update,
+ gesture_pinch_handle_end,
+};
+
+# undef LOG
+#endif /* ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Pointer Gesture: Swipe), #zwp_pointer_gesture_swipe_v1
+ *
+ * \note In both Gnome-Shell & KDE this gesture isn't emitted at time of writing,
+ * instead, high resolution 2D #wl_pointer_listener.axis data is generated which works well.
+ * There may be some situations where WAYLAND compositors generate this gesture
+ * (swiping with 3+ fingers, for e.g.). So keep this to allow logging & testing gestures.
+ * \{ */
+
+#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
+static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {"ghost.wl.handle.pointer_gesture.swipe"};
+# define LOG (&LOG_WL_POINTER_GESTURE_SWIPE)
+
+static void gesture_swipe_handle_begin(
+ void * /*data*/,
+ struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*surface*/,
+ uint32_t fingers)
+{
+ CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers);
+}
+
+static void gesture_swipe_handle_update(
+ void * /*data*/,
+ struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/,
+ uint32_t /*time*/,
+ wl_fixed_t dx,
+ wl_fixed_t dy)
+{
+ CLOG_INFO(LOG, 2, "update (dx=%.3f, dy=%.3f)", wl_fixed_to_double(dx), wl_fixed_to_double(dy));
+}
+
+static void gesture_swipe_handle_end(
+ void * /*data*/,
+ struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t cancelled)
+{
+ CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled);
+}
+
+static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = {
+ gesture_swipe_handle_begin,
+ gesture_swipe_handle_update,
+ gesture_swipe_handle_end,
+};
+
+# undef LOG
+#endif /* ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Touch Seat), #wl_touch_listener
+ *
+ * NOTE(@campbellbarton): It's not clear if this interface is used by popular compositors.
+ * It looks like GNOME/KDE only support `zwp_pointer_gestures_v1_interface`.
+ * If this isn't used anywhere, it could be removed.
+ * \{ */
+
+static CLG_LogRef LOG_WL_TOUCH = {"ghost.wl.handle.touch"};
+#define LOG (&LOG_WL_TOUCH)
+
+static void touch_seat_handle_down(void * /*data*/,
+ struct wl_touch * /*wl_touch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*wl_surface*/,
+ int32_t /*id*/,
+ wl_fixed_t /*x*/,
+ wl_fixed_t /*y*/)
+{
+ CLOG_INFO(LOG, 2, "down");
+}
+
+static void touch_seat_handle_up(void * /*data*/,
+ struct wl_touch * /*wl_touch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t /*id*/)
+{
+ CLOG_INFO(LOG, 2, "up");
+}
+
+static void touch_seat_handle_motion(void * /*data*/,
+ struct wl_touch * /*wl_touch*/,
+ uint32_t /*time*/,
+ int32_t /*id*/,
+ wl_fixed_t /*x*/,
+ wl_fixed_t /*y*/)
+{
+ CLOG_INFO(LOG, 2, "motion");
+}
+
+static void touch_seat_handle_frame(void * /*data*/, struct wl_touch * /*wl_touch*/)
+{
+ CLOG_INFO(LOG, 2, "frame");
+}
+
+static void touch_seat_handle_cancel(void * /*data*/, struct wl_touch * /*wl_touch*/)
+{
+
+ CLOG_INFO(LOG, 2, "cancel");
+}
+
+static void touch_seat_handle_shape(void * /*data*/,
+ struct wl_touch * /*touch*/,
+ int32_t /*id*/,
+ wl_fixed_t /*major*/,
+ wl_fixed_t /*minor*/)
+{
+ CLOG_INFO(LOG, 2, "shape");
+}
+
+static void touch_seat_handle_orientation(void * /*data*/,
+ struct wl_touch * /*touch*/,
+ int32_t /*id*/,
+ wl_fixed_t /*orientation*/)
+{
+ CLOG_INFO(LOG, 2, "orientation");
+}
+
+static const struct wl_touch_listener touch_seat_listener = {
+ touch_seat_handle_down,
+ touch_seat_handle_up,
+ touch_seat_handle_motion,
+ touch_seat_handle_frame,
+ touch_seat_handle_cancel,
+ touch_seat_handle_shape,
+ touch_seat_handle_orientation,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Listener (Tablet Tool), #zwp_tablet_tool_v2_listener
* \{ */
@@ -1983,11 +2978,13 @@ static void tablet_tool_handle_proximity_in(void *data,
GWL_Seat *seat = tablet_tool->seat;
seat->cursor_source_serial = serial;
- seat->tablet.wl_surface = wl_surface;
+ seat->tablet.wl_surface_window = wl_surface;
seat->tablet.serial = serial;
seat->data_source_serial = serial;
+ seat->system->seat_active_set(seat);
+
/* Update #GHOST_TabletData. */
GHOST_TabletData &td = tablet_tool->data;
/* Reset, to avoid using stale tilt/pressure. */
@@ -1996,7 +2993,7 @@ static void tablet_tool_handle_proximity_in(void *data,
/* In case pressure isn't supported. */
td.Pressure = 1.0f;
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl_surface);
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl_surface_window);
win->activate();
@@ -2026,7 +3023,7 @@ static void tablet_tool_handle_down(void *data,
seat->data_source_serial = serial;
seat->tablet.buttons.set(ebutton, true);
- if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
seat->system->pushEvent(new GHOST_EventButton(
seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data));
@@ -2044,7 +3041,7 @@ static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_
seat->tablet.buttons.set(ebutton, false);
- if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
seat->system->pushEvent(new GHOST_EventButton(
seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data));
@@ -2129,7 +3126,7 @@ static void tablet_tool_handle_wheel(void *data,
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(data);
GWL_Seat *seat = tablet_tool->seat;
- if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
seat->system->pushEvent(new GHOST_EventWheel(seat->system->getMilliSeconds(), win, clicks));
}
@@ -2158,10 +3155,10 @@ static void tablet_tool_handle_button(void *data,
GHOST_TButton ebutton = GHOST_kButtonMaskLeft;
switch (button) {
case BTN_STYLUS:
- ebutton = GHOST_kButtonMaskRight;
+ ebutton = GHOST_kButtonMaskMiddle;
break;
case BTN_STYLUS2:
- ebutton = GHOST_kButtonMaskMiddle;
+ ebutton = GHOST_kButtonMaskRight;
break;
case BTN_STYLUS3:
ebutton = GHOST_kButtonMaskButton4;
@@ -2171,7 +3168,7 @@ static void tablet_tool_handle_button(void *data,
seat->data_source_serial = serial;
seat->tablet.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
- if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
seat->system->pushEvent(new GHOST_EventButton(
seat->system->getMilliSeconds(), etype, win, ebutton, tablet_tool->data));
@@ -2187,7 +3184,7 @@ static void tablet_tool_handle_frame(void *data,
GWL_Seat *seat = tablet_tool->seat;
/* No need to check the surfaces origin, it's already known to be owned by GHOST. */
- if (wl_surface *wl_surface_focus = seat->tablet.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
seat->system->pushEvent(new GHOST_EventCursor(seat->system->getMilliSeconds(),
@@ -2202,7 +3199,7 @@ static void tablet_tool_handle_frame(void *data,
}
if (tablet_tool->proximity == false) {
- seat->tablet.wl_surface = nullptr;
+ seat->tablet.wl_surface_window = nullptr;
}
}
@@ -2330,9 +3327,23 @@ static void keyboard_handle_keymap(void *data,
xkb_state_unref(seat->xkb_state_empty);
seat->xkb_state_empty = xkb_state_new(keymap);
+ for (int i = 0; i < MOD_INDEX_NUM; i++) {
+ const GWL_ModifierInfo &mod_info = g_modifier_info_table[i];
+ seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id);
+ }
+
+ xkb_state_unref(seat->xkb_state_empty_with_shift);
+ seat->xkb_state_empty_with_shift = nullptr;
+ {
+ const xkb_mod_index_t mod_shift = seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT];
+ if (mod_shift != XKB_MOD_INVALID) {
+ seat->xkb_state_empty_with_shift = xkb_state_new(keymap);
+ xkb_state_update_mask(seat->xkb_state_empty_with_shift, (1 << mod_shift), 0, 0, 0, 0, 0);
+ }
+ }
+
xkb_state_unref(seat->xkb_state_empty_with_numlock);
seat->xkb_state_empty_with_numlock = nullptr;
-
{
const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock");
@@ -2343,10 +3354,21 @@ static void keyboard_handle_keymap(void *data,
}
}
- for (int i = 0; i < MOD_INDEX_NUM; i++) {
- const GWL_ModifierInfo &mod_info = g_modifier_info_table[i];
- seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id);
+#ifdef USE_NON_LATIN_KB_WORKAROUND
+ seat->xkb_use_non_latin_workaround = false;
+ if (seat->xkb_state_empty_with_shift) {
+ seat->xkb_use_non_latin_workaround = true;
+ for (xkb_keycode_t key_code = KEY_1 + EVDEV_OFFSET; key_code <= KEY_0 + EVDEV_OFFSET;
+ key_code++) {
+ const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(seat->xkb_state_empty_with_shift,
+ key_code);
+ if (!(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9)) {
+ seat->xkb_use_non_latin_workaround = false;
+ break;
+ }
+ }
}
+#endif
keyboard_depressed_state_reset(seat);
@@ -2372,12 +3394,14 @@ static void keyboard_handle_enter(void *data,
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
seat->keyboard.serial = serial;
- seat->keyboard.wl_surface = wl_surface;
+ seat->keyboard.wl_surface_window = wl_surface;
+
+ seat->system->seat_active_set(seat);
/* If there are any keys held when activating the window,
* modifiers will be compared against the seat state,
* only enabling modifiers that were previously disabled. */
- WGL_KeyboardDepressedState key_depressed_prev = seat->key_depressed;
+ GWL_KeyboardDepressedState key_depressed_prev = seat->key_depressed;
keyboard_depressed_state_reset(seat);
uint32_t *key;
@@ -2415,7 +3439,7 @@ static void keyboard_handle_leave(void *data,
CLOG_INFO(LOG, 2, "leave");
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- seat->keyboard.wl_surface = nullptr;
+ seat->keyboard.wl_surface_window = nullptr;
/* Losing focus must stop repeating text. */
if (seat->key_repeat.timer) {
@@ -2435,6 +3459,8 @@ static void keyboard_handle_leave(void *data,
static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(
struct xkb_state *xkb_state_empty,
struct xkb_state *xkb_state_empty_with_numlock,
+ struct xkb_state *xkb_state_empty_with_shift,
+ const bool xkb_use_non_latin_workaround,
const xkb_keycode_t key)
{
/* Use an empty keyboard state to access key symbol without modifiers. */
@@ -2448,11 +3474,30 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(
/* Accounts for key-pad keys typically swapped for numbers when number-lock is enabled:
* `Home Left Up Right Down Prior Page_Up Next Page_Dow End Begin Insert Delete`. */
- if (xkb_state_empty_with_numlock && (sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete)) {
- const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_numlock, key);
- if (sym_test != XKB_KEY_NoSymbol) {
- sym = sym_test;
+ if (sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete) {
+ if (xkb_state_empty_with_numlock) {
+ const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_numlock, key);
+ if (sym_test != XKB_KEY_NoSymbol) {
+ sym = sym_test;
+ }
+ }
+ }
+ else {
+#ifdef USE_NON_LATIN_KB_WORKAROUND
+ if (key >= (KEY_1 + EVDEV_OFFSET) && key <= (KEY_0 + EVDEV_OFFSET)) {
+ if (xkb_state_empty_with_shift && xkb_use_non_latin_workaround) {
+ const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_shift, key);
+ if (sym_test != XKB_KEY_NoSymbol) {
+ /* Should never happen as enabling `xkb_use_non_latin_workaround` checks this. */
+ GHOST_ASSERT(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9, "Unexpected key");
+ sym = sym_test;
+ }
+ }
}
+#else
+ (void)xkb_state_empty_with_shift;
+ (void)xkb_use_non_latin_workaround;
+#endif
}
return sym;
@@ -2495,7 +3540,15 @@ static void keyboard_handle_key(void *data,
const xkb_keycode_t key_code = key + EVDEV_OFFSET;
const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers(
- seat->xkb_state_empty, seat->xkb_state_empty_with_numlock, key_code);
+ seat->xkb_state_empty,
+ seat->xkb_state_empty_with_numlock,
+ seat->xkb_state_empty_with_shift,
+#ifdef USE_NON_LATIN_KB_WORKAROUND
+ seat->xkb_use_non_latin_workaround,
+#else
+ false,
+#endif
+ key_code);
if (sym == XKB_KEY_NoSymbol) {
CLOG_INFO(LOG, 2, "key (code=%d, state=%u, no symbol, skipped)", int(key_code), state);
return;
@@ -2576,7 +3629,7 @@ static void keyboard_handle_key(void *data,
keyboard_depressed_state_key_event(seat, gkey, etype);
- if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface_window) {
GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
seat->system->pushEvent(
new GHOST_EventKey(seat->system->getMilliSeconds(), etype, win, gkey, false, utf8_buf));
@@ -2587,11 +3640,10 @@ static void keyboard_handle_key(void *data,
/* Start timer for repeating key, if applicable. */
if ((seat->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) &&
xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) {
- key_repeat_payload = new GWL_KeyRepeatPlayload({
- .seat = seat,
- .key_code = key_code,
- .key_data = {.gkey = gkey},
- });
+ key_repeat_payload = new GWL_KeyRepeatPlayload();
+ key_repeat_payload->seat = seat;
+ key_repeat_payload->key_code = key_code;
+ key_repeat_payload->key_data.gkey = gkey;
}
}
@@ -2601,7 +3653,7 @@ static void keyboard_handle_key(void *data,
task->getUserData());
GWL_Seat *seat = payload->seat;
- if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->keyboard.wl_surface_window) {
GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
GHOST_SystemWayland *system = seat->system;
/* Calculate this value every time in case modifier keys are pressed. */
@@ -2681,12 +3733,285 @@ static const struct wl_keyboard_listener keyboard_listener = {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Listener (Primary Selection Offer), #zwp_primary_selection_offer_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_PRIMARY_SELECTION_OFFER = {"ghost.wl.handle.primary_selection_offer"};
+#define LOG (&LOG_WL_PRIMARY_SELECTION_OFFER)
+
+static void primary_selection_offer_offer(void *data,
+ struct zwp_primary_selection_offer_v1 *id,
+ const char *type)
+{
+ GWL_PrimarySelection_DataOffer *data_offer = static_cast<GWL_PrimarySelection_DataOffer *>(data);
+ if (data_offer->id != id) {
+ CLOG_INFO(LOG, 2, "offer: %p: offer for unknown selection %p of %s (skipped)", data, id, type);
+ return;
+ }
+
+ data_offer->types.insert(std::string(type));
+}
+
+static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener = {
+ primary_selection_offer_offer,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Primary Selection Device), #zwp_primary_selection_device_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_PRIMARY_SELECTION_DEVICE = {"ghost.wl.handle.primary_selection_device"};
+#define LOG (&LOG_WL_PRIMARY_SELECTION_DEVICE)
+
+static void primary_selection_device_handle_data_offer(
+ void * /*data*/,
+ struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/,
+ struct zwp_primary_selection_offer_v1 *id)
+{
+ CLOG_INFO(LOG, 2, "data_offer");
+
+ GWL_PrimarySelection_DataOffer *data_offer = new GWL_PrimarySelection_DataOffer;
+ data_offer->id = id;
+ zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, data_offer);
+}
+
+static void primary_selection_device_handle_selection(
+ void *data,
+ struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/,
+ struct zwp_primary_selection_offer_v1 *id)
+{
+ GWL_PrimarySelection *primary = static_cast<GWL_PrimarySelection *>(data);
+
+ std::lock_guard lock{primary->data_offer_mutex};
+
+ /* Delete old data offer. */
+ if (primary->data_offer != nullptr) {
+ gwl_primary_selection_discard_offer(primary);
+ }
+
+ if (id == nullptr) {
+ CLOG_INFO(LOG, 2, "selection: (skipped)");
+ return;
+ }
+ CLOG_INFO(LOG, 2, "selection");
+ /* Get new data offer. */
+ GWL_PrimarySelection_DataOffer *data_offer = static_cast<GWL_PrimarySelection_DataOffer *>(
+ zwp_primary_selection_offer_v1_get_user_data(id));
+ primary->data_offer = data_offer;
+}
+
+static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
+ primary_selection_device_handle_data_offer,
+ primary_selection_device_handle_selection,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Primary Selection Source), #zwp_primary_selection_source_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_PRIMARY_SELECTION_SOURCE = {"ghost.wl.handle.primary_selection_source"};
+#define LOG (&LOG_WL_PRIMARY_SELECTION_SOURCE)
+
+static void primary_selection_source_send(void *data,
+ struct zwp_primary_selection_source_v1 * /*source*/,
+ const char * /*mime_type*/,
+ int32_t fd)
+{
+ CLOG_INFO(LOG, 2, "send");
+
+ GWL_PrimarySelection *primary = static_cast<GWL_PrimarySelection *>(data);
+
+ auto write_file_fn = [](GWL_PrimarySelection *primary, const int fd) {
+ if (UNLIKELY(write(fd,
+ primary->data_source->buffer_out.data,
+ primary->data_source->buffer_out.data_size) < 0)) {
+ CLOG_WARN(LOG, "error writing to primary clipboard: %s", std::strerror(errno));
+ }
+ close(fd);
+ primary->data_source_mutex.unlock();
+ };
+
+ primary->data_source_mutex.lock();
+ std::thread write_thread(write_file_fn, primary, fd);
+ write_thread.detach();
+}
+
+static void primary_selection_source_cancelled(void *data,
+ struct zwp_primary_selection_source_v1 *source)
+{
+ CLOG_INFO(LOG, 2, "cancelled");
+
+ GWL_PrimarySelection *primary = static_cast<GWL_PrimarySelection *>(data);
+
+ if (source == primary->data_source->wp_source) {
+ gwl_primary_selection_discard_source(primary);
+ }
+}
+
+static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = {
+ primary_selection_source_send,
+ primary_selection_source_cancelled,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Listener (Seat), #wl_seat_listener
* \{ */
static CLG_LogRef LOG_WL_SEAT = {"ghost.wl.handle.seat"};
#define LOG (&LOG_WL_SEAT)
+static void gwl_seat_capability_pointer_enable(GWL_Seat *seat)
+{
+ if (seat->wl_pointer) {
+ return;
+ }
+ seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat);
+ seat->cursor.wl_surface_cursor = wl_compositor_create_surface(seat->system->wl_compositor());
+ seat->cursor.visible = true;
+ seat->cursor.wl_buffer = nullptr;
+ if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) {
+ seat->cursor.theme_name = std::string();
+ seat->cursor.theme_size = default_cursor_size;
+ }
+ wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
+
+ wl_surface_add_listener(seat->cursor.wl_surface_cursor, &cursor_surface_listener, seat);
+ ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface_cursor);
+
+ zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures();
+ if (pointer_gestures) {
+#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
+ { /* Hold gesture. */
+ struct zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture(
+ pointer_gestures, seat->wl_pointer);
+ zwp_pointer_gesture_hold_v1_set_user_data(gesture, seat);
+ zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat);
+ seat->wp_pointer_gesture_hold = gesture;
+ }
+#endif
+#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
+ { /* Pinch gesture. */
+ struct zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture(
+ pointer_gestures, seat->wl_pointer);
+ zwp_pointer_gesture_pinch_v1_set_user_data(gesture, seat);
+ zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat);
+ seat->wp_pointer_gesture_pinch = gesture;
+ }
+#endif
+#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
+ { /* Swipe gesture. */
+ struct zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture(
+ pointer_gestures, seat->wl_pointer);
+ zwp_pointer_gesture_swipe_v1_set_user_data(gesture, seat);
+ zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat);
+ seat->wp_pointer_gesture_swipe = gesture;
+ }
+#endif
+ }
+}
+
+static void gwl_seat_capability_pointer_disable(GWL_Seat *seat)
+{
+ if (!seat->wl_pointer) {
+ return;
+ }
+
+ zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures();
+ if (pointer_gestures) {
+#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
+ { /* Hold gesture. */
+ struct zwp_pointer_gesture_hold_v1 **gesture_p = &seat->wp_pointer_gesture_hold;
+ if (*gesture_p) {
+ zwp_pointer_gesture_hold_v1_destroy(*gesture_p);
+ *gesture_p = nullptr;
+ }
+ }
+#endif
+#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
+ { /* Pinch gesture. */
+ struct zwp_pointer_gesture_pinch_v1 **gesture_p = &seat->wp_pointer_gesture_pinch;
+ if (*gesture_p) {
+ zwp_pointer_gesture_pinch_v1_destroy(*gesture_p);
+ *gesture_p = nullptr;
+ }
+ }
+#endif
+#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
+ { /* Swipe gesture. */
+ struct zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->wp_pointer_gesture_swipe;
+ if (*gesture_p) {
+ zwp_pointer_gesture_swipe_v1_destroy(*gesture_p);
+ *gesture_p = nullptr;
+ }
+ }
+#endif
+ }
+
+ if (seat->cursor.wl_surface_cursor) {
+ wl_surface_destroy(seat->cursor.wl_surface_cursor);
+ seat->cursor.wl_surface_cursor = nullptr;
+ }
+ if (seat->cursor.wl_theme) {
+ wl_cursor_theme_destroy(seat->cursor.wl_theme);
+ seat->cursor.wl_theme = nullptr;
+ }
+
+ wl_pointer_destroy(seat->wl_pointer);
+ seat->wl_pointer = nullptr;
+}
+
+static void gwl_seat_capability_keyboard_enable(GWL_Seat *seat)
+{
+ if (seat->wl_keyboard) {
+ return;
+ }
+ seat->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat);
+ wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, seat);
+}
+
+static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat)
+{
+ if (!seat->wl_keyboard) {
+ return;
+ }
+ if (seat->key_repeat.timer) {
+ keyboard_handle_key_repeat_cancel(seat);
+ }
+ wl_keyboard_destroy(seat->wl_keyboard);
+ seat->wl_keyboard = nullptr;
+}
+
+static void gwl_seat_capability_touch_enable(GWL_Seat *seat)
+{
+ if (seat->wl_touch) {
+ return;
+ }
+ seat->wl_touch = wl_seat_get_touch(seat->wl_seat);
+ wl_touch_set_user_data(seat->wl_touch, seat);
+ wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat);
+}
+
+static void gwl_seat_capability_touch_disable(GWL_Seat *seat)
+{
+ if (!seat->wl_touch) {
+ return;
+ }
+ wl_touch_destroy(seat->wl_touch);
+ seat->wl_touch = nullptr;
+}
+
static void seat_handle_capabilities(void *data,
struct wl_seat *wl_seat,
const uint32_t capabilities)
@@ -2699,27 +4024,27 @@ static void seat_handle_capabilities(void *data,
(capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0);
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- seat->wl_pointer = nullptr;
- seat->wl_keyboard = nullptr;
+ GHOST_ASSERT(seat->wl_seat == wl_seat, "Seat mismatch");
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
- seat->wl_pointer = wl_seat_get_pointer(wl_seat);
- seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor());
- seat->cursor.visible = true;
- seat->cursor.wl_buffer = nullptr;
- if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) {
- seat->cursor.theme_name = std::string();
- seat->cursor.size = default_cursor_size;
- }
- wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data);
-
- wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, data);
- ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface);
+ gwl_seat_capability_pointer_enable(seat);
+ }
+ else {
+ gwl_seat_capability_pointer_disable(seat);
}
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
- seat->wl_keyboard = wl_seat_get_keyboard(wl_seat);
- wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data);
+ gwl_seat_capability_keyboard_enable(seat);
+ }
+ else {
+ gwl_seat_capability_keyboard_disable(seat);
+ }
+
+ if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
+ gwl_seat_capability_touch_enable(seat);
+ }
+ else {
+ gwl_seat_capability_touch_disable(seat);
}
}
@@ -2929,11 +4254,17 @@ static void output_handle_done(void *data, struct wl_output * /*wl_output*/)
static void output_handle_scale(void *data, struct wl_output * /*wl_output*/, const int32_t factor)
{
CLOG_INFO(LOG, 2, "scale");
- static_cast<GWL_Output *>(data)->scale = factor;
+ GWL_Output *output = static_cast<GWL_Output *>(data);
+ output->scale = factor;
+ GHOST_WindowManager *window_manager = output->system->getWindowManager();
if (window_manager) {
for (GHOST_IWindow *iwin : window_manager->getWindows()) {
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
+ const std::vector<GWL_Output *> &outputs = win->outputs();
+ if (std::find(outputs.begin(), outputs.end(), output) == outputs.cend()) {
+ continue;
+ }
win->outputs_changed_update_scale();
}
}
@@ -3011,89 +4342,573 @@ static struct libdecor_interface libdecor_interface = {
static CLG_LogRef LOG_WL_REGISTRY = {"ghost.wl.handle.registry"};
#define LOG (&LOG_WL_REGISTRY)
-static void global_handle_add(void *data,
- struct wl_registry *wl_registry,
- const uint32_t name,
- const char *interface,
- const uint32_t version)
+/* #GWL_Display.wl_compositor */
+
+static void gwl_registry_compositor_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->wl_compositor = static_cast<wl_compositor *>(
+ wl_registry_bind(display->wl_registry, params->name, &wl_compositor_interface, 3));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_compositor_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct wl_compositor **value_p = &display->wl_compositor;
+ wl_compositor_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.xdg_decor.shell */
+
+static void gwl_registry_xdg_wm_base_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ GWL_XDG_Decor_System &decor = *display->xdg_decor;
+ decor.shell = static_cast<xdg_wm_base *>(
+ wl_registry_bind(display->wl_registry, params->name, &xdg_wm_base_interface, 1));
+ xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr);
+ decor.shell_name = params->name;
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_xdg_wm_base_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ GWL_XDG_Decor_System &decor = *display->xdg_decor;
+ struct xdg_wm_base **value_p = &decor.shell;
+ uint32_t *name_p = &decor.shell_name;
+ xdg_wm_base_destroy(*value_p);
+ *value_p = nullptr;
+ *name_p = WL_NAME_UNSET;
+}
+
+/* #GWL_Display.xdg_decor.manager */
+
+static void gwl_registry_xdg_decoration_manager_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ GWL_XDG_Decor_System &decor = *display->xdg_decor;
+ decor.manager = static_cast<zxdg_decoration_manager_v1 *>(wl_registry_bind(
+ display->wl_registry, params->name, &zxdg_decoration_manager_v1_interface, 1));
+ decor.manager_name = params->name;
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_xdg_decoration_manager_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ GWL_XDG_Decor_System &decor = *display->xdg_decor;
+ struct zxdg_decoration_manager_v1 **value_p = &decor.manager;
+ uint32_t *name_p = &decor.manager_name;
+ zxdg_decoration_manager_v1_destroy(*value_p);
+ *value_p = nullptr;
+ *name_p = WL_NAME_UNSET;
+}
+
+/* #GWL_Display.xdg_output_manager */
+
+static void gwl_registry_xdg_output_manager_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
+ wl_registry_bind(display->wl_registry, params->name, &zxdg_output_manager_v1_interface, 2));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_xdg_output_manager_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct zxdg_output_manager_v1 **value_p = &display->xdg_output_manager;
+ zxdg_output_manager_v1_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wl_output */
+
+static void gwl_registry_wl_output_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params)
+{
+ GWL_Output *output = new GWL_Output;
+ output->system = display->system;
+ output->wl_output = static_cast<wl_output *>(
+ wl_registry_bind(display->wl_registry, params->name, &wl_output_interface, 2));
+ ghost_wl_output_tag(output->wl_output);
+ wl_output_set_user_data(output->wl_output, output);
+
+ display->outputs.push_back(output);
+ wl_output_add_listener(output->wl_output, &output_listener, output);
+ gwl_registry_entry_add(display, params, static_cast<void *>(output));
+}
+static void gwl_registry_wl_output_update(GWL_Display *display,
+ const GWL_RegisteryUpdate_Params *params)
{
- /* Log last since it can be noted if the interface was handled or not. */
- bool found = true;
-
- struct GWL_Display *display = static_cast<struct GWL_Display *>(data);
- if (STREQ(interface, wl_compositor_interface.name)) {
- display->wl_compositor = static_cast<wl_compositor *>(
- wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
- }
- else if (STREQ(interface, xdg_wm_base_interface.name)) {
- WGL_XDG_Decor_System &decor = *display->xdg_decor;
- decor.shell = static_cast<xdg_wm_base *>(
- wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
- xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr);
- }
- else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) {
- WGL_XDG_Decor_System &decor = *display->xdg_decor;
- decor.manager = static_cast<zxdg_decoration_manager_v1 *>(
- wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
- }
- else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) {
- display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
- wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
- for (GWL_Output *output : display->outputs) {
+ GWL_Output *output = static_cast<GWL_Output *>(params->user_data);
+ if (display->xdg_output_manager) {
+ if (output->xdg_output == nullptr) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager,
output->wl_output);
zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
}
}
- else if (STREQ(interface, wl_output_interface.name)) {
- GWL_Output *output = new GWL_Output;
- output->wl_output = static_cast<wl_output *>(
- wl_registry_bind(wl_registry, name, &wl_output_interface, 2));
- ghost_wl_output_tag(output->wl_output);
- wl_output_set_user_data(output->wl_output, output);
+ else {
+ output->xdg_output = nullptr;
+ }
+}
+static void gwl_registry_wl_output_remove(GWL_Display *display,
+ void *user_data,
+ const bool /*on_exit*/)
+{
+ /* While windows & cursors hold references to outputs, there is no need to manually remove
+ * these references as the compositor will remove references via #wl_surface_listener.leave. */
+ GWL_Output *output = static_cast<GWL_Output *>(user_data);
+ wl_output_destroy(output->wl_output);
+ std::vector<GWL_Output *>::iterator iter = std::find(
+ display->outputs.begin(), display->outputs.end(), output);
+ const int index = (iter != display->outputs.cend()) ?
+ std::distance(display->outputs.begin(), iter) :
+ -1;
+ GHOST_ASSERT(index != -1, "invalid internal state");
+ /* NOTE: always erase even when `on_exit` because `output->xdg_output` is cleared later. */
+ display->outputs.erase(display->outputs.begin() + index);
+ delete output;
+}
+
+/* #GWL_Display.seats */
+
+static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params)
+{
+ GWL_Seat *seat = new GWL_Seat;
+ seat->system = display->system;
+ seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ seat->data_source = new GWL_DataSource;
+ seat->wl_seat = static_cast<wl_seat *>(
+ wl_registry_bind(display->wl_registry, params->name, &wl_seat_interface, 5));
+ display->seats.push_back(seat);
+ wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
+ gwl_registry_entry_add(display, params, static_cast<void *>(seat));
+}
+static void gwl_registry_wl_seat_update(GWL_Display *display,
+ const GWL_RegisteryUpdate_Params *params)
+{
+ GWL_Seat *seat = static_cast<GWL_Seat *>(params->user_data);
+
+ /* Register data device per seat for IPC between WAYLAND clients. */
+ if (display->wl_data_device_manager) {
+ if (seat->wl_data_device == nullptr) {
+ seat->wl_data_device = wl_data_device_manager_get_data_device(
+ display->wl_data_device_manager, seat->wl_seat);
+ wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat);
+ }
+ }
+ else {
+ seat->wl_data_device = nullptr;
+ }
- display->outputs.push_back(output);
- wl_output_add_listener(output->wl_output, &output_listener, output);
+ if (display->wp_tablet_manager) {
+ if (seat->wp_tablet_seat == nullptr) {
+ seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display->wp_tablet_manager,
+ seat->wl_seat);
+ zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat);
+ }
+ }
+ else {
+ seat->wp_tablet_seat = nullptr;
+ }
- if (display->xdg_output_manager) {
- output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager,
- output->wl_output);
- zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
+ if (display->wp_primary_selection_device_manager) {
+ if (seat->wp_primary_selection_device == nullptr) {
+ seat->wp_primary_selection_device = zwp_primary_selection_device_manager_v1_get_device(
+ display->wp_primary_selection_device_manager, seat->wl_seat);
+
+ zwp_primary_selection_device_v1_add_listener(seat->wp_primary_selection_device,
+ &primary_selection_device_listener,
+ &seat->primary_selection);
+ }
+ }
+ else {
+ seat->wp_primary_selection_device = nullptr;
+ }
+}
+static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, const bool on_exit)
+{
+ GWL_Seat *seat = static_cast<GWL_Seat *>(user_data);
+
+ /* First handle members that require locking.
+ * While highly unlikely, it's possible they are being used while this function runs. */
+ {
+ std::lock_guard lock{seat->data_source_mutex};
+ if (seat->data_source) {
+ gwl_simple_buffer_free_data(&seat->data_source->buffer_out);
+ if (seat->data_source->wl_source) {
+ wl_data_source_destroy(seat->data_source->wl_source);
+ }
+ delete seat->data_source;
+ }
+ }
+
+ {
+ std::lock_guard lock{seat->data_offer_dnd_mutex};
+ if (seat->data_offer_dnd) {
+ wl_data_offer_destroy(seat->data_offer_dnd->id);
+ delete seat->data_offer_dnd;
+ }
+ }
+
+ {
+ std::lock_guard lock{seat->data_offer_copy_paste_mutex};
+ if (seat->data_offer_copy_paste) {
+ wl_data_offer_destroy(seat->data_offer_copy_paste->id);
+ delete seat->data_offer_copy_paste;
}
}
- else if (STREQ(interface, wl_seat_interface.name)) {
- GWL_Seat *seat = new GWL_Seat;
- seat->system = display->system;
- seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- seat->data_source = new GWL_DataSource;
- seat->wl_seat = static_cast<wl_seat *>(
- wl_registry_bind(wl_registry, name, &wl_seat_interface, 5));
- display->seats.push_back(seat);
- wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
+
+ {
+ GWL_PrimarySelection *primary = &seat->primary_selection;
+ std::lock_guard lock{primary->data_offer_mutex};
+ gwl_primary_selection_discard_offer(primary);
}
- else if (STREQ(interface, wl_shm_interface.name)) {
- display->wl_shm = static_cast<wl_shm *>(
- wl_registry_bind(wl_registry, name, &wl_shm_interface, 1));
+
+ {
+ GWL_PrimarySelection *primary = &seat->primary_selection;
+ std::lock_guard lock{primary->data_source_mutex};
+ gwl_primary_selection_discard_source(primary);
}
- else if (STREQ(interface, wl_data_device_manager_interface.name)) {
- display->data_device_manager = static_cast<wl_data_device_manager *>(
- wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3));
+
+ if (seat->wp_primary_selection_device) {
+ zwp_primary_selection_device_v1_destroy(seat->wp_primary_selection_device);
}
- else if (STREQ(interface, zwp_tablet_manager_v2_interface.name)) {
- display->tablet_manager = static_cast<zwp_tablet_manager_v2 *>(
- wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1));
+
+ if (seat->wl_data_device) {
+ wl_data_device_release(seat->wl_data_device);
}
- else if (STREQ(interface, zwp_relative_pointer_manager_v1_interface.name)) {
- display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
- wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1));
+
+ if (seat->cursor.custom_data) {
+ munmap(seat->cursor.custom_data, seat->cursor.custom_data_size);
}
- else if (STREQ(interface, zwp_pointer_constraints_v1_interface.name)) {
- display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(
- wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1));
+
+ /* Disable all capabilities as a way to free:
+ * - `seat.wl_pointer` (and related cursor variables).
+ * - `seat.wl_touch`.
+ * - `seat.wl_keyboard`.
+ */
+ gwl_seat_capability_pointer_disable(seat);
+ gwl_seat_capability_keyboard_disable(seat);
+ gwl_seat_capability_touch_disable(seat);
+
+ /* Un-referencing checks for NULL case. */
+ xkb_state_unref(seat->xkb_state);
+ xkb_state_unref(seat->xkb_state_empty);
+ xkb_state_unref(seat->xkb_state_empty_with_shift);
+ xkb_state_unref(seat->xkb_state_empty_with_numlock);
+
+ xkb_context_unref(seat->xkb_context);
+
+ /* Remove the seat. */
+ wl_seat_destroy(seat->wl_seat);
+
+ std::vector<GWL_Seat *>::iterator iter = std::find(
+ display->seats.begin(), display->seats.end(), seat);
+ const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) :
+ -1;
+ GHOST_ASSERT(index != -1, "invalid internal state");
+
+ if (!on_exit) {
+ if (display->seats_active_index >= index) {
+ display->seats_active_index -= 1;
+ }
+ display->seats.erase(display->seats.begin() + index);
}
- else {
- found = false;
+ delete seat;
+}
+
+/* #GWL_Display.wl_shm */
+static void gwl_registry_wl_shm_add(GWL_Display *display, const GWL_RegisteryAdd_Params *params)
+{
+ display->wl_shm = static_cast<wl_shm *>(
+ wl_registry_bind(display->wl_registry, params->name, &wl_shm_interface, 1));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wl_shm_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct wl_shm **value_p = &display->wl_shm;
+ wl_shm_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wl_data_device_manager */
+
+static void gwl_registry_wl_data_device_manager_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->wl_data_device_manager = static_cast<wl_data_device_manager *>(
+ wl_registry_bind(display->wl_registry, params->name, &wl_data_device_manager_interface, 3));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wl_data_device_manager_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct wl_data_device_manager **value_p = &display->wl_data_device_manager;
+ wl_data_device_manager_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wp_tablet_manager */
+
+static void gwl_registry_wp_tablet_manager_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->wp_tablet_manager = static_cast<zwp_tablet_manager_v2 *>(
+ wl_registry_bind(display->wl_registry, params->name, &zwp_tablet_manager_v2_interface, 1));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wp_tablet_manager_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct zwp_tablet_manager_v2 **value_p = &display->wp_tablet_manager;
+ zwp_tablet_manager_v2_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wp_relative_pointer_manager */
+
+static void gwl_registry_wp_relative_pointer_manager_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->wp_relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
+ wl_registry_bind(
+ display->wl_registry, params->name, &zwp_relative_pointer_manager_v1_interface, 1));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wp_relative_pointer_manager_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct zwp_relative_pointer_manager_v1 **value_p = &display->wp_relative_pointer_manager;
+ zwp_relative_pointer_manager_v1_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wp_pointer_constraints */
+
+static void gwl_registry_wp_pointer_constraints_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->wp_pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(wl_registry_bind(
+ display->wl_registry, params->name, &zwp_pointer_constraints_v1_interface, 1));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wp_pointer_constraints_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct zwp_pointer_constraints_v1 **value_p = &display->wp_pointer_constraints;
+ zwp_pointer_constraints_v1_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wp_pointer_gestures */
+
+static void gwl_registry_wp_pointer_gestures_add(GWL_Display *display,
+ const GWL_RegisteryAdd_Params *params)
+{
+ display->wp_pointer_gestures = static_cast<zwp_pointer_gestures_v1 *>(
+ wl_registry_bind(display->wl_registry, params->name, &zwp_pointer_gestures_v1_interface, 3));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wp_pointer_gestures_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct zwp_pointer_gestures_v1 **value_p = &display->wp_pointer_gestures;
+ zwp_pointer_gestures_v1_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/* #GWL_Display.wp_primary_selection_device_manager */
+
+static void gwl_registry_wp_primary_selection_device_manager_add(
+ struct GWL_Display *display, const GWL_RegisteryAdd_Params *params)
+{
+ display->wp_primary_selection_device_manager =
+ static_cast<zwp_primary_selection_device_manager_v1 *>(
+ wl_registry_bind(display->wl_registry,
+ params->name,
+ &zwp_primary_selection_device_manager_v1_interface,
+ 1));
+ gwl_registry_entry_add(display, params, nullptr);
+}
+static void gwl_registry_wp_primary_selection_device_manager_remove(GWL_Display *display,
+ void * /*user_data*/,
+ const bool /*on_exit*/)
+{
+ struct zwp_primary_selection_device_manager_v1 **value_p =
+ &display->wp_primary_selection_device_manager;
+ zwp_primary_selection_device_manager_v1_destroy(*value_p);
+ *value_p = nullptr;
+}
+
+/**
+ * Map interfaces to initialization functions.
+ *
+ * \note This list also defines the order interfaces are removed.
+ * On exit interface removal runs from last to first to avoid potential bugs
+ * caused by undefined order of removal.
+ *
+ * In general fundamental, low level objects such as the compositor and shared memory
+ * should be declared earlier and other interfaces that may use them should be declared later.
+ */
+static const GWL_RegistryHandler gwl_registry_handlers[] = {
+ /* Low level interfaces. */
+ {
+ &wl_compositor_interface.name,
+ gwl_registry_compositor_add,
+ nullptr,
+ gwl_registry_compositor_remove,
+ },
+ {
+ &wl_shm_interface.name,
+ gwl_registry_wl_shm_add,
+ nullptr,
+ gwl_registry_wl_shm_remove,
+ },
+ {
+ &xdg_wm_base_interface.name,
+ gwl_registry_xdg_wm_base_add,
+ nullptr,
+ gwl_registry_xdg_wm_base_remove,
+ },
+ /* Managers. */
+ {
+ &zxdg_decoration_manager_v1_interface.name,
+ gwl_registry_xdg_decoration_manager_add,
+ nullptr,
+ gwl_registry_xdg_decoration_manager_remove,
+ },
+ {
+ &zxdg_output_manager_v1_interface.name,
+ gwl_registry_xdg_output_manager_add,
+ nullptr,
+ gwl_registry_xdg_output_manager_remove,
+ },
+ {
+ &wl_data_device_manager_interface.name,
+ gwl_registry_wl_data_device_manager_add,
+ nullptr,
+ gwl_registry_wl_data_device_manager_remove,
+ },
+ {
+ &zwp_primary_selection_device_manager_v1_interface.name,
+ gwl_registry_wp_primary_selection_device_manager_add,
+ nullptr,
+ gwl_registry_wp_primary_selection_device_manager_remove,
+ },
+ {
+ &zwp_tablet_manager_v2_interface.name,
+ gwl_registry_wp_tablet_manager_add,
+ nullptr,
+ gwl_registry_wp_tablet_manager_remove,
+ },
+ {
+ &zwp_relative_pointer_manager_v1_interface.name,
+ gwl_registry_wp_relative_pointer_manager_add,
+ nullptr,
+ gwl_registry_wp_relative_pointer_manager_remove,
+ },
+ /* Higher level interfaces. */
+ {
+ &zwp_pointer_constraints_v1_interface.name,
+ gwl_registry_wp_pointer_constraints_add,
+ nullptr,
+ gwl_registry_wp_pointer_constraints_remove,
+ },
+ {
+ &zwp_pointer_gestures_v1_interface.name,
+ gwl_registry_wp_pointer_gestures_add,
+ nullptr,
+ gwl_registry_wp_pointer_gestures_remove,
+ },
+ /* Display outputs. */
+ {
+ &wl_output_interface.name,
+ gwl_registry_wl_output_add,
+ gwl_registry_wl_output_update,
+ gwl_registry_wl_output_remove,
+ },
+ /* Seats.
+ * Keep the seat near the end to ensure other types are created first.
+ * as the seat creates data based on other interfaces. */
+ {
+ &wl_seat_interface.name,
+ gwl_registry_wl_seat_add,
+ gwl_registry_wl_seat_update,
+ gwl_registry_wl_seat_remove,
+ },
+ {nullptr, nullptr, nullptr},
+};
+
+/**
+ * Workaround for `gwl_registry_handlers` order of declaration,
+ * preventing `ARRAY_SIZE(gwl_registry_handlers) - 1` being used.
+ */
+static int gwl_registry_handler_interface_slot_max()
+{
+ return ARRAY_SIZE(gwl_registry_handlers) - 1;
+}
+
+static int gwl_registry_handler_interface_slot_from_string(const char *interface)
+{
+ for (const GWL_RegistryHandler *handler = gwl_registry_handlers; handler->interface_p != nullptr;
+ handler++) {
+ if (STREQ(interface, *handler->interface_p)) {
+ return int(handler - gwl_registry_handlers);
+ }
+ }
+ return -1;
+}
+
+static const GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(int interface_slot)
+{
+ GHOST_ASSERT(uint32_t(interface_slot) < uint32_t(gwl_registry_handler_interface_slot_max()),
+ "Index out of range");
+ return &gwl_registry_handlers[interface_slot];
+}
+
+static void global_handle_add(void *data,
+ [[maybe_unused]] struct wl_registry *wl_registry,
+ const uint32_t name,
+ const char *interface,
+ const uint32_t version)
+{
+ /* Log last since it's useful to know if the interface was handled or not. */
+ GWL_Display *display = static_cast<GWL_Display *>(data);
+ GHOST_ASSERT(display->wl_registry == wl_registry, "Registry argument must match!");
+
+ const int interface_slot = gwl_registry_handler_interface_slot_from_string(interface);
+ bool added = false;
+
+ if (interface_slot != -1) {
+ const GWL_RegistryHandler *handler = &gwl_registry_handlers[interface_slot];
+ const GWL_RegistryEntry *registry_entry_prev = display->registry_entry;
+
+ /* The interface name that is ensured not to be freed. */
+ GWL_RegisteryAdd_Params params = {
+ .name = name,
+ .interface_slot = interface_slot,
+ .version = version,
+ };
+
+ handler->add_fn(display, &params);
+
+ added = display->registry_entry != registry_entry_prev;
+ }
+ else {
+ /* Not found. */
#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */
/* Only require `libdecor` when built with X11 support,
@@ -3106,10 +4921,18 @@ static void global_handle_add(void *data,
CLOG_INFO(LOG,
2,
"add %s(interface=%s, version=%u, name=%u)",
- found ? "" : "(skipped), ",
+ (interface_slot != -1) ? (added ? "" : "(found but not added)") : "(skipped), ",
interface,
version,
name);
+
+ /* Initialization avoids excessive calls by calling update after all have been initialized. */
+ if (added) {
+ if (display->registry_skip_update_all == false) {
+ /* See doc-string for rationale on updating all on add/removal. */
+ gwl_registry_entry_update_all(display, interface_slot);
+ }
+ }
}
/**
@@ -3121,11 +4944,28 @@ static void global_handle_add(void *data,
* name is no longer available. If the client bound to the global
* using the bind request, the client should now destroy that object.
*/
-static void global_handle_remove(void * /*data*/,
- struct wl_registry * /*wl_registry*/,
+static void global_handle_remove(void *data,
+ [[maybe_unused]] struct wl_registry *wl_registry,
const uint32_t name)
{
- CLOG_INFO(LOG, 2, "remove (name=%u)", name);
+ GWL_Display *display = static_cast<GWL_Display *>(data);
+ GHOST_ASSERT(display->wl_registry == wl_registry, "Registry argument must match!");
+
+ int interface_slot = 0;
+ const bool removed = gwl_registry_entry_remove_by_name(display, name, &interface_slot);
+
+ CLOG_INFO(LOG,
+ 2,
+ "remove (name=%u, interface=%s)",
+ name,
+ removed ? *gwl_registry_handlers[interface_slot].interface_p : "(unknown)");
+
+ if (removed) {
+ if (display->registry_skip_update_all == false) {
+ /* See doc-string for rationale on updating all on add/removal. */
+ gwl_registry_entry_update_all(display, interface_slot);
+ }
+ }
}
static const struct wl_registry_listener registry_listener = {
@@ -3143,7 +4983,8 @@ static const struct wl_registry_listener registry_listener = {
* WAYLAND specific implementation of the #GHOST_System interface.
* \{ */
-GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Display)
+GHOST_SystemWayland::GHOST_SystemWayland(bool background)
+ : GHOST_System(), display_(new GWL_Display)
{
wl_log_set_handler_client(ghost_wayland_log_handler);
@@ -3151,25 +4992,41 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
/* Connect to the Wayland server. */
display_->wl_display = wl_display_connect(nullptr);
if (!display_->wl_display) {
- display_destroy(display_);
+ gwl_display_destroy(display_);
throw std::runtime_error("Wayland: unable to connect to display!");
}
/* This may be removed later if decorations are required, needed as part of registration. */
- display_->xdg_decor = new WGL_XDG_Decor_System;
+ display_->xdg_decor = new GWL_XDG_Decor_System;
/* Register interfaces. */
- struct wl_registry *registry = wl_display_get_registry(display_->wl_display);
- wl_registry_add_listener(registry, &registry_listener, display_);
- /* Call callback for registry listener. */
- wl_display_roundtrip(display_->wl_display);
- /* Call callbacks for registered listeners. */
- wl_display_roundtrip(display_->wl_display);
- wl_registry_destroy(registry);
+ {
+ display_->registry_skip_update_all = true;
+ struct wl_registry *registry = wl_display_get_registry(display_->wl_display);
+ display_->wl_registry = registry;
+ wl_registry_add_listener(registry, &registry_listener, display_);
+ /* First round-trip to receive all registry objects. */
+ wl_display_roundtrip(display_->wl_display);
+ /* Second round-trip to receive all output events. */
+ wl_display_roundtrip(display_->wl_display);
+
+ /* Account for dependencies between interfaces. */
+ gwl_registry_entry_update_all(display_, -1);
+
+ display_->registry_skip_update_all = false;
+ }
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ /* Ignore windowing requirements when running in background mode,
+ * as it doesn't make sense to fall back to X11 because of windowing functionality
+ * in background mode, also LIBDECOR is crashing in background mode `blender -b -f 1`
+ * for e.g. while it could be fixed, requiring the library at all makes no sense . */
+ if (background) {
+ display_->libdecor_required = false;
+ }
+
if (display_->libdecor_required) {
- wgl_xdg_decor_system_destroy(display_->xdg_decor);
+ gwl_xdg_decor_system_destroy(display_, display_->xdg_decor);
display_->xdg_decor = nullptr;
if (!has_libdecor) {
@@ -3179,8 +5036,10 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
"WAYLAND found but libdecor was not, install libdecor for Wayland support, "
"falling back to X11\n");
# endif
- display_destroy(display_);
+ gwl_display_destroy(display_);
throw std::runtime_error("Wayland: unable to find libdecor!");
+
+ use_libdecor = true;
}
}
else {
@@ -3190,45 +5049,28 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
- display_->libdecor = new WGL_LibDecor_System;
- WGL_LibDecor_System &decor = *display_->libdecor;
+ display_->libdecor = new GWL_LibDecor_System;
+ GWL_LibDecor_System &decor = *display_->libdecor;
decor.context = libdecor_new(display_->wl_display, &libdecor_interface);
if (!decor.context) {
- display_destroy(display_);
+ gwl_display_destroy(display_);
throw std::runtime_error("Wayland: unable to create window decorations!");
}
}
else
#endif
{
- WGL_XDG_Decor_System &decor = *display_->xdg_decor;
+ GWL_XDG_Decor_System &decor = *display_->xdg_decor;
if (!decor.shell) {
- display_destroy(display_);
+ gwl_display_destroy(display_);
throw std::runtime_error("Wayland: unable to access xdg_shell!");
}
}
-
- /* Register data device per seat for IPC between Wayland clients. */
- if (display_->data_device_manager) {
- for (GWL_Seat *seat : display_->seats) {
- seat->data_device = wl_data_device_manager_get_data_device(display_->data_device_manager,
- seat->wl_seat);
- wl_data_device_add_listener(seat->data_device, &data_device_listener, seat);
- }
- }
-
- if (display_->tablet_manager) {
- for (GWL_Seat *seat : display_->seats) {
- seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->tablet_manager,
- seat->wl_seat);
- zwp_tablet_seat_v2_add_listener(seat->tablet_seat, &tablet_seat_listener, seat);
- }
- }
}
GHOST_SystemWayland::~GHOST_SystemWayland()
{
- display_destroy(display_);
+ gwl_display_destroy(display_);
}
GHOST_TSuccess GHOST_SystemWayland::init()
@@ -3283,12 +5125,11 @@ bool GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*acti
GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
-
const xkb_mod_mask_t state = xkb_state_serialize_mods(seat->xkb_state, XKB_STATE_MODS_DEPRESSED);
bool show_warning = true;
@@ -3300,7 +5141,7 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
}
#endif
- /* Use local #WGL_KeyboardDepressedState to check which key is pressed.
+ /* Use local #GWL_KeyboardDepressedState to check which key is pressed.
* Use XKB as the source of truth, if there is any discrepancy. */
for (int i = 0; i < MOD_INDEX_NUM; i++) {
if (UNLIKELY(seat->xkb_keymap_mod_index[i] == XKB_MOD_INVALID)) {
@@ -3345,11 +5186,11 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
- GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat);
+ GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
if (!seat_state_pointer) {
return GHOST_kFailure;
}
@@ -3358,43 +5199,208 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
return GHOST_kSuccess;
}
-char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const
+/**
+ * Return a mime type which is supported by GHOST and exists in `types`
+ * (defined by the data offer).
+ */
+static const char *system_clipboard_text_mime_type(
+ const std::unordered_set<std::string> &data_offer_types)
+{
+ const char *ghost_supported_types[] = {ghost_wl_mime_text_utf8, ghost_wl_mime_text_plain};
+ for (size_t i = 0; i < ARRAY_SIZE(ghost_supported_types); i++) {
+ if (data_offer_types.count(ghost_supported_types[i])) {
+ return ghost_supported_types[i];
+ }
+ }
+ return nullptr;
+}
+
+static char *system_clipboard_get_primary_selection(GWL_Display *display)
+{
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return nullptr;
+ }
+ GWL_PrimarySelection *primary = &seat->primary_selection;
+ std::mutex &mutex = primary->data_offer_mutex;
+
+ mutex.lock();
+ bool mutex_locked = true;
+ char *data = nullptr;
+
+ GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer;
+ if (data_offer != nullptr) {
+ const char *mime_receive = system_clipboard_text_mime_type(data_offer->types);
+ if (mime_receive) {
+ /* Receive the clipboard in a thread, performing round-trips while waiting.
+ * This is needed so pasting contents from our own `primary->data_source` doesn't hang. */
+ struct ThreadResult {
+ char *data = nullptr;
+ std::atomic<bool> done = false;
+ } thread_result;
+ auto read_clipboard_fn = [](GWL_PrimarySelection_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ struct ThreadResult *thread_result) {
+ size_t data_len = 0;
+ thread_result->data = read_buffer_from_primary_selection_offer(
+ data_offer, mime_receive, mutex, true, &data_len);
+ thread_result->done = true;
+ };
+ std::thread read_thread(read_clipboard_fn, data_offer, mime_receive, &mutex, &thread_result);
+ read_thread.detach();
+
+ while (!thread_result.done) {
+ wl_display_roundtrip(display->wl_display);
+ }
+ data = thread_result.data;
+
+ /* Reading the data offer unlocks the mutex. */
+ mutex_locked = false;
+ }
+ }
+ if (mutex_locked) {
+ mutex.unlock();
+ }
+ return data;
+}
+
+static char *system_clipboard_get(GWL_Display *display)
+{
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return nullptr;
+ }
+ std::mutex &mutex = seat->data_offer_copy_paste_mutex;
+
+ mutex.lock();
+ bool mutex_locked = true;
+ char *data = nullptr;
+
+ GWL_DataOffer *data_offer = seat->data_offer_copy_paste;
+ if (data_offer != nullptr) {
+ const char *mime_receive = system_clipboard_text_mime_type(data_offer->types);
+ if (mime_receive) {
+ /* Receive the clipboard in a thread, performing round-trips while waiting.
+ * This is needed so pasting contents from our own `seat->data_source` doesn't hang. */
+ struct ThreadResult {
+ char *data = nullptr;
+ std::atomic<bool> done = false;
+ } thread_result;
+ auto read_clipboard_fn = [](GWL_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ struct ThreadResult *thread_result) {
+ size_t data_len = 0;
+ thread_result->data = read_buffer_from_data_offer(
+ data_offer, mime_receive, mutex, true, &data_len);
+ thread_result->done = true;
+ };
+ std::thread read_thread(read_clipboard_fn, data_offer, mime_receive, &mutex, &thread_result);
+ read_thread.detach();
+
+ while (!thread_result.done) {
+ wl_display_roundtrip(display->wl_display);
+ }
+ data = thread_result.data;
+
+ /* Reading the data offer unlocks the mutex. */
+ mutex_locked = false;
+ }
+ }
+ if (mutex_locked) {
+ mutex.unlock();
+ }
+ return data;
+}
+
+char *GHOST_SystemWayland::getClipboard(bool selection) const
{
- char *clipboard = static_cast<char *>(malloc(clipboard_.size() + 1));
- memcpy(clipboard, clipboard_.data(), clipboard_.size() + 1);
- return clipboard;
+ char *data = nullptr;
+ if (selection) {
+ data = system_clipboard_get_primary_selection(display_);
+ }
+ else {
+ data = system_clipboard_get(display_);
+ }
+ return data;
}
-void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const
+static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer)
{
- if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) {
+ if (!display->wp_primary_selection_device_manager) {
+ return;
+ }
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
return;
}
+ GWL_PrimarySelection *primary = &seat->primary_selection;
+
+ std::lock_guard lock{primary->data_source_mutex};
+
+ gwl_primary_selection_discard_source(primary);
+
+ GWL_PrimarySelection_DataSource *data_source = new GWL_PrimarySelection_DataSource;
+ primary->data_source = data_source;
+
+ /* Copy buffer. */
+ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer);
+
+ data_source->wp_source = zwp_primary_selection_device_manager_v1_create_source(
+ display->wp_primary_selection_device_manager);
+
+ zwp_primary_selection_source_v1_add_listener(
+ data_source->wp_source, &primary_selection_source_listener, primary);
+
+ for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_send); i++) {
+ zwp_primary_selection_source_v1_offer(data_source->wp_source, ghost_wl_mime_send[i]);
+ }
- GWL_Seat *seat = display_->seats[0];
+ if (seat->wp_primary_selection_device) {
+ zwp_primary_selection_device_v1_set_selection(
+ seat->wp_primary_selection_device, data_source->wp_source, seat->data_source_serial);
+ }
+}
+static void system_clipboard_put(GWL_Display *display, const char *buffer)
+{
+ if (!display->wl_data_device_manager) {
+ return;
+ }
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return;
+ }
std::lock_guard lock{seat->data_source_mutex};
GWL_DataSource *data_source = seat->data_source;
/* Copy buffer. */
- free(data_source->buffer_out);
- const size_t buffer_size = strlen(buffer) + 1;
- data_source->buffer_out = static_cast<char *>(malloc(buffer_size));
- std::memcpy(data_source->buffer_out, buffer, buffer_size);
+ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer);
- data_source->data_source = wl_data_device_manager_create_data_source(
- display_->data_device_manager);
+ data_source->wl_source = wl_data_device_manager_create_data_source(
+ display->wl_data_device_manager);
- wl_data_source_add_listener(data_source->data_source, &data_source_listener, seat);
+ wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat);
- for (const std::string &type : mime_send) {
- wl_data_source_offer(data_source->data_source, type.c_str());
+ for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_send); i++) {
+ wl_data_source_offer(data_source->wl_source, ghost_wl_mime_send[i]);
}
- if (seat->data_device) {
+ if (seat->wl_data_device) {
wl_data_device_set_selection(
- seat->data_device, data_source->data_source, seat->data_source_serial);
+ seat->wl_data_device, data_source->wl_source, seat->data_source_serial);
+ }
+}
+
+void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const
+{
+ if (selection) {
+ system_clipboard_put_primary_selection(display_, buffer);
+ }
+ else {
+ system_clipboard_put(display_, buffer);
}
}
@@ -3423,7 +5429,7 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat,
/* NOTE: WAYLAND doesn't support warping the cursor.
* However when grab is enabled, we already simulate a cursor location
* so that can be set to a new location. */
- if (!seat->relative_pointer) {
+ if (!seat->wp_relative_pointer) {
return GHOST_kFailure;
}
const wl_fixed_t scale = win->scale();
@@ -3442,12 +5448,12 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_
int32_t &x,
int32_t &y) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
- GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat);
- if (!seat_state_pointer || !seat_state_pointer->wl_surface) {
+ GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
+ if (!seat_state_pointer || !seat_state_pointer->wl_surface_window) {
return GHOST_kFailure;
}
const GHOST_WindowWayland *win = static_cast<const GHOST_WindowWayland *>(window);
@@ -3458,26 +5464,26 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPositionClientRelative(GHOST_IWindo
const int32_t x,
const int32_t y)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(window);
return setCursorPositionClientRelative_impl(seat, win, x, y);
}
GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
- GWL_SeatStatePointer *seat_state_pointer = seat_state_pointer_active(seat);
+ GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
if (!seat_state_pointer) {
return GHOST_kFailure;
}
- if (wl_surface *wl_surface_focus = seat_state_pointer->wl_surface) {
+ if (wl_surface *wl_surface_focus = seat_state_pointer->wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
return getCursorPositionClientRelative_impl(seat_state_pointer, win, x, y);
}
@@ -3486,14 +5492,14 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co
GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int32_t y)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
/* Intentionally different from `getCursorPosition` which supports both tablet & pointer.
* In the case of setting the cursor location, tablets don't support this. */
- if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
return setCursorPositionClientRelative_impl(seat, win, x, y);
}
@@ -3616,17 +5622,12 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
const uint32_t width,
const uint32_t height,
const GHOST_TWindowState state,
- const GHOST_TDrawingContextType type,
const GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
{
/* Globally store pointer to window manager. */
- if (!window_manager) {
- window_manager = getWindowManager();
- }
-
GHOST_WindowWayland *window = new GHOST_WindowWayland(
this,
title,
@@ -3636,7 +5637,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
height,
state,
parentWindow,
- type,
+ glSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive);
@@ -3664,22 +5665,22 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
*/
static void cursor_buffer_show(const GWL_Seat *seat)
{
- const GWL_Cursor *c = &seat->cursor;
+ const GWL_Cursor *cursor = &seat->cursor;
if (seat->wl_pointer) {
- const int scale = c->is_custom ? c->custom_scale : seat->pointer.theme_scale;
- const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
- const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
+ const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale;
+ const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale;
+ const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale;
if (seat->wl_pointer) {
wl_pointer_set_cursor(
- seat->wl_pointer, seat->pointer.serial, c->wl_surface, hotspot_x, hotspot_y);
+ seat->wl_pointer, seat->pointer.serial, cursor->wl_surface_cursor, hotspot_x, hotspot_y);
}
}
if (!seat->tablet_tools.empty()) {
- const int scale = c->is_custom ? c->custom_scale : seat->tablet.theme_scale;
- const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
- const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
+ const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale;
+ const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale;
+ const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale;
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
@@ -3688,6 +5689,9 @@ static void cursor_buffer_show(const GWL_Seat *seat)
tablet_tool->wl_surface_cursor,
hotspot_x,
hotspot_y);
+#ifdef USE_KDE_TABLET_HIDDEN_CURSOR_HACK
+ wl_surface_commit(tablet_tool->wl_surface_cursor);
+#endif
}
}
}
@@ -3742,21 +5746,21 @@ static void cursor_buffer_set_surface_impl(const GWL_Seat *seat,
static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
{
- const GWL_Cursor *c = &seat->cursor;
+ const GWL_Cursor *cursor = &seat->cursor;
const wl_cursor_image *wl_image = &seat->cursor.wl_image;
- const bool visible = (c->visible && c->is_hardware);
+ const bool visible = (cursor->visible && cursor->is_hardware);
/* This is a requirement of WAYLAND, when this isn't the case,
* it causes Blender's window to close intermittently. */
if (seat->wl_pointer) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : seat->pointer.theme_scale);
+ wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
- cursor_buffer_set_surface_impl(seat, buffer, c->wl_surface, scale);
+ cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface_cursor, scale);
wl_pointer_set_cursor(seat->wl_pointer,
seat->pointer.serial,
- visible ? c->wl_surface : nullptr,
+ visible ? cursor->wl_surface_cursor : nullptr,
hotspot_x,
hotspot_y);
}
@@ -3764,7 +5768,7 @@ static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
/* Set the cursor for all tablet tools as well. */
if (!seat->tablet_tools.empty()) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : seat->tablet.theme_scale);
+ wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
@@ -3842,40 +5846,40 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_
GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor shape)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- auto cursor_find = cursors.find(shape);
- const char *cursor_name = (cursor_find == cursors.end()) ?
- cursors.at(GHOST_kStandardCursorDefault) :
+ auto cursor_find = ghost_wl_cursors.find(shape);
+ const char *cursor_name = (cursor_find == ghost_wl_cursors.end()) ?
+ ghost_wl_cursors.at(GHOST_kStandardCursorDefault) :
(*cursor_find).second;
- GWL_Seat *seat = display_->seats[0];
- GWL_Cursor *c = &seat->cursor;
+ GWL_Cursor *cursor = &seat->cursor;
- if (!c->wl_theme) {
+ if (!cursor->wl_theme) {
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
- c->wl_theme = wl_cursor_theme_load(
- c->theme_name.c_str(), c->size, display_->seats[0]->system->wl_shm());
+ cursor->wl_theme = wl_cursor_theme_load(
+ cursor->theme_name.c_str(), cursor->theme_size, wl_shm());
}
- wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name);
+ wl_cursor *wl_cursor = wl_cursor_theme_get_cursor(cursor->wl_theme, cursor_name);
- if (!cursor) {
+ if (!wl_cursor) {
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
return GHOST_kFailure;
}
- struct wl_cursor_image *image = cursor->images[0];
+ struct wl_cursor_image *image = wl_cursor->images[0];
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
if (!buffer) {
return GHOST_kFailure;
}
- c->visible = true;
- c->is_custom = false;
- c->wl_buffer = buffer;
- c->wl_image = *image;
+ cursor->visible = true;
+ cursor->is_custom = false;
+ cursor->wl_buffer = buffer;
+ cursor->wl_image = *image;
cursor_buffer_set(seat, buffer);
@@ -3884,8 +5888,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(const GHOST_TStandardCursor cursorShape)
{
- auto cursor_find = cursors.find(cursorShape);
- if (cursor_find == cursors.end()) {
+ auto cursor_find = ghost_wl_cursors.find(cursorShape);
+ if (cursor_find == ghost_wl_cursors.end()) {
return GHOST_kFailure;
}
const char *value = (*cursor_find).second;
@@ -3903,12 +5907,12 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
const int hotY,
const bool /*canInvertColor*/)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Cursor *cursor = &display_->seats[0]->cursor;
-
+ GWL_Cursor *cursor = &seat->cursor;
if (cursor->custom_data) {
munmap(cursor->custom_data, cursor->custom_data_size);
cursor->custom_data = nullptr;
@@ -3966,14 +5970,19 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
cursor->wl_image.hotspot_x = uint32_t(hotX);
cursor->wl_image.hotspot_y = uint32_t(hotY);
- cursor_buffer_set(display_->seats[0], buffer);
+ cursor_buffer_set(seat, buffer);
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap)
{
- GWL_Cursor *cursor = &display_->seats[0]->cursor;
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
+ return GHOST_kFailure;
+ }
+
+ GWL_Cursor *cursor = &seat->cursor;
if (cursor->custom_data == nullptr) {
return GHOST_kFailure;
}
@@ -3994,11 +6003,11 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(const bool visible)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
cursor_visible_set(seat, visible, seat->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET);
return GHOST_kSuccess;
}
@@ -4018,12 +6027,12 @@ bool GHOST_SystemWayland::supportsWindowPosition()
bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return false;
}
#ifdef USE_GNOME_CONFINE_HACK
- GWL_Seat *seat = display_->seats[0];
const bool use_software_confine = seat->use_pointer_software_confine;
#else
const bool use_software_confine = false;
@@ -4062,11 +6071,10 @@ static GWL_SeatStateGrab seat_grab_state_from_mode(const GHOST_TGrabCursorMode m
const bool use_software_confine)
{
/* Initialize all members. */
- const struct GWL_SeatStateGrab grab_state = {
- /* Warping happens to require software cursor which also hides. */
- .use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine,
- .use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false),
- };
+ GWL_SeatStateGrab grab_state;
+ /* Warping happens to require software cursor which also hides. */
+ grab_state.use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine;
+ grab_state.use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false);
return grab_state;
}
@@ -4140,6 +6148,16 @@ wl_compositor *GHOST_SystemWayland::wl_compositor()
return display_->wl_compositor;
}
+struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wp_primary_selection_manager()
+{
+ return display_->wp_primary_selection_device_manager;
+}
+
+struct zwp_pointer_gestures_v1 *GHOST_SystemWayland::wp_pointer_gestures()
+{
+ return display_->wp_pointer_gestures;
+}
+
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *GHOST_SystemWayland::libdecor_context()
@@ -4202,9 +6220,9 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface)
* Functionality only used for the WAYLAND implementation.
* \{ */
-void GHOST_SystemWayland::clipboard_set(const std::string &clipboard)
+void GHOST_SystemWayland::seat_active_set(const struct GWL_Seat *seat)
{
- clipboard_ = clipboard;
+ gwl_display_seat_active_set(display_, seat);
}
void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
@@ -4217,10 +6235,10 @@ void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
/* Only clear window surfaces (not cursors, off-screen surfaces etc). */
for (GWL_Seat *seat : display_->seats) {
- SURFACE_CLEAR_PTR(seat->pointer.wl_surface);
- SURFACE_CLEAR_PTR(seat->tablet.wl_surface);
- SURFACE_CLEAR_PTR(seat->keyboard.wl_surface);
- SURFACE_CLEAR_PTR(seat->wl_surface_focus_dnd);
+ SURFACE_CLEAR_PTR(seat->pointer.wl_surface_window);
+ SURFACE_CLEAR_PTR(seat->tablet.wl_surface_window);
+ SURFACE_CLEAR_PTR(seat->keyboard.wl_surface_window);
+ SURFACE_CLEAR_PTR(seat->wl_surface_window_focus_dnd);
}
#undef SURFACE_CLEAR_PTR
}
@@ -4234,11 +6252,12 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
const int scale)
{
/* Ignore, if the required protocols are not supported. */
- if (UNLIKELY(!display_->relative_pointer_manager || !display_->pointer_constraints)) {
+ if (UNLIKELY(!display_->wp_relative_pointer_manager || !display_->wp_pointer_constraints)) {
return GHOST_kFailure;
}
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
/* No change, success. */
@@ -4246,8 +6265,6 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
return GHOST_kSuccess;
}
- GWL_Seat *seat = display_->seats[0];
-
#ifdef USE_GNOME_CONFINE_HACK
const bool was_software_confine = seat->use_pointer_software_confine;
const bool use_software_confine = setCursorGrab_use_software_confine(mode, wl_surface);
@@ -4273,11 +6290,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
* in this case disable the current locks as it makes logic confusing,
* postpone changing the cursor to avoid flickering. */
if (!grab_state_next.use_lock) {
- if (seat->relative_pointer) {
- zwp_relative_pointer_v1_destroy(seat->relative_pointer);
- seat->relative_pointer = nullptr;
+ if (seat->wp_relative_pointer) {
+ zwp_relative_pointer_v1_destroy(seat->wp_relative_pointer);
+ seat->wp_relative_pointer = nullptr;
}
- if (seat->locked_pointer) {
+ if (seat->wp_locked_pointer) {
/* Potentially add a motion event so the application has updated X/Y coordinates. */
int32_t xy_motion[2] = {0, 0};
bool xy_motion_create_event = false;
@@ -4306,7 +6323,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
seat->pointer.xy[0] = xy_next[0];
seat->pointer.xy[1] = xy_next[1];
- zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next));
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, UNPACK2(xy_next));
wl_surface_commit(wl_surface);
}
else if (mode_current == GHOST_kGrabHide) {
@@ -4316,7 +6333,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
wl_fixed_from_int(init_grab_xy[0]) / scale,
wl_fixed_from_int(init_grab_xy[1]) / scale,
};
- zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next));
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer,
+ UNPACK2(xy_next));
wl_surface_commit(wl_surface);
/* NOTE(@campbellbarton): The new cursor position is a hint,
@@ -4330,7 +6348,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
#ifdef USE_GNOME_CONFINE_HACK
else if (mode_current == GHOST_kGrabNormal) {
if (was_software_confine) {
- zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer,
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer,
UNPACK2(seat->pointer.xy));
wl_surface_commit(wl_surface);
}
@@ -4346,15 +6364,15 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
GHOST_TABLET_DATA_NONE));
}
- zwp_locked_pointer_v1_destroy(seat->locked_pointer);
- seat->locked_pointer = nullptr;
+ zwp_locked_pointer_v1_destroy(seat->wp_locked_pointer);
+ seat->wp_locked_pointer = nullptr;
}
}
if (!grab_state_next.use_confine) {
- if (seat->confined_pointer) {
- zwp_confined_pointer_v1_destroy(seat->confined_pointer);
- seat->confined_pointer = nullptr;
+ if (seat->wp_confined_pointer) {
+ zwp_confined_pointer_v1_destroy(seat->wp_confined_pointer);
+ seat->wp_confined_pointer = nullptr;
}
}
@@ -4365,12 +6383,12 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
* An alternative could be to draw the cursor in software (and hide the real cursor),
* or just accept a locked cursor on WAYLAND. */
- seat->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
- display_->relative_pointer_manager, seat->wl_pointer);
+ seat->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
+ display_->wp_relative_pointer_manager, seat->wl_pointer);
zwp_relative_pointer_v1_add_listener(
- seat->relative_pointer, &relative_pointer_listener, seat);
- seat->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
- display_->pointer_constraints,
+ seat->wp_relative_pointer, &relative_pointer_listener, seat);
+ seat->wp_locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
+ display_->wp_pointer_constraints,
wl_surface,
seat->wl_pointer,
nullptr,
@@ -4387,8 +6405,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
}
else if (grab_state_next.use_confine) {
if (!grab_state_prev.use_confine) {
- seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
- display_->pointer_constraints,
+ seat->wp_confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
+ display_->wp_pointer_constraints,
wl_surface,
seat->wl_pointer,
nullptr,
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index 5d2cfe45582..a8e8d8ddc45 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -23,6 +23,7 @@
# include <libdecor.h>
#endif
+#include <mutex>
#include <string>
class GHOST_WindowWayland;
@@ -51,6 +52,8 @@ void ghost_wl_dynload_libraries_exit();
#endif
struct GWL_Output {
+ GHOST_SystemWayland *system = nullptr;
+
struct wl_output *wl_output = nullptr;
struct zxdg_output_v1 *xdg_output = nullptr;
/** Dimensions in pixels. */
@@ -84,11 +87,12 @@ struct GWL_Output {
class GHOST_SystemWayland : public GHOST_System {
public:
- GHOST_SystemWayland();
+ GHOST_SystemWayland(bool background);
+ GHOST_SystemWayland() : GHOST_SystemWayland(true){};
~GHOST_SystemWayland() override;
- GHOST_TSuccess init();
+ GHOST_TSuccess init() override;
bool processEvents(bool waitForEvent) override;
@@ -128,7 +132,6 @@ class GHOST_SystemWayland : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -150,8 +153,8 @@ class GHOST_SystemWayland : public GHOST_System {
GHOST_TSuccess setCursorVisibility(bool visible);
- bool supportsCursorWarp();
- bool supportsWindowPosition();
+ bool supportsCursorWarp() override;
+ bool supportsWindowPosition() override;
bool getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode);
@@ -159,6 +162,8 @@ class GHOST_SystemWayland : public GHOST_System {
struct wl_display *wl_display();
struct wl_compositor *wl_compositor();
+ struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager();
+ struct zwp_pointer_gestures_v1 *wp_pointer_gestures();
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *libdecor_context();
@@ -173,7 +178,8 @@ class GHOST_SystemWayland : public GHOST_System {
/* WAYLAND utility functions. */
- void clipboard_set(const std::string &clipboard);
+ /** Set this seat to be active. */
+ void seat_active_set(const struct GWL_Seat *seat);
/** Clear all references to this surface to prevent accessing NULL pointers. */
void window_surface_unref(const wl_surface *wl_surface);
@@ -192,5 +198,4 @@ class GHOST_SystemWayland : public GHOST_System {
private:
struct GWL_Display *display_;
- std::string clipboard_;
};
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 667198241f0..54c892d296e 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -213,7 +213,6 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -227,7 +226,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
width,
height,
state,
- type,
+ glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
false,
(GHOST_WindowWin32 *)parentWindow,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index f5cd0055b34..98a7e5dfb35 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -103,7 +103,6 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
@@ -115,7 +114,6 @@ class GHOST_SystemWin32 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 4523f6fa37c..5c89febe97c 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -308,7 +308,6 @@ void GHOST_SystemX11::getAllDisplayDimensions(uint32_t &width, uint32_t &height)
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
@@ -320,7 +319,6 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -341,7 +339,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
height,
state,
(GHOST_WindowX11 *)parentWindow,
- type,
+ glSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 572be30174d..1f071da6da7 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -113,7 +113,6 @@ class GHOST_SystemX11 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param stereoVisual: Create a stereo visual for quad buffered stereo.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
@@ -125,7 +124,6 @@ class GHOST_SystemX11 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 1c0991bba30..396691fa161 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -74,7 +74,7 @@ class GHOST_Window : public GHOST_IWindow {
*/
virtual bool getValid() const override
{
- return m_context != NULL;
+ return m_context != nullptr;
}
/**
@@ -283,8 +283,9 @@ class GHOST_Window : public GHOST_IWindow {
float getNativePixelSize(void) override
{
- if (m_nativePixelSize > 0.0f)
+ if (m_nativePixelSize > 0.0f) {
return m_nativePixelSize;
+ }
return 1.0f;
}
@@ -298,7 +299,8 @@ class GHOST_Window : public GHOST_IWindow {
}
#ifdef WITH_INPUT_IME
- virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) override
+ virtual void beginIME(
+ int32_t /*x*/, int32_t /*y*/, int32_t /*w*/, int32_t /*h*/, bool /*completed*/) override
{
/* do nothing temporarily if not in windows */
}
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 737fd64bdf0..bc1f1e99a3a 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -803,10 +803,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
{
- if (type == GHOST_kDrawingContextTypeOpenGL) {
+ if (type == GHOST_kDrawingContextTypeOpenGL || type == GHOST_kDrawingContextTypeMetal) {
GHOST_Context *context = new GHOST_ContextCGL(
- m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView);
+ m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView, type);
if (context->initializeDrawingContext())
return context;
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index b29c5efd8d4..ad94a02b514 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -53,7 +53,7 @@ struct WGL_LibDecor_Window {
bool configured = false;
};
-static void wgl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
+static void gwl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
{
libdecor_frame_unref(decor->frame);
delete decor;
@@ -67,7 +67,7 @@ struct WGL_XDG_Decor_Window {
enum zxdg_toplevel_decoration_v1_mode mode = (enum zxdg_toplevel_decoration_v1_mode)0;
};
-static void wgl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
+static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
{
if (decor->toplevel_decor) {
zxdg_toplevel_decoration_v1_destroy(decor->toplevel_decor);
@@ -91,12 +91,10 @@ struct GWL_Window {
/** The scale value written to #wl_surface_set_buffer_scale. */
int scale = 0;
/**
- * The DPI, either:
- * - `scale * base_dpi`
- * - `wl_fixed_to_int(scale_fractional * base_dpi)`
- * When fractional scaling is available.
+ * The fractional scale used to calculate the DPI.
+ * (always set, even when scaling is rounded to whole units).
*/
- uint32_t dpi = 0;
+ wl_fixed_t scale_fractional = 0;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
WGL_LibDecor_Window *libdecor = nullptr;
@@ -147,7 +145,7 @@ static int output_scale_cmp(const GWL_Output *output_a, const GWL_Output *output
static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs,
const int32_t scale_default,
- uint32_t *r_dpi)
+ wl_fixed_t *r_scale_fractional)
{
const GWL_Output *output_max = nullptr;
for (const GWL_Output *reg_output : outputs) {
@@ -157,18 +155,16 @@ static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs
}
if (output_max) {
- if (r_dpi) {
- *r_dpi = output_max->has_scale_fractional ?
- /* Fractional DPI. */
- wl_fixed_to_int(output_max->scale_fractional * base_dpi) :
- /* Simple non-fractional DPI. */
- (output_max->scale * base_dpi);
+ if (r_scale_fractional) {
+ *r_scale_fractional = output_max->has_scale_fractional ?
+ output_max->scale_fractional :
+ wl_fixed_from_int(output_max->scale);
}
return output_max->scale;
}
- if (r_dpi) {
- *r_dpi = scale_default * base_dpi;
+ if (r_scale_fractional) {
+ *r_scale_fractional = wl_fixed_from_int(scale_default);
}
return scale_default;
}
@@ -479,7 +475,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
*
* Using the maximum scale is best as it results in the window first being smaller,
* avoiding a large window flashing before it's made smaller. */
- window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->dpi);
+ window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->scale_fractional);
/* Window surfaces. */
window_->wl_surface = wl_compositor_create_surface(system_->wl_compositor());
@@ -727,12 +723,12 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
- wgl_libdecor_window_destroy(window_->libdecor);
+ gwl_libdecor_window_destroy(window_->libdecor);
}
else
#endif
{
- wgl_xdg_decor_window_destroy(window_->xdg_decor);
+ gwl_xdg_decor_window_destroy(window_->xdg_decor);
}
/* Clear any pointers to this window. This is needed because there are no guarantees
@@ -751,7 +747,9 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
uint16_t GHOST_WindowWayland::getDPIHint()
{
- return window_->dpi;
+ /* Using the physical DPI will cause wrong scaling of the UI
+ * use a multiplier for the default DPI as a workaround. */
+ return wl_fixed_to_int(window_->scale_fractional * base_dpi);
}
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
@@ -946,7 +944,12 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
EGL_OPENGL_API);
}
- return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+
+ delete context;
+ return nullptr;
}
/** \} */
@@ -957,14 +960,14 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
* Expose some members via methods.
* \{ */
-uint16_t GHOST_WindowWayland::dpi() const
+int GHOST_WindowWayland::scale() const
{
- return window_->dpi;
+ return window_->scale;
}
-int GHOST_WindowWayland::scale() const
+wl_fixed_t GHOST_WindowWayland::scale_fractional() const
{
- return window_->scale;
+ return window_->scale_fractional;
}
wl_surface *GHOST_WindowWayland::wl_surface() const
@@ -1030,30 +1033,39 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size()
*/
bool GHOST_WindowWayland::outputs_changed_update_scale()
{
- uint32_t dpi_next;
- const int scale_next = outputs_max_scale_or_default(outputs(), 0, &dpi_next);
+ wl_fixed_t scale_fractional_next = 0;
+ const int scale_next = outputs_max_scale_or_default(outputs(), 0, &scale_fractional_next);
if (UNLIKELY(scale_next == 0)) {
return false;
}
- const uint32_t dpi_curr = window_->dpi;
+ const wl_fixed_t scale_fractional_curr = window_->scale_fractional;
const int scale_curr = window_->scale;
bool changed = false;
if (scale_next != scale_curr) {
- /* Unlikely but possible there is a pending size change is set. */
- window_->size_pending[0] = (window_->size_pending[0] / scale_curr) * scale_next;
- window_->size_pending[1] = (window_->size_pending[1] / scale_curr) * scale_next;
-
window_->scale = scale_next;
wl_surface_set_buffer_scale(window_->wl_surface, scale_next);
+
+ /* It's important to resize the window immediately, to avoid the window changing size
+ * and flickering in a constant feedback loop (in some bases). */
+ if ((window_->size_pending[0] != 0) && (window_->size_pending[1] != 0)) {
+ /* Unlikely but possible there is a pending size change is set. */
+ window_->size[0] = window_->size_pending[0];
+ window_->size[1] = window_->size_pending[1];
+ window_->size_pending[0] = 0;
+ window_->size_pending[1] = 0;
+ }
+ window_->size[0] = (window_->size[0] / scale_curr) * scale_next;
+ window_->size[1] = (window_->size[1] / scale_curr) * scale_next;
+ wl_egl_window_resize(window_->egl_window, UNPACK2(window_->size), 0, 0);
+ window_->ghost_window->notify_size();
+
changed = true;
}
- if (dpi_next != dpi_curr) {
- /* Using the real DPI will cause wrong scaling of the UI
- * use a multiplier for the default DPI as workaround. */
- window_->dpi = dpi_next;
+ if (scale_fractional_next != scale_fractional_curr) {
+ window_->scale_fractional = scale_fractional_next;
changed = true;
/* As this is a low-level function, we might want adding this event to be optional,
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index e95f5386310..ec473c4a710 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -12,6 +12,8 @@
#include <vector>
+#include <wayland-util.h> /* For #wl_fixed_t */
+
class GHOST_SystemWayland;
struct GWL_Output;
@@ -95,8 +97,8 @@ class GHOST_WindowWayland : public GHOST_Window {
/* WAYLAND direct-data access. */
- uint16_t dpi() const;
int scale() const;
+ wl_fixed_t scale_fractional() const;
struct wl_surface *wl_surface() const;
const std::vector<GWL_Output *> &outputs();
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
index 1891f1eca77..3c9206b2010 100644
--- a/intern/ghost/test/gears/GHOST_Test.cpp
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -407,17 +407,12 @@ Application::Application(GHOST_ISystem *system)
stereo(false)
{
GHOST_GLSettings glSettings = {0};
+ glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
fApp = this;
// Create the main window
- m_mainWindow = system->createWindow("gears - main window",
- 10,
- 64,
- 320,
- 200,
- GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
- glSettings);
+ m_mainWindow = system->createWindow(
+ "gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
if (!m_mainWindow) {
std::cout << "could not create main window\n";
@@ -425,14 +420,8 @@ Application::Application(GHOST_ISystem *system)
}
// Create a secondary window
- m_secondaryWindow = system->createWindow("gears - secondary window",
- 340,
- 64,
- 320,
- 200,
- GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
- glSettings);
+ m_secondaryWindow = system->createWindow(
+ "gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
if (!m_secondaryWindow) {
std::cout << "could not create secondary window\n";
exit(-1);
diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc
index 288d78fd206..5b565b15920 100644
--- a/intern/guardedalloc/intern/leak_detector.cc
+++ b/intern/guardedalloc/intern/leak_detector.cc
@@ -41,7 +41,7 @@ class MemLeakPrinter {
if (fail_on_memleak) {
/* There are many other ways to change the exit code to failure here:
- * - Make the destructor noexcept(false) and throw an exception.
+ * - Make the destructor `noexcept(false)` and throw an exception.
* - Call exit(EXIT_FAILURE).
* - Call terminate().
*/
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index 1dddd70928a..920b8d5c542 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -81,12 +81,6 @@ if(WITH_OPENSUBDIV)
)
endif()
- opensubdiv_define_component(OPENSUBDIV_HAS_OPENMP)
- opensubdiv_define_component(OPENSUBDIV_HAS_OPENCL)
- opensubdiv_define_component(OPENSUBDIV_HAS_CUDA)
- opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
- opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_COMPUTE)
-
if(WIN32)
add_definitions(-DNOMINMAX)
add_definitions(-D_USE_MATH_DEFINES)
diff --git a/intern/wayland_dynload/extern/wayland_dynload_client.h b/intern/wayland_dynload/extern/wayland_dynload_client.h
index 8e9dddd91a3..d80ef5c9f0c 100644
--- a/intern/wayland_dynload/extern/wayland_dynload_client.h
+++ b/intern/wayland_dynload/extern/wayland_dynload_client.h
@@ -41,6 +41,7 @@ WAYLAND_DYNLOAD_IFACE(wl_seat_interface)
WAYLAND_DYNLOAD_IFACE(wl_shm_interface)
WAYLAND_DYNLOAD_IFACE(wl_shm_pool_interface)
WAYLAND_DYNLOAD_IFACE(wl_surface_interface)
+WAYLAND_DYNLOAD_IFACE(wl_touch_interface)
#else
/* Header guard. */
diff --git a/make.bat b/make.bat
index ff8059b0754..394b2d0dad5 100644
--- a/make.bat
+++ b/make.bat
@@ -62,9 +62,19 @@ if "%SVN_FIX%" == "1" (
)
if "%BUILD_UPDATE%" == "1" (
+ REM First see if the SVN libs are there and check them out if they are not.
call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd"
if errorlevel 1 goto EOF
-
+ if "%BUILD_UPDATE_SVN%" == "1" (
+ REM Then update SVN platform libraries, since updating python while python is
+ REM running tends to be problematic. The python script that update_sources
+ REM calls later on may still try to switch branches and run into trouble,
+ REM but for *most* people this will side step the problem.
+ call "%BLENDER_DIR%\build_files\windows\svn_update.cmd"
+ )
+ REM Finally call the python script shared between all platforms that updates git
+ REM and does any other SVN work like update the tests or branch switches
+ REM if required.
call "%BLENDER_DIR%\build_files\windows\update_sources.cmd"
goto EOF
)
diff --git a/release/scripts/modules/gpu_extras/batch.py b/release/scripts/modules/gpu_extras/batch.py
index ba8e3879a8e..6c9ab52c1a3 100644
--- a/release/scripts/modules/gpu_extras/batch.py
+++ b/release/scripts/modules/gpu_extras/batch.py
@@ -34,13 +34,13 @@ def batch_for_shader(shader, type, content, *, indices=None):
return 'I32'
def recommended_attr_len(attr_name):
- item = content[attr_name][0]
attr_len = 1
try:
+ item = content[attr_name][0]
while True:
attr_len *= len(item)
item = item[0]
- except TypeError:
+ except (TypeError, IndexError):
pass
return attr_len
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 7f6d0b1e9bf..5bd38acb19c 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -184,6 +184,7 @@ def write_sysinfo(filepath):
output.write("vendor:\t\t%r\n" % gpu.platform.vendor_get())
output.write("version:\t%r\n" % gpu.platform.version_get())
output.write("device type:\t%r\n" % gpu.platform.device_type_get())
+ output.write("backend type:\t%r\n" % gpu.platform.backend_type_get())
output.write("extensions:\n")
glext = sorted(gpu.capabilities.extensions_get())
diff --git a/release/scripts/startup/bl_ui/node_add_menu.py b/release/scripts/startup/bl_ui/node_add_menu.py
index 31b84b8f08a..873dbd533a5 100644
--- a/release/scripts/startup/bl_ui/node_add_menu.py
+++ b/release/scripts/startup/bl_ui/node_add_menu.py
@@ -59,6 +59,14 @@ def draw_node_group_add_menu(context, layout):
ops.value = "bpy.data.node_groups[%r]" % group.name
+def draw_assets_for_catalog(layout, catalog_path):
+ layout.template_node_asset_menu_items(catalog_path=catalog_path)
+
+
+def draw_root_assets(layout):
+ layout.menu_contents("NODE_MT_node_add_root_catalogs")
+
+
classes = (
)
diff --git a/release/scripts/startup/bl_ui/node_add_menu_geometry.py b/release/scripts/startup/bl_ui/node_add_menu_geometry.py
index e1b57ec4f43..c076cd7395a 100644
--- a/release/scripts/startup/bl_ui/node_add_menu_geometry.py
+++ b/release/scripts/startup/bl_ui/node_add_menu_geometry.py
@@ -16,6 +16,7 @@ class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeAttributeDomainSize")
node_add_menu.add_node_type(layout, "GeometryNodeRemoveAttribute")
node_add_menu.add_node_type(layout, "GeometryNodeStoreNamedAttribute")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_COLOR(Menu):
@@ -32,6 +33,7 @@ class NODE_MT_geometry_node_GEO_COLOR(Menu):
ops.value = "'RGBA'"
node_add_menu.add_node_type(layout, "ShaderNodeRGBCurve")
node_add_menu.add_node_type(layout, "FunctionNodeSeparateColor")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_CURVE(Menu):
@@ -70,6 +72,7 @@ class NODE_MT_geometry_node_GEO_CURVE(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineCyclic")
node_add_menu.add_node_type(layout, "GeometryNodeSetSplineResolution")
node_add_menu.add_node_type(layout, "GeometryNodeCurveSplineType")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu):
@@ -86,6 +89,7 @@ class NODE_MT_geometry_node_GEO_PRIMITIVES_CURVE(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeCurveQuadraticBezier")
node_add_menu.add_node_type(layout, "GeometryNodeCurvePrimitiveQuadrilateral")
node_add_menu.add_node_type(layout, "GeometryNodeCurveStar")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_curve_topology(Menu):
@@ -97,6 +101,7 @@ class NODE_MT_geometry_node_curve_topology(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeOffsetPointInCurve")
node_add_menu.add_node_type(layout, "GeometryNodeCurveOfPoint")
node_add_menu.add_node_type(layout, "GeometryNodePointsOfCurve")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_GEOMETRY(Menu):
@@ -122,6 +127,7 @@ class NODE_MT_geometry_node_GEO_GEOMETRY(Menu):
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSetID")
node_add_menu.add_node_type(layout, "GeometryNodeSetPosition")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_INPUT(Menu):
@@ -149,6 +155,7 @@ class NODE_MT_geometry_node_GEO_INPUT(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeInputPosition")
node_add_menu.add_node_type(layout, "GeometryNodeInputRadius")
node_add_menu.add_node_type(layout, "GeometryNodeInputSceneTime")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_INSTANCE(Menu):
@@ -166,6 +173,7 @@ class NODE_MT_geometry_node_GEO_INSTANCE(Menu):
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceRotation")
node_add_menu.add_node_type(layout, "GeometryNodeInputInstanceScale")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_MATERIAL(Menu):
@@ -181,6 +189,7 @@ class NODE_MT_geometry_node_GEO_MATERIAL(Menu):
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterial")
node_add_menu.add_node_type(layout, "GeometryNodeSetMaterialIndex")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_GEO_MESH(Menu):
@@ -219,6 +228,7 @@ class NODE_MT_geometry_node_GEO_MESH(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshVertexNeighbors")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSetShadeSmooth")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_PRIMITIVES_MESH(Menu):
@@ -235,6 +245,7 @@ class NODE_MT_category_PRIMITIVES_MESH(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeMeshCircle")
node_add_menu.add_node_type(layout, "GeometryNodeMeshLine")
node_add_menu.add_node_type(layout, "GeometryNodeMeshUVSphere")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_mesh_topology(Menu):
@@ -250,6 +261,7 @@ class NODE_MT_geometry_node_mesh_topology(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeFaceOfCorner"),
node_add_menu.add_node_type(layout, "GeometryNodeOffsetCornerInFace"),
node_add_menu.add_node_type(layout, "GeometryNodeVertexOfCorner"),
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_OUTPUT(Menu):
@@ -259,6 +271,7 @@ class NODE_MT_category_GEO_OUTPUT(Menu):
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeViewer")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_POINT(Menu):
@@ -274,6 +287,7 @@ class NODE_MT_category_GEO_POINT(Menu):
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_TEXT(Menu):
@@ -290,6 +304,7 @@ class NODE_MT_category_GEO_TEXT(Menu):
node_add_menu.add_node_type(layout, "FunctionNodeValueToString")
layout.separator()
node_add_menu.add_node_type(layout, "FunctionNodeInputSpecialCharacters")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_TEXTURE(Menu):
@@ -308,6 +323,7 @@ class NODE_MT_category_GEO_TEXTURE(Menu):
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")
node_add_menu.add_node_type(layout, "ShaderNodeTexWhiteNoise")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_UTILITIES(Menu):
@@ -331,6 +347,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
node_add_menu.add_node_type(layout, "FunctionNodeRandomValue")
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
node_add_menu.add_node_type(layout, "GeometryNodeSwitch")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_UV(Menu):
@@ -341,6 +358,7 @@ class NODE_MT_category_GEO_UV(Menu):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeUVPackIslands")
node_add_menu.add_node_type(layout, "GeometryNodeUVUnwrap")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_VECTOR(Menu):
@@ -354,6 +372,7 @@ class NODE_MT_category_GEO_VECTOR(Menu):
node_add_menu.add_node_type(layout, "ShaderNodeVectorCurve")
node_add_menu.add_node_type(layout, "ShaderNodeVectorMath")
node_add_menu.add_node_type(layout, "ShaderNodeVectorRotate")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_VOLUME(Menu):
@@ -364,6 +383,7 @@ class NODE_MT_category_GEO_VOLUME(Menu):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_GROUP(Menu):
@@ -373,6 +393,7 @@ class NODE_MT_category_GEO_GROUP(Menu):
def draw(self, context):
layout = self.layout
node_add_menu.draw_node_group_add_menu(context, layout)
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_LAYOUT(Menu):
@@ -383,6 +404,7 @@ class NODE_MT_category_GEO_LAYOUT(Menu):
layout = self.layout
node_add_menu.add_node_type(layout, "NodeFrame")
node_add_menu.add_node_type(layout, "NodeReroute")
+ node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_geometry_node_add_all(Menu):
@@ -413,6 +435,7 @@ class NODE_MT_geometry_node_add_all(Menu):
layout.menu("NODE_MT_category_GEO_VOLUME")
layout.menu("NODE_MT_category_GEO_GROUP")
layout.menu("NODE_MT_category_GEO_LAYOUT")
+ node_add_menu.draw_root_assets(layout)
classes = (
diff --git a/release/scripts/startup/bl_ui/properties_data_curves.py b/release/scripts/startup/bl_ui/properties_data_curves.py
index ff0eabeb7d9..df80bdb4552 100644
--- a/release/scripts/startup/bl_ui/properties_data_curves.py
+++ b/release/scripts/startup/bl_ui/properties_data_curves.py
@@ -44,7 +44,13 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel):
layout.use_property_split = True
layout.prop(ob.data, "surface")
- layout.prop(ob.data, "surface_uv_map", text="UV Map")
+ has_surface = ob.data.surface is not None
+ if has_surface:
+ layout.prop_search(ob.data, "surface_uv_map", ob.data.surface.data, "uv_layers", text="UV Map")
+ else:
+ row = layout.row()
+ row.prop(ob.data, "surface_uv_map", text="UV Map")
+ row.enabled = has_surface
class CURVES_MT_add_attribute(Menu):
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index a775a3cfa1b..a6b97fbdc85 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -586,7 +586,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
def draw_attribute_warnings(self, context, layout):
ob = context.object
- mesh = ob.data
+ mesh = context.mesh
unique_names = set()
colliding_names = []
@@ -595,8 +595,11 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
{"position": None, "shade_smooth": None, "normal": None, "crease": None},
mesh.attributes,
mesh.uv_layers,
- ob.vertex_groups,
+ None if ob is None else ob.vertex_groups,
):
+ if collection is None:
+ colliding_names.append("Cannot check for object vertex groups when pinning mesh")
+ continue
for name in collection.keys():
unique_names_len = len(unique_names)
unique_names.add(name)
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index ca0e698500e..61384f25afb 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -380,7 +380,14 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
layout = self.layout
ffmpeg = context.scene.render.ffmpeg
- needs_codec = ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4', 'WEBM'}
+ needs_codec = ffmpeg.format in {
+ 'AVI',
+ 'QUICKTIME',
+ 'MKV',
+ 'OGG',
+ 'MPEG4',
+ 'WEBM'
+ }
if needs_codec:
layout.prop(ffmpeg, "codec")
@@ -391,7 +398,12 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
layout.prop(ffmpeg, "use_lossless_output")
# Output quality
- use_crf = needs_codec and ffmpeg.codec in {'H264', 'MPEG4', 'WEBM'}
+ use_crf = needs_codec and ffmpeg.codec in {
+ 'H264',
+ 'MPEG4',
+ 'WEBM',
+ 'AV1'
+ }
if use_crf:
layout.prop(ffmpeg, "constant_rate_factor")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index ea257498e11..39684aaf161 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3018,6 +3018,7 @@ class VIEW3D_MT_brush_paint_modes(Menu):
layout.prop(brush, "use_paint_vertex", text="Vertex Paint")
layout.prop(brush, "use_paint_weight", text="Weight Paint")
layout.prop(brush, "use_paint_image", text="Texture Paint")
+ layout.prop(brush, "use_paint_sculpt_curves", text="Sculpt Curves")
class VIEW3D_MT_paint_vertex(Menu):
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 328e45f79b9..fec156580cf 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -52,6 +52,8 @@ class VIEW3D_MT_brush_context_menu(Menu):
elif context.sculpt_object:
layout.prop_menu_enum(brush, "sculpt_tool")
layout.operator("brush.reset")
+ elif context.tool_settings.curves_sculpt:
+ layout.prop_menu_enum(brush, "curves_sculpt_tool")
class VIEW3D_MT_brush_gpencil_context_menu(Menu):
@@ -81,22 +83,6 @@ class VIEW3D_MT_brush_gpencil_context_menu(Menu):
layout.operator("gpencil.brush_reset_all")
-class VIEW3D_MT_brush_context_menu_paint_modes(Menu):
- bl_label = "Enabled Modes"
-
- def draw(self, context):
- layout = self.layout
-
- settings = UnifiedPaintPanel.paint_settings(context)
- brush = settings.brush
-
- layout.prop(brush, "use_paint_sculpt", text="Sculpt")
- layout.prop(brush, "use_paint_uv_sculpt", text="UV Sculpt")
- layout.prop(brush, "use_paint_vertex", text="Vertex Paint")
- layout.prop(brush, "use_paint_weight", text="Weight Paint")
- layout.prop(brush, "use_paint_image", text="Texture Paint")
-
-
class View3DPanel:
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -2373,7 +2359,6 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
classes = (
VIEW3D_MT_brush_context_menu,
VIEW3D_MT_brush_gpencil_context_menu,
- VIEW3D_MT_brush_context_menu_paint_modes,
VIEW3D_PT_tools_object_options,
VIEW3D_PT_tools_object_options_transform,
VIEW3D_PT_tools_meshedit_options,
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index ee0f41937e2..eff05e471aa 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -34,9 +34,9 @@ typedef struct EditBone {
/** User-Defined Properties on this Bone */
struct IDProperty *prop;
/**
- * Editbones have a one-way link (i.e. children refer
+ * Edit-bones have a one-way link (i.e. children refer
* to parents. This is converted to a two-way link for
- * normal bones when leaving editmode.
+ * normal bones when leaving edit-mode.
*/
struct EditBone *parent;
/** (64 == MAXBONENAME) */
diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index caed12d4fdf..73c2e00c4c4 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -307,7 +307,7 @@ class AssetCatalogTreeItem {
/** Iterate over children calling \a callback for each of them, but do not recurse into their
* children. */
- void foreach_child(const ItemIterFn callback);
+ void foreach_child(ItemIterFn callback);
protected:
/** Child tree items, ordered by their names. */
@@ -345,10 +345,15 @@ class AssetCatalogTree {
/** Ensure an item representing \a path is in the tree, adding it if necessary. */
void insert_item(const AssetCatalog &catalog);
- void foreach_item(const AssetCatalogTreeItem::ItemIterFn callback);
+ void foreach_item(ItemIterFn callback);
/** Iterate over root items calling \a callback for each of them, but do not recurse into their
* children. */
- void foreach_root_item(const ItemIterFn callback);
+ void foreach_root_item(ItemIterFn callback);
+
+ bool is_empty() const;
+
+ AssetCatalogTreeItem *find_item(const AssetCatalogPath &path);
+ AssetCatalogTreeItem *find_root_item(const AssetCatalogPath &path);
protected:
/** Child tree items, ordered by their names. */
diff --git a/source/blender/blenkernel/BKE_asset_catalog_path.hh b/source/blender/blenkernel/BKE_asset_catalog_path.hh
index 135906dd064..93ab0389daf 100644
--- a/source/blender/blenkernel/BKE_asset_catalog_path.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog_path.hh
@@ -49,7 +49,7 @@ class AssetCatalogPath {
AssetCatalogPath() = default;
AssetCatalogPath(StringRef path);
- AssetCatalogPath(const std::string &path);
+ AssetCatalogPath(std::string path);
AssetCatalogPath(const char *path);
AssetCatalogPath(const AssetCatalogPath &other_path) = default;
AssetCatalogPath(AssetCatalogPath &&other_path) noexcept;
diff --git a/source/blender/blenkernel/BKE_asset_library.hh b/source/blender/blenkernel/BKE_asset_library.hh
index e0a39e3aee8..2058df71f6a 100644
--- a/source/blender/blenkernel/BKE_asset_library.hh
+++ b/source/blender/blenkernel/BKE_asset_library.hh
@@ -10,6 +10,8 @@
# error This is a C++-only header file. Use BKE_asset_library.h instead.
#endif
+#include "DNA_asset_types.h"
+
#include "BKE_asset_library.h"
#include "BKE_asset_catalog.hh"
@@ -44,19 +46,24 @@ struct AssetLibrary {
* No-op if the catalog cannot be found. This could be the kind of "the
* catalog definition file is corrupt/lost" scenario that the simple name is
* meant to help recover from. */
- void refresh_catalog_simplename(struct AssetMetaData *asset_data);
+ void refresh_catalog_simplename(AssetMetaData *asset_data);
void on_blend_save_handler_register();
void on_blend_save_handler_unregister();
- void on_blend_save_post(struct Main *, struct PointerRNA **pointers, int num_pointers);
+ void on_blend_save_post(Main *bmain, PointerRNA **pointers, int num_pointers);
private:
bCallbackFuncStore on_save_callback_store_{};
};
+Vector<AssetLibraryReference> all_valid_asset_library_refs();
+
} // namespace blender::bke
+blender::bke::AssetLibrary *BKE_asset_library_load(const Main *bmain,
+ const AssetLibraryReference &library_reference);
+
blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service(
const ::AssetLibrary *library);
blender::bke::AssetCatalogTree *BKE_asset_library_get_catalog_tree(const ::AssetLibrary *library);
diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh
index 7b13b8a2b09..a4f9d73c31e 100644
--- a/source/blender/blenkernel/BKE_attribute.hh
+++ b/source/blender/blenkernel/BKE_attribute.hh
@@ -793,7 +793,9 @@ class CustomDataAttributes {
~CustomDataAttributes();
CustomDataAttributes(const CustomDataAttributes &other);
CustomDataAttributes(CustomDataAttributes &&other);
+
CustomDataAttributes &operator=(const CustomDataAttributes &other);
+ CustomDataAttributes &operator=(CustomDataAttributes &&other);
void reallocate(int size);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 96df8f7a443..806fff2099e 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -25,7 +25,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 4
+#define BLENDER_FILE_SUBVERSION 5
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h
index bc60b6f050e..5b1dea0833a 100644
--- a/source/blender/blenkernel/BKE_bpath.h
+++ b/source/blender/blenkernel/BKE_bpath.h
@@ -55,15 +55,18 @@ typedef enum eBPathForeachFlag {
* This is needed for directory manipulation callbacks which might otherwise modify the same
* directory multiple times. */
BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE = (1 << 8),
- /** Reload data (when the path is edited).
- * \note Only used by Image IDType currently. */
+ /**
+ * Reload data (when the path is edited).
+ * \note Only used by Image #IDType currently.
+ */
BKE_BPATH_FOREACH_PATH_RELOAD_EDITED = (1 << 9),
} eBPathForeachFlag;
ENUM_OPERATORS(eBPathForeachFlag, BKE_BPATH_FOREACH_PATH_RELOAD_EDITED)
struct BPathForeachPathData;
-/** Callback used to iterate over an ID's file paths.
+/**
+ * Callback used to iterate over an ID's file paths.
*
* \note `path`s parameters should be considered as having a maximal `FILE_MAX` string length.
*
@@ -145,8 +148,9 @@ bool BKE_bpath_foreach_path_allocated_process(struct BPathForeachPathData *bpath
/** Check for missing files. */
void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports);
-/** Recursively search into given search directory, for all file paths of all IDs in given \a
- * bmain, and replace existing paths as needed.
+/**
+ * Recursively search into given search directory, for all file paths of all IDs in given
+ * \a bmain, and replace existing paths as needed.
*
* \note The search will happen into the whole search directory tree recursively (with a limit of
* MAX_DIR_RECURSE), if several files are found matching a searched filename, the biggest one will
@@ -156,7 +160,7 @@ void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *report
* \param searchpath: The root directory in which the new filepaths should be searched for.
* \param find_all: If `true`, also search for files which current path is still valid, if `false`
* skip those still valid paths.
- * */
+ */
void BKE_bpath_missing_files_find(struct Main *bmain,
const char *searchpath,
struct ReportList *reports,
@@ -178,23 +182,28 @@ void BKE_bpath_absolute_convert(struct Main *bmain,
const char *basedir,
struct ReportList *reports);
-/** Temp backup of paths from all IDs in given \a bmain.
+/**
+ * Temp backup of paths from all IDs in given \a bmain.
*
- * \return An opaque handle to pass to #BKE_bpath_list_restore and #BKE_bpath_list_free.
+ * \return An opaque handle to pass to #BKE_bpath_list_restore and #BKE_bpath_list_free.
*/
void *BKE_bpath_list_backup(struct Main *bmain, eBPathForeachFlag flag);
-/** Restore the temp backup of paths from \a path_list_handle into all IDs in given \a bmain.
+/**
+ * Restore the temp backup of paths from \a path_list_handle into all IDs in given \a bmain.
*
* \note This function assumes that the data in given Main did not change (no
* addition/deletion/re-ordering of IDs, or their file paths) since the call to
- * #BKE_bpath_list_backup that generated the given \a path_list_handle. */
+ * #BKE_bpath_list_backup that generated the given \a path_list_handle.
+ */
void BKE_bpath_list_restore(struct Main *bmain, eBPathForeachFlag flag, void *path_list_handle);
-/** Free the temp backup of paths in \a path_list_handle.
+/**
+ * Free the temp backup of paths in \a path_list_handle.
*
* \note This function assumes that the path list has already been restored with a call to
- * #BKE_bpath_list_restore, and is therefore empty. */
+ * #BKE_bpath_list_restore, and is therefore empty.
+ */
void BKE_bpath_list_free(void *path_list_handle);
/** \} */
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 4d728002c87..a763b3d12c2 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -18,7 +18,9 @@ extern "C" {
struct Brush;
struct ImBuf;
struct ImagePool;
+struct Object;
struct Main;
+struct MTex;
struct Scene;
struct ToolSettings;
struct UnifiedPaintSettings;
@@ -109,6 +111,7 @@ float BKE_brush_curve_strength(const struct Brush *br, float p, float len);
*/
float BKE_brush_sample_tex_3d(const struct Scene *scene,
const struct Brush *br,
+ const struct MTex *mtex,
const float point[3],
float rgba[4],
int thread,
@@ -120,6 +123,24 @@ float BKE_brush_sample_masktex(const struct Scene *scene,
struct ImagePool *pool);
/**
+ * Get the mask texture for this given object mode.
+ *
+ * This is preferred above using mtex/mask_mtex attributes directly as due to legacy these
+ * attributes got switched in sculpt mode.
+ */
+const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush,
+ const eObjectMode object_mode);
+
+/**
+ * Get the color texture for this given object mode.
+ *
+ * This is preferred above using mtex/mask_mtex attributes directly as due to legacy these
+ * attributes got switched in sculpt mode.
+ */
+const struct MTex *BKE_brush_color_texture_get(const struct Brush *brush,
+ const eObjectMode object_mode);
+
+/**
* Radial control.
*/
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br,
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 4b9d78e45ec..512982adb7c 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -288,7 +288,7 @@ bool CTX_data_dir(const char *member);
CTX_DATA_BEGIN (C, Type, instance, member) \
Type_id instance_id = (Type_id)ctx_link->ptr.owner_id;
-int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *));
+int ctx_data_list_count(const bContext *C, bool (*func)(const bContext *, ListBase *));
#define CTX_DATA_COUNT(C, member) ctx_data_list_count(C, CTX_data_##member)
@@ -319,22 +319,22 @@ void CTX_data_main_set(bContext *C, struct Main *bmain);
void CTX_data_scene_set(bContext *C, struct Scene *scene);
/* Only Outliner currently! */
-int CTX_data_selected_ids(const bContext *C, ListBase *list);
+bool CTX_data_selected_ids(const bContext *C, ListBase *list);
-int CTX_data_selected_editable_objects(const bContext *C, ListBase *list);
-int CTX_data_selected_editable_bases(const bContext *C, ListBase *list);
+bool CTX_data_selected_editable_objects(const bContext *C, ListBase *list);
+bool CTX_data_selected_editable_bases(const bContext *C, ListBase *list);
-int CTX_data_editable_objects(const bContext *C, ListBase *list);
-int CTX_data_editable_bases(const bContext *C, ListBase *list);
+bool CTX_data_editable_objects(const bContext *C, ListBase *list);
+bool CTX_data_editable_bases(const bContext *C, ListBase *list);
-int CTX_data_selected_objects(const bContext *C, ListBase *list);
-int CTX_data_selected_bases(const bContext *C, ListBase *list);
+bool CTX_data_selected_objects(const bContext *C, ListBase *list);
+bool CTX_data_selected_bases(const bContext *C, ListBase *list);
-int CTX_data_visible_objects(const bContext *C, ListBase *list);
-int CTX_data_visible_bases(const bContext *C, ListBase *list);
+bool CTX_data_visible_objects(const bContext *C, ListBase *list);
+bool CTX_data_visible_bases(const bContext *C, ListBase *list);
-int CTX_data_selectable_objects(const bContext *C, ListBase *list);
-int CTX_data_selectable_bases(const bContext *C, ListBase *list);
+bool CTX_data_selectable_objects(const bContext *C, ListBase *list);
+bool CTX_data_selectable_bases(const bContext *C, ListBase *list);
struct Object *CTX_data_active_object(const bContext *C);
struct Base *CTX_data_active_base(const bContext *C);
@@ -348,25 +348,25 @@ struct Mask *CTX_data_edit_mask(const bContext *C);
struct CacheFile *CTX_data_edit_cachefile(const bContext *C);
-int CTX_data_selected_nodes(const bContext *C, ListBase *list);
+bool CTX_data_selected_nodes(const bContext *C, ListBase *list);
struct EditBone *CTX_data_active_bone(const bContext *C);
-int CTX_data_selected_bones(const bContext *C, ListBase *list);
-int CTX_data_selected_editable_bones(const bContext *C, ListBase *list);
-int CTX_data_visible_bones(const bContext *C, ListBase *list);
-int CTX_data_editable_bones(const bContext *C, ListBase *list);
+bool CTX_data_selected_bones(const bContext *C, ListBase *list);
+bool CTX_data_selected_editable_bones(const bContext *C, ListBase *list);
+bool CTX_data_visible_bones(const bContext *C, ListBase *list);
+bool CTX_data_editable_bones(const bContext *C, ListBase *list);
struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C);
-int CTX_data_selected_pose_bones(const bContext *C, ListBase *list);
-int CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list);
-int CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
+bool CTX_data_selected_pose_bones(const bContext *C, ListBase *list);
+bool CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list);
+bool CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
struct bGPdata *CTX_data_gpencil_data(const bContext *C);
struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
-int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
-int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
-int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+bool CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
+bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
+bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid);
diff --git a/source/blender/blenkernel/BKE_duplilist.h b/source/blender/blenkernel/BKE_duplilist.h
index 44c4df1fc2e..a0732bf39cf 100644
--- a/source/blender/blenkernel/BKE_duplilist.h
+++ b/source/blender/blenkernel/BKE_duplilist.h
@@ -76,16 +76,20 @@ typedef struct DupliObject {
unsigned int random_id;
} DupliObject;
-/** Look up the RGBA value of a uniform shader attribute.
- * \return true if the attribute was found; if not, r_value is also set to zero. */
+/**
+ * Look up the RGBA value of a uniform shader attribute.
+ * \return true if the attribute was found; if not, r_value is also set to zero.
+ */
bool BKE_object_dupli_find_rgba_attribute(struct Object *ob,
struct DupliObject *dupli,
struct Object *dupli_parent,
const char *name,
float r_value[4]);
-/** Look up the RGBA value of a view layer/scene/world shader attribute.
- * \return true if the attribute was found; if not, r_value is also set to zero. */
+/**
+ * Look up the RGBA value of a view layer/scene/world shader attribute.
+ * \return true if the attribute was found; if not, r_value is also set to zero.
+ */
bool BKE_view_layer_find_rgba_attribute(struct Scene *scene,
struct ViewLayer *layer,
const char *name,
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index b9219814c08..976961f27ae 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -332,8 +332,12 @@ bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps,
* \param gps: Target stroke.
* \param index_from: the index of the first point to be used in the trimmed result.
* \param index_to: the index of the last point to be used in the trimmed result.
+ * \param keep_point: Keep strokes with one point. False remove the single points strokes
*/
-bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps, int index_from, int index_to);
+bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps,
+ int index_from,
+ int index_to,
+ const bool keep_point);
/**
* Split the given stroke into several new strokes, partitioning
* it based on whether the stroke points have a particular flag
diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh
index 6502fefec88..f17ebba0dfa 100644
--- a/source/blender/blenkernel/BKE_instances.hh
+++ b/source/blender/blenkernel/BKE_instances.hh
@@ -5,7 +5,7 @@
/** \file
* \ingroup bke
*
- * #Instances is a container for geometry instances. It fullfills some key requirements:
+ * #Instances is a container for geometry instances. It fulfills some key requirements:
* - Support nested instances.
* - Support instance attributes.
* - Support referencing different kinds of instances (objects, collections, geometry sets).
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 0fe351c0aa4..6cae56b775f 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -167,9 +167,9 @@ void BKE_keyblock_update_from_offset(const struct Object *ob,
* Move shape key from org_index to new_index. Safe, clamps index to valid range,
* updates reference keys, the object's active shape index,
* the 'frame' value in case of absolute keys, etc.
- * Note indices are expected in real values (not 'fake' shapenr +1 ones).
+ * Note indices are expected in real values (not *fake* `shapenr +1` ones).
*
- * \param org_index: if < 0, current object's active shape will be used as skey to move.
+ * \param org_index: if < 0, current object's active shape will be used as shape-key to move.
* \return true if something was done, else false.
*/
bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index);
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index efadd5c11d6..2913beee759 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -249,8 +249,8 @@ float BKE_nlastrip_compute_frame_to_next_strip(struct NlaStrip *strip);
/**
* Returns the next strip in this strip's NLA track, or a null pointer.
*
- * \param strip The strip to find the next trip from.
- * \param check_transitions Whether or not to skip transitions.
+ * \param strip: The strip to find the next trip from.
+ * \param check_transitions: Whether or not to skip transitions.
* \return The next strip in the track, or NULL if none are present.
*/
struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions);
@@ -258,8 +258,8 @@ struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_tr
/**
* Returns the previous strip in this strip's NLA track, or a null pointer.
*
- * \param strip The strip to find the previous trip from.
- * \param check_transitions Whether or not to skip transitions.
+ * \param strip: The strip to find the previous trip from.
+ * \param check_transitions: Whether or not to skip transitions.
* \return The previous strip in the track, or NULL if none are present.
*/
struct NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 60dfc0af25f..5cbd7937f3f 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -323,7 +323,7 @@ struct Base **BKE_object_pose_base_array_get(const struct Scene *scene,
void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4]);
/**
- * Compute object world transform and store it in `ob->obmat`.
+ * Compute object world transform and store it in `ob->object_to_world`.
*/
void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_object_where_is_calc_ex(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 437a22e4782..9fc4aa5307d 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -886,7 +886,7 @@ void BKE_sculpt_sync_face_visibility_to_grids(struct Mesh *mesh, struct SubdivCC
* Test if PBVH can be used directly for drawing, which is faster than
* drawing the mesh and all updates that come with it.
*/
-bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
+bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct RegionView3D *rv3d);
enum {
SCULPT_MASK_LAYER_CALC_VERT = (1 << 0),
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index efb8c2a9bb1..4331a25c112 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -293,6 +293,7 @@ void BKE_ptcache_ids_from_object(struct ListBase *lb,
bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis);
/************ ID specific functions ************************/
+
void BKE_ptcache_id_clear(PTCacheID *id, int mode, unsigned int cfra);
bool BKE_ptcache_id_exist(PTCacheID *id, int cfra);
int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 9a7d2bde810..a86953f35cc 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -385,6 +385,7 @@ typedef struct MenuType {
bool (*poll)(const struct bContext *C, struct MenuType *mt);
/* draw entirely, view changes should be handled here */
void (*draw)(const struct bContext *C, struct Menu *menu);
+ void (*listener)(const wmRegionListenerParams *params);
/* RNA integration */
ExtensionRNA rna_ext;
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index f3a929dc5b9..5d1a27f8ba0 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -75,7 +75,7 @@ typedef struct UndoStep {
/** Some situations require the global state to be stored, edge cases when exiting modes. */
bool use_memfile_step;
/** When this is true, undo/memfile read code is allowed to re-use old data-blocks for unchanged
- * IDs, and existing depsgraphes. This has to be forbidden in some cases (like renamed IDs). */
+ * IDs, and existing depsgraphs. This has to be forbidden in some cases (like renamed IDs). */
bool use_old_bmain_data;
/** For use by undo systems that accumulate changes (mesh-sculpt & image-painting). */
bool is_applied;
diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h
index 736f7548bb4..cfe246eb470 100644
--- a/source/blender/blenkernel/BKE_writeffmpeg.h
+++ b/source/blender/blenkernel/BKE_writeffmpeg.h
@@ -27,6 +27,7 @@ enum {
FFMPEG_OGG = 10,
FFMPEG_INVALID = 11,
FFMPEG_WEBM = 12,
+ FFMPEG_AV1 = 13,
};
enum {
@@ -38,6 +39,7 @@ enum {
FFMPEG_PRESET_H264 = 5,
FFMPEG_PRESET_THEORA = 6,
FFMPEG_PRESET_XVID = 7,
+ FFMPEG_PRESET_AV1 = 8,
};
struct RenderData;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 10aa4ec7906..8f6bd812d8e 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1738,7 +1738,7 @@ void what_does_obaction(Object *ob,
BKE_object_workob_clear(workob);
/* init workob */
- copy_m4_m4(workob->obmat, ob->obmat);
+ copy_m4_m4(workob->object_to_world, ob->object_to_world);
copy_m4_m4(workob->parentinv, ob->parentinv);
copy_m4_m4(workob->constinv, ob->constinv);
workob->parent = ob->parent;
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 965f48d1e51..b3990b2b7fc 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -237,7 +237,7 @@ bool BKE_appdir_font_folder_default(char *dir)
}
#elif defined(__APPLE__)
STRNCPY(test_dir, BLI_expand_tilde("~/Library/Fonts/"));
- BLI_path_slash_ensure(test_dir);
+ BLI_path_slash_ensure(test_dir, sizeof(test_dir));
#else
STRNCPY(test_dir, "/usr/share/fonts");
#endif
@@ -1093,13 +1093,13 @@ void BKE_appdir_app_templates(ListBase *templates)
* \param userdir: Directory specified in user preferences (may be NULL).
* note that by default this is an empty string, only use when non-empty.
*/
-static void where_is_temp(char *tempdir, const size_t tempdir_len, const char *userdir)
+static void where_is_temp(char *tempdir, const size_t tempdir_maxlen, const char *userdir)
{
tempdir[0] = '\0';
if (userdir && BLI_is_dir(userdir)) {
- BLI_strncpy(tempdir, userdir, tempdir_len);
+ BLI_strncpy(tempdir, userdir, tempdir_maxlen);
}
if (tempdir[0] == '\0') {
@@ -1116,23 +1116,23 @@ static void where_is_temp(char *tempdir, const size_t tempdir_len, const char *u
for (int i = 0; i < ARRAY_SIZE(env_vars); i++) {
const char *tmp = BLI_getenv(env_vars[i]);
if (tmp && (tmp[0] != '\0') && BLI_is_dir(tmp)) {
- BLI_strncpy(tempdir, tmp, tempdir_len);
+ BLI_strncpy(tempdir, tmp, tempdir_maxlen);
break;
}
}
}
if (tempdir[0] == '\0') {
- BLI_strncpy(tempdir, "/tmp/", tempdir_len);
+ BLI_strncpy(tempdir, "/tmp/", tempdir_maxlen);
}
else {
/* add a trailing slash if needed */
- BLI_path_slash_ensure(tempdir);
+ BLI_path_slash_ensure(tempdir, tempdir_maxlen);
}
}
static void tempdir_session_create(char *tempdir_session,
- const size_t tempdir_session_len,
+ const size_t tempdir_session_maxlen,
const char *tempdir)
{
tempdir_session[0] = '\0';
@@ -1146,9 +1146,9 @@ static void tempdir_session_create(char *tempdir_session,
* #_mktemp_s also requires the last null character is included. */
const int tempdir_session_len_required = tempdir_len + session_name_len + 1;
- if (tempdir_session_len_required <= tempdir_session_len) {
+ if (tempdir_session_len_required <= tempdir_session_maxlen) {
/* No need to use path joining utility as we know the last character of #tempdir is a slash. */
- BLI_string_join(tempdir_session, tempdir_session_len, tempdir, session_name);
+ BLI_string_join(tempdir_session, tempdir_session_maxlen, tempdir, session_name);
#ifdef WIN32
const bool needs_create = (_mktemp_s(tempdir_session, tempdir_session_len_required) == 0);
#else
@@ -1158,7 +1158,7 @@ static void tempdir_session_create(char *tempdir_session,
BLI_dir_create_recursive(tempdir_session);
}
if (BLI_is_dir(tempdir_session)) {
- BLI_path_slash_ensure(tempdir_session);
+ BLI_path_slash_ensure(tempdir_session, tempdir_session_maxlen);
/* Success. */
return;
}
@@ -1168,7 +1168,7 @@ static void tempdir_session_create(char *tempdir_session,
"Could not generate a temp file name for '%s', falling back to '%s'",
tempdir_session,
tempdir);
- BLI_strncpy(tempdir_session, tempdir, tempdir_session_len);
+ BLI_strncpy(tempdir_session, tempdir, tempdir_session_maxlen);
}
void BKE_tempdir_init(const char *userdir)
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 2e73cac99b5..0f8bf0e9928 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1596,7 +1596,7 @@ void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float o
}
/* Get inverse of (armature) object's matrix. */
- invert_m4_m4(obmat, ob->obmat);
+ invert_m4_m4(obmat, ob->object_to_world);
/* multiply given matrix by object's-inverse to find pose-space matrix */
mul_m4_m4m4(outmat, inmat, obmat);
@@ -2569,7 +2569,7 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
}
}
else {
- invert_m4_m4(ob->imat, ob->obmat); /* imat is needed */
+ invert_m4_m4(ob->imat, ob->object_to_world); /* imat is needed */
/* 1. clear flags */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
@@ -2696,14 +2696,14 @@ void BKE_pchan_minmax(const Object *ob,
pchan->custom_translation[0],
pchan->custom_translation[1],
pchan->custom_translation[2]);
- mul_m4_series(mat, ob->obmat, tmp, rmat, smat);
+ mul_m4_series(mat, ob->object_to_world, tmp, rmat, smat);
BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
}
else {
float vec[3];
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
+ mul_v3_m4v3(vec, ob->object_to_world, pchan_tx->pose_head);
minmax_v3v3_v3(r_min, r_max, vec);
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
+ mul_v3_m4v3(vec, ob->object_to_world, pchan_tx->pose_tail);
minmax_v3v3_v3(r_min, r_max, vec);
}
}
diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c
index 89afb886fc2..64a3937c191 100644
--- a/source/blender/blenkernel/intern/armature_deform.c
+++ b/source/blender/blenkernel/intern/armature_deform.c
@@ -582,9 +582,9 @@ static void armature_deform_coords_impl(const Object *ob_arm,
};
float obinv[4][4];
- invert_m4_m4(obinv, ob_target->obmat);
+ invert_m4_m4(obinv, ob_target->object_to_world);
- mul_m4_m4m4(data.postmat, obinv, ob_arm->obmat);
+ mul_m4_m4m4(data.postmat, obinv, ob_arm->object_to_world);
invert_m4_m4(data.premat, data.postmat);
if (em_target != NULL) {
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 6d7aed239e7..b9f46118c0d 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -249,7 +249,7 @@ static void apply_curve_transform(
* unless the option to allow curve to be positioned elsewhere is activated (i.e. no root).
*/
if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) {
- mul_m4_v3(ik_data->tar->obmat, r_vec);
+ mul_m4_v3(ik_data->tar->object_to_world, r_vec);
}
/* Convert the position to pose-space. */
@@ -819,7 +819,7 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec
BLI_assert((object->pose->flag & POSE_RECALC) == 0);
/* imat is needed for solvers. */
- invert_m4_m4(object->imat, object->obmat);
+ invert_m4_m4(object->imat, object->object_to_world);
/* clear flags */
for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index 38c712d7e75..62d03b2d79b 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -9,6 +9,7 @@
#include "BKE_asset_catalog.hh"
#include "BKE_asset_library.h"
+#include "BKE_asset_library.hh"
#include "BLI_fileops.hh"
#include "BLI_path_util.h"
@@ -787,6 +788,41 @@ void AssetCatalogTree::foreach_root_item(const ItemIterFn callback)
}
}
+bool AssetCatalogTree::is_empty() const
+{
+ return root_items_.empty();
+}
+
+AssetCatalogTreeItem *AssetCatalogTree::find_item(const AssetCatalogPath &path)
+{
+ AssetCatalogTreeItem *result = nullptr;
+ this->foreach_item([&](AssetCatalogTreeItem &item) {
+ if (result) {
+ /* There is no way to stop iteration. */
+ return;
+ }
+ if (item.catalog_path() == path) {
+ result = &item;
+ }
+ });
+ return result;
+}
+
+AssetCatalogTreeItem *AssetCatalogTree::find_root_item(const AssetCatalogPath &path)
+{
+ AssetCatalogTreeItem *result = nullptr;
+ this->foreach_root_item([&](AssetCatalogTreeItem &item) {
+ if (result) {
+ /* There is no way to stop iteration. */
+ return;
+ }
+ if (item.catalog_path() == path) {
+ result = &item;
+ }
+ });
+ return result;
+}
+
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/asset_catalog_path.cc b/source/blender/blenkernel/intern/asset_catalog_path.cc
index 669adb7adf4..9c653c1a137 100644
--- a/source/blender/blenkernel/intern/asset_catalog_path.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_path.cc
@@ -12,7 +12,7 @@ namespace blender::bke {
const char AssetCatalogPath::SEPARATOR = '/';
-AssetCatalogPath::AssetCatalogPath(const std::string &path) : path_(path)
+AssetCatalogPath::AssetCatalogPath(std::string path) : path_(std::move(path))
{
}
diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc
index 543b71e9da8..6a667d572a0 100644
--- a/source/blender/blenkernel/intern/asset_library.cc
+++ b/source/blender/blenkernel/intern/asset_library.cc
@@ -10,6 +10,7 @@
#include "BKE_asset_library_custom.h"
#include "BKE_main.h"
+#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "DNA_asset_types.h"
@@ -19,6 +20,13 @@
bool blender::bke::AssetLibrary::save_catalogs_when_file_is_saved = true;
+blender::bke::AssetLibrary *BKE_asset_library_load(const Main *bmain,
+ const AssetLibraryReference &library_reference)
+{
+ blender::bke::AssetLibraryService *service = blender::bke::AssetLibraryService::get();
+ return service->get_asset_library(bmain, library_reference);
+}
+
/**
* Loading an asset library at this point only means loading the catalogs. Later on this should
* invoke reading of asset representations too.
@@ -172,4 +180,26 @@ void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data)
}
STRNCPY(asset_data->catalog_simple_name, catalog->simple_name.c_str());
}
+
+Vector<AssetLibraryReference> all_valid_asset_library_refs()
+{
+ Vector<AssetLibraryReference> result;
+ int i;
+ LISTBASE_FOREACH_INDEX (const bUserAssetLibrary *, asset_library, &U.asset_libraries, i) {
+ if (!BLI_is_dir(asset_library->path)) {
+ continue;
+ }
+ AssetLibraryReference library_ref{};
+ library_ref.custom_library_index = i;
+ library_ref.type = ASSET_LIBRARY_CUSTOM;
+ result.append(library_ref);
+ }
+
+ AssetLibraryReference library_ref{};
+ library_ref.custom_library_index = -1;
+ library_ref.type = ASSET_LIBRARY_LOCAL;
+ result.append(library_ref);
+ return result;
+}
+
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc
index a6b2b7548a2..cd8de7908bf 100644
--- a/source/blender/blenkernel/intern/asset_library_service.cc
+++ b/source/blender/blenkernel/intern/asset_library_service.cc
@@ -7,11 +7,15 @@
#include "asset_library_service.hh"
#include "BKE_blender.h"
+#include "BKE_preferences.h"
#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
#include "BLI_path_util.h"
#include "BLI_string_ref.hh"
+#include "DNA_asset_types.h"
+#include "DNA_userdef_types.h"
+
#include "CLG_log.h"
static CLG_LogRef LOG = {"bke.asset_service"};
@@ -38,13 +42,45 @@ void AssetLibraryService::destroy()
instance_.reset();
}
+AssetLibrary *AssetLibraryService::get_asset_library(
+ const Main *bmain, const AssetLibraryReference &library_reference)
+{
+ if (library_reference.type == ASSET_LIBRARY_LOCAL) {
+ /* For the "Current File" library we get the asset library root path based on main. */
+ char root_path[FILE_MAX];
+ if (bmain) {
+ BKE_asset_library_find_suitable_root_path_from_main(bmain, root_path);
+ }
+ else {
+ root_path[0] = '\0';
+ }
+
+ if (root_path[0] == '\0') {
+ /* File wasn't saved yet. */
+ return get_asset_library_current_file();
+ }
+
+ return get_asset_library_on_disk(root_path);
+ }
+ if (library_reference.type == ASSET_LIBRARY_CUSTOM) {
+ bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
+ &U, library_reference.custom_library_index);
+
+ if (user_library) {
+ return get_asset_library_on_disk(user_library->path);
+ }
+ }
+
+ return nullptr;
+}
+
namespace {
std::string normalize_directory_path(StringRefNull directory)
{
char dir_normalized[PATH_MAX];
STRNCPY(dir_normalized, directory.c_str());
- BLI_path_normalize_dir(nullptr, dir_normalized);
+ BLI_path_normalize_dir(nullptr, dir_normalized, sizeof(dir_normalized));
return std::string(dir_normalized);
}
} // namespace
diff --git a/source/blender/blenkernel/intern/asset_library_service.hh b/source/blender/blenkernel/intern/asset_library_service.hh
index 277fb9db6cc..c22c6b182ce 100644
--- a/source/blender/blenkernel/intern/asset_library_service.hh
+++ b/source/blender/blenkernel/intern/asset_library_service.hh
@@ -44,6 +44,9 @@ class AssetLibraryService {
/** Destroy the AssetLibraryService singleton. It will be reallocated by #get() if necessary. */
static void destroy();
+ AssetLibrary *get_asset_library(const Main *bmain,
+ const AssetLibraryReference &library_reference);
+
/**
* Get the given asset library. Opens it (i.e. creates a new AssetLibrary instance) if necessary.
*/
diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc
index d105c5644de..7952e7ea3b0 100644
--- a/source/blender/blenkernel/intern/asset_library_service_test.cc
+++ b/source/blender/blenkernel/intern/asset_library_service_test.cc
@@ -118,7 +118,7 @@ TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes)
asset_lib_no_slash[strlen(asset_lib_no_slash) - 1] = '\0';
}
- BLI_path_slash_ensure(asset_lib_with_slash);
+ BLI_path_slash_ensure(asset_lib_with_slash, PATH_MAX);
AssetLibrary *const lib_no_slash = service->get_asset_library_on_disk(asset_lib_no_slash);
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index b86353bdb74..544427cfdd3 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -642,15 +642,26 @@ CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other)
size_ = other.size_;
data = other.data;
CustomData_reset(&other.data);
+ other.size_ = 0;
}
CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes &other)
{
- if (this != &other) {
- CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, other.size_);
- size_ = other.size_;
+ if (this == &other) {
+ return *this;
}
+ this->~CustomDataAttributes();
+ new (this) CustomDataAttributes(other);
+ return *this;
+}
+CustomDataAttributes &CustomDataAttributes::operator=(CustomDataAttributes &&other)
+{
+ if (this == &other) {
+ return *this;
+ }
+ this->~CustomDataAttributes();
+ new (this) CustomDataAttributes(std::move(other));
return *this;
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 23cf368af01..3598201d906 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -59,7 +59,7 @@ void BKE_blender_free(void)
{
/* samples are in a global list..., also sets G_MAIN->sound->sample NULL */
- /* Needs to run before main free as wm is still referenced for icons preview jobs. */
+ /* Needs to run before main free as window-manager is still referenced for icons preview jobs. */
BKE_studiolight_free();
BKE_blender_globals_clear();
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index e39c8756d96..f625f06d4d0 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -187,7 +187,7 @@ static void setup_app_data(bContext *C,
clean_paths(bfd->main);
}
- /* XXX here the complex windowmanager matching */
+ /* The following code blocks performs complex window-manager matching. */
/* no load screens? */
if (mode != LOAD_UI) {
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index 394469e19a4..4dd225c09ec 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -1494,6 +1494,7 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
* code is wrong, we need to redo it here after adding them back to main. */
BKE_main_id_refcount_recompute(bmain, false);
+ BKE_layer_collection_resync_forbid();
/* Note that in reload case, we also want to replace indirect usages. */
const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
(do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
@@ -1523,6 +1524,8 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
id_us_plus_no_lib(&old_key->id);
}
}
+ BKE_layer_collection_resync_allow();
+ BKE_main_collection_sync_remap(bmain);
BKE_main_unlock(bmain);
@@ -1614,6 +1617,9 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
(id->tag & LIB_TAG_PRE_EXISTING) == 0) {
continue;
}
+ if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) {
+ id->tag &= ~LIB_TAG_MISSING;
+ }
if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) {
BKE_lib_override_library_update(bmain, id);
}
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 2e07b52c7bf..a0458f0f8d8 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -959,7 +959,7 @@ void boids_precalc_rules(ParticleSettings *part, float cfra)
if (flbr->ob && flbr->cfra != cfra) {
/* save object locations for velocity calculations */
copy_v3_v3(flbr->oloc, flbr->loc);
- copy_v3_v3(flbr->loc, flbr->ob->obmat[3]);
+ copy_v3_v3(flbr->loc, flbr->ob->object_to_world[3]);
flbr->cfra = cfra;
}
}
diff --git a/source/blender/blenkernel/intern/brush.cc b/source/blender/blenkernel/intern/brush.cc
index 20d86ea5a2d..6f1435e90b8 100644
--- a/source/blender/blenkernel/intern/brush.cc
+++ b/source/blender/blenkernel/intern/brush.cc
@@ -1974,19 +1974,37 @@ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset)
BKE_curvemapping_changed(cumap, false);
}
+const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush,
+ const eObjectMode object_mode)
+{
+ if (object_mode == OB_MODE_SCULPT) {
+ return &brush->mtex;
+ }
+ return &brush->mask_mtex;
+}
+
+const struct MTex *BKE_brush_color_texture_get(const struct Brush *brush,
+ const eObjectMode object_mode)
+{
+ if (object_mode == OB_MODE_SCULPT) {
+ return &brush->mask_mtex;
+ }
+ return &brush->mtex;
+}
+
float BKE_brush_sample_tex_3d(const Scene *scene,
const Brush *br,
+ const MTex *mtex,
const float point[3],
float rgba[4],
const int thread,
struct ImagePool *pool)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- const MTex *mtex = &br->mtex;
float intensity = 1.0;
bool hasrgb = false;
- if (!mtex->tex) {
+ if (mtex == nullptr || mtex->tex == nullptr) {
intensity = 1;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 8608ce97397..7c1193d80ab 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -221,16 +221,16 @@ float BKE_camera_object_dof_distance(const Object *ob)
}
if (cam->dof.focus_object) {
float view_dir[3], dof_dir[3];
- normalize_v3_v3(view_dir, ob->obmat[2]);
+ normalize_v3_v3(view_dir, ob->object_to_world[2]);
bPoseChannel *pchan = BKE_pose_channel_find_name(cam->dof.focus_object->pose,
cam->dof.focus_subtarget);
if (pchan) {
float posemat[4][4];
- mul_m4_m4m4(posemat, cam->dof.focus_object->obmat, pchan->pose_mat);
- sub_v3_v3v3(dof_dir, ob->obmat[3], posemat[3]);
+ mul_m4_m4m4(posemat, cam->dof.focus_object->object_to_world, pchan->pose_mat);
+ sub_v3_v3v3(dof_dir, ob->object_to_world[3], posemat[3]);
}
else {
- sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof.focus_object->obmat[3]);
+ sub_v3_v3v3(dof_dir, ob->object_to_world[3], cam->dof.focus_object->object_to_world[3]);
}
return fabsf(dot_v3v3(view_dir, dof_dir));
}
@@ -628,7 +628,7 @@ static void camera_frame_fit_data_init(const Scene *scene,
BKE_camera_params_compute_matrix(params);
/* initialize callback data */
- copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->obmat);
+ copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->object_to_world);
normalize_m3(data->camera_rotmat);
/* To transform a plane which is in its homogeneous representation (4d vector),
* we need the inverse of the transpose of the transform matrix... */
@@ -828,7 +828,7 @@ bool BKE_camera_view_frame_fit_to_coords(const Depsgraph *depsgraph,
static void camera_model_matrix(const Object *camera, float r_modelmat[4][4])
{
- copy_m4_m4(r_modelmat, camera->obmat);
+ copy_m4_m4(r_modelmat, camera->object_to_world);
}
static void camera_stereo3d_model_matrix(const Object *camera,
@@ -854,7 +854,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
float size[3];
- mat4_to_size(size, camera->obmat);
+ mat4_to_size(size, camera->object_to_world);
size_to_mat4(sizemat, size);
if (pivot == CAM_S3D_PIVOT_CENTER) {
@@ -894,7 +894,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
toeinmat[3][0] = interocular_distance * fac_signed;
/* transform */
- normalize_m4_m4(r_modelmat, camera->obmat);
+ normalize_m4_m4(r_modelmat, camera->object_to_world);
mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
/* scale back to the original size */
@@ -902,7 +902,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
/* rotate perpendicular to the interocular line */
- normalize_m4_m4(r_modelmat, camera->obmat);
+ normalize_m4_m4(r_modelmat, camera->object_to_world);
mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
/* translate along the interocular line */
@@ -918,7 +918,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
}
else {
- normalize_m4_m4(r_modelmat, camera->obmat);
+ normalize_m4_m4(r_modelmat, camera->object_to_world);
/* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 89983eb8f62..910869bbc72 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -269,7 +269,7 @@ static int do_step_cloth(
/* Get the current position. */
copy_v3_v3(verts->xconst, mvert[i].co);
- mul_m4_v3(ob->obmat, verts->xconst);
+ mul_m4_v3(ob->object_to_world, verts->xconst);
if (vert_mass_changed) {
verts->mass = clmd->sim_parms->mass;
@@ -581,7 +581,7 @@ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexC
if (clmd->clothObject) {
/* Inverse matrix is not up to date. */
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
for (i = 0; i < cloth->mvert_num; i++) {
copy_v3_v3(vertexCos[i], cloth->verts[i].x);
@@ -763,11 +763,11 @@ static bool cloth_from_object(
if (first) {
copy_v3_v3(verts->x, mvert[i].co);
- mul_m4_v3(ob->obmat, verts->x);
+ mul_m4_v3(ob->object_to_world, verts->x);
if (shapekey_rest) {
copy_v3_v3(verts->xrest, shapekey_rest[i]);
- mul_m4_v3(ob->obmat, verts->xrest);
+ mul_m4_v3(ob->object_to_world, verts->xrest);
}
else {
copy_v3_v3(verts->xrest, verts->x);
@@ -1155,7 +1155,7 @@ static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh)
/* vertex count is already ensured to match */
for (i = 0; i < mesh->totvert; i++, verts++) {
copy_v3_v3(verts->xrest, mvert[i].co);
- mul_m4_v3(ob->obmat, verts->xrest);
+ mul_m4_v3(ob->object_to_world, verts->xrest);
}
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a6a6a1ca28f..1f288aef5ad 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -149,7 +149,7 @@ bConstraintOb *BKE_constraints_make_evalob(
/* Quats/Axis-Angle, so Eulers should just use default order */
cob->rotOrder = EULER_ORDER_DEFAULT;
}
- copy_m4_m4(cob->matrix, ob->obmat);
+ copy_m4_m4(cob->matrix, ob->object_to_world);
}
else {
unit_m4(cob->matrix);
@@ -175,7 +175,7 @@ bConstraintOb *BKE_constraints_make_evalob(
}
/* matrix in world-space */
- mul_m4_m4m4(cob->matrix, ob->obmat, cob->pchan->pose_mat);
+ mul_m4_m4m4(cob->matrix, ob->object_to_world, cob->pchan->pose_mat);
}
else {
unit_m4(cob->matrix);
@@ -216,7 +216,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
/* cob->ob might not exist! */
if (cob->ob) {
/* copy new ob-matrix back to owner */
- copy_m4_m4(cob->ob->obmat, cob->matrix);
+ copy_m4_m4(cob->ob->object_to_world, cob->matrix);
/* copy inverse of delta back to owner */
invert_m4_m4(cob->ob->constinv, delta);
@@ -276,7 +276,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
}
else {
/* World to pose. */
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_m4_m4m4(mat, imat, mat);
/* Use pose-space as stepping stone for other spaces. */
@@ -319,7 +319,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
}
else {
/* Pose to world. */
- mul_m4_m4m4(mat, ob->obmat, mat);
+ mul_m4_m4m4(mat, ob->object_to_world, mat);
/* Use world-space as stepping stone for other spaces. */
if (to != CONSTRAINT_SPACE_WORLD) {
/* Call self with slightly different values. */
@@ -429,7 +429,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
/* Check if object has a parent. */
if (ob->parent) {
/* 'subtract' parent's effects from owner. */
- mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv);
+ mul_m4_m4m4(diff_mat, ob->parent->object_to_world, ob->parentinv);
invert_m4_m4_safe(imat, diff_mat);
mul_m4_m4m4(mat, imat, mat);
}
@@ -465,7 +465,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
/* check that object has a parent - otherwise this won't work */
if (ob->parent) {
/* 'add' parent's effect back to owner */
- mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv);
+ mul_m4_m4m4(diff_mat, ob->parent->object_to_world, ob->parentinv);
mul_m4_m4m4(mat, diff_mat, mat);
}
else {
@@ -518,7 +518,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
const int defgroup = BKE_object_defgroup_name_index(ob, substring);
/* initialize target matrix using target matrix */
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
/* get index of vertex group */
if (defgroup == -1) {
@@ -584,7 +584,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
* calc_gizmo_stats, V3D_ORIENT_NORMAL case */
/* We need the transpose of the inverse for a normal. */
- copy_m3_m4(imat, ob->obmat);
+ copy_m3_m4(imat, ob->object_to_world);
invert_m3_m3(tmat, imat);
transpose_m3(tmat);
@@ -605,7 +605,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
normalize_m4(mat);
/* apply the average coordinate as the new location */
- mul_v3_m4v3(mat[3], ob->obmat, vec);
+ mul_v3_m4v3(mat[3], ob->object_to_world, vec);
}
/* function that sets the given matrix based on given vertex group in lattice */
@@ -627,7 +627,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
const int defgroup = BKE_object_defgroup_name_index(ob, substring);
/* initialize target matrix using target matrix */
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
/* get index of vertex group */
if (defgroup == -1) {
@@ -661,11 +661,11 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
}
}
- /* find average location, then multiply by ob->obmat to find world-space location */
+ /* find average location, then multiply by ob->object_to_world to find world-space location */
if (grouped) {
mul_v3_fl(vec, 1.0f / grouped);
}
- mul_v3_m4v3(tvec, ob->obmat, vec);
+ mul_v3_m4v3(tvec, ob->object_to_world, vec);
/* copy new location to matrix */
copy_v3_v3(mat[3], tvec);
@@ -684,7 +684,7 @@ static void constraint_target_to_mat4(Object *ob,
{
/* Case OBJECT */
if (substring[0] == '\0') {
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
BKE_constraint_mat_convertspace(ob, NULL, cob, mat, from, to, false);
}
/* Case VERTEXGROUP */
@@ -719,7 +719,7 @@ static void constraint_target_to_mat4(Object *ob,
if (headtail < 0.000001f && !(is_bbone && full_bbone)) {
/* skip length interpolation if set to head */
- mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat);
}
else if (is_bbone && pchan->bone->segments == pchan->runtime.bbone_segments) {
/* use point along bbone */
@@ -745,7 +745,7 @@ static void constraint_target_to_mat4(Object *ob,
mul_v3_m4v3(tempmat[3], pchan->pose_mat, loc);
}
- mul_m4_m4m4(mat, ob->obmat, tempmat);
+ mul_m4_m4m4(mat, ob->object_to_world, tempmat);
}
else {
float tempmat[4][4], loc[3];
@@ -757,11 +757,11 @@ static void constraint_target_to_mat4(Object *ob,
copy_m4_m4(tempmat, pchan->pose_mat);
copy_v3_v3(tempmat[3], loc);
- mul_m4_m4m4(mat, ob->obmat, tempmat);
+ mul_m4_m4m4(mat, ob->object_to_world, tempmat);
}
}
else {
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
}
/* convert matrix space as required */
@@ -1069,7 +1069,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
if (data->flag & CHILDOF_SET_INVERSE) {
invert_m4_m4(data->invmat, parmat);
if (cob->pchan != NULL) {
- mul_m4_series(data->invmat, data->invmat, cob->ob->obmat);
+ mul_m4_series(data->invmat, data->invmat, cob->ob->object_to_world);
}
copy_m4_m4(inverse_matrix, data->invmat);
@@ -1388,8 +1388,8 @@ static void kinematic_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
else {
float vec[3];
/* move grabtarget into world space */
- mul_v3_m4v3(vec, ob->obmat, data->grabtarget);
- copy_m4_m4(ct->matrix, ob->obmat);
+ mul_v3_m4v3(vec, ob->object_to_world, data->grabtarget);
+ copy_m4_m4(ct->matrix, ob->object_to_world);
copy_v3_v3(ct->matrix[3], vec);
}
}
@@ -1528,7 +1528,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
copy_v3_v3(totmat[3], vec);
- mul_m4_m4m4(ct->matrix, ct->tar->obmat, totmat);
+ mul_m4_m4m4(ct->matrix, ct->tar->object_to_world, totmat);
}
}
}
@@ -2557,7 +2557,7 @@ static void armdef_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
bPoseChannel *pchan = BKE_pose_channel_find_name(ct->tar->pose, ct->subtarget);
if (pchan != NULL) {
- mul_m4_m4m4(ct->matrix, ct->tar->obmat, pchan->pose_mat);
+ mul_m4_m4m4(ct->matrix, ct->tar->object_to_world, pchan->pose_mat);
return;
}
}
@@ -2613,7 +2613,7 @@ static void armdef_accumulate_bone(bConstraintTarget *ct,
float weight = ct->weight;
/* Our object's location in target pose space. */
- invert_m4_m4(iobmat, ct->tar->obmat);
+ invert_m4_m4(iobmat, ct->tar->object_to_world);
mul_v3_m4v3(co, iobmat, wco);
/* Multiply by the envelope weight when appropriate. */
@@ -2644,7 +2644,7 @@ static void armdef_accumulate_bone(bConstraintTarget *ct,
mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index].mat);
}
- armdef_accumulate_matrix(ct->tar->obmat,
+ armdef_accumulate_matrix(ct->tar->object_to_world,
iobmat,
basemat,
b_bone_mats[index + 1].mat,
@@ -2657,7 +2657,7 @@ static void armdef_accumulate_bone(bConstraintTarget *ct,
mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index + 1].mat);
}
- armdef_accumulate_matrix(ct->tar->obmat,
+ armdef_accumulate_matrix(ct->tar->object_to_world,
iobmat,
basemat,
b_bone_mats[index + 2].mat,
@@ -2667,8 +2667,13 @@ static void armdef_accumulate_bone(bConstraintTarget *ct,
}
else {
/* Simple bone. This requires DEG_OPCODE_BONE_DONE dependency due to chan_mat. */
- armdef_accumulate_matrix(
- ct->tar->obmat, iobmat, bone->arm_mat, pchan->chan_mat, weight, r_sum_mat, r_sum_dq);
+ armdef_accumulate_matrix(ct->tar->object_to_world,
+ iobmat,
+ bone->arm_mat,
+ pchan->chan_mat,
+ weight,
+ r_sum_mat,
+ r_sum_dq);
}
/* Accumulate the weight. */
@@ -2694,7 +2699,7 @@ static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
/* For constraints on bones, use the rest position to bind b-bone segments
* and envelopes, to allow safely changing the bone location as if parented. */
copy_v3_v3(input_co, cob->pchan->bone->arm_head);
- mul_m4_v3(cob->ob->obmat, input_co);
+ mul_m4_v3(cob->ob->object_to_world, input_co);
}
else {
copy_v3_v3(input_co, cob->matrix[3]);
@@ -3927,7 +3932,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
unit_m4(totmat);
copy_v3_v3(totmat[3], vec);
- mul_m4_m4m4(targetMatrix, ct->tar->obmat, totmat);
+ mul_m4_m4m4(targetMatrix, ct->tar->object_to_world, totmat);
}
}
@@ -4227,7 +4232,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
if (BKE_shrinkwrap_init_tree(
&tree, target_eval, scon->shrinkType, scon->shrinkMode, do_track_normal)) {
- BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat);
+ BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->object_to_world);
switch (scon->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
@@ -4902,7 +4907,7 @@ static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *co
/* Object matrix of the camera. */
float camera_obmat[4][4];
- copy_m4_m4(camera_obmat, camera_object->obmat);
+ copy_m4_m4(camera_obmat, camera_object->object_to_world);
/* Calculate inverted matrix of the solved camera at the current time. */
float reconstructed_camera_mat[4][4];
@@ -5054,10 +5059,10 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co
}
float depth_object_mat_inv[4][4];
- invert_m4_m4(depth_object_mat_inv, depth_object->obmat);
+ invert_m4_m4(depth_object_mat_inv, depth_object->object_to_world);
float ray_start[3], ray_end[3];
- mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->obmat[3]);
+ mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->object_to_world[3]);
mul_v3_m4v3(ray_end, depth_object_mat_inv, cob->matrix[3]);
float ray_direction[3];
@@ -5080,7 +5085,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co
&tree_data);
if (result != -1) {
- mul_v3_m4v3(cob->matrix[3], depth_object->obmat, hit.co);
+ mul_v3_m4v3(cob->matrix[3], depth_object->object_to_world, hit.co);
}
free_bvhtree_from_mesh(&tree_data);
@@ -5128,9 +5133,9 @@ static void followtrack_evaluate_using_2d_position(FollowTrackContext *context,
}
float disp[3];
- mul_v3_m4v3(disp, camera_object->obmat, vec);
+ mul_v3_m4v3(disp, camera_object->object_to_world, vec);
- copy_m4_m4(rmat, camera_object->obmat);
+ copy_m4_m4(rmat, camera_object->object_to_world);
zero_v3(rmat[3]);
mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
@@ -5152,10 +5157,10 @@ static void followtrack_evaluate_using_2d_position(FollowTrackContext *context,
}
float disp[3];
- mul_v3_m4v3(disp, camera_object->obmat, vec);
+ mul_v3_m4v3(disp, camera_object->object_to_world, vec);
/* apply camera rotation so Z-axis would be co-linear */
- copy_m4_m4(rmat, camera_object->obmat);
+ copy_m4_m4(rmat, camera_object->object_to_world);
zero_v3(rmat[3]);
mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
@@ -5303,7 +5308,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat);
invert_m4_m4(imat, mat);
- mul_m4_m4m4(parmat, camob->obmat, imat);
+ mul_m4_m4m4(parmat, camob->object_to_world, imat);
copy_m4_m4(obmat, cob->matrix);
@@ -5650,7 +5655,7 @@ bool BKE_constraint_apply_for_object(Depsgraph *depsgraph,
BLI_freelinkN(&single_con, new_con);
/* Apply transform from matrix. */
- BKE_object_apply_mat4(ob, ob_eval->obmat, true, true);
+ BKE_object_apply_mat4(ob, ob_eval->object_to_world, true, true);
return true;
}
@@ -6237,7 +6242,7 @@ void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
cob->ob = (Object *)ownerdata;
cob->pchan = NULL;
if (cob->ob) {
- copy_m4_m4(cob->matrix, cob->ob->obmat);
+ copy_m4_m4(cob->matrix, cob->ob->object_to_world);
copy_m4_m4(cob->startmat, cob->matrix);
}
else {
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index e44058032fc..ed6f55cc8f9 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -394,37 +394,37 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member)
return NULL;
}
-static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
+static bool ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
{
/* if context is NULL, pointer must be NULL too and that is a valid return */
if (C == NULL) {
*pointer = NULL;
- return 1;
+ return true;
}
bContextDataResult result;
if (ctx_data_get((bContext *)C, member, &result) == CTX_RESULT_OK) {
BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
*pointer = result.ptr.data;
- return 1;
+ return true;
}
*pointer = NULL;
- return 0;
+ return false;
}
-static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
+static bool ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
{
bContextDataResult result;
if (ctx_data_get((bContext *)C, member, &result) == CTX_RESULT_OK) {
BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
*list = result.list;
- return 1;
+ return true;
}
BLI_listbase_clear(list);
- return 0;
+ return false;
}
static int ctx_data_base_collection_get(const bContext *C, const char *member, ListBase *list)
@@ -682,7 +682,7 @@ void CTX_data_list_add_ptr(bContextDataResult *result, const PointerRNA *ptr)
BLI_addtail(&result->list, link);
}
-int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *))
+int ctx_data_list_count(const bContext *C, bool (*func)(const bContext *, ListBase *))
{
ListBase list;
@@ -1306,62 +1306,62 @@ ToolSettings *CTX_data_tool_settings(const bContext *C)
return NULL;
}
-int CTX_data_selected_ids(const bContext *C, ListBase *list)
+bool CTX_data_selected_ids(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_ids", list);
}
-int CTX_data_selected_nodes(const bContext *C, ListBase *list)
+bool CTX_data_selected_nodes(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_nodes", list);
}
-int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
+bool CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_editable_objects", list);
}
-int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
+bool CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
{
return ctx_data_base_collection_get(C, "selected_editable_objects", list);
}
-int CTX_data_editable_objects(const bContext *C, ListBase *list)
+bool CTX_data_editable_objects(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "editable_objects", list);
}
-int CTX_data_editable_bases(const bContext *C, ListBase *list)
+bool CTX_data_editable_bases(const bContext *C, ListBase *list)
{
return ctx_data_base_collection_get(C, "editable_objects", list);
}
-int CTX_data_selected_objects(const bContext *C, ListBase *list)
+bool CTX_data_selected_objects(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_objects", list);
}
-int CTX_data_selected_bases(const bContext *C, ListBase *list)
+bool CTX_data_selected_bases(const bContext *C, ListBase *list)
{
return ctx_data_base_collection_get(C, "selected_objects", list);
}
-int CTX_data_visible_objects(const bContext *C, ListBase *list)
+bool CTX_data_visible_objects(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_objects", list);
}
-int CTX_data_visible_bases(const bContext *C, ListBase *list)
+bool CTX_data_visible_bases(const bContext *C, ListBase *list)
{
return ctx_data_base_collection_get(C, "visible_objects", list);
}
-int CTX_data_selectable_objects(const bContext *C, ListBase *list)
+bool CTX_data_selectable_objects(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selectable_objects", list);
}
-int CTX_data_selectable_bases(const bContext *C, ListBase *list)
+bool CTX_data_selectable_bases(const bContext *C, ListBase *list)
{
return ctx_data_base_collection_get(C, "selectable_objects", list);
}
@@ -1419,22 +1419,22 @@ struct CacheFile *CTX_data_edit_cachefile(const bContext *C)
return ctx_data_pointer_get(C, "edit_cachefile");
}
-int CTX_data_selected_bones(const bContext *C, ListBase *list)
+bool CTX_data_selected_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_bones", list);
}
-int CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
+bool CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_editable_bones", list);
}
-int CTX_data_visible_bones(const bContext *C, ListBase *list)
+bool CTX_data_visible_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_bones", list);
}
-int CTX_data_editable_bones(const bContext *C, ListBase *list)
+bool CTX_data_editable_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "editable_bones", list);
}
@@ -1444,17 +1444,17 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C)
return ctx_data_pointer_get(C, "active_pose_bone");
}
-int CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
+bool CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_pose_bones", list);
}
-int CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list)
+bool CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "selected_pose_bones_from_active_object", list);
}
-int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
+bool CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_pose_bones", list);
}
@@ -1474,17 +1474,17 @@ bGPDframe *CTX_data_active_gpencil_frame(const bContext *C)
return ctx_data_pointer_get(C, "active_gpencil_frame");
}
-int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list)
+bool CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_gpencil_layers", list);
}
-int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list)
+bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "editable_gpencil_layers", list);
}
-int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
+bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
diff --git a/source/blender/blenkernel/intern/crazyspace.cc b/source/blender/blenkernel/intern/crazyspace.cc
index 190e2d3bb7e..f83c321c4ae 100644
--- a/source/blender/blenkernel/intern/crazyspace.cc
+++ b/source/blender/blenkernel/intern/crazyspace.cc
@@ -70,47 +70,48 @@ static void set_crazy_vertex_quat(float r_quat[4],
sub_qt_qtqt(r_quat, q2, q1);
}
-static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob)
+static bool modifiers_disable_subsurf_temporary(Object *ob, const int cageIndex)
{
- bool disabled = false;
- int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true);
+ bool changed = false;
ModifierData *md = static_cast<ModifierData *>(ob->modifiers.first);
for (int i = 0; md && i <= cageIndex; i++, md = md->next) {
if (md->type == eModifierType_Subsurf) {
md->mode ^= eModifierMode_DisableTemporary;
- disabled = true;
+ changed = true;
}
}
- return disabled;
+ return changed;
}
float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, Object *obedit))[3]
{
- Scene *scene = DEG_get_input_scene(depsgraph);
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
- Mesh *mesh_eval = static_cast<Mesh *>(obedit_eval->data);
- BMEditMesh *editmesh_eval = mesh_eval->edit_mesh;
+ const int cageIndex = BKE_modifiers_get_cage_index(scene_eval, obedit_eval, nullptr, true);
- /* disable subsurf temporal, get mapped cos, and enable it */
- if (modifiers_disable_subsurf_temporary(scene_eval, obedit_eval)) {
- /* Need to make new derived-mesh. */
+ /* Disable subsurf temporal, get mapped cos, and enable it. */
+ if (modifiers_disable_subsurf_temporary(obedit_eval, cageIndex)) {
+ /* Need to make new cage.
+ * TODO: Avoid losing original evaluated geometry. */
makeDerivedMesh(depsgraph, scene_eval, obedit_eval, &CD_MASK_BAREMESH);
}
- /* now get the cage */
- Mesh *mesh_eval_cage = editbmesh_get_eval_cage_from_orig(
- depsgraph, scene, obedit, &CD_MASK_BAREMESH);
+ /* Now get the cage. */
+ BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
+ Mesh *mesh_eval_cage = editbmesh_get_eval_cage(
+ depsgraph, scene_eval, obedit_eval, em_eval, &CD_MASK_BAREMESH);
- const int nverts = editmesh_eval->bm->totvert;
+ const int nverts = em_eval->bm->totvert;
float(*vertexcos)[3] = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map"));
mesh_get_mapped_verts_coords(mesh_eval_cage, vertexcos, nverts);
- /* set back the flag, no new cage needs to be built, transform does it */
- modifiers_disable_subsurf_temporary(scene_eval, obedit_eval);
+ /* Set back the flag, and ensure new cage needs to be built. */
+ if (modifiers_disable_subsurf_temporary(obedit_eval, cageIndex)) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
return vertexcos;
}
diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c
index 9a27ba91c2f..066d8494451 100644
--- a/source/blender/blenkernel/intern/curve_deform.c
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -44,8 +44,8 @@ typedef struct {
static void init_curve_deform(const Object *ob_curve, const Object *ob_target, CurveDeform *cd)
{
float imat[4][4];
- invert_m4_m4(imat, ob_target->obmat);
- mul_m4_m4m4(cd->objectspace, imat, ob_curve->obmat);
+ invert_m4_m4(imat, ob_target->object_to_world);
+ mul_m4_m4m4(cd->objectspace, imat, ob_curve->object_to_world);
invert_m4_m4(cd->curvespace, cd->objectspace);
copy_m3_m4(cd->objectspace3, cd->objectspace);
cd->no_rot_axis = 0;
diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
index b9fea2a27b8..ecf3be9bd81 100644
--- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
+++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
@@ -332,7 +332,8 @@ static eAttrDomain get_attribute_domain_for_mesh(const AttributeAccessor &mesh_a
static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attributes,
const AttributeAccessor &mesh_attributes,
- const AttributeIDRef &id)
+ const AttributeIDRef &id,
+ const AttributeMetaData &meta_data)
{
/* The position attribute has special non-generic evaluation. */
@@ -346,6 +347,9 @@ static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attribut
if (!id.should_be_kept()) {
return false;
}
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return false;
+ }
return true;
}
@@ -714,7 +718,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
main_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
- if (!should_add_attribute_to_mesh(main_attributes, mesh_attributes, id)) {
+ if (!should_add_attribute_to_mesh(main_attributes, mesh_attributes, id, meta_data)) {
return true;
}
main_attributes_set.add_new(id);
@@ -751,7 +755,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
if (main_attributes.contains(id)) {
return true;
}
- if (!should_add_attribute_to_mesh(profile_attributes, mesh_attributes, id)) {
+ if (!should_add_attribute_to_mesh(profile_attributes, mesh_attributes, id, meta_data)) {
return true;
}
const eAttrDomain src_domain = meta_data.domain;
diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc
index 01be22a57b0..61755a5be9b 100644
--- a/source/blender/blenkernel/intern/curves.cc
+++ b/source/blender/blenkernel/intern/curves.cc
@@ -287,7 +287,10 @@ static void curves_evaluate_modifiers(struct Depsgraph *depsgraph,
{
/* Modifier evaluation modes. */
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+ int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+ if (BKE_object_is_in_editmode(object)) {
+ required_mode = (ModifierMode)(int(required_mode) | eModifierMode_Editmode);
+ }
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
@@ -409,11 +412,11 @@ void curves_copy_parameters(const Curves &src, Curves &dst)
CurvesSurfaceTransforms::CurvesSurfaceTransforms(const Object &curves_ob, const Object *surface_ob)
{
- this->curves_to_world = curves_ob.obmat;
+ this->curves_to_world = curves_ob.object_to_world;
this->world_to_curves = this->curves_to_world.inverted();
if (surface_ob != nullptr) {
- this->surface_to_world = surface_ob->obmat;
+ this->surface_to_world = surface_ob->object_to_world;
this->world_to_surface = this->surface_to_world.inverted();
this->surface_to_curves = this->world_to_curves * this->surface_to_world;
this->curves_to_surface = this->world_to_surface * this->curves_to_world;
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index f5c845443f1..7c338480c71 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -9,6 +9,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array_utils.hh"
#include "BLI_bounds.hh"
#include "BLI_index_mask_ops.hh"
#include "BLI_length_parameterize.hh"
@@ -1111,21 +1112,11 @@ static void copy_between_buffers(const CPPType &type,
src_range.size());
}
-template<typename T>
-static void copy_with_map(const Span<T> src, const Span<int> map, MutableSpan<T> dst)
-{
- threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) {
- for (const int i : range) {
- dst[i] = src[map[i]];
- }
- });
-}
-
static void copy_with_map(const GSpan src, const Span<int> map, GMutableSpan dst)
{
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
- copy_with_map(src.typed<T>(), map, dst.typed<T>());
+ array_utils::gather(src.typed<T>(), map, dst.typed<T>());
});
}
@@ -1233,6 +1224,10 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves,
attribute.dst.finish();
}
+ if (new_curves.curves_num() != curves.curves_num()) {
+ new_curves.remove_attributes_based_on_types();
+ }
+
return new_curves;
}
@@ -1338,6 +1333,8 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
attribute.dst.finish();
}
+ new_curves.remove_attributes_based_on_types();
+
return new_curves;
}
@@ -1402,6 +1399,9 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse)
if (meta_data.domain != ATTR_DOMAIN_POINT) {
return true;
}
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
if (id.is_named() && bezier_handle_names.contains(id.name())) {
return true;
}
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 6f2390fc28f..03a0f17a4bb 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -19,6 +19,7 @@
#include "BLI_bitmap.h"
#include "BLI_color.hh"
+#include "BLI_cpp_type_make.hh"
#include "BLI_endian_switch.h"
#include "BLI_index_range.hh"
#include "BLI_math.h"
@@ -5387,6 +5388,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
return &CPPType::get<int8_t>();
case CD_PROP_BYTE_COLOR:
return &CPPType::get<ColorGeometry4b>();
+ case CD_PROP_STRING:
+ return &CPPType::get<MStringProperty>();
default:
return nullptr;
}
@@ -5419,6 +5422,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
if (type.is<ColorGeometry4b>()) {
return CD_PROP_BYTE_COLOR;
}
+ if (type.is<MStringProperty>()) {
+ return CD_PROP_STRING;
+ }
return static_cast<eCustomDataType>(-1);
}
@@ -5430,3 +5436,5 @@ size_t CustomData_get_elem_size(CustomDataLayer *layer)
{
return LAYERTYPEINFO[layer->type].size;
}
+
+BLI_CPP_TYPE_MAKE(MStringProperty, MStringProperty, CPPTypeFlags::None);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index e177250ae5a..b9cec17b6e0 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -3783,7 +3783,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
numOfVerts_p = mesh_p->totvert;
mvert_p = BKE_mesh_verts_for_write(mesh_p);
- copy_m4_m4(prev_obmat, ob->obmat);
+ copy_m4_m4(prev_obmat, ob->object_to_world);
/* current frame mesh */
scene->r.cfra = cur_fra;
@@ -3816,7 +3816,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
.brush_vel = *brushVel,
.mvert_p = mvert_p,
.mvert_c = mvert_c,
- .obmat = ob->obmat,
+ .obmat = ob->object_to_world,
.prev_obmat = prev_obmat,
.timescale = timescale,
};
@@ -3856,7 +3856,7 @@ static void dynamicPaint_brushObjectCalculateVelocity(
SUBFRAME_RECURSION,
BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
- copy_m4_m4(prev_obmat, ob->obmat);
+ copy_m4_m4(prev_obmat, ob->object_to_world);
/* current frame mesh */
scene->r.cfra = cur_fra;
@@ -3871,7 +3871,7 @@ static void dynamicPaint_brushObjectCalculateVelocity(
/* calculate speed */
mul_m4_v3(prev_obmat, prev_loc);
- mul_m4_v3(ob->obmat, cur_loc);
+ mul_m4_v3(ob->object_to_world, cur_loc);
sub_v3_v3v3(brushVel->v, cur_loc, prev_loc);
mul_v3_fl(brushVel->v, 1.0f / timescale);
@@ -4279,14 +4279,14 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
* (Faster than transforming per surface point
* coordinates and normals to object space) */
for (ii = 0; ii < numOfVerts; ii++) {
- mul_m4_v3(brushOb->obmat, mvert[ii].co);
+ mul_m4_v3(brushOb->object_to_world, mvert[ii].co);
boundInsert(&mesh_bb, mvert[ii].co);
/* for proximity project calculate average normal */
if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
float nor[3];
copy_v3_v3(nor, vert_normals[ii]);
- mul_mat3_m4_v3(brushOb->obmat, nor);
+ mul_mat3_m4_v3(brushOb->object_to_world, nor);
normalize_v3(nor);
add_v3_v3(avg_brushNor, nor);
@@ -5870,7 +5870,7 @@ static bool dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *o
}
/* matrix comparison */
- if (!equals_m4m4(bData->prev_obmat, ob->obmat)) {
+ if (!equals_m4m4(bData->prev_obmat, ob->object_to_world)) {
return true;
}
@@ -5957,7 +5957,7 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata,
mul_v3_v3v3(scaled_nor, temp_nor, ob->scale);
bData->bNormal[index].normal_scale = len_v3(scaled_nor);
}
- mul_mat3_m4_v3(ob->obmat, temp_nor);
+ mul_mat3_m4_v3(ob->object_to_world, temp_nor);
normalize_v3(temp_nor);
negate_v3_v3(bData->bNormal[index].invNorm, temp_nor);
}
@@ -5995,7 +5995,7 @@ static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata,
mul_v3_v3v3(scaled_nor, temp_nor, ob->scale);
bData->bNormal[index].normal_scale = len_v3(scaled_nor);
}
- mul_mat3_m4_v3(ob->obmat, temp_nor);
+ mul_mat3_m4_v3(ob->object_to_world, temp_nor);
normalize_v3(temp_nor);
negate_v3_v3(bData->bNormal[index].invNorm, temp_nor);
}
@@ -6113,7 +6113,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
bData->mesh_bounds.valid = false;
for (index = 0; index < canvasNumOfVerts; index++) {
copy_v3_v3(canvas_verts[index].v, mvert[index].co);
- mul_m4_v3(ob->obmat, canvas_verts[index].v);
+ mul_m4_v3(ob->object_to_world, canvas_verts[index].v);
boundInsert(&bData->mesh_bounds, canvas_verts[index].v);
}
@@ -6143,7 +6143,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
dynamicPaint_prepareAdjacencyData(surface, false);
/* Copy current frame vertices to check against in next frame */
- copy_m4_m4(bData->prev_obmat, ob->obmat);
+ copy_m4_m4(bData->prev_obmat, ob->object_to_world);
memcpy(bData->prev_verts, mvert, canvasNumOfVerts * sizeof(MVert));
bData->clear = 0;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 42b38854248..983e4b3c6e6 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -154,8 +154,8 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef
if (eff->ob->runtime.curve_cache->anim_path_accum_length) {
BKE_where_on_path(
eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
- mul_m4_v3(eff->ob->obmat, eff->guide_loc);
- mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
+ mul_m4_v3(eff->ob->object_to_world, eff->guide_loc);
+ mul_mat3_m4_v3(eff->ob->object_to_world, eff->guide_dir);
}
}
}
@@ -707,8 +707,8 @@ bool get_effector_data(EffectorCache *eff,
copy_v3_v3(efd->loc, verts[*efd->index].co);
copy_v3_v3(efd->nor, vert_normals[*efd->index]);
- mul_m4_v3(eff->ob->obmat, efd->loc);
- mul_mat3_m4_v3(eff->ob->obmat, efd->nor);
+ mul_m4_v3(eff->ob->object_to_world, efd->loc);
+ mul_mat3_m4_v3(eff->ob->object_to_world, efd->nor);
normalize_v3(efd->nor);
@@ -760,23 +760,23 @@ bool get_effector_data(EffectorCache *eff,
const Object *ob = eff->ob;
/* Use z-axis as normal. */
- normalize_v3_v3(efd->nor, ob->obmat[2]);
+ normalize_v3_v3(efd->nor, ob->object_to_world[2]);
if (eff->pd && ELEM(eff->pd->shape, PFIELD_SHAPE_PLANE, PFIELD_SHAPE_LINE)) {
float temp[3], translate[3];
- sub_v3_v3v3(temp, point->loc, ob->obmat[3]);
+ sub_v3_v3v3(temp, point->loc, ob->object_to_world[3]);
project_v3_v3v3(translate, temp, efd->nor);
/* for vortex the shape chooses between old / new force */
if (eff->pd->forcefield == PFIELD_VORTEX || eff->pd->shape == PFIELD_SHAPE_LINE) {
- add_v3_v3v3(efd->loc, ob->obmat[3], translate);
+ add_v3_v3v3(efd->loc, ob->object_to_world[3], translate);
}
else { /* normally efd->loc is closest point on effector xy-plane */
sub_v3_v3v3(efd->loc, point->loc, translate);
}
}
else {
- copy_v3_v3(efd->loc, ob->obmat[3]);
+ copy_v3_v3(efd->loc, ob->object_to_world[3]);
}
zero_v3(efd->vel);
@@ -801,8 +801,8 @@ bool get_effector_data(EffectorCache *eff,
}
else {
/* for some effectors we need the object center every time */
- sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
- normalize_v3_v3(efd->nor2, eff->ob->obmat[2]);
+ sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->object_to_world[3]);
+ normalize_v3_v3(efd->nor2, eff->ob->object_to_world[2]);
}
}
diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c
index 9f63e2d3743..3d1439b5530 100644
--- a/source/blender/blenkernel/intern/fcurve_driver.c
+++ b/source/blender/blenkernel/intern/fcurve_driver.c
@@ -321,7 +321,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
}
else {
/* Object. */
- mat[i] = ob->obmat;
+ mat[i] = ob->object_to_world;
}
}
@@ -399,7 +399,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
else {
/* Convert to world-space. */
copy_v3_v3(tmp_loc, pchan->pose_head);
- mul_m4_v3(ob->obmat, tmp_loc);
+ mul_m4_v3(ob->object_to_world, tmp_loc);
}
}
else {
@@ -410,7 +410,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
float mat[4][4];
/* Extract transform just like how the constraints do it! */
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
BKE_constraint_mat_convertspace(
ob, NULL, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
@@ -424,7 +424,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
}
else {
/* World-space. */
- copy_v3_v3(tmp_loc, ob->obmat[3]);
+ copy_v3_v3(tmp_loc, ob->object_to_world[3]);
}
}
@@ -500,7 +500,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
}
else {
/* World-space matrix. */
- mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat);
}
}
else {
@@ -514,7 +514,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* Just like how the constraints do it! */
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
BKE_constraint_mat_convertspace(
ob, NULL, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
}
@@ -525,7 +525,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
}
else {
/* World-space matrix - just the good-old one. */
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
}
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 5470231cd07..b0e99e10acc 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -433,7 +433,7 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds,
copy_v3_v3(fds->global_size, size);
copy_v3_v3(fds->dp0, min);
- invert_m4_m4(fds->imat, ob->obmat);
+ invert_m4_m4(fds->imat, ob->object_to_world);
/* Prevent crash when initializing a plane as domain. */
if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) ||
@@ -498,8 +498,8 @@ static bool fluid_modifier_init(
zero_v3(fds->shift_f);
add_v3_fl(fds->shift_f, 0.5f);
zero_v3(fds->prev_loc);
- mul_m4_v3(ob->obmat, fds->prev_loc);
- copy_m4_m4(fds->obmat, ob->obmat);
+ mul_m4_v3(ob->object_to_world, fds->prev_loc);
+ copy_m4_m4(fds->obmat, ob->object_to_world);
/* Set resolutions. */
if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS &&
@@ -566,11 +566,11 @@ static int get_light(Scene *scene, ViewLayer *view_layer, float *light)
Light *la = base_tmp->object->data;
if (la->type == LA_LOCAL) {
- copy_v3_v3(light, base_tmp->object->obmat[3]);
+ copy_v3_v3(light, base_tmp->object->object_to_world[3]);
return 1;
}
if (!found_light) {
- copy_v3_v3(light, base_tmp->object->obmat[3]);
+ copy_v3_v3(light, base_tmp->object->object_to_world[3]);
found_light = 1;
}
}
@@ -1036,7 +1036,7 @@ static void obstacles_from_mesh(Object *coll_ob,
float co[3];
/* Vertex position. */
- mul_m4_v3(coll_ob->obmat, verts[i].co);
+ mul_m4_v3(coll_ob->object_to_world, verts[i].co);
manta_pos_to_cell(fds, verts[i].co);
/* Vertex velocity. */
@@ -2099,11 +2099,11 @@ static void emit_from_mesh(
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(me);
for (i = 0; i < numverts; i++) {
/* Vertex position. */
- mul_m4_v3(flow_ob->obmat, verts[i].co);
+ mul_m4_v3(flow_ob->object_to_world, verts[i].co);
manta_pos_to_cell(fds, verts[i].co);
/* Vertex normal. */
- mul_mat3_m4_v3(flow_ob->obmat, vert_normals[i]);
+ mul_mat3_m4_v3(flow_ob->object_to_world, vert_normals[i]);
mul_mat3_m4_v3(fds->imat, vert_normals[i]);
normalize_v3(vert_normals[i]);
@@ -2121,7 +2121,7 @@ static void emit_from_mesh(
/* Calculate emission map bounds. */
bb_boundInsert(bb, verts[i].co);
}
- mul_m4_v3(flow_ob->obmat, flow_center);
+ mul_m4_v3(flow_ob->object_to_world, flow_center);
manta_pos_to_cell(fds, flow_center);
/* Set emission map.
@@ -2191,7 +2191,7 @@ static void adaptive_domain_adjust(
float frame_shift_f[3];
float ob_loc[3] = {0};
- mul_m4_v3(ob->obmat, ob_loc);
+ mul_m4_v3(ob->object_to_world, ob_loc);
sub_v3_v3v3(frame_shift_f, ob_loc, fds->prev_loc);
copy_v3_v3(fds->prev_loc, ob_loc);
@@ -3495,8 +3495,8 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
/* Calculate required shift to match domain's global position
* it was originally simulated at (if object moves without manta step). */
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->obmat, ob_loc);
+ invert_m4_m4(ob->imat, ob->object_to_world);
+ mul_m4_v3(ob->object_to_world, ob_loc);
mul_m4_v3(fds->obmat, ob_cache_loc);
sub_v3_v3v3(fds->obj_shift_f, ob_cache_loc, ob_loc);
/* Convert shift to local space and apply to vertices. */
@@ -3525,8 +3525,8 @@ static int manta_step(
bool mode_replay = (mode == FLUID_DOMAIN_CACHE_REPLAY);
/* Update object state. */
- invert_m4_m4(fds->imat, ob->obmat);
- copy_m4_m4(fds->obmat, ob->obmat);
+ invert_m4_m4(fds->imat, ob->object_to_world);
+ copy_m4_m4(fds->obmat, ob->object_to_world);
/* Gas domain might use adaptive domain. */
if (fds->type == FLUID_DOMAIN_TYPE_GAS) {
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 90568a8a080..ee4c398c3d6 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -607,7 +607,10 @@ void GeometrySet::gather_attributes_for_propagation(
return;
}
}
-
+ if (meta_data.data_type == CD_PROP_STRING) {
+ /* Propagating string attributes is not supported yet. */
+ return;
+ }
if (!attribute_id.should_be_kept()) {
return;
}
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index e078991187d..2b36020b4e7 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -98,7 +98,7 @@ static void geometry_set_collect_recursive_collection(const Collection &collecti
LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) {
BLI_assert(collection_object->ob != nullptr);
const Object &object = *collection_object->ob;
- const float4x4 object_transform = transform * object.obmat;
+ const float4x4 object_transform = transform * object.object_to_world;
geometry_set_collect_recursive_object(object, object_transform, r_sets);
}
LISTBASE_FOREACH (const CollectionChild *, collection_child, &collection.children) {
@@ -220,7 +220,7 @@ void Instances::ensure_geometry_instances()
Collection &collection = reference.collection();
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) {
const int handle = instances->add_reference(*object);
- instances->add_instance(handle, object->obmat);
+ instances->add_instance(handle, object->object_to_world);
float4x4 &transform = instances->transforms().last();
sub_v3_v3(transform.values[3], collection.instance_offset);
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 45e56717d6a..666142e3a54 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -2691,7 +2691,7 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
/* if not layer parented, try with object parented */
if (obparent_eval == NULL) {
if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) {
- copy_m4_m4(diff_mat, ob_eval->obmat);
+ copy_m4_m4(diff_mat, ob_eval->object_to_world);
mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
return;
}
@@ -2701,8 +2701,8 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
}
if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ mul_m4_m4m4(diff_mat, obparent_eval->object_to_world, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->object_to_world[3]);
mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
return;
}
@@ -2710,14 +2710,14 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
if (pchan) {
float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
+ mul_m4_m4m4(tmp_mat, obparent_eval->object_to_world, pchan->pose_mat);
mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ add_v3_v3(diff_mat[3], ob_eval->object_to_world[3]);
}
else {
/* if bone not found use object (armature) */
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ mul_m4_m4m4(diff_mat, obparent_eval->object_to_world, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->object_to_world[3]);
}
mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
return;
@@ -2771,12 +2771,12 @@ void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent);
/* calculate new matrix */
if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
- mul_m4_m4m4(cur_mat, ob->imat, ob_parent->obmat);
+ mul_m4_m4m4(cur_mat, ob->imat, ob_parent->object_to_world);
}
else if (gpl->partype == PARBONE) {
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr);
if (pchan != NULL) {
- mul_m4_series(cur_mat, ob->imat, ob_parent->obmat, pchan->pose_mat);
+ mul_m4_series(cur_mat, ob->imat, ob_parent->object_to_world, pchan->pose_mat);
}
else {
unit_m4(cur_mat);
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index 52fcdef8a43..9297663b157 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -789,7 +789,10 @@ bool BKE_gpencil_stroke_stretch(bGPDstroke *gps,
/** \name Stroke Trim
* \{ */
-bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const int index_to)
+bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps,
+ const int index_from,
+ const int index_to,
+ const bool keep_point)
{
bGPDspoint *pt = gps->points, *new_pt;
MDeformVert *dv, *new_dv;
@@ -800,7 +803,7 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
return false;
}
- if (new_count == 1) {
+ if ((!keep_point) && (new_count == 1)) {
if (gps->dvert) {
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->dvert);
@@ -894,7 +897,7 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
/* Trim the original stroke into a shorter one.
* Keep the end point. */
- BKE_gpencil_stroke_trim_points(gps, 0, old_count);
+ BKE_gpencil_stroke_trim_points(gps, 0, old_count, false);
BKE_gpencil_stroke_geometry_update(gpd, gps);
return true;
}
@@ -917,7 +920,7 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo
if (gps->totpoints == 1) {
second_last = &pt[1];
if (len_v3v3(&second_last->x, &pt->x) < dist) {
- BKE_gpencil_stroke_trim_points(gps, 0, 0);
+ BKE_gpencil_stroke_trim_points(gps, 0, 0, false);
return true;
}
}
@@ -969,7 +972,7 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo
index_start = index_end = 0; /* no length left to cut */
}
- BKE_gpencil_stroke_trim_points(gps, index_start, index_end);
+ BKE_gpencil_stroke_trim_points(gps, index_start, index_end, false);
if (gps->totpoints == 0) {
return false;
@@ -3562,8 +3565,8 @@ void BKE_gpencil_stroke_start_set(bGPDstroke *gps, int start_idx)
}
bGPDstroke *gps_b = BKE_gpencil_stroke_duplicate(gps, true, false);
- BKE_gpencil_stroke_trim_points(gps_b, 0, start_idx - 1);
- BKE_gpencil_stroke_trim_points(gps, start_idx, gps->totpoints - 1);
+ BKE_gpencil_stroke_trim_points(gps_b, 0, start_idx - 1, true);
+ BKE_gpencil_stroke_trim_points(gps, start_idx, gps->totpoints - 1, true);
/* Join both strokes. */
BKE_gpencil_stroke_join(gps, gps_b, false, false, false, false);
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index c84ee2e4a56..1ad7aeed41c 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -942,7 +942,7 @@ void BKE_gpencil_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
BLO_read_data_address(reader, &gpmd->curve_intensity);
if (gpmd->curve_intensity) {
BKE_curvemapping_blend_read(reader, gpmd->curve_intensity);
- /* initialize the curve. Maybe this could be moved to modififer logic */
+ /* Initialize the curve. Maybe this could be moved to modifier logic. */
BKE_curvemapping_init(gpmd->curve_intensity);
}
}
diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc
index dc1d23de7e0..7fd0515b52c 100644
--- a/source/blender/blenkernel/intern/icons.cc
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -530,7 +530,7 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
thumb = IMB_thumb_manage(filepath, THB_LARGE, (ThumbSource)source);
if (thumb) {
- /* PreviewImage assumes premultiplied alhpa... */
+ /* #PreviewImage assumes pre-multiplied alpha. */
IMB_premultiply_alpha(thumb);
if (do_preview) {
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index 51d8f02616f..eae8b454189 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -3082,16 +3082,10 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
/* Free all but the first tile. */
image_remove_all_tiles(ima);
- /* If the remaining tile is generated, we need to again ensure that we
- * wouldn't continue to use the old filepath.
- *
- * Otherwise, if this used to be a UDIM image, get the concrete filepath associated
+ /* If this used to be a UDIM image, get the concrete filepath associated
* with the remaining tile and use that as the new filepath. */
ImageTile *base_tile = BKE_image_get_tile(ima, 0);
- if ((base_tile->gen_flag & IMA_GEN_TILE) != 0) {
- ima->filepath[0] = '\0';
- }
- else if (BKE_image_is_filename_tokenized(ima->filepath)) {
+ if (BKE_image_is_filename_tokenized(ima->filepath)) {
const bool was_relative = BLI_path_is_rel(ima->filepath);
eUDIM_TILE_FORMAT tile_format;
@@ -3183,10 +3177,14 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
* left. */
image_remove_all_tiles(ima);
- int remaining_tile_number = ((ImageTile *)ima->tiles.first)->tile_number;
+ ImageTile *base_tile = BKE_image_get_tile(ima, 0);
+ int remaining_tile_number = base_tile->tile_number;
bool needs_final_cleanup = true;
- /* Add in all the new tiles. */
+ /* Add in all the new tiles. As the image is proven to be on disk at this point, remove
+ * the generation flag from the remaining tile in case this was previously a generated
+ * image. */
+ base_tile->gen_flag &= ~IMA_GEN_TILE;
LISTBASE_FOREACH (LinkData *, new_tile, &new_tiles) {
int new_tile_number = POINTER_AS_INT(new_tile->data);
BKE_image_add_tile(ima, new_tile_number, nullptr);
@@ -3202,6 +3200,11 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
}
BLI_freelistN(&new_tiles);
}
+ else if (ima->filepath[0] != '\0') {
+ /* If the filepath is set at this point remove the generation flag. */
+ ImageTile *base_tile = BKE_image_get_tile(ima, 0);
+ base_tile->gen_flag &= ~IMA_GEN_TILE;
+ }
if (iuser) {
image_tag_reload(ima, nullptr, iuser, ima);
diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc
index 8d1aeac76fb..5b861eff166 100644
--- a/source/blender/blenkernel/intern/image_format.cc
+++ b/source/blender/blenkernel/intern/image_format.cc
@@ -201,6 +201,7 @@ bool BKE_imtype_is_movie(const char imtype)
case R_IMF_IMTYPE_H264:
case R_IMF_IMTYPE_THEORA:
case R_IMF_IMTYPE_XVID:
+ case R_IMF_IMTYPE_AV1:
return true;
}
return false;
@@ -433,7 +434,8 @@ static bool do_add_image_extension(char *string,
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_THEORA,
- R_IMF_IMTYPE_XVID)) {
+ R_IMF_IMTYPE_XVID,
+ R_IMF_IMTYPE_AV1)) {
if (!BLI_path_extension_check(string, extension_test = ".png")) {
extension = extension_test;
}
@@ -627,7 +629,8 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf)
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_THEORA,
- R_IMF_IMTYPE_XVID)) {
+ R_IMF_IMTYPE_XVID,
+ R_IMF_IMTYPE_AV1)) {
ibuf->ftype = IMB_FTYPE_PNG;
if (imtype == R_IMF_IMTYPE_PNG) {
diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc
index 4e47e71fb2b..003211e6288 100644
--- a/source/blender/blenkernel/intern/image_save.cc
+++ b/source/blender/blenkernel/intern/image_save.cc
@@ -968,6 +968,7 @@ bool BKE_image_render_write(ReportList *reports,
/* optional preview images for exr */
if (ok && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
image_format.imtype = R_IMF_IMTYPE_JPEG90;
+ image_format.depth = R_IMF_CHAN_DEPTH_8;
if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0;
@@ -1025,6 +1026,7 @@ bool BKE_image_render_write(ReportList *reports,
/* optional preview images for exr */
if (ok && is_exr_rr && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
image_format.imtype = R_IMF_IMTYPE_JPEG90;
+ image_format.depth = R_IMF_CHAN_DEPTH_8;
if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0;
diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc
index dd759453630..4675562e927 100644
--- a/source/blender/blenkernel/intern/instances.cc
+++ b/source/blender/blenkernel/intern/instances.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_cpp_type_make.hh"
#include "BLI_rand.hh"
#include "BLI_task.hh"
@@ -107,18 +108,6 @@ blender::Span<InstanceReference> Instances::references() const
return references_;
}
-template<typename T>
-static void copy_data_based_on_mask(Span<T> src, MutableSpan<T> dst, IndexMask mask)
-{
- BLI_assert(src.data() != dst.data());
- using namespace blender;
- threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) {
- for (const int i : range) {
- dst[i] = src[mask[i]];
- }
- });
-}
-
void Instances::remove(const IndexMask mask)
{
using namespace blender;
@@ -129,11 +118,14 @@ void Instances::remove(const IndexMask mask)
return;
}
+ const Span<int> old_handles = this->reference_handles();
Vector<int> new_handles(mask.size());
- copy_data_based_on_mask<int>(this->reference_handles(), new_handles, mask);
+ array_utils::gather(old_handles, mask.indices(), new_handles.as_mutable_span());
reference_handles_ = std::move(new_handles);
+
+ const Span<float4x4> old_tansforms = this->transforms();
Vector<float4x4> new_transforms(mask.size());
- copy_data_based_on_mask<float4x4>(this->transforms(), new_transforms, mask);
+ array_utils::gather(old_tansforms, mask.indices(), new_transforms.as_mutable_span());
transforms_ = std::move(new_transforms);
const bke::CustomDataAttributes &src_attributes = attributes_;
@@ -150,11 +142,8 @@ void Instances::remove(const IndexMask mask)
GSpan src = *src_attributes.get_for_read(id);
dst_attributes.create(id, meta_data.data_type);
GMutableSpan dst = *dst_attributes.get_for_write(id);
+ array_utils::gather(src, mask.indices(), dst);
- attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
- using T = decltype(dummy);
- copy_data_based_on_mask<T>(src.typed<T>(), dst.typed<T>(), mask);
- });
return true;
},
ATTR_DOMAIN_INSTANCE);
@@ -266,7 +255,7 @@ bool Instances::owns_direct_data() const
void Instances::ensure_owns_direct_data()
{
for (const InstanceReference &const_reference : references_) {
- /* Const cast is fine because we are not changing anything that would change the hash of the
+ /* `const` cast is fine because we are not changing anything that would change the hash of the
* reference. */
InstanceReference &reference = const_cast<InstanceReference &>(const_reference);
reference.ensure_owns_direct_data();
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index bd655caae2b..a21033a8b91 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1147,7 +1147,7 @@ static char *get_rna_access(ID *id,
/* 'buf' _must_ be initialized in this block */
/* append preceding bits to path */
- /* NOTE: strings are not escapted and they should be! */
+ /* NOTE: strings are not escaped and they should be! */
if ((actname && actname[0]) && (constname && constname[0])) {
/* Constraint in Pose-Channel */
char actname_esc[sizeof(((bActionChannel *)NULL)->name) * 2];
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index f6a409ee3f0..0adf162b4eb 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -355,10 +355,10 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
BKE_displist_free(&ltOb->runtime.curve_cache->disp);
}
- copy_m4_m4(mat, ltOb->obmat);
- unit_m4(ltOb->obmat);
+ copy_m4_m4(mat, ltOb->object_to_world);
+ unit_m4(ltOb->object_to_world);
BKE_lattice_deform_coords(ltOb, NULL, vert_coords, uNew * vNew * wNew, 0, NULL, 1.0f);
- copy_m4_m4(ltOb->obmat, mat);
+ copy_m4_m4(ltOb->object_to_world, mat);
lt->typeu = typeu;
lt->typev = typev;
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
index 3a1c42b9178..892889aa426 100644
--- a/source/blender/blenkernel/intern/lattice_deform.c
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -79,15 +79,15 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob
/* for example with a particle system: (ob == NULL) */
if (ob == NULL) {
/* In deform-space, calc matrix. */
- invert_m4_m4(latmat, oblatt->obmat);
+ invert_m4_m4(latmat, oblatt->object_to_world);
/* back: put in deform array */
invert_m4_m4(imat, latmat);
}
else {
/* In deform-space, calc matrix. */
- invert_m4_m4(imat, oblatt->obmat);
- mul_m4_m4m4(latmat, imat, ob->obmat);
+ invert_m4_m4(imat, oblatt->object_to_world);
+ mul_m4_m4m4(latmat, imat, ob->object_to_world);
/* back: put in deform array. */
invert_m4_m4(imat, latmat);
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 06d69b6ff61..5b54f16661c 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -614,7 +614,7 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc)
return true;
}
- /* Check visiblilty restriction flags */
+ /* Check visibility restriction flags */
if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_HIDE_VIEWPORT) {
return true;
}
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 158aaa961ce..f60234a684d 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1612,7 +1612,7 @@ static void library_make_local_copying_check(ID *id,
if (!BLI_gset_haskey(done_ids, from_id)) {
if (BLI_gset_haskey(loop_tags, from_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
+ * Note that this is the situation that can lead to archipelagos 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...). */
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index f4f5ca7a1d7..c7643c56212 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -16,6 +16,7 @@
#include "BLI_utildefines.h"
+#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BKE_anim_data.h"
@@ -23,10 +24,10 @@
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_remap.h"
-#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_main_namemap.h"
@@ -202,7 +203,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
{
const int tag = LIB_TAG_DOIT;
ListBase *lbarray[INDEX_ID_MAX];
- 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,
@@ -217,6 +217,9 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
BKE_main_lock(bmain);
if (do_tagged_deletion) {
+ struct IDRemapper *id_remapper = BKE_id_remapper_create();
+ BKE_layer_collection_resync_forbid();
+
/* 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.
@@ -227,7 +230,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
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.
@@ -243,6 +245,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
BLI_remlink(lb, id);
BKE_main_namemap_remove_name(bmain, id, id->name + 2);
BLI_addtail(&tagged_deleted_ids, id);
+ BKE_id_remapper_add(id_remapper, id, NULL);
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
* code has some specific handling of 'no main' IDs that would be a problem in that
* case). */
@@ -251,33 +254,38 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
}
}
}
- 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: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
- * 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 |
- ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS));
- /* 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,
- (ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR));
- }
+
+ /* Will tag 'never NULL' users of this ID too.
+ *
+ * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
+ * 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_multiple_locked(bmain,
+ id_remapper,
+ ID_REMAP_FLAG_NEVER_NULL_USAGE |
+ ID_REMAP_FORCE_NEVER_NULL_USAGE |
+ ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS);
+ BKE_id_remapper_clear(id_remapper);
+ }
+
+ /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */
+ LinkNode *cleanup_ids = NULL;
+ for (ID *id = tagged_deleted_ids.first; id; id = id->next) {
+ BLI_linklist_prepend(&cleanup_ids, id);
}
+ BKE_libblock_relink_multiple(bmain,
+ cleanup_ids,
+ ID_REMAP_TYPE_CLEANUP,
+ id_remapper,
+ ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS |
+ ID_REMAP_SKIP_USER_CLEAR);
+
+ BKE_id_remapper_free(id_remapper);
+ BLI_linklist_free(cleanup_ids, NULL);
+
+ BKE_layer_collection_resync_allow();
+ BKE_main_collection_sync_remap(bmain);
/* Now we can safely mark that ID as not being in Main database anymore. */
/* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of
@@ -285,10 +293,14 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
* is never affected). */
for (ID *id = tagged_deleted_ids.first; id; id = id->next) {
id->tag |= LIB_TAG_NO_MAIN;
+ /* User-count needs to be reset artificially, since some usages may not be cleared in batch
+ * deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by
+ * remapping code, depending on order in which these are handled). */
+ id->us = ID_FAKE_USERS(id);
}
}
else {
- /* First tag all datablocks directly from target lib.
+ /* First tag all data-blocks 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. */
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 55834d5cf4e..adc0eb5f78c 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -521,7 +521,7 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size)
}
if (1) {
- /* now convert linknodes into arrays for faster per pixel access */
+ /* Now convert link-nodes into arrays for faster per pixel access. */
uint **buckets_face = MEM_mallocN(bucket_tot * sizeof(*buckets_face), __func__);
uint bucket_index;
@@ -1186,7 +1186,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
// printf("tris %d, feather tris %d\n", sf_tri_tot, tot_feather_quads);
}
- /* add trianges */
+ /* Add triangles. */
BLI_scanfill_end_arena(&sf_ctx, sf_arena);
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 6c6d2298dbd..59530a6d6a6 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -1450,7 +1450,7 @@ static bool fill_texpaint_slots_cb(bNode *node, void *userdata)
NodeTexImage *storage = (NodeTexImage *)node->storage;
slot->interp = storage->interpolation;
slot->image_user = &storage->iuser;
- /* for new renderer, we need to traverse the treeback in search of a UV node */
+ /* For new renderer, we need to traverse the tree back in search of a UV node. */
bNode *uvnode = nodetree_uv_node_recursive(node);
if (uvnode) {
@@ -1512,58 +1512,65 @@ static ePaintSlotFilter material_paint_slot_filter(const struct Object *ob)
void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const struct Object *ob)
{
- int count = 0;
-
if (!ma) {
return;
}
const ePaintSlotFilter slot_filter = material_paint_slot_filter(ob);
- /* COW needed when adding texture slot on an object with no materials. */
- DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE);
+ const TexPaintSlot *prev_texpaintslot = ma->texpaintslot;
+ const int prev_paint_active_slot = ma->paint_active_slot;
+ const int prev_paint_clone_slot = ma->paint_clone_slot;
+ const int prev_tot_slots = ma->tot_slots;
- if (ma->texpaintslot) {
- MEM_freeN(ma->texpaintslot);
- ma->tot_slots = 0;
- ma->texpaintslot = NULL;
- }
+ ma->texpaintslot = NULL;
+ ma->tot_slots = 0;
if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
- return;
}
-
- if (!(ma->nodetree)) {
+ else if (!(ma->nodetree)) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
- return;
}
+ else {
+ int count = count_texture_nodes_recursive(ma->nodetree, slot_filter);
- count = count_texture_nodes_recursive(ma->nodetree, slot_filter);
-
- if (count == 0) {
- ma->paint_active_slot = 0;
- ma->paint_clone_slot = 0;
- return;
- }
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ }
+ else {
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
- ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+ bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree);
- bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree);
+ fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter);
- fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter);
+ ma->tot_slots = count;
- ma->tot_slots = count;
+ if (ma->paint_active_slot >= count) {
+ ma->paint_active_slot = count - 1;
+ }
- if (ma->paint_active_slot >= count) {
- ma->paint_active_slot = count - 1;
+ if (ma->paint_clone_slot >= count) {
+ ma->paint_clone_slot = count - 1;
+ }
+ }
}
- if (ma->paint_clone_slot >= count) {
- ma->paint_clone_slot = count - 1;
+ /* COW needed when adding texture slot on an object with no materials.
+ * But do it only when slots actually change to avoid continuous depsgraph updates. */
+ if (ma->tot_slots != prev_tot_slots || ma->paint_active_slot != prev_paint_active_slot ||
+ ma->paint_clone_slot != prev_paint_clone_slot ||
+ (ma->texpaintslot && prev_texpaintslot &&
+ memcmp(ma->texpaintslot, prev_texpaintslot, sizeof(*ma->texpaintslot) * ma->tot_slots) !=
+ 0)) {
+ DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE);
}
+
+ MEM_SAFE_FREE(prev_texpaintslot);
}
void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob)
diff --git a/source/blender/blenkernel/intern/mball_tessellate.cc b/source/blender/blenkernel/intern/mball_tessellate.cc
index bb3713e770a..f8a64a7cd8b 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.cc
+++ b/source/blender/blenkernel/intern/mball_tessellate.cc
@@ -1188,8 +1188,9 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
const eEvaluationMode deg_eval_mode = DEG_get_mode(depsgraph);
const short parenting_dupli_transflag = (OB_DUPLIFACES | OB_DUPLIVERTS);
- copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from BKE_scene_base_iter_next */
- invert_m4_m4(obinv, ob->obmat);
+ copy_m4_m4(obmat,
+ ob->object_to_world); /* to cope with duplicators from BKE_scene_base_iter_next */
+ invert_m4_m4(obinv, ob->object_to_world);
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
@@ -1237,13 +1238,13 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
/* when metaball object has zero scale, then MetaElem to this MetaBall
* will not be put to mainb array */
- if (has_zero_axis_m4(bob->obmat)) {
+ if (has_zero_axis_m4(bob->object_to_world)) {
zero_size = 1;
}
else if (bob->parent) {
struct Object *pob = bob->parent;
while (pob) {
- if (has_zero_axis_m4(pob->obmat)) {
+ if (has_zero_axis_m4(pob->object_to_world)) {
zero_size = 1;
break;
}
@@ -1307,7 +1308,7 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
* rotation ->
* ml local space
*/
- mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot);
+ mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->object_to_world, pos, rot);
/* ml local space -> basis object space */
invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index 027423f5774..784d35a8d65 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -1313,6 +1313,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly);
CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop);
+ const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert;
mesh_dst->totvert = mesh_src->totvert;
mesh_dst->totedge = mesh_src->totedge;
mesh_dst->totpoly = mesh_src->totpoly;
@@ -1339,11 +1340,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1;
move_shapekey_layers_to_keyblocks(*mesh_dst, mesh_src->vdata, *key_dst, uid_active);
}
- else if (mesh_src->totvert != mesh_dst->totvert) {
- CLOG_ERROR(&LOG, "Mesh in Main '%s' lost shape keys", mesh_src->id.name);
- if (mesh_src->key) {
- id_us_min(&mesh_src->key->id);
- }
+ else if (verts_num_changed) {
+ CLOG_WARN(&LOG, "Shape key data lost when replacing mesh '%s' in Main", mesh_src->id.name);
+ id_us_min(&mesh_dst->key->id);
+ mesh_dst->key = nullptr;
}
}
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index 261bc3d150b..ce3fc5d99c8 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -152,8 +152,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* tmp is a transform from coords relative to the object's own origin,
* to coords relative to the mirror object origin */
- invert_m4_m4(tmp, mirror_ob->obmat);
- mul_m4_m4m4(tmp, tmp, ob->obmat);
+ invert_m4_m4(tmp, mirror_ob->object_to_world);
+ mul_m4_m4m4(tmp, tmp, ob->object_to_world);
/* itmp is the reverse transform back to origin-relative coordinates */
invert_m4_m4(itmp, tmp);
@@ -169,9 +169,9 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* Account for non-uniform scale in `ob`, see: T87592. */
float ob_scale[3] = {
- len_squared_v3(ob->obmat[0]),
- len_squared_v3(ob->obmat[1]),
- len_squared_v3(ob->obmat[2]),
+ len_squared_v3(ob->object_to_world[0]),
+ len_squared_v3(ob->object_to_world[1]),
+ len_squared_v3(ob->object_to_world[2]),
};
/* Scale to avoid precision loss with extreme values. */
const float ob_scale_max = max_fff(UNPACK3(ob_scale));
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index ba63cdff917..c0aff204069 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -464,6 +464,7 @@ NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_libo
*/
nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
+ BLI_strncpy(nlt->name, act->id.name + 2, sizeof(nlt->name));
}
/* automatically name it too */
@@ -1918,7 +1919,7 @@ bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride)
* NOTE: this must be done *after* adding the strip to the track, or else
* the strip locking will prevent the strip from getting added
*/
- nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED);
+ nlt->flag |= (NLATRACK_MUTED | NLATRACK_PROTECTED);
strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
/* also mark the strip for auto syncing the length, so that the strips accurately
@@ -2054,7 +2055,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
/* If block is already in tweak-mode, just leave, but we should report
- * that this block is in tweak-mode (as our returncode). */
+ * that this block is in tweak-mode (as our return-code). */
if (adt->flag & ADT_NLA_EDIT_ON) {
return true;
}
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 8028f990c42..8f8cd02e119 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -516,10 +516,6 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
write_node_socket(writer, sock);
}
- LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
- BLO_write_struct(writer, bNodeLink, link);
- }
-
if (node->storage) {
if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) &&
ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB, SH_NODE_CURVE_FLOAT)) {
@@ -703,13 +699,7 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
BLO_read_data_address(reader, &node->prop);
IDP_BlendDataRead(reader, &node->prop);
- BLO_read_list(reader, &node->internal_links);
- LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
- BLO_read_data_address(reader, &link->fromnode);
- BLO_read_data_address(reader, &link->fromsock);
- BLO_read_data_address(reader, &link->tonode);
- BLO_read_data_address(reader, &link->tosock);
- }
+ BLI_listbase_clear(&node->internal_links);
if (node->type == CMP_NODE_MOVIEDISTORTION) {
/* Do nothing, this is runtime cache and hence handled by generic code using
@@ -2032,21 +2022,29 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
{
*r_node = nullptr;
+ if (!ntree->runtime->topology_cache_is_dirty) {
+ bNode *node = &sock->owner_node();
+ *r_node = node;
+ if (r_sockindex) {
+ ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
+ *r_sockindex = BLI_findindex(sockets, sock);
+ }
+ return true;
+ }
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
- int index = 0;
- LISTBASE_FOREACH (bNodeSocket *, tsock, sockets) {
+ int i;
+ LISTBASE_FOREACH_INDEX (bNodeSocket *, tsock, sockets, i) {
if (sock == tsock) {
if (r_node != nullptr) {
*r_node = node;
}
if (r_sockindex != nullptr) {
- *r_sockindex = index;
+ *r_sockindex = i;
}
return true;
}
- index++;
}
}
return false;
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 2d949fb5c65..53e6d47860f 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -1330,14 +1330,14 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
/* Calculate the world-space matrix for the pose-channel target first,
* then carry on as usual. */
- mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat, hmd->object->object_to_world, pchan->pose_mat);
invert_m4_m4(imat, mat);
- mul_m4_m4m4(hmd->parentinv, imat, ob->obmat);
+ mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world);
}
else {
- invert_m4_m4(hmd->object->imat, hmd->object->obmat);
- mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat);
+ invert_m4_m4(hmd->object->imat, hmd->object->object_to_world);
+ mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->object_to_world);
}
}
}
@@ -1355,14 +1355,14 @@ void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData
/* Calculate the world-space matrix for the pose-channel target first,
* then carry on as usual. */
- mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat, hmd->object->object_to_world, pchan->pose_mat);
invert_m4_m4(imat, mat);
- mul_m4_m4m4(hmd->parentinv, imat, ob->obmat);
+ mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world);
}
else {
- invert_m4_m4(hmd->object->imat, hmd->object->obmat);
- mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat);
+ invert_m4_m4(hmd->object->imat, hmd->object->object_to_world);
+ mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->object_to_world);
}
}
@@ -1902,6 +1902,7 @@ bool BKE_object_is_in_editmode(const Object *ob)
/* Grease Pencil object has no edit mode data. */
return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
case OB_CURVES:
+ /* Curves object has no edit mode data. */
return ob->mode == OB_MODE_EDIT;
default:
return false;
@@ -3101,10 +3102,10 @@ void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4])
BKE_object_get_parent_matrix(ob, ob->parent, par_imat);
invert_m4(par_imat);
- mul_m4_m4m4(r_mat, par_imat, ob->obmat);
+ mul_m4_m4m4(r_mat, par_imat, ob->object_to_world);
}
else {
- copy_m4_m4(r_mat, ob->obmat);
+ copy_m4_m4(r_mat, ob->object_to_world);
}
}
@@ -3358,32 +3359,32 @@ void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][
}
if (ok) {
- mul_m4_m4m4(r_parentmat, par->obmat, tmat);
+ mul_m4_m4m4(r_parentmat, par->object_to_world, tmat);
}
else {
- copy_m4_m4(r_parentmat, par->obmat);
+ copy_m4_m4(r_parentmat, par->object_to_world);
}
break;
}
case PARBONE:
ob_parbone(ob, par, tmat);
- mul_m4_m4m4(r_parentmat, par->obmat, tmat);
+ mul_m4_m4m4(r_parentmat, par->object_to_world, tmat);
break;
case PARVERT1:
unit_m4(r_parentmat);
give_parvert(par, ob->par1, vec);
- mul_v3_m4v3(r_parentmat[3], par->obmat, vec);
+ mul_v3_m4v3(r_parentmat[3], par->object_to_world, vec);
break;
case PARVERT3:
ob_parvert3(ob, par, tmat);
- mul_m4_m4m4(r_parentmat, par->obmat, tmat);
+ mul_m4_m4m4(r_parentmat, par->object_to_world, tmat);
break;
case PARSKEL:
- copy_m4_m4(r_parentmat, par->obmat);
+ copy_m4_m4(r_parentmat, par->object_to_world);
break;
}
}
@@ -3421,7 +3422,7 @@ static void solve_parenting(
/* origin, for help line */
if (set_origin) {
if ((ob->partype & PARTYPE) == PARSKEL) {
- copy_v3_v3(ob->runtime.parent_display_origin, par->obmat[3]);
+ copy_v3_v3(ob->runtime.parent_display_origin, par->object_to_world[3]);
}
else {
copy_v3_v3(ob->runtime.parent_display_origin, totmat[3]);
@@ -3440,10 +3441,10 @@ static void object_where_is_calc_ex(Depsgraph *depsgraph,
Object *par = ob->parent;
/* calculate parent matrix */
- solve_parenting(ob, par, true, ob->obmat, r_originmat);
+ solve_parenting(ob, par, true, ob->object_to_world, r_originmat);
}
else {
- BKE_object_to_mat4(ob, ob->obmat);
+ BKE_object_to_mat4(ob, ob->object_to_world);
}
/* try to fall back to the scene rigid body world if none given */
@@ -3460,7 +3461,7 @@ static void object_where_is_calc_ex(Depsgraph *depsgraph,
}
/* set negative scale flag in object */
- if (is_negative_m4(ob->obmat)) {
+ if (is_negative_m4(ob->object_to_world)) {
ob->transflag |= OB_NEG_SCALE;
}
else {
@@ -3506,7 +3507,7 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o
{
BKE_object_workob_clear(workob);
- unit_m4(workob->obmat);
+ unit_m4(workob->object_to_world);
unit_m4(workob->parentinv);
unit_m4(workob->constinv);
@@ -3598,7 +3599,7 @@ void BKE_object_apply_parent_inverse(struct Object *ob)
* `inv(parent) @ world = parentinv`
* `parentinv = inv(parent) @ world`
*
- * NOTE: If `ob->obmat` has shear, then this `parentinv` is insufficient because
+ * NOTE: If `ob->object_to_world` has shear, then this `parentinv` is insufficient because
* `parent @ parentinv => shearless result`
*
* Thus, local will have shear which cannot be decomposed into TRS:
@@ -3627,7 +3628,7 @@ void BKE_object_apply_parent_inverse(struct Object *ob)
copy_m4_m4(ob_local, ob->parentinv);
invert_m4(ob_local);
mul_m4_m4_post(ob_local, par_imat);
- mul_m4_m4_post(ob_local, ob->obmat);
+ mul_m4_m4_post(ob_local, ob->object_to_world);
/* Send use_compat=False so the rotation is predictable. */
BKE_object_apply_mat4(ob, ob_local, false, false);
@@ -3792,7 +3793,7 @@ void BKE_object_dimensions_get(Object *ob, float r_vec[3])
const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
float3 scale;
- mat4_to_size(scale, ob->obmat);
+ mat4_to_size(scale, ob->object_to_world);
r_vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
r_vec[1] = fabsf(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]);
@@ -3849,19 +3850,19 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
case OB_FONT:
case OB_SURF: {
const BoundBox bb = *BKE_curve_boundbox_get(ob);
- BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
+ BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
changed = true;
break;
}
case OB_MESH: {
const BoundBox bb = *BKE_mesh_boundbox_get(ob);
- BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
+ BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
changed = true;
break;
}
case OB_GPENCIL: {
const BoundBox bb = *BKE_gpencil_boundbox_get(ob);
- BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
+ BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
changed = true;
break;
}
@@ -3874,7 +3875,7 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
for (v = 0; v < lt->pntsv; v++) {
for (u = 0; u < lt->pntsu; u++, bp++) {
float3 vec;
- mul_v3_m4v3(vec, ob->obmat, bp->vec);
+ mul_v3_m4v3(vec, ob->object_to_world, bp->vec);
minmax_v3v3_v3(r_min, r_max, vec);
}
}
@@ -3889,7 +3890,8 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
case OB_MBALL: {
float ob_min[3], ob_max[3];
- changed = BKE_mball_minmax_ex((const MetaBall *)ob->data, ob_min, ob_max, ob->obmat, 0);
+ changed = BKE_mball_minmax_ex(
+ (const MetaBall *)ob->data, ob_min, ob_max, ob->object_to_world, 0);
if (changed) {
minmax_v3v3_v3(r_min, r_max, ob_min);
minmax_v3v3_v3(r_min, r_max, ob_max);
@@ -3898,20 +3900,20 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
}
case OB_CURVES: {
const BoundBox bb = *BKE_curves_boundbox_get(ob);
- BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
+ BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
changed = true;
break;
}
case OB_POINTCLOUD: {
const BoundBox bb = *BKE_pointcloud_boundbox_get(ob);
- BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
+ BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
changed = true;
break;
}
case OB_VOLUME: {
const BoundBox bb = *BKE_volume_boundbox_get(ob);
- BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
+ BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
changed = true;
break;
}
@@ -3925,14 +3927,14 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
size *= ob->empty_drawsize;
}
- minmax_v3v3_v3(r_min, r_max, ob->obmat[3]);
+ minmax_v3v3_v3(r_min, r_max, ob->object_to_world[3]);
float3 vec;
- copy_v3_v3(vec, ob->obmat[3]);
+ copy_v3_v3(vec, ob->object_to_world[3]);
add_v3_v3(vec, size);
minmax_v3v3_v3(r_min, r_max, vec);
- copy_v3_v3(vec, ob->obmat[3]);
+ copy_v3_v3(vec, ob->object_to_world[3]);
sub_v3_v3(vec, size);
minmax_v3v3_v3(r_min, r_max, vec);
}
@@ -3979,12 +3981,12 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
* however the issue with empty objects being visible when viewed from the side
* is only noticeable in orthographic views. */
float3 view_dir;
- sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->obmat[3]);
- dot = dot_v3v3(ob->obmat[2], view_dir);
+ sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->object_to_world[3]);
+ dot = dot_v3v3(ob->object_to_world[2], view_dir);
eps = 0.0f;
}
else {
- dot = dot_v3v3(ob->obmat[2], rv3d->viewinv[2]);
+ dot = dot_v3v3(ob->object_to_world[2], rv3d->viewinv[2]);
eps = 1e-5f;
}
if (visibility_flag & OB_EMPTY_IMAGE_HIDE_BACK) {
@@ -4001,7 +4003,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) {
float3 proj, ob_z_axis;
- normalize_v3_v3(ob_z_axis, ob->obmat[2]);
+ normalize_v3_v3(ob_z_axis, ob->object_to_world[2]);
project_plane_v3_v3v3(proj, ob_z_axis, rv3d->viewinv[2]);
const float proj_length_sq = len_squared_v3(proj);
if (proj_length_sq > 1e-5f) {
@@ -4193,7 +4195,7 @@ void BKE_scene_foreach_display_point(Depsgraph *depsgraph,
DEG_ITER_OBJECT_FLAG_DUPLI;
DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
if ((ob->base_flag & BASE_SELECTED) != 0) {
- BKE_object_foreach_display_point(ob, ob->obmat, func_cb, user_data);
+ BKE_object_foreach_display_point(ob, ob->object_to_world, func_cb, user_data);
}
}
DEG_OBJECT_ITER_END;
@@ -4236,7 +4238,7 @@ void *BKE_object_tfm_backup(Object *ob)
copy_v3_v3(obtfm->drotAxis, ob->drotAxis);
obtfm->rotAngle = ob->rotAngle;
obtfm->drotAngle = ob->drotAngle;
- copy_m4_m4(obtfm->obmat, ob->obmat);
+ copy_m4_m4(obtfm->obmat, ob->object_to_world);
copy_m4_m4(obtfm->parentinv, ob->parentinv);
copy_m4_m4(obtfm->constinv, ob->constinv);
copy_m4_m4(obtfm->imat, ob->imat);
@@ -4259,7 +4261,7 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
copy_v3_v3(ob->drotAxis, obtfm->drotAxis);
ob->rotAngle = obtfm->rotAngle;
ob->drotAngle = obtfm->drotAngle;
- copy_m4_m4(ob->obmat, obtfm->obmat);
+ copy_m4_m4(ob->object_to_world, obtfm->obmat);
copy_m4_m4(ob->parentinv, obtfm->parentinv);
copy_m4_m4(ob->constinv, obtfm->constinv);
copy_m4_m4(ob->imat, obtfm->imat);
@@ -5290,7 +5292,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
for (i = 0; i < verts.size(); i++) {
if (index[i] != ORIGINDEX_NONE) {
float co[3];
- mul_v3_m4v3(co, ob->obmat, verts[i].co);
+ mul_v3_m4v3(co, ob->object_to_world, verts[i].co);
BLI_kdtree_3d_insert(tree, index[i], co);
tot++;
}
@@ -5304,7 +5306,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
for (i = 0; i < tot; i++) {
float co[3];
- mul_v3_m4v3(co, ob->obmat, verts[i].co);
+ mul_v3_m4v3(co, ob->object_to_world, verts[i].co);
BLI_kdtree_3d_insert(tree, i, co);
}
}
@@ -5333,7 +5335,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
a = nu->pntsu;
while (a--) {
float co[3];
- mul_v3_m4v3(co, ob->obmat, bezt->vec[1]);
+ mul_v3_m4v3(co, ob->object_to_world, bezt->vec[1]);
BLI_kdtree_3d_insert(tree, i++, co);
bezt++;
}
@@ -5345,7 +5347,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
a = nu->pntsu * nu->pntsv;
while (a--) {
float co[3];
- mul_v3_m4v3(co, ob->obmat, bp->vec);
+ mul_v3_m4v3(co, ob->object_to_world, bp->vec);
BLI_kdtree_3d_insert(tree, i++, co);
bp++;
}
@@ -5368,7 +5370,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
for (bp = lt->def; i < tot; bp++) {
float co[3];
- mul_v3_m4v3(co, ob->obmat, bp->vec);
+ mul_v3_m4v3(co, ob->object_to_world, bp->vec);
BLI_kdtree_3d_insert(tree, i++, co);
}
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index d43eff6f9b4..d029d307d6e 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -197,7 +197,8 @@ static bool copy_dupli_context(DupliContext *r_ctx,
/**
* Generate a dupli instance.
*
- * \param mat: is transform of the object relative to current context (including #Object.obmat).
+ * \param mat: is transform of the object relative to current context (including
+ * #Object.object_to_world).
*/
static DupliObject *make_dupli(const DupliContext *ctx,
Object *ob,
@@ -296,7 +297,7 @@ static DupliObject *make_dupli(const DupliContext *ctx,
/**
* Recursive dupli-objects.
*
- * \param space_mat: is the local dupli-space (excluding dupli #Object.obmat).
+ * \param space_mat: is the local dupli-space (excluding dupli #Object.object_to_world).
*/
static void make_recursive_duplis(const DupliContext *ctx,
Object *ob,
@@ -468,8 +469,8 @@ static void make_duplis_collection(const DupliContext *ctx)
/* Combine collection offset and `obmat`. */
unit_m4(collection_mat);
sub_v3_v3(collection_mat[3], collection->instance_offset);
- mul_m4_m4m4(collection_mat, ob->obmat, collection_mat);
- /* Don't access 'ob->obmat' from now on. */
+ mul_m4_m4m4(collection_mat, ob->object_to_world, collection_mat);
+ /* Don't access 'ob->object_to_world' from now on. */
eEvaluationMode mode = DEG_get_mode(ctx->depsgraph);
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, cob, mode) {
@@ -477,7 +478,7 @@ static void make_duplis_collection(const DupliContext *ctx)
float mat[4][4];
/* Collection dupli-offset, should apply after everything else. */
- mul_m4_m4m4(mat, collection_mat, cob->obmat);
+ mul_m4_m4m4(mat, collection_mat, cob->object_to_world);
make_dupli(ctx, cob, mat, _base_id);
@@ -584,7 +585,7 @@ static DupliObject *vertex_dupli(const DupliContext *ctx,
/* Make offset relative to inst_ob using relative child transform. */
mul_mat3_m4_v3(child_imat, obmat[3]);
/* Apply `obmat` _after_ the local vertex transform. */
- mul_m4_m4m4(obmat, inst_ob->obmat, obmat);
+ mul_m4_m4m4(obmat, inst_ob->object_to_world, obmat);
/* Space matrix is constructed by removing `obmat` transform,
* this yields the world-space transform for recursive duplis. */
@@ -608,10 +609,10 @@ static void make_child_duplis_verts_from_mesh(const DupliContext *ctx,
const MVert *mvert = vdd->mvert;
const int totvert = vdd->totvert;
- invert_m4_m4(inst_ob->imat, inst_ob->obmat);
+ invert_m4_m4(inst_ob->imat, inst_ob->object_to_world);
/* Relative transform from parent to child space. */
float child_imat[4][4];
- mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);
+ mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world);
for (int i = 0; i < totvert; i++) {
DupliObject *dob = vertex_dupli(
@@ -630,10 +631,10 @@ static void make_child_duplis_verts_from_editmesh(const DupliContext *ctx,
BMEditMesh *em = vdd->em;
const bool use_rotation = vdd->params.use_rotation;
- invert_m4_m4(inst_ob->imat, inst_ob->obmat);
+ invert_m4_m4(inst_ob->imat, inst_ob->object_to_world);
/* Relative transform from parent to child space. */
float child_imat[4][4];
- mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);
+ mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world);
BMVert *v;
BMIter iter;
@@ -758,7 +759,7 @@ static void make_duplis_font(const DupliContext *ctx)
return;
}
- copy_m4_m4(pmat, par->obmat);
+ copy_m4_m4(pmat, par->object_to_world);
/* In `par` the family name is stored, use this to find the other objects. */
@@ -803,7 +804,7 @@ static void make_duplis_font(const DupliContext *ctx)
mul_m4_v3(pmat, vec);
- copy_m4_m4(obmat, par->obmat);
+ copy_m4_m4(obmat, par->object_to_world);
if (UNLIKELY(ct->rot != 0.0f)) {
float rmat[4][4];
@@ -951,7 +952,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx,
}
float instance_matrix[4][4];
- mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat);
+ mul_m4_m4m4(instance_matrix, collection_matrix, object->object_to_world);
make_dupli(&sub_ctx, object, instance_matrix, object_id++);
make_recursive_duplis(&sub_ctx, object, collection_matrix, object_id++);
@@ -986,7 +987,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx,
static void make_duplis_geometry_set(const DupliContext *ctx)
{
const GeometrySet *geometry_set = ctx->object->runtime.geometry_set_eval;
- make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->obmat, false, false);
+ make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->object_to_world, false, false);
}
static const DupliGenerator gen_dupli_geometry_set = {
@@ -1092,7 +1093,7 @@ static DupliObject *face_dupli(const DupliContext *ctx,
}
/* Apply `obmat` _after_ the local face transform. */
- mul_m4_m4m4(obmat, inst_ob->obmat, obmat);
+ mul_m4_m4m4(obmat, inst_ob->object_to_world, obmat);
/* Space matrix is constructed by removing `obmat` transform,
* this yields the world-space transform for recursive duplis. */
@@ -1176,9 +1177,9 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
float child_imat[4][4];
- invert_m4_m4(inst_ob->imat, inst_ob->obmat);
+ invert_m4_m4(inst_ob->imat, inst_ob->object_to_world);
/* Relative transform from parent to child space. */
- mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);
+ mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world);
const float scale_fac = ctx->object->instance_faces_scale;
for (a = 0, mp = mpoly; a < totface; a++, mp++) {
@@ -1216,9 +1217,9 @@ static void make_child_duplis_faces_from_editmesh(const DupliContext *ctx,
BLI_assert((vert_coords == nullptr) || (em->bm->elem_index_dirty & BM_VERT) == 0);
- invert_m4_m4(inst_ob->imat, inst_ob->obmat);
+ invert_m4_m4(inst_ob->imat, inst_ob->object_to_world);
/* Relative transform from parent to child space. */
- mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat);
+ mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->object_to_world);
const float scale_fac = ctx->object->instance_faces_scale;
BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, a) {
@@ -1348,7 +1349,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
sim.psys = psys;
sim.psmd = psys_get_modifier(par, psys);
/* Make sure emitter `imat` is in global coordinates instead of render view coordinates. */
- invert_m4_m4(par->imat, par->obmat);
+ invert_m4_m4(par->imat, par->object_to_world);
/* First check for loops (particle system object used as dupli-object). */
if (part->ren_as == PART_DRAW_OB) {
@@ -1535,7 +1536,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
b = 0;
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (
part->instance_collection, object, mode) {
- copy_m4_m4(tmat, oblist[b]->obmat);
+ copy_m4_m4(tmat, oblist[b]->object_to_world);
/* Apply collection instance offset. */
sub_v3_v3(tmat[3], part->instance_collection->instance_offset);
@@ -1558,7 +1559,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
else {
float obmat[4][4];
- copy_m4_m4(obmat, ob->obmat);
+ copy_m4_m4(obmat, ob->object_to_world);
float vec[3];
copy_v3_v3(vec, obmat[3]);
@@ -1752,7 +1753,7 @@ ListBase *object_duplilist_preview(Depsgraph *depsgraph,
*viewer_path)) {
ctx.preview_base_geometry = &viewer_log->geometry;
make_duplis_geometry_set_impl(
- &ctx, viewer_log->geometry, ob_eval->obmat, true, ob_eval->type == OB_CURVES);
+ &ctx, viewer_log->geometry, ob_eval->object_to_world, true, ob_eval->type == OB_CURVES);
}
}
return duplilist;
diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc
index ceef6404bf0..7ea13bfcc84 100644
--- a/source/blender/blenkernel/intern/object_update.cc
+++ b/source/blender/blenkernel/intern/object_update.cc
@@ -61,7 +61,7 @@ void BKE_object_eval_local_transform(Depsgraph *depsgraph, Object *ob)
DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
/* calculate local matrix */
- BKE_object_to_mat4(ob, ob->obmat);
+ BKE_object_to_mat4(ob, ob->object_to_world);
}
void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob)
@@ -78,18 +78,18 @@ void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob)
/* get local matrix (but don't calculate it, as that was done already!) */
/* XXX: redundant? */
- copy_m4_m4(locmat, ob->obmat);
+ copy_m4_m4(locmat, ob->object_to_world);
/* get parent effect matrix */
BKE_object_get_parent_matrix(ob, par, totmat);
/* total */
mul_m4_m4m4(tmat, totmat, ob->parentinv);
- mul_m4_m4m4(ob->obmat, tmat, locmat);
+ mul_m4_m4m4(ob->object_to_world, tmat, locmat);
/* origin, for help line */
if ((ob->partype & PARTYPE) == PARSKEL) {
- copy_v3_v3(ob->runtime.parent_display_origin, par->obmat[3]);
+ copy_v3_v3(ob->runtime.parent_display_origin, par->object_to_world[3]);
}
else {
copy_v3_v3(ob->runtime.parent_display_origin, totmat[3]);
@@ -121,9 +121,9 @@ void BKE_object_eval_transform_final(Depsgraph *depsgraph, Object *ob)
DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
/* Make sure inverse matrix is always up to date. This way users of it
* do not need to worry about recalculating it. */
- invert_m4_m4_safe(ob->imat, ob->obmat);
+ invert_m4_m4_safe(ob->imat, ob->object_to_world);
/* Set negative scale flag in object. */
- if (is_negative_m4(ob->obmat)) {
+ if (is_negative_m4(ob->object_to_world)) {
ob->transflag |= OB_NEG_SCALE;
}
else {
@@ -257,7 +257,7 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object)
/* Base flags. */
object_orig->base_flag = object->base_flag;
/* Transformation flags. */
- copy_m4_m4(object_orig->obmat, object->obmat);
+ copy_m4_m4(object_orig->object_to_world, object->object_to_world);
copy_m4_m4(object_orig->imat, object->imat);
copy_m4_m4(object_orig->constinv, object->constinv);
object_orig->transflag = object->transflag;
@@ -292,6 +292,8 @@ void BKE_object_batch_cache_dirty_tag(Object *ob)
BKE_lattice_batch_cache_dirty_tag((struct Lattice *)ob->data, BKE_LATTICE_BATCH_DIRTY_ALL);
break;
case OB_CURVES_LEGACY:
+ case OB_SURF:
+ case OB_FONT:
BKE_curve_batch_cache_dirty_tag((struct Curve *)ob->data, BKE_CURVE_BATCH_DIRTY_ALL);
break;
case OB_MBALL: {
diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc
index 13243925b28..a39e53662aa 100644
--- a/source/blender/blenkernel/intern/paint.cc
+++ b/source/blender/blenkernel/intern/paint.cc
@@ -1043,6 +1043,8 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode)
return OB_MODE_TEXTURE_PAINT;
case PAINT_MODE_SCULPT_UV:
return OB_MODE_EDIT;
+ case PAINT_MODE_SCULPT_CURVES:
+ return OB_MODE_SCULPT_CURVES;
case PAINT_MODE_INVALID:
default:
return OB_MODE_OBJECT;
@@ -1199,7 +1201,7 @@ void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3])
mul_v3_v3fl(stroke, ups->average_stroke_accum, fac);
}
else {
- copy_v3_v3(stroke, ob->obmat[3]);
+ copy_v3_v3(stroke, ob->object_to_world[3]);
}
}
@@ -2314,7 +2316,7 @@ void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
&key);
}
-bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D * /*v3d*/)
+bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
{
SculptSession *ss = ob->sculpt;
if (ss == nullptr || ss->pbvh == nullptr || ss->mode_type != OB_MODE_SCULPT) {
@@ -2322,9 +2324,10 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D * /*v3d*/)
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
- /* Regular mesh only draws from PBVH without modifiers and shape keys. */
-
- return !(ss->shapekey_active || ss->deform_modifiers_active);
+ /* Regular mesh only draws from PBVH without modifiers and shape keys, or for
+ * external engines that do not have access to the PBVH like Eevee does. */
+ const bool external_engine = rv3d && rv3d->render_engine != nullptr;
+ return !(ss->shapekey_active || ss->deform_modifiers_active || external_engine);
}
/* Multires and dyntopo always draw directly from the PBVH. */
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index d6dd3cf0dbb..f111e2dde17 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -2370,8 +2370,8 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
0,
0);
- mul_m4_v3(sim->ob->obmat, state.co);
- mul_mat3_m4_v3(sim->ob->obmat, state.vel);
+ mul_m4_v3(sim->ob->object_to_world, state.co);
+ mul_mat3_m4_v3(sim->ob->object_to_world, state.vel);
pd_point_from_particle(sim, pa, &state, &point);
@@ -2454,8 +2454,8 @@ bool do_guides(Depsgraph *depsgraph,
}
}
- mul_m4_v3(eff->ob->obmat, guidevec);
- mul_mat3_m4_v3(eff->ob->obmat, guidedir);
+ mul_m4_v3(eff->ob->object_to_world, guidevec);
+ mul_mat3_m4_v3(eff->ob->object_to_world, guidedir);
normalize_v3(guidedir);
@@ -2956,7 +2956,7 @@ static void psys_thread_create_path(ParticleTask *task,
psys_particle_on_emitter(
ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco);
- mul_m4_v3(ob->obmat, co);
+ mul_m4_v3(ob->object_to_world, co);
for (w = 0; w < 4; w++) {
sub_v3_v3v3(off1[w], co, key[w]->co);
@@ -3419,7 +3419,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
/* dynamic hair is in object space */
/* keyed and baked are already in global space */
if (hair_mesh) {
- mul_m4_v3(sim->ob->obmat, ca->co);
+ mul_m4_v3(sim->ob->object_to_world, ca->co);
}
else if (!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) {
mul_m4_v3(hairmat, ca->co);
@@ -3929,7 +3929,7 @@ void psys_mat_hair_to_global(
psys_mat_hair_to_object(ob, mesh, from, pa, facemat);
- mul_m4_m4m4(hairmat, ob->obmat, facemat);
+ mul_m4_m4m4(hairmat, ob->object_to_world, facemat);
}
/************************************************/
@@ -4661,8 +4661,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
do_particle_interpolation(psys, p, pa, t, &pind, state);
if (pind.mesh) {
- mul_m4_v3(sim->ob->obmat, state->co);
- mul_mat3_m4_v3(sim->ob->obmat, state->vel);
+ mul_m4_v3(sim->ob->object_to_world, state->co);
+ mul_mat3_m4_v3(sim->ob->object_to_world, state->vel);
}
else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
if ((pa->flag & PARS_REKEY) == 0) {
@@ -4685,7 +4685,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
}
}
else if (totchild) {
- // invert_m4_m4(imat, ob->obmat);
+ // invert_m4_m4(imat, ob->object_to_world);
/* interpolate childcache directly if it exists */
if (psys->childcache) {
@@ -4733,7 +4733,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
* positioning it accurately to the surface of the emitter. */
// copy_v3_v3(cpa_1st, co);
- // mul_m4_v3(ob->obmat, cpa_1st);
+ // mul_m4_v3(ob->object_to_world, cpa_1st);
pa = psys->particles + cpa->parent;
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index a890812cfc4..6cc7dbc70d0 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -187,7 +187,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx,
zero_v3(kink_base);
kink_base[part->kink_axis] = 1.0f;
- mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base);
+ mul_mat3_m4_v3(ctx->sim.ob->object_to_world, kink_base);
/* Fill in invariant part of modifier context. */
ParticleChildModifierContext modifier_ctx = {NULL};
@@ -873,7 +873,7 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx,
part->kink_flat,
part->kink,
part->kink_axis,
- sim->ob->obmat,
+ sim->ob->object_to_world,
smooth_start);
}
}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index c72bbe2fd08..7317318e828 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -750,10 +750,10 @@ void psys_get_birth_coords(
/* particles live in global space so */
/* let's convert: */
/* -location */
- mul_m4_v3(ob->obmat, loc);
+ mul_m4_v3(ob->object_to_world, loc);
/* -normal */
- mul_mat3_m4_v3(ob->obmat, nor);
+ mul_mat3_m4_v3(ob->object_to_world, nor);
normalize_v3(nor);
/* -tangent */
@@ -771,7 +771,7 @@ void psys_get_birth_coords(
fac = -sinf((float)M_PI * (part->tanphase + phase));
madd_v3_v3fl(vtan, utan, fac);
- mul_mat3_m4_v3(ob->obmat, vtan);
+ mul_mat3_m4_v3(ob->object_to_world, vtan);
copy_v3_v3(utan, nor);
mul_v3_fl(utan, dot_v3v3(vtan, nor));
@@ -786,7 +786,7 @@ void psys_get_birth_coords(
r_vel[1] = 2.0f * (psys_frand(psys, p + 11) - 0.5f);
r_vel[2] = 2.0f * (psys_frand(psys, p + 12) - 0.5f);
- mul_mat3_m4_v3(ob->obmat, r_vel);
+ mul_mat3_m4_v3(ob->object_to_world, r_vel);
normalize_v3(r_vel);
}
@@ -796,7 +796,7 @@ void psys_get_birth_coords(
r_ave[1] = 2.0f * (psys_frand(psys, p + 14) - 0.5f);
r_ave[2] = 2.0f * (psys_frand(psys, p + 15) - 0.5f);
- mul_mat3_m4_v3(ob->obmat, r_ave);
+ mul_mat3_m4_v3(ob->object_to_world, r_ave);
normalize_v3(r_ave);
}
@@ -808,7 +808,7 @@ void psys_get_birth_coords(
r_rot[3] = 2.0f * (psys_frand(psys, p + 19) - 0.5f);
normalize_qt(r_rot);
- mat4_to_quat(rot, ob->obmat);
+ mat4_to_quat(rot, ob->object_to_world);
mul_qt_qtqt(r_rot, r_rot, rot);
}
@@ -822,7 +822,7 @@ void psys_get_birth_coords(
/* boids store direction in ave */
if (fabsf(nor[2]) == 1.0f) {
- sub_v3_v3v3(state->ave, loc, ob->obmat[3]);
+ sub_v3_v3v3(state->ave, loc, ob->object_to_world[3]);
normalize_v3(state->ave);
}
else {
@@ -868,15 +868,15 @@ void psys_get_birth_coords(
/* *emitter object orientation */
if (part->ob_vel[0] != 0.0f) {
- normalize_v3_v3(vec, ob->obmat[0]);
+ normalize_v3_v3(vec, ob->object_to_world[0]);
madd_v3_v3fl(vel, vec, part->ob_vel[0]);
}
if (part->ob_vel[1] != 0.0f) {
- normalize_v3_v3(vec, ob->obmat[1]);
+ normalize_v3_v3(vec, ob->object_to_world[1]);
madd_v3_v3fl(vel, vec, part->ob_vel[1]);
}
if (part->ob_vel[2] != 0.0f) {
- normalize_v3_v3(vec, ob->obmat[2]);
+ normalize_v3_v3(vec, ob->object_to_world[2]);
madd_v3_v3fl(vel, vec, part->ob_vel[2]);
}
@@ -924,7 +924,7 @@ void psys_get_birth_coords(
case PART_ROT_OB_X:
case PART_ROT_OB_Y:
case PART_ROT_OB_Z:
- copy_v3_v3(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]);
+ copy_v3_v3(rot_vec, ob->object_to_world[part->rotmode - PART_ROT_OB_X]);
use_global_space = false;
break;
default:
@@ -951,7 +951,7 @@ void psys_get_birth_coords(
float q_obmat[4];
float q_imat[4];
- mat4_to_quat(q_obmat, ob->obmat);
+ mat4_to_quat(q_obmat, ob->object_to_world);
invert_qt_qt_normalized(q_imat, q_obmat);
if (part->rotmode != PART_ROT_NOR_TAN) {
@@ -1639,7 +1639,7 @@ static void sph_springs_modify(ParticleSystem *psys, float dtime)
}
}
- /* Loop through springs backwaqrds - for efficient delete function */
+ /* Loop through springs backwards - for efficient delete function. */
for (i = psys->tot_fluidsprings - 1; i >= 0; i--) {
if (psys->fluid_springs[i].delete_flag) {
sph_spring_delete(psys, i);
@@ -3364,7 +3364,7 @@ static void hair_create_input_mesh(ParticleSimulationData *sim,
use_hair = psys_hair_use_simulation(pa, max_length);
psys_mat_hair_to_object(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
- mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
+ mul_m4_m4m4(root_mat, sim->ob->object_to_world, hairmat);
normalize_m4(root_mat);
bending_stiffness = CLAMPIS(
@@ -3555,7 +3555,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
HairKey *key, *root;
PARTICLE_P;
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
@@ -4380,7 +4380,7 @@ static void particles_fluid_step(ParticleSimulationData *sim,
mul_v3_v3(pa->state.co, scaleAbs);
/* Match domain scale. */
- mul_m4_v3(ob->obmat, pa->state.co);
+ mul_m4_v3(ob->object_to_world, pa->state.co);
/* Add origin offset to particle position. */
zero_v3(tmp);
@@ -4764,7 +4764,7 @@ void particle_system_update(struct Depsgraph *depsgraph,
float cfra;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- /* drawdata is outdated after ANY change */
+ /* Draw data is outdated after ANY change. */
if (psys->pdd) {
psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
}
@@ -4963,7 +4963,7 @@ void particle_system_update(struct Depsgraph *depsgraph,
/* Save matrix for duplicators,
* at render-time the actual dupli-object's matrix is used so don't update! */
- invert_m4_m4(psys->imat, ob->obmat);
+ invert_m4_m4(psys->imat, ob->object_to_world);
BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index ac98bed2cf0..868cdde6d01 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1317,7 +1317,7 @@ static int ptcache_path(PTCacheID *pid, char *dirname)
BLI_path_abs(dirname, blendfilename);
}
- return BLI_path_slash_ensure(dirname); /* new strlen() */
+ return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */
}
if ((blendfile_path[0] != '\0') || lib) {
char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
@@ -1334,14 +1334,14 @@ static int ptcache_path(PTCacheID *pid, char *dirname)
BLI_snprintf(dirname, MAX_PTCACHE_PATH, "//" PTCACHE_PATH "%s", file);
BLI_path_abs(dirname, blendfilename);
- return BLI_path_slash_ensure(dirname); /* new strlen() */
+ return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */
}
/* use the temp path. this is weak but better than not using point cache at all */
/* temporary directory is assumed to exist and ALWAYS has a trailing slash */
BLI_snprintf(dirname, MAX_PTCACHE_PATH, "%s" PTCACHE_PATH, BKE_tempdir_session());
- return BLI_path_slash_ensure(dirname); /* new strlen() */
+ return BLI_path_slash_ensure(dirname, MAX_PTCACHE_FILE); /* new strlen() */
}
static size_t ptcache_filepath_ext_append(PTCacheID *pid,
@@ -2611,7 +2611,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra)
}
#endif
- /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
+ /* Clear all files in the temp dir with the prefix of the ID and the `.bphys` suffix. */
switch (mode) {
case PTCACHE_CLEAR_ALL:
case PTCACHE_CLEAR_BEFORE:
@@ -2775,7 +2775,7 @@ void BKE_ptcache_id_time(
/* time handling for point cache:
* - simulation time is scaled by result of bsystem_time
* - for offsetting time only time offset is taken into account, since
- * that's always the same and can't be animated. a timeoffset which
+ * that's always the same and can't be animated. a time-offset which
* varies over time is not simple to support.
* - field and motion blur offsets are currently ignored, proper solution
* is probably to interpolate results from two frames for that ..
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index ffc6bc8d7a3..5e91b23bce3 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -264,13 +264,13 @@ static RigidBodyCon *rigidbody_copy_constraint(const Object *ob, const int UNUSE
RigidBodyCon *rbcN = NULL;
if (ob->rigidbody_constraint) {
- /* just duplicate the whole struct first (to catch all the settings) */
+ /* Just duplicate the whole struct first (to catch all the settings). */
rbcN = MEM_dupallocN(ob->rigidbody_constraint);
- /* tag object as needing to be verified */
+ /* Tag object as needing to be verified. */
rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE;
- /* clear out all the fields which need to be revalidated later */
+ /* Clear out all the fields which need to be re-validated later. */
rbcN->physics_constraint = NULL;
}
@@ -684,7 +684,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
if (totvert > 0 && tottri > 0) {
BKE_mesh_calc_volume(mvert, totvert, lt, tottri, mloop, &volume, NULL);
- const float volume_scale = mat4_to_volume_scale(ob->obmat);
+ const float volume_scale = mat4_to_volume_scale(ob->object_to_world);
volume *= fabsf(volume_scale);
}
}
@@ -809,7 +809,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
return;
}
- mat4_to_loc_quat(loc, rot, ob->obmat);
+ mat4_to_loc_quat(loc, rot, ob->object_to_world);
rbo->shared->physics_object = RB_body_new(rbo->shared->physics_shape, loc, rot);
@@ -974,7 +974,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
rbc->physics_constraint = NULL;
}
- mat4_to_loc_quat(loc, rot, ob->obmat);
+ mat4_to_loc_quat(loc, rot, ob->object_to_world);
if (rb1 && rb2) {
switch (rbc->type) {
@@ -1266,7 +1266,7 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
rbo->mesh_source = RBO_MESH_DEFORM;
/* set initial transform */
- mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
+ mat4_to_loc_quat(rbo->pos, rbo->orn, ob->object_to_world);
/* flag cache as outdated */
BKE_rigidbody_cache_reset(rbw);
@@ -1689,7 +1689,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Object *ob, RigidBodyO
if (!(rbo->flag & RBO_FLAG_KINEMATIC)) {
/* update scale for all non kinematic objects */
float new_scale[3], old_scale[3];
- mat4_to_size(new_scale, ob->obmat);
+ mat4_to_size(new_scale, ob->object_to_world);
RB_body_get_scale(rbo->shared->physics_object, old_scale);
/* Avoid updating collision shape AABBs if scale didn't change. */
@@ -1886,7 +1886,7 @@ static ListBase rigidbody_create_substep_data(RigidBodyWorld *rbw)
copy_v4_v4(data->old_rot, rot);
copy_v3_v3(data->old_scale, scale);
- mat4_decompose(loc, rot, scale, ob->obmat);
+ mat4_decompose(loc, rot, scale, ob->object_to_world);
copy_v3_v3(data->new_pos, loc);
copy_v4_v4(data->new_rot, rot);
@@ -2055,15 +2055,15 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
quat_to_mat4(mat, rbo->orn);
copy_v3_v3(mat[3], rbo->pos);
- mat4_to_size(size, ob->obmat);
+ mat4_to_size(size, ob->object_to_world);
size_to_mat4(size_mat, size);
mul_m4_m4m4(mat, mat, size_mat);
- copy_m4_m4(ob->obmat, mat);
+ copy_m4_m4(ob->object_to_world, mat);
}
/* otherwise set rigid body transform to current obmat */
else {
- mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
+ mat4_to_loc_quat(rbo->pos, rbo->orn, ob->object_to_world);
}
}
diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc
index bd26075f81f..c921cf603de 100644
--- a/source/blender/blenkernel/intern/scene.cc
+++ b/source/blender/blenkernel/intern/scene.cc
@@ -2278,13 +2278,13 @@ int BKE_scene_base_iter_next(
if (iter->dupli_refob != *ob) {
if (iter->dupli_refob) {
/* Restore previous object's real matrix. */
- copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ copy_m4_m4(iter->dupli_refob->object_to_world, iter->omat);
}
/* Backup new object's real matrix. */
iter->dupli_refob = *ob;
- copy_m4_m4(iter->omat, iter->dupli_refob->obmat);
+ copy_m4_m4(iter->omat, iter->dupli_refob->object_to_world);
}
- copy_m4_m4((*ob)->obmat, iter->dupob->mat);
+ copy_m4_m4((*ob)->object_to_world, iter->dupob->mat);
iter->dupob = iter->dupob->next;
}
@@ -2294,7 +2294,7 @@ int BKE_scene_base_iter_next(
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
- copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ copy_m4_m4(iter->dupli_refob->object_to_world, iter->omat);
iter->dupli_refob = nullptr;
}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 3e5dbc47c40..2c896788b20 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -304,7 +304,7 @@ IDTypeInfo IDType_ID_SCR = {
/* ************ Space-type/region-type handling ************** */
-/* keep global; this has to be accessible outside of windowmanager */
+/** Keep global; this has to be accessible outside of window-manager. */
static ListBase spacetypes = {NULL, NULL};
/* not SpaceType itself */
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 14a7d26a354..4147999bef8 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -133,9 +133,9 @@ typedef struct SB_thread_context {
#define BSF_INTERSECT 1 /* edge intersects collider face */
-/* private definitions for bodypoint states */
-#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy. */
-#define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide. */
+/* private definitions for body-point states */
+#define SBF_DOFUZZY 1 /* Body-point do fuzzy. */
+#define SBF_OUTOFCOLLISION 2 /* Body-point does not collide. */
#define BFF_INTERSECT 1 /* collider edge intrudes face. */
#define BFF_CLOSEVERT 2 /* collider vertex repulses face. */
@@ -318,7 +318,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
/* OBBs for idea1 */
pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax) * pccd_M->tri_num, "ccd_Mesh_Faces_mima");
- /* anyhoo we need to walk the list of faces and find OBB they live in */
+ /* Anyhow we need to walk the list of faces and find OBB they live in. */
for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
const float *v;
@@ -413,7 +413,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
}
- /* anyhoo we need to walk the list of faces and find OBB they live in */
+ /* Anyhow we need to walk the list of faces and find OBB they live in. */
for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
const float *v;
@@ -2644,7 +2644,7 @@ static void springs_from_mesh(Object *ob)
bp = ob->soft->bpoint;
for (a = 0; a < me->totvert; a++, bp++) {
copy_v3_v3(bp->origS, verts[a].co);
- mul_m4_v3(ob->obmat, bp->origS);
+ mul_m4_v3(ob->object_to_world, bp->origS);
}
}
/* recalculate spring length for meshes here */
@@ -2809,9 +2809,9 @@ static float globallen(float *v1, float *v2, Object *ob)
{
float p1[3], p2[3];
copy_v3_v3(p1, v1);
- mul_m4_v3(ob->obmat, p1);
+ mul_m4_v3(ob->object_to_world, p1);
copy_v3_v3(p2, v2);
- mul_m4_v3(ob->obmat, p2);
+ mul_m4_v3(ob->object_to_world, p2);
return len_v3v3(p1, p2);
}
@@ -3073,7 +3073,7 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts,
SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale);
}
/* Inverse matrix is not up to date. */
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
for (a = 0; a < numVerts; a++, bp++) {
copy_v3_v3(vertexCos[a], bp->pos);
@@ -3223,7 +3223,7 @@ static void softbody_update_positions(Object *ob,
/* copy the position of the goals at desired end time */
copy_v3_v3(bp->origE, vertexCos[a]);
/* vertexCos came from local world, go global */
- mul_m4_v3(ob->obmat, bp->origE);
+ mul_m4_v3(ob->object_to_world, bp->origE);
/* just to be save give bp->origT a defined value
* will be calculated in interpolate_exciter() */
copy_v3_v3(bp->origT, bp->origE);
@@ -3279,7 +3279,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int
for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) {
copy_v3_v3(bp->pos, vertexCos[a]);
- mul_m4_v3(ob->obmat, bp->pos); /* Yep, soft-body is global coords. */
+ mul_m4_v3(ob->object_to_world, bp->pos); /* Yep, soft-body is global coords. */
copy_v3_v3(bp->origS, bp->pos);
copy_v3_v3(bp->origE, bp->pos);
copy_v3_v3(bp->origT, bp->pos);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index d08fba0e657..1aef42ef037 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -1129,9 +1129,9 @@ static void sound_update_base(Scene *scene, Object *object, void *new_set)
AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
- mat4_to_quat(quat, object->obmat);
+ mat4_to_quat(quat, object->object_to_world);
AUD_SequenceEntry_setAnimationData(
- strip->speaker_handle, AUD_AP_LOCATION, scene->r.cfra, object->obmat[3], 1);
+ strip->speaker_handle, AUD_AP_LOCATION, scene->r.cfra, object->object_to_world[3], 1);
AUD_SequenceEntry_setAnimationData(
strip->speaker_handle, AUD_AP_ORIENTATION, scene->r.cfra, quat, 1);
AUD_SequenceEntry_setAnimationData(
@@ -1171,9 +1171,9 @@ void BKE_sound_update_scene(Depsgraph *depsgraph, Scene *scene)
}
if (scene->camera) {
- mat4_to_quat(quat, scene->camera->obmat);
+ mat4_to_quat(quat, scene->camera->object_to_world);
AUD_Sequence_setAnimationData(
- scene->sound_scene, AUD_AP_LOCATION, scene->r.cfra, scene->camera->obmat[3], 1);
+ scene->sound_scene, AUD_AP_LOCATION, scene->r.cfra, scene->camera->object_to_world[3], 1);
AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_ORIENTATION, scene->r.cfra, quat, 1);
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index f7ea4c81fbf..f5badfc9e94 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -715,7 +715,7 @@ static const char *unit_find_str(const char *str, const char *substr, bool case_
/* Weak unicode support!, so "µm" won't match up be replaced by "m"
* since non ascii utf8 values will NEVER return true */
isalpha_or_utf8(*BLI_str_find_prev_char_utf8(str_found, str)) == 0) {
- /* Next char cannot be alphanum. */
+ /* Next char cannot be alpha-numeric. */
int len_name = strlen(substr);
if (!isalpha_or_utf8(*(str_found + len_name))) {
diff --git a/source/blender/blenkernel/intern/vfont.c b/source/blender/blenkernel/intern/vfont.c
index 7ace1a3aa3b..9f48b9b9c4a 100644
--- a/source/blender/blenkernel/intern/vfont.c
+++ b/source/blender/blenkernel/intern/vfont.c
@@ -1310,14 +1310,14 @@ static bool vfont_to_curve(Object *ob,
float timeofs, sizefac;
if (ob != NULL) {
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
}
else {
unit_m4(imat);
}
copy_m3_m4(imat3, imat);
- copy_m3_m4(cmat, cu->textoncurve->obmat);
+ copy_m3_m4(cmat, cu->textoncurve->object_to_world);
mul_m3_m3m3(cmat, cmat, imat3);
sizefac = normalize_v3(cmat[0]) / font_size;
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 7c54b4d3f2f..e81657f9ef0 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -445,7 +445,7 @@ struct VolumeGrid {
* may actually be loaded by another user while this is false. But only after
* calling load() and is_loaded changes to true is it safe to access.
*
- * Const write access to this must be protected by `entry->mutex`.
+ * `const` write access to this must be protected by `entry->mutex`.
*/
mutable bool is_loaded;
};
@@ -480,7 +480,7 @@ struct VolumeGridVector : public std::list<VolumeGrid> {
metadata.reset();
}
- /* Mutex for file loading of grids list. Const write access to the fields after this must be
+ /* Mutex for file loading of grids list. `const` write access to the fields after this must be
* protected by locking with this mutex. */
mutable std::mutex mutex;
/* Absolute file path that grids have been loaded from. */
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index dbdf8cc395d..de2e196c163 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -122,7 +122,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_XVID,
- R_IMF_IMTYPE_THEORA)) {
+ R_IMF_IMTYPE_THEORA,
+ R_IMF_IMTYPE_AV1)) {
mh.start_movie = BKE_ffmpeg_start;
mh.append_movie = BKE_ffmpeg_append;
mh.end_movie = BKE_ffmpeg_end;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 99df07b6105..ee827cd8cd4 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -299,6 +299,10 @@ static const char **get_file_extensions(int format)
static const char *rv[] = {".webm", NULL};
return rv;
}
+ case FFMPEG_AV1: {
+ static const char *rv[] = {".mp4", ".mkv", NULL};
+ return rv;
+ }
default:
return NULL;
}
@@ -455,6 +459,204 @@ static AVRational calc_time_base(uint den, double num, int codec_id)
return time_base;
}
+static const AVCodec *get_av1_encoder(
+ FFMpegContext *context, RenderData *rd, AVDictionary **opts, int rectx, int recty)
+{
+ /* There are three possible encoders for AV1: libaom-av1, librav1e, and libsvtav1. librav1e tends
+ * to give the best compression quality while libsvtav1 tends to be the fastest encoder. One of
+ * each will be picked based on the preset setting, and if a particular encoder is not available,
+ * then use the default returned by FFMpeg. */
+ const AVCodec *codec = NULL;
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_BEST:
+ /* Default to libaom-av1 for BEST preset due to it performing better than rav1e in terms of
+ * video quality (VMAF scores). Fallback to rav1e if libaom-av1 isn't available. */
+ codec = avcodec_find_encoder_by_name("libaom-av1");
+ if (!codec) {
+ codec = avcodec_find_encoder_by_name("librav1e");
+ }
+ break;
+ case FFM_PRESET_REALTIME:
+ codec = avcodec_find_encoder_by_name("libsvtav1");
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ codec = avcodec_find_encoder_by_name("libaom-av1");
+ break;
+ }
+
+ /* Use the default AV1 encoder if the specified encoder wasn't found. */
+ if (!codec) {
+ codec = avcodec_find_encoder(AV_CODEC_ID_AV1);
+ }
+
+ /* Apply AV1 encoder specific settings. */
+ if (codec) {
+ if (STREQ(codec->name, "librav1e")) {
+ /* Set "tiles" to 8 to enable multi-threaded encoding. */
+ if (rd->threads > 8) {
+ ffmpeg_dict_set_int(opts, "tiles", rd->threads);
+ }
+ else {
+ ffmpeg_dict_set_int(opts, "tiles", 8);
+ }
+
+ /* Use a reasonable speed setting based on preset. Speed ranges from 0-10.
+ * Must check context->ffmpeg_preset again in case this encoder was selected due to the
+ * absence of another. */
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_BEST:
+ ffmpeg_dict_set_int(opts, "speed", 4);
+ break;
+ case FFM_PRESET_REALTIME:
+ ffmpeg_dict_set_int(opts, "speed", 10);
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ ffmpeg_dict_set_int(opts, "speed", 6);
+ break;
+ }
+ if (context->ffmpeg_crf >= 0) {
+ /* librav1e does not use -crf, but uses -qp in the range of 0-255. Calculates the roughly
+ * equivalent float, and truncates it to an integer. */
+ unsigned int qp_value = ((float)context->ffmpeg_crf) * 255.0F / 51.0F;
+ if (qp_value > 255) {
+ qp_value = 255;
+ }
+ ffmpeg_dict_set_int(opts, "qp", qp_value);
+ }
+ /* Set gop_size as rav1e's "--keyint". */
+ char buffer[64];
+ BLI_snprintf(buffer, sizeof(buffer), "keyint=%d", context->ffmpeg_gop_size);
+ av_dict_set(opts, "rav1e-params", buffer, 0);
+ }
+ else if (STREQ(codec->name, "libsvtav1")) {
+ /* Set preset value based on ffmpeg_preset.
+ * Must check context->ffmpeg_preset again in case this encoder was selected due to the
+ * absence of another. */
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_REALTIME:
+ ffmpeg_dict_set_int(opts, "preset", 8);
+ break;
+ case FFM_PRESET_BEST:
+ ffmpeg_dict_set_int(opts, "preset", 3);
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ ffmpeg_dict_set_int(opts, "preset", 5);
+ break;
+ }
+ if (context->ffmpeg_crf >= 0) {
+ /* libsvtav1 does not support crf until FFmpeg builds since 2022-02-24, use qp as fallback.
+ */
+ ffmpeg_dict_set_int(opts, "qp", context->ffmpeg_crf);
+ }
+ }
+ else if (STREQ(codec->name, "libaom-av1")) {
+ /* Speed up libaom-av1 encoding by enabling multithreading and setting tiles. */
+ ffmpeg_dict_set_int(opts, "row-mt", 1);
+ const char *tiles_string = NULL;
+ bool tiles_string_is_dynamic = false;
+ if (rd->threads > 0) {
+ /* See if threads is a square. */
+ int threads_sqrt = sqrtf(rd->threads);
+ if (threads_sqrt < 4) {
+ /* Ensure a default minimum. */
+ threads_sqrt = 4;
+ }
+ if (is_power_of_2_i(threads_sqrt) && threads_sqrt * threads_sqrt == rd->threads) {
+ /* Is a square num, therefore just do "sqrt x sqrt" for tiles parameter. */
+ int digits = 0;
+ for (int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) {
+ ++digits;
+ }
+ /* A char array need only an alignment of 1. */
+ char *tiles_string_mut = (char *)calloc(digits * 2 + 2, 1);
+ BLI_snprintf(tiles_string_mut, digits * 2 + 2, "%dx%d", threads_sqrt, threads_sqrt);
+ tiles_string_is_dynamic = true;
+ tiles_string = tiles_string_mut;
+ }
+ else {
+ /* Is not a square num, set greater side based on longer side, or use a square if both
+ sides are equal. */
+ int sqrt_p2 = power_of_2_min_i(threads_sqrt);
+ if (sqrt_p2 < 2) {
+ /* Ensure a default minimum. */
+ sqrt_p2 = 2;
+ }
+ int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2);
+ if (sqrt_p2_next < 1) {
+ sqrt_p2_next = 1;
+ }
+ if (sqrt_p2 > sqrt_p2_next) {
+ /* Ensure sqrt_p2_next is greater or equal to sqrt_p2. */
+ int temp = sqrt_p2;
+ sqrt_p2 = sqrt_p2_next;
+ sqrt_p2_next = temp;
+ }
+ int combined_digits = 0;
+ for (int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
+ ++combined_digits;
+ }
+ for (int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
+ ++combined_digits;
+ }
+ /* A char array need only an alignment of 1. */
+ char *tiles_string_mut = (char *)calloc(combined_digits + 2, 1);
+ if (rectx > recty) {
+ BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2_next, sqrt_p2);
+ }
+ else if (rectx < recty) {
+ BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2_next);
+ }
+ else {
+ BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2);
+ }
+ tiles_string_is_dynamic = true;
+ tiles_string = tiles_string_mut;
+ }
+ }
+ else {
+ /* Thread count unknown, default to 8. */
+ if (rectx > recty) {
+ tiles_string = "4x2";
+ }
+ else if (rectx < recty) {
+ tiles_string = "2x4";
+ }
+ else {
+ tiles_string = "2x2";
+ }
+ }
+ av_dict_set(opts, "tiles", tiles_string, 0);
+ if (tiles_string_is_dynamic) {
+ free((void *)tiles_string);
+ }
+ /* libaom-av1 uses "cpu-used" instead of "preset" for defining compression quality.
+ * This value is in a range from 0-8. 0 and 8 are extremes, but we will allow 8.
+ * Must check context->ffmpeg_preset again in case this encoder was selected due to the
+ * absence of another. */
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_REALTIME:
+ ffmpeg_dict_set_int(opts, "cpu-used", 8);
+ break;
+ case FFM_PRESET_BEST:
+ ffmpeg_dict_set_int(opts, "cpu-used", 4);
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ ffmpeg_dict_set_int(opts, "cpu-used", 6);
+ break;
+ }
+
+ /* CRF related settings is similar to H264 for libaom-av1, so we will rely on those settings
+ * applied later. */
+ }
+ }
+
+ return codec;
+}
+
/* prepare a video stream for the output file */
static AVStream *alloc_video_stream(FFMpegContext *context,
@@ -480,7 +682,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
/* Set up the codec context */
- codec = avcodec_find_encoder(codec_id);
+ if (codec_id == AV_CODEC_ID_AV1) {
+ /* Use get_av1_encoder() to get the ideal (hopefully) encoder for AV1 based
+ * on given parameters, and also set up opts. */
+ codec = get_av1_encoder(context, rd, &opts, rectx, recty);
+ }
+ else {
+ codec = avcodec_find_encoder(codec_id);
+ }
if (!codec) {
fprintf(stderr, "Couldn't find valid video codec\n");
context->video_codec = NULL;
@@ -568,7 +777,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
default:
printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset);
}
- if (preset_name != NULL) {
+ /* "codec_id != AV_CODEC_ID_AV1" is required due to "preset" already being set by an AV1 codec.
+ */
+ if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) {
av_dict_set(&opts, "preset", preset_name, 0);
}
if (deadline_name != NULL) {
@@ -806,7 +1017,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
return NULL;
}
- /* need to prevent floating point exception when using vorbis audio codec,
+ /* Need to prevent floating point exception when using VORBIS audio codec,
* initialize this value in the same way as it's done in FFmpeg itself (sergey) */
c->time_base.num = 1;
c->time_base.den = c->sample_rate;
@@ -951,6 +1162,9 @@ static int start_ffmpeg_impl(FFMpegContext *context,
case FFMPEG_FLV:
video_codec = AV_CODEC_ID_FLV1;
break;
+ case FFMPEG_AV1:
+ video_codec = AV_CODEC_ID_AV1;
+ break;
default:
/* These containers are not restricted to any specific codec types.
* Currently we expect these to be .avi, .mov, .mkv, and .mp4.
@@ -1482,6 +1696,18 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
rd->ffcodecdata.mux_packet_size = 2048;
rd->ffcodecdata.mux_rate = 10080000;
break;
+ case FFMPEG_PRESET_AV1:
+ rd->ffcodecdata.type = FFMPEG_AV1;
+ rd->ffcodecdata.codec = AV_CODEC_ID_AV1;
+ rd->ffcodecdata.video_bitrate = 6000;
+ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15;
+ rd->ffcodecdata.rc_max_rate = 9000;
+ rd->ffcodecdata.rc_min_rate = 0;
+ rd->ffcodecdata.rc_buffer_size = 224 * 8;
+ rd->ffcodecdata.mux_packet_size = 2048;
+ rd->ffcodecdata.mux_rate = 10080000;
+
+ break;
}
}
@@ -1521,6 +1747,12 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf)
audio = 1;
}
}
+ else if (imf->imtype == R_IMF_IMTYPE_AV1) {
+ if (rd->ffcodecdata.codec != AV_CODEC_ID_AV1) {
+ BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_AV1);
+ audio = 1;
+ }
+ }
if (audio && rd->ffcodecdata.audio_codec < 0) {
rd->ffcodecdata.audio_codec = AV_CODEC_ID_NONE;
diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh
index 95b3bde10f4..264ac00e034 100644
--- a/source/blender/blenlib/BLI_array_utils.hh
+++ b/source/blender/blenlib/BLI_array_utils.hh
@@ -42,6 +42,11 @@ void gather(const GVArray &src, IndexMask indices, GMutableSpan dst, int64_t gra
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
+void gather(GSpan src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096);
+
+/**
+ * Fill the destination span by gathering indexed values from the `src` array.
+ */
template<typename T>
inline void gather(const VArray<T> &src,
const IndexMask indices,
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 7e1b7c2ba56..538474f58b6 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -624,7 +624,7 @@ void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float n
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3]);
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target) \
- BLI_space_transform_from_matrices((data), (local)->obmat, (target)->obmat)
+ BLI_space_transform_from_matrices((data), (local)->object_to_world, (target)->object_to_world)
/** \} */
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index d4d2ddead71..1b723ab038d 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -68,8 +68,15 @@ const char *BLI_path_extension(const char *filepath) ATTR_NONNULL();
/**
* Append a filename to a dir, ensuring slash separates.
+ * \return The new length of `dst`.
*/
-void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file)
+size_t BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file)
+ ATTR_NONNULL();
+/**
+ * A version of #BLI_path_append that ensures a trailing slash if there is space in `dst`.
+ * \return The new length of `dst`.
+ */
+size_t BLI_path_append_dir(char *__restrict dst, size_t maxlen, const char *__restrict dir)
ATTR_NONNULL();
/**
@@ -218,7 +225,7 @@ const char *BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UN
* Appends a slash to string if there isn't one there already.
* Returns the new length of the string.
*/
-int BLI_path_slash_ensure(char *string) ATTR_NONNULL();
+int BLI_path_slash_ensure(char *string, size_t string_maxlen) ATTR_NONNULL(1);
/**
* Removes the last slash and everything after it to the end of string, if there is one.
*/
@@ -314,7 +321,7 @@ void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2);
*
* \note Same as #BLI_path_normalize but adds a trailing slash.
*/
-void BLI_path_normalize_dir(const char *relabase, char *dir) ATTR_NONNULL(2);
+void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen) ATTR_NONNULL(2);
/**
* Make given name safe to be used in paths.
@@ -357,6 +364,8 @@ bool BLI_path_make_safe(char *path) ATTR_NONNULL(1);
*
* Replaces path with the path of its parent directory, returning true if
* it was able to find a parent directory within the path.
+ *
+ * On success, the resulting path will always have a trailing slash.
*/
bool BLI_path_parent_dir(char *path) ATTR_NONNULL();
/**
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 15926e8f2d2..17abcf52ecc 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -309,6 +309,28 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) A
*/
void BLI_str_format_decimal_unit(char dst[7], int number_to_format) ATTR_NONNULL();
/**
+ * Format a count to up to 3 places (plus minus sign, plus '\0' terminator) string using long
+ * number names abbreviations. Used to produce a compact representation of large numbers as
+ * integers.
+ *
+ * It shows a lower bound instead of rounding the number.
+ *
+ * 1 -> 1
+ * 15 -> 15
+ * 155 -> 155
+ * 1555 -> 1K
+ * 15555 -> 15K
+ * 155555 -> .1M
+ * 1555555 -> 1M
+ * 15555555 -> 15M
+ * 155555555 -> .1B
+ * 1000000000 -> 1B
+ * ...
+ *
+ * Length of 5 is the maximum of the resulting string, for example, `-15K\0`.
+ */
+void BLI_str_format_integer_unit(char dst[5], int number_to_format) ATTR_NONNULL();
+/**
* Compare two strings without regard to case.
*
* \retval True if the strings are equal, false otherwise.
diff --git a/source/blender/blenlib/BLI_uvproject.h b/source/blender/blenlib/BLI_uvproject.h
index 75f39de6b7f..a94fd796121 100644
--- a/source/blender/blenlib/BLI_uvproject.h
+++ b/source/blender/blenlib/BLI_uvproject.h
@@ -15,7 +15,7 @@ struct ProjCameraInfo;
/**
* Create UV info from the camera, needs to be freed.
*
- * \param rotmat: can be `obedit->obmat` when uv project is used.
+ * \param rotmat: can be `obedit->object_to_world` when uv project is used.
* \param winx, winy: can be from `scene->r.xsch / ysch`.
*/
struct ProjCameraInfo *BLI_uvproject_camera_info(struct Object *ob,
diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc
index a837d6aceec..2a231228dcb 100644
--- a/source/blender/blenlib/intern/array_utils.cc
+++ b/source/blender/blenlib/intern/array_utils.cc
@@ -28,4 +28,9 @@ void gather(const GVArray &src,
});
}
+void gather(const GSpan src, const IndexMask indices, GMutableSpan dst, const int64_t grain_size)
+{
+ gather(GVArray::ForSpan(src), indices, dst, grain_size);
+}
+
} // namespace blender::array_utils
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index a157302e51e..005de1f85b4 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -401,7 +401,7 @@ static bool delete_recursive(const char *dir)
/* dir listing produces dir path without trailing slash... */
BLI_strncpy(path, fl->path, sizeof(path));
- BLI_path_slash_ensure(path);
+ BLI_path_slash_ensure(path, sizeof(path));
if (delete_recursive(path)) {
err = true;
diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h
index 6614f1bf964..f7993eb5adc 100644
--- a/source/blender/blenlib/intern/kdtree_impl.h
+++ b/source/blender/blenlib/intern/kdtree_impl.h
@@ -11,9 +11,9 @@
#include "BLI_strict_flags.h"
#include "BLI_utildefines.h"
-#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
-#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
-#define BLI_kdtree_nd_(id) _CONCAT(KDTREE_PREFIX_ID, _##id)
+#define _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
+#define _BLI_KDTREE_CONCAT(MACRO_ARG1, MACRO_ARG2) _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
+#define BLI_kdtree_nd_(id) _BLI_KDTREE_CONCAT(KDTREE_PREFIX_ID, _##id)
typedef struct KDTreeNode_head {
uint left, right;
diff --git a/source/blender/blenlib/intern/list_sort_impl.h b/source/blender/blenlib/intern/list_sort_impl.h
index e1b93986f4a..7c38fc60b29 100644
--- a/source/blender/blenlib/intern/list_sort_impl.h
+++ b/source/blender/blenlib/intern/list_sort_impl.h
@@ -47,24 +47,25 @@
#endif
#ifdef SORT_IMPL_USE_THUNK
-# define THUNK_APPEND1(a, thunk) a, thunk
-# define THUNK_PREPEND2(thunk, a, b) thunk, a, b
+# define BLI_LIST_THUNK_APPEND1(a, thunk) a, thunk
+# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) thunk, a, b
#else
-# define THUNK_APPEND1(a, thunk) a
-# define THUNK_PREPEND2(thunk, a, b) a, b
+# define BLI_LIST_THUNK_APPEND1(a, thunk) a
+# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) a, b
#endif
-#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
-#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
-#define _SORT_PREFIX(id) _CONCAT(SORT_IMPL_FUNC, _##id)
+#define _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
+#define _BLI_LIST_SORT_CONCAT(MACRO_ARG1, MACRO_ARG2) \
+ _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
+#define _BLI_LIST_SORT_PREFIX(id) _BLI_LIST_SORT_CONCAT(SORT_IMPL_FUNC, _##id)
/* local identifiers */
-#define SortInfo _SORT_PREFIX(SortInfo)
-#define CompareFn _SORT_PREFIX(CompareFn)
-#define init_sort_info _SORT_PREFIX(init_sort_info)
-#define merge_lists _SORT_PREFIX(merge_lists)
-#define sweep_up _SORT_PREFIX(sweep_up)
-#define insert_list _SORT_PREFIX(insert_list)
+#define SortInfo _BLI_LIST_SORT_PREFIX(SortInfo)
+#define CompareFn _BLI_LIST_SORT_PREFIX(CompareFn)
+#define init_sort_info _BLI_LIST_SORT_PREFIX(init_sort_info)
+#define merge_lists _BLI_LIST_SORT_PREFIX(merge_lists)
+#define sweep_up _BLI_LIST_SORT_PREFIX(sweep_up)
+#define insert_list _BLI_LIST_SORT_PREFIX(insert_list)
typedef int (*CompareFn)(
#ifdef SORT_IMPL_USE_THUNK
@@ -159,7 +160,7 @@ BLI_INLINE list_node *merge_lists(list_node *first,
list_node *list = NULL;
list_node **pos = &list;
while (first && second) {
- if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
+ if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
*pos = second;
second = second->next;
}
@@ -181,7 +182,7 @@ BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned in
{
unsigned int i;
for (i = si->min_rank; i < upto; i++) {
- list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
si->ranks[i] = NULL;
}
return list;
@@ -225,17 +226,19 @@ BLI_INLINE void insert_list(struct SortInfo *si, list_node *list, unsigned int r
// printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank);
rank = MAX_RANKS;
}
- list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(
+ sweep_up(si, NULL, si->n_ranks), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
for (i = si->n_ranks; i < rank; i++) {
si->ranks[i] = NULL;
}
}
else {
if (rank) {
- list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(
+ sweep_up(si, NULL, rank), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
}
for (i = rank; i < si->n_ranks && si->ranks[i]; i++) {
- list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
si->ranks[i] = NULL;
}
}
@@ -281,7 +284,7 @@ BLI_INLINE list_node *list_sort_do(list_node *list,
list_node *next = list->next;
list_node *tail = next->next;
- if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
+ if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
next->next = list;
next = list;
list = list->next;
@@ -296,8 +299,8 @@ BLI_INLINE list_node *list_sort_do(list_node *list,
return sweep_up(&si, list, si.n_ranks);
}
-#undef _CONCAT_AUX
-#undef _CONCAT
+#undef _BLI_LIST_SORT_CONCAT_AUX
+#undef _BLI_LIST_SORT_CONCAT
#undef _SORT_PREFIX
#undef SortInfo
@@ -310,6 +313,6 @@ BLI_INLINE list_node *list_sort_do(list_node *list,
#undef list_node
#undef list_sort_do
-#undef THUNK_APPEND1
-#undef THUNK_PREPEND2
+#undef BLI_LIST_THUNK_APPEND1
+#undef BLI_LIST_THUNK_PREPEND2
#undef SORT_ARG
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index afe8c3cc033..3a87b39a446 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -153,6 +153,19 @@ void BLI_path_normalize(const char *relabase, char *path)
*/
#ifdef WIN32
+
+ while ((start = strstr(path, "\\.\\"))) {
+ eind = start + strlen("\\.\\") - 1;
+ memmove(start, eind, strlen(eind) + 1);
+ }
+
+ /* remove two consecutive backslashes, but skip the UNC prefix,
+ * which needs to be preserved */
+ while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) {
+ eind = start + strlen("\\\\") - 1;
+ memmove(start, eind, strlen(eind) + 1);
+ }
+
while ((start = strstr(path, "\\..\\"))) {
eind = start + strlen("\\..\\") - 1;
a = start - path - 1;
@@ -170,18 +183,18 @@ void BLI_path_normalize(const char *relabase, char *path)
}
}
- while ((start = strstr(path, "\\.\\"))) {
- eind = start + strlen("\\.\\") - 1;
+#else
+
+ while ((start = strstr(path, "/./"))) {
+ eind = start + (3 - 1) /* strlen("/./") - 1 */;
memmove(start, eind, strlen(eind) + 1);
}
- /* remove two consecutive backslashes, but skip the UNC prefix,
- * which needs to be preserved */
- while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) {
- eind = start + strlen("\\\\") - 1;
+ while ((start = strstr(path, "//"))) {
+ eind = start + (2 - 1) /* strlen("//") - 1 */;
memmove(start, eind, strlen(eind) + 1);
}
-#else
+
while ((start = strstr(path, "/../"))) {
a = start - path - 1;
if (a > 0) {
@@ -206,19 +219,10 @@ void BLI_path_normalize(const char *relabase, char *path)
}
}
- while ((start = strstr(path, "/./"))) {
- eind = start + (3 - 1) /* strlen("/./") - 1 */;
- memmove(start, eind, strlen(eind) + 1);
- }
-
- while ((start = strstr(path, "//"))) {
- eind = start + (2 - 1) /* strlen("//") - 1 */;
- memmove(start, eind, strlen(eind) + 1);
- }
#endif
}
-void BLI_path_normalize_dir(const char *relabase, char *dir)
+void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen)
{
/* Would just create an unexpected "/" path, just early exit entirely. */
if (dir[0] == '\0') {
@@ -226,7 +230,7 @@ void BLI_path_normalize_dir(const char *relabase, char *dir)
}
BLI_path_normalize(relabase, dir);
- BLI_path_slash_ensure(dir);
+ BLI_path_slash_ensure(dir, dir_maxlen);
}
bool BLI_filename_make_safe_ex(char *fname, bool allow_tokens)
@@ -622,18 +626,38 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
bool BLI_path_parent_dir(char *path)
{
- const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
- char tmp[FILE_MAX + 4];
-
- BLI_path_join(tmp, sizeof(tmp), path, parent_dir);
- BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */
+ char tmp[FILE_MAX];
- if (!BLI_path_extension_check(tmp, parent_dir)) {
- strcpy(path, tmp); /* We assume the parent directory is always shorter. */
- return true;
+ STRNCPY(tmp, path);
+ /* Does all the work of normalizing the path for us.
+ *
+ * NOTE(@campbellbarton): While it's possible strip text after the second last slash,
+ * this would have to be clever and skip cases like "/./" & multiple slashes.
+ * Since this ends up solving some of the same problems as #BLI_path_normalize,
+ * call this function instead of attempting to handle them separately. */
+ BLI_path_normalize(NULL, tmp);
+
+ /* Use #BLI_path_name_at_index instead of checking if the strings ends with `parent_dir`
+ * to ensure the logic isn't confused by:
+ * - Directory names that happen to end with `..`.
+ * - When `path` is empty, the contents will be `../`
+ * which would cause checking for a tailing `/../` fail.
+ * Extracting the span of the final directory avoids both these issues. */
+ int tail_ofs = 0, tail_len = 0;
+ if (!BLI_path_name_at_index(tmp, -1, &tail_ofs, &tail_len)) {
+ return false;
+ }
+ if (tail_len == 1) {
+ /* Last path is ".", as normalize should remove this, it's safe to assume failure.
+ * This happens when the input a single period (possibly with slashes before or after). */
+ if (tmp[tail_ofs] == '.') {
+ return false;
+ }
}
- return false;
+ memcpy(path, tmp, tail_ofs);
+ path[tail_ofs] = '\0';
+ return true;
}
bool BLI_path_parent_dir_until_exists(char *dir)
@@ -1431,21 +1455,34 @@ const char *BLI_path_extension(const char *filepath)
return extension;
}
-void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
+size_t BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
{
size_t dirlen = BLI_strnlen(dst, maxlen);
- /* inline BLI_path_slash_ensure */
+ /* Inline #BLI_path_slash_ensure. */
if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
dst[dirlen++] = SEP;
dst[dirlen] = '\0';
}
if (dirlen >= maxlen) {
- return; /* fills the path */
+ return dirlen; /* fills the path */
}
- BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
+ return dirlen + BLI_strncpy_rlen(dst + dirlen, file, maxlen - dirlen);
+}
+
+size_t BLI_path_append_dir(char *__restrict dst, const size_t maxlen, const char *__restrict dir)
+{
+ size_t dirlen = BLI_path_append(dst, maxlen, dir);
+ if (dirlen + 1 < maxlen) {
+ /* Inline #BLI_path_slash_ensure. */
+ if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
+ dst[dirlen++] = SEP;
+ dst[dirlen] = '\0';
+ }
+ }
+ return dirlen;
}
size_t BLI_path_join_array(char *__restrict dst,
@@ -1469,14 +1506,36 @@ size_t BLI_path_join_array(char *__restrict dst,
return ofs;
}
+#ifdef WIN32
+ /* Special case "//" for relative paths, don't use separator #SEP
+ * as this has a special meaning on both WIN32 & UNIX.
+ * Without this check joining `"//", "path"`. results in `"//\path"`. */
+ if (ofs != 0) {
+ size_t i;
+ for (i = 0; i < ofs; i++) {
+ if (dst[i] != '/') {
+ break;
+ }
+ }
+ if (i == ofs) {
+ /* All slashes, keep them as-is, and join the remaining path array. */
+ return path_array_num > 1 ?
+ BLI_path_join_array(
+ dst + ofs, dst_len - ofs, &path_array[1], path_array_num - 1) :
+ ofs;
+ }
+ }
+#endif
+
/* Remove trailing slashes, unless there are *only* trailing slashes
* (allow `//` or `//some_path` as the first argument). */
bool has_trailing_slash = false;
if (ofs != 0) {
size_t len = ofs;
- while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ while ((len != 0) && (path[len - 1] == SEP)) {
len -= 1;
}
+
if (len != 0) {
ofs = len;
}
@@ -1487,18 +1546,18 @@ size_t BLI_path_join_array(char *__restrict dst,
path = path_array[path_index];
has_trailing_slash = false;
const char *path_init = path;
- while (ELEM(path[0], SEP, ALTSEP)) {
+ while (path[0] == SEP) {
path++;
}
size_t len = strlen(path);
if (len != 0) {
- while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ while ((len != 0) && (path[len - 1] == SEP)) {
len -= 1;
}
if (len != 0) {
/* the very first path may have a slash at the end */
- if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) {
+ if (ofs && (dst[ofs - 1] != SEP)) {
dst[ofs++] = SEP;
if (ofs == dst_last) {
break;
@@ -1521,7 +1580,7 @@ size_t BLI_path_join_array(char *__restrict dst,
}
if (has_trailing_slash) {
- if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) {
+ if ((ofs != dst_last) && (ofs != 0) && (dst[ofs - 1] != SEP)) {
dst[ofs++] = SEP;
}
}
@@ -1549,7 +1608,7 @@ bool BLI_path_name_at_index(const char *__restrict path,
int i = 0;
while (true) {
const char c = path[i];
- if (ELEM(c, SEP, ALTSEP, '\0')) {
+ if (ELEM(c, SEP, '\0')) {
if (prev + 1 != i) {
prev += 1;
if (index_step == index) {
@@ -1576,7 +1635,7 @@ bool BLI_path_name_at_index(const char *__restrict path,
int i = prev - 1;
while (true) {
const char c = i >= 0 ? path[i] : '\0';
- if (ELEM(c, SEP, ALTSEP, '\0')) {
+ if (ELEM(c, SEP, '\0')) {
if (prev - 1 != i) {
i += 1;
if (index_step == index) {
@@ -1624,7 +1683,7 @@ bool BLI_path_contains(const char *container_path, const char *containee_path)
/* Add a trailing slash to prevent same-prefix directories from matching.
* e.g. "/some/path" doesn't contain "/some/path_lib". */
- BLI_path_slash_ensure(container_native);
+ BLI_path_slash_ensure(container_native, sizeof(container_native));
return BLI_str_startswith(containee_native, container_native);
}
@@ -1659,13 +1718,17 @@ const char *BLI_path_slash_rfind(const char *string)
return (lfslash > lbslash) ? lfslash : lbslash;
}
-int BLI_path_slash_ensure(char *string)
+int BLI_path_slash_ensure(char *string, size_t string_maxlen)
{
int len = strlen(string);
+ BLI_assert(len < string_maxlen);
if (len == 0 || string[len - 1] != SEP) {
- string[len] = SEP;
- string[len + 1] = '\0';
- return len + 1;
+ /* Avoid unlikely buffer overflow. */
+ if (len + 1 < string_maxlen) {
+ string[len] = SEP;
+ string[len + 1] = '\0';
+ return len + 1;
+ }
}
return len;
}
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 89d31c5e93f..755d2dbd55d 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -1176,4 +1176,34 @@ void BLI_str_format_decimal_unit(char dst[7], int number_to_format)
BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]);
}
+void BLI_str_format_integer_unit(char dst[5], const int number_to_format)
+{
+ float number_to_format_converted = number_to_format;
+ int order = 0;
+ const float base = 1000;
+ const char *units[] = {"", "K", "M", "B"};
+ const int units_num = ARRAY_SIZE(units);
+
+ while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) {
+ number_to_format_converted /= base;
+ order++;
+ }
+
+ const bool add_dot = (abs(number_to_format) > 99999) && fabsf(number_to_format_converted) > 99;
+
+ if (add_dot) {
+ number_to_format_converted /= 100;
+ order++;
+ }
+
+ const size_t dst_len = 5;
+ BLI_snprintf(dst,
+ dst_len,
+ "%s%s%d%s",
+ number_to_format < 0 ? "-" : "",
+ add_dot ? "." : "",
+ (int)floorf(fabsf(number_to_format_converted)),
+ units[order]);
+}
+
/** \} */
diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c
index 347166bd57d..0398bf0b3fe 100644
--- a/source/blender/blenlib/intern/uvproject.c
+++ b/source/blender/blenlib/intern/uvproject.c
@@ -129,7 +129,7 @@ ProjCameraInfo *BLI_uvproject_camera_info(Object *ob, float rotmat[4][4], float
uci.camsize = uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale;
/* account for scaled cameras */
- copy_m4_m4(uci.caminv, ob->obmat);
+ copy_m4_m4(uci.caminv, ob->object_to_world);
normalize_m4(uci.caminv);
if (invert_m4(uci.caminv)) {
diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc
index 89e537235db..293d353efcc 100644
--- a/source/blender/blenlib/tests/BLI_path_util_test.cc
+++ b/source/blender/blenlib/tests/BLI_path_util_test.cc
@@ -9,69 +9,166 @@
#include "BLI_string.h"
/* -------------------------------------------------------------------- */
-/* tests */
+/** \name Local Utilities
+ * \{ */
-/* BLI_path_normalize */
-#ifndef _WIN32
-TEST(path_util, Clean)
+static void str_replace_char_with_relative_exception(char *str, char src, char dst)
{
- /* "/./" -> "/" */
- {
- char path[FILE_MAX] = "/a/./b/./c/./";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/a/b/c/", path);
+ /* Always keep "//" or more leading slashes (special meaning). */
+ if (src == '/') {
+ if (str[0] == '/' && str[1] == '/') {
+ str += 2;
+ while (*str == '/') {
+ str++;
+ }
+ }
}
+ BLI_str_replace_char(str, src, dst);
+}
- {
- char path[FILE_MAX] = "/./././";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/", path);
+static char *str_replace_char_strdup(const char *str, char src, char dst)
+{
+ if (str == nullptr) {
+ return nullptr;
}
+ char *str_dupe = strdup(str);
+ BLI_str_replace_char(str_dupe, src, dst);
+ return str_dupe;
+}
- {
- char path[FILE_MAX] = "/a/./././b/";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/a/b/", path);
- }
+/** \} */
- /* "//" -> "/" */
- {
- char path[FILE_MAX] = "a////";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("a/", path);
- }
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_normalize
+ * \{ */
- if (false) /* FIXME */
- {
- char path[FILE_MAX] = "./a////";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("./a/", path);
- }
+#define NORMALIZE_WITH_BASEDIR(input, input_base, output) \
+ { \
+ char path[FILE_MAX] = input; \
+ const char *input_base_test = input_base; \
+ if (SEP == '\\') { \
+ str_replace_char_with_relative_exception(path, '/', '\\'); \
+ input_base_test = str_replace_char_strdup(input_base_test, '/', '\\'); \
+ } \
+ BLI_path_normalize(input_base_test, path); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '\\', '/'); \
+ if (input_base_test) { \
+ free((void *)input_base_test); \
+ } \
+ } \
+ EXPECT_STREQ(output, path); \
+ } \
+ ((void)0)
- /* "foo/bar/../" -> "foo/" */
- {
- char path[FILE_MAX] = "/a/b/c/../../../";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/", path);
- }
+#define NORMALIZE(input, output) NORMALIZE_WITH_BASEDIR(input, nullptr, output)
- {
- char path[FILE_MAX] = "/a/../a/b/../b/c/../c/";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/a/b/c/", path);
- }
+/* #BLI_path_normalize: "/./" -> "/" */
+TEST(path_util, Clean_Dot)
+{
+ NORMALIZE("/./", "/");
+ NORMALIZE("/a/./b/./c/./", "/a/b/c/");
+ NORMALIZE("/./././", "/");
+ NORMALIZE("/a/./././b/", "/a/b/");
+}
+/* #BLI_path_normalize: complex "/./" -> "/", "//" -> "/", "./path/../" -> "./". */
+TEST(path_util, Clean_Complex)
+{
+ NORMALIZE("/a/./b/./c/./.././.././", "/a/");
+ NORMALIZE("/a//.//b//.//c//.//..//.//..//.//", "/a/");
+}
+/* #BLI_path_normalize: "//" -> "/" */
+TEST(path_util, Clean_DoubleSlash)
+{
+ NORMALIZE("//", "//"); /* Exception, double forward slash. */
+ NORMALIZE(".//", "./");
+ NORMALIZE("a////", "a/");
+ NORMALIZE("./a////", "./a/");
+}
+/* #BLI_path_normalize: "foo/bar/../" -> "foo/" */
+TEST(path_util, Clean_Parent)
+{
+ NORMALIZE("/a/b/c/../../../", "/");
+ NORMALIZE("/a/../a/b/../b/c/../c/", "/a/b/c/");
+ NORMALIZE_WITH_BASEDIR("//../", "/a/b/c/", "/a/b/");
+}
- {
- char path[FILE_MAX] = "//../";
- BLI_path_normalize("/a/b/c/", path);
- EXPECT_STREQ("/a/b/", path);
- }
+#undef NORMALIZE_WITH_BASEDIR
+#undef NORMALIZE
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_parent_dir
+ * \{ */
+
+#define PARENT_DIR(input, output) \
+ { \
+ char path[FILE_MAX] = input; \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '/', '\\'); \
+ } \
+ BLI_path_parent_dir(path); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '\\', '/'); \
+ } \
+ EXPECT_STREQ(output, path); \
+ } \
+ ((void)0)
+
+TEST(path_util, ParentDir_Simple)
+{
+ PARENT_DIR("/a/b/", "/a/");
+ PARENT_DIR("/a/b", "/a/");
+ PARENT_DIR("/a", "/");
}
-#endif
+
+TEST(path_util, ParentDir_NOP)
+{
+ PARENT_DIR("/", "/");
+ PARENT_DIR("", "");
+ PARENT_DIR(".", ".");
+ PARENT_DIR("./", "./");
+ PARENT_DIR(".//", ".//");
+ PARENT_DIR("./.", "./.");
+}
+
+TEST(path_util, ParentDir_TrailingPeriod)
+{
+ /* Ensure trailing dots aren't confused with parent path. */
+ PARENT_DIR("/.../.../.../", "/.../.../");
+ PARENT_DIR("/.../.../...", "/.../.../");
+
+ PARENT_DIR("/a../b../c../", "/a../b../");
+ PARENT_DIR("/a../b../c..", "/a../b../");
+
+ PARENT_DIR("/a./b./c./", "/a./b./");
+ PARENT_DIR("/a./b./c.", "/a./b./");
+}
+
+TEST(path_util, ParentDir_Complex)
+{
+ PARENT_DIR("./a/", "./");
+ PARENT_DIR("./a", "./");
+ PARENT_DIR("../a/", "../");
+ PARENT_DIR("../a", "../");
+}
+
+#undef PARENT_DIR
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_name_at_index
+ * \{ */
#define AT_INDEX(str_input, index_input, str_expect) \
{ \
char path[] = str_input; \
+ /* Test input assumes forward slash, support back-slash on WIN32. */ \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '/', '\\'); \
+ } \
const char *expect = str_expect; \
int index_output, len_output; \
const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \
@@ -87,7 +184,6 @@ TEST(path_util, Clean)
} \
((void)0)
-/* BLI_path_name_at_index */
TEST(path_util, NameAtIndex_Single)
{
AT_INDEX("/a", 0, "a");
@@ -166,21 +262,21 @@ TEST(path_util, NameAtIndex_MiscNeg)
TEST(path_util, NameAtIndex_MiscComplex)
{
AT_INDEX("how//now/brown/cow", 0, "how");
- AT_INDEX("//how///now\\/brown/cow", 1, "now");
- AT_INDEX("/how/now\\//brown\\/cow", 2, "brown");
- AT_INDEX("/how/now/brown/cow//\\", 3, "cow");
- AT_INDEX("/how/now/brown/\\cow", 4, nullptr);
- AT_INDEX("how/now/brown/\\cow\\", 4, nullptr);
+ AT_INDEX("//how///now//brown/cow", 1, "now");
+ AT_INDEX("/how/now///brown//cow", 2, "brown");
+ AT_INDEX("/how/now/brown/cow///", 3, "cow");
+ AT_INDEX("/how/now/brown//cow", 4, nullptr);
+ AT_INDEX("how/now/brown//cow/", 4, nullptr);
}
TEST(path_util, NameAtIndex_MiscComplexNeg)
{
AT_INDEX("how//now/brown/cow", -4, "how");
- AT_INDEX("//how///now\\/brown/cow", -3, "now");
- AT_INDEX("/how/now\\//brown\\/cow", -2, "brown");
- AT_INDEX("/how/now/brown/cow//\\", -1, "cow");
- AT_INDEX("/how/now/brown/\\cow", -5, nullptr);
- AT_INDEX("how/now/brown/\\cow\\", -5, nullptr);
+ AT_INDEX("//how///now//brown/cow", -3, "now");
+ AT_INDEX("/how/now///brown//cow", -2, "brown");
+ AT_INDEX("/how/now/brown/cow///", -1, "cow");
+ AT_INDEX("/how/now/brown//cow", -5, nullptr);
+ AT_INDEX("how/now/brown//cow/", -5, nullptr);
}
TEST(path_util, NameAtIndex_NoneComplex)
@@ -201,21 +297,59 @@ TEST(path_util, NameAtIndex_NoneComplexNeg)
#undef AT_INDEX
-#define JOIN(str_expect, out_size, ...) \
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_join
+ * \{ */
+
+/* For systems with `/` path separator (non WIN32). */
+#define JOIN_FORWARD_SLASH(str_expect, out_size, ...) \
{ \
const char *expect = str_expect; \
char result[(out_size) + 1024]; \
- /* check we don't write past the last byte */ \
+ /* Check we don't write past the last byte. */ \
result[out_size] = '\0'; \
BLI_path_join(result, out_size, __VA_ARGS__); \
- /* simplify expected string */ \
+ EXPECT_STREQ(result, expect); \
+ EXPECT_EQ(result[out_size], '\0'); \
+ } \
+ ((void)0)
+
+/* For systems with `\` path separator (WIN32).
+ * Perform additional manipulation to behave as if input arguments used `\` separators.
+ * Needed since #BLI_path_join uses native slashes. */
+#define JOIN_BACK_SLASH(str_expect, out_size, ...) \
+ { \
+ const char *expect = str_expect; \
+ char result[(out_size) + 1024]; \
+ const char *input_forward_slash[] = {__VA_ARGS__}; \
+ char *input_back_slash[ARRAY_SIZE(input_forward_slash)] = {nullptr}; \
+ for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
+ input_back_slash[i] = strdup(input_forward_slash[i]); \
+ BLI_str_replace_char(input_back_slash[i], '/', '\\'); \
+ } \
+ /* Check we don't write past the last byte. */ \
+ result[out_size] = '\0'; \
+ BLI_path_join_array(result, \
+ out_size, \
+ const_cast<const char **>(input_back_slash), \
+ ARRAY_SIZE(input_back_slash)); \
BLI_str_replace_char(result, '\\', '/'); \
EXPECT_STREQ(result, expect); \
EXPECT_EQ(result[out_size], '\0'); \
+ for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
+ free(input_back_slash[i]); \
+ } \
} \
((void)0)
-/* BLI_path_join */
+#ifdef WIN32
+# define JOIN JOIN_BACK_SLASH
+#else
+# define JOIN JOIN_FORWARD_SLASH
+#endif
+
TEST(path_util, JoinNop)
{
JOIN("", 100, "");
@@ -293,9 +427,9 @@ TEST(path_util, JoinTruncateLong)
TEST(path_util, JoinComplex)
{
- JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//");
- JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//");
- JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\");
+ JOIN("/a/b/c/d/e/f/g/", 100, "/", "a/b", "//////c/d", "", "e", "f", "g//");
+ JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "aa/bb", "//////cc/dd", "", "ee", "ff", "gg//");
+ JOIN("1/2/3/", 100, "1", "////////", "", "2", "3///");
}
TEST(path_util, JoinRelativePrefix)
@@ -306,8 +440,15 @@ TEST(path_util, JoinRelativePrefix)
}
#undef JOIN
+#undef JOIN_BACK_SLASH
+#undef JOIN_FORWARD_SLASH
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame
+ * \{ */
-/* BLI_path_frame */
TEST(path_util, Frame)
{
bool ret;
@@ -384,7 +525,12 @@ TEST(path_util, Frame)
}
}
-/* BLI_split_dirfile */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_split_dirfile
+ * \{ */
+
TEST(path_util, SplitDirfile)
{
{
@@ -440,6 +586,12 @@ TEST(path_util, SplitDirfile)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_strip
+ * \{ */
+
#define PATH_FRAME_STRIP(input_path, expect_path, expect_ext) \
{ \
char path[FILE_MAX]; \
@@ -451,7 +603,6 @@ TEST(path_util, SplitDirfile)
} \
((void)0)
-/* BLI_path_frame_strip */
TEST(path_util, PathFrameStrip)
{
PATH_FRAME_STRIP("", "", "");
@@ -463,6 +614,12 @@ TEST(path_util, PathFrameStrip)
}
#undef PATH_FRAME_STRIP
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_extension_check
+ * \{ */
+
#define PATH_EXTENSION_CHECK(input_path, input_ext, expect_ext) \
{ \
const bool ret = BLI_path_extension_check(input_path, input_ext); \
@@ -475,7 +632,6 @@ TEST(path_util, PathFrameStrip)
} \
((void)0)
-/* BLI_path_extension_check */
TEST(path_util, PathExtensionCheck)
{
PATH_EXTENSION_CHECK("a/b/c.exe", ".exe", ".exe");
@@ -501,6 +657,12 @@ TEST(path_util, PathExtensionCheck)
}
#undef PATH_EXTENSION_CHECK
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_check_chars
+ * \{ */
+
#define PATH_FRAME_CHECK_CHARS(input_path, expect_hasChars) \
{ \
const bool ret = BLI_path_frame_check_chars(input_path); \
@@ -513,7 +675,6 @@ TEST(path_util, PathExtensionCheck)
} \
((void)0)
-/* BLI_path_frame_check_chars */
TEST(path_util, PathFrameCheckChars)
{
PATH_FRAME_CHECK_CHARS("a#", true);
@@ -533,6 +694,12 @@ TEST(path_util, PathFrameCheckChars)
}
#undef PATH_FRAME_CHECK_CHARS
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_range
+ * \{ */
+
#define PATH_FRAME_RANGE(input_path, sta, end, digits, expect_outpath) \
{ \
char path[FILE_MAX]; \
@@ -549,7 +716,6 @@ TEST(path_util, PathFrameCheckChars)
} \
((void)0)
-/* BLI_path_frame_range */
TEST(path_util, PathFrameRange)
{
int dummy = -1;
@@ -565,6 +731,12 @@ TEST(path_util, PathFrameRange)
}
#undef PATH_FRAME_RANGE
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_get
+ * \{ */
+
#define PATH_FRAME_GET(input_path, expect_frame, expect_numdigits, expect_pathisvalid) \
{ \
char path[FILE_MAX]; \
@@ -582,7 +754,6 @@ TEST(path_util, PathFrameRange)
} \
((void)0)
-/* BLI_path_frame_get */
TEST(path_util, PathFrameGet)
{
PATH_FRAME_GET("001.avi", 1, 3, true);
@@ -594,7 +765,12 @@ TEST(path_util, PathFrameGet)
}
#undef PATH_FRAME_GET
-/* BLI_path_extension */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_extension
+ * \{ */
+
TEST(path_util, PathExtension)
{
EXPECT_EQ(nullptr, BLI_path_extension("some.def/file"));
@@ -608,62 +784,88 @@ TEST(path_util, PathExtension)
EXPECT_STREQ(".001", BLI_path_extension("Text.001"));
}
-/* BLI_path_rel. */
-#ifndef _WIN32
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_rel
+ * \{ */
-# define PATH_REL(abs_path, ref_path, rel_path) \
- { \
- char path[FILE_MAX]; \
- BLI_strncpy(path, abs_path, sizeof(path)); \
- BLI_path_rel(path, ref_path); \
- EXPECT_STREQ(rel_path, path); \
+#define PATH_REL(abs_path, ref_path, rel_path) \
+ { \
+ char path[FILE_MAX]; \
+ const char *ref_path_test = ref_path; \
+ BLI_strncpy(path, abs_path, sizeof(path)); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '/', '\\'); \
+ ref_path_test = str_replace_char_strdup(ref_path_test, '/', '\\'); \
} \
- void(0)
+ BLI_path_rel(path, ref_path_test); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '\\', '/'); \
+ free((void *)ref_path_test); \
+ } \
+ EXPECT_STREQ(rel_path, path); \
+ } \
+ void(0)
-TEST(path_util, PathRelPath)
+#ifdef WIN32
+# define ABS_PREFIX "C:"
+#else
+# define ABS_PREFIX ""
+#endif
+
+TEST(path_util, PathRelPath_Simple)
{
- PATH_REL("/foo/bar/blender.blend", "/foo/bar/", "//blender.blend");
- PATH_REL("/foo/bar/blender.blend", "/foo/bar", "//bar/blender.blend");
+ PATH_REL(ABS_PREFIX "/foo/bar/blender.blend", ABS_PREFIX "/foo/bar/", "//blender.blend");
+}
- /* Check for potential buffer overflows. */
- {
- char abs_path_in[FILE_MAX];
- abs_path_in[0] = '/';
- for (int i = 1; i < FILE_MAX - 1; i++) {
- abs_path_in[i] = 'A';
- }
- abs_path_in[FILE_MAX - 1] = '\0';
- char abs_path_out[FILE_MAX];
- abs_path_out[0] = '/';
- abs_path_out[1] = '/';
- for (int i = 2; i < FILE_MAX - 1; i++) {
- abs_path_out[i] = 'A';
- }
- abs_path_out[FILE_MAX - 1] = '\0';
- PATH_REL(abs_path_in, "/", abs_path_out);
-
- const char *ref_path_in = "/foo/bar/";
- const size_t ref_path_in_len = strlen(ref_path_in);
- strcpy(abs_path_in, ref_path_in);
- for (int i = ref_path_in_len; i < FILE_MAX - 1; i++) {
- abs_path_in[i] = 'A';
- }
- abs_path_in[FILE_MAX - 1] = '\0';
- abs_path_out[0] = '/';
- abs_path_out[1] = '/';
- for (int i = 2; i < FILE_MAX - (int(ref_path_in_len) - 1); i++) {
- abs_path_out[i] = 'A';
- }
- abs_path_out[FILE_MAX - (ref_path_in_len - 1)] = '\0';
- PATH_REL(abs_path_in, ref_path_in, abs_path_out);
+TEST(path_util, PathRelPath_SimpleSubdir)
+{
+ PATH_REL(ABS_PREFIX "/foo/bar/blender.blend", ABS_PREFIX "/foo/bar", "//bar/blender.blend");
+}
+
+TEST(path_util, PathRelPath_BufferOverflowRoot)
+{
+ char abs_path_in[FILE_MAX];
+ const char *abs_prefix = ABS_PREFIX "/";
+ for (int i = STRNCPY_RLEN(abs_path_in, abs_prefix); i < FILE_MAX - 1; i++) {
+ abs_path_in[i] = 'A';
+ }
+ abs_path_in[FILE_MAX - 1] = '\0';
+ char abs_path_out[FILE_MAX];
+ for (int i = STRNCPY_RLEN(abs_path_out, "//"); i < FILE_MAX - 1; i++) {
+ abs_path_out[i] = 'A';
+ }
+ abs_path_out[FILE_MAX - std::max((strlen(abs_prefix) - 1), size_t(1))] = '\0';
+ PATH_REL(abs_path_in, abs_prefix, abs_path_out);
+}
+
+TEST(path_util, PathRelPath_BufferOverflowSubdir)
+{
+ char abs_path_in[FILE_MAX];
+ const char *ref_path_in = ABS_PREFIX "/foo/bar/";
+ const size_t ref_path_in_len = strlen(ref_path_in);
+ for (int i = STRNCPY_RLEN(abs_path_in, ref_path_in); i < FILE_MAX - 1; i++) {
+ abs_path_in[i] = 'A';
}
+ abs_path_in[FILE_MAX - 1] = '\0';
+ char abs_path_out[FILE_MAX];
+ for (int i = STRNCPY_RLEN(abs_path_out, "//"); i < FILE_MAX - (int(ref_path_in_len) - 1); i++) {
+ abs_path_out[i] = 'A';
+ }
+ abs_path_out[FILE_MAX - std::max((ref_path_in_len - 1), size_t(1))] = '\0';
+ PATH_REL(abs_path_in, ref_path_in, abs_path_out);
}
-# undef PATH_REL
+#undef PATH_REL
+#undef ABS_PREFIX
-#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_contains
+ * \{ */
-/* BLI_path_contains */
TEST(path_util, PathContains)
{
EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path")) << "A path contains itself";
@@ -692,4 +894,6 @@ TEST(path_util, PathContains_Windows_case_insensitive)
EXPECT_TRUE(BLI_path_contains("C:\\some\\path", "c:\\SOME\\path\\inside"))
<< "On Windows path comparison should ignore case";
}
-#endif
+#endif /* WIN32 */
+
+/** \} */
diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc
index 9bdf6075c70..d726fbccf20 100644
--- a/source/blender/blenlib/tests/BLI_string_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_test.cc
@@ -515,6 +515,103 @@ TEST(string, StrFormatDecimalUnits)
EXPECT_STREQ("-2.1B", size_str);
}
+/* BLI_str_format_integer_unit */
+TEST(string, StrFormatIntegerUnits)
+{
+ char size_str[7];
+ int size;
+
+ BLI_str_format_integer_unit(size_str, size = 0);
+ EXPECT_STREQ("0", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1);
+ EXPECT_STREQ("1", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10);
+ EXPECT_STREQ("10", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15);
+ EXPECT_STREQ("15", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100);
+ EXPECT_STREQ("100", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155);
+ EXPECT_STREQ("155", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000);
+ EXPECT_STREQ("1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1555);
+ EXPECT_STREQ("1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10000);
+ EXPECT_STREQ("10K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15555);
+ EXPECT_STREQ("15K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100000);
+ EXPECT_STREQ(".1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155555);
+ EXPECT_STREQ(".1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000000);
+ EXPECT_STREQ("1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1555555);
+ EXPECT_STREQ("1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 2555555);
+ EXPECT_STREQ("2M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10000000);
+ EXPECT_STREQ("10M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15555555);
+ EXPECT_STREQ("15M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100000000);
+ EXPECT_STREQ(".1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155555555);
+ EXPECT_STREQ(".1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 255555555);
+ EXPECT_STREQ(".2B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000000000);
+ EXPECT_STREQ("1B", size_str);
+
+ /* Largest possible value. */
+ BLI_str_format_integer_unit(size_str, size = INT32_MAX);
+ EXPECT_STREQ("2B", size_str);
+
+ BLI_str_format_integer_unit(size_str, size = -0);
+ EXPECT_STREQ("0", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1);
+ EXPECT_STREQ("-1", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10);
+ EXPECT_STREQ("-10", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15);
+ EXPECT_STREQ("-15", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100);
+ EXPECT_STREQ("-100", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155);
+ EXPECT_STREQ("-155", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000);
+ EXPECT_STREQ("-1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1555);
+ EXPECT_STREQ("-1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10000);
+ EXPECT_STREQ("-10K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15555);
+ EXPECT_STREQ("-15K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100000);
+ EXPECT_STREQ("-.1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155555);
+ EXPECT_STREQ("-.1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000000);
+ EXPECT_STREQ("-1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1555555);
+ EXPECT_STREQ("-1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10000000);
+ EXPECT_STREQ("-10M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15555555);
+ EXPECT_STREQ("-15M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100000000);
+ EXPECT_STREQ("-.1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155555555);
+ EXPECT_STREQ("-.1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000000000);
+ EXPECT_STREQ("-1B", size_str);
+
+ /* Smallest possible value. */
+ BLI_str_format_integer_unit(size_str, size = -INT32_MAX);
+ EXPECT_STREQ("-2B", size_str);
+}
+
struct WordInfo {
WordInfo() = default;
WordInfo(int start, int end) : start(start), end(end)
diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc
index ec1768232c8..569798048f6 100644
--- a/source/blender/blenloader/intern/readfile.cc
+++ b/source/blender/blenloader/intern/readfile.cc
@@ -2143,7 +2143,7 @@ static void direct_link_id_common(
BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag)
{
if (!BLO_read_data_is_undo(reader)) {
- /* When actually reading a file, we do want to reset/re-generate session uuids.
+ /* When actually reading a file, we do want to reset/re-generate session UUIDS.
* In undo case, we want to re-use existing ones. */
id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
}
diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc
index e2b98b2283f..a2bd7fd2fd1 100644
--- a/source/blender/blenloader/intern/versioning_300.cc
+++ b/source/blender/blenloader/intern/versioning_300.cc
@@ -3630,6 +3630,29 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 304, 5)) {
+ /* Fix for T101622 - update flags of sequence editor regions that were not initialized
+ * properly. */
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
+ &sl->regionbase;
+ if (sl->spacetype == SPACE_SEQ) {
+ LISTBASE_FOREACH (ARegion *, region, regionbase) {
+ if (region->regiontype == RGN_TYPE_TOOLS) {
+ region->v2d.flag &= ~V2D_VIEWSYNC_AREA_VERTICAL;
+ }
+ if (region->regiontype == RGN_TYPE_CHANNELS) {
+ region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 8da28af3ca7..c45f9dbe49c 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -2058,7 +2058,7 @@ 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 sub-samples in `prof_co_2`. */
int subsample_spacing = bp->pro_spacing.seg_2 / nseg;
copy_v3_v3(r_co, pro->prof_co_2 + 3 * i * subsample_spacing);
}
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index 14ec45f14b0..bdc36559e05 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -175,7 +175,7 @@ void BM_mesh_wireframe(BMesh *bm,
BMVert **verts_neg = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
BMVert **verts_pos = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
- /* Will over-alloc, but makes for easy lookups by index to keep aligned. */
+ /* Will over-allocate, but makes for easy lookups by index to keep aligned. */
BMVert **verts_boundary = use_boundary ? MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__) :
NULL;
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h
index 16d1e2e6bb5..ffd02ed5a2f 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertOperation.h
@@ -98,7 +98,7 @@ class ConvertVectorToValueOperation : public ConvertBaseOperation {
class ConvertRGBToYCCOperation : public ConvertBaseOperation {
private:
- /** YCbCr mode (Jpeg, ITU601, ITU709) */
+ /** YCbCr mode (JPEG, ITU601, ITU709) */
int mode_;
public:
@@ -116,7 +116,7 @@ class ConvertRGBToYCCOperation : public ConvertBaseOperation {
class ConvertYCCToRGBOperation : public ConvertBaseOperation {
private:
- /** YCbCr mode (Jpeg, ITU601, ITU709) */
+ /** YCbCr mode (JPEG, ITU601, ITU709) */
int mode_;
public:
diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt
index 90cbe0988ad..bab0b5385ec 100644
--- a/source/blender/compositor/realtime_compositor/CMakeLists.txt
+++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt
@@ -2,7 +2,7 @@
set(INC
.
- ./algorithms
+ algorithms
../../blenkernel
../../blenlib
../../gpu
diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
index 9d0851eff84..f6d479f9bbe 100644
--- a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
+++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
@@ -27,6 +27,13 @@ float sum_blue(Context &context, GPUTexture *texture);
* coefficients to compute the luminance. */
float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+/* Computes the sum of the logarithm of the luminance of all pixels in the given texture, using the
+ * given luminance coefficients to compute the luminance. */
+float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* Computes the sum of the colors of all pixels in the given texture. */
+float4 sum_color(Context &context, GPUTexture *texture);
+
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
@@ -55,4 +62,42 @@ float sum_luminance_squared_difference(Context &context,
float3 luminance_coefficients,
float subtrahend);
+/* --------------------------------------------------------------------
+ * Maximum Reductions.
+ */
+
+/* Computes the maximum luminance of all pixels in the given texture, using the given luminance
+ * coefficients to compute the luminance. */
+float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* Computes the maximum float of all pixels in the given float texture, limited to the given range.
+ * Values outside of the given range are ignored. If non of the pixel values are in the range, the
+ * lower bound of the range is returned. For instance, if the given range is [-10, 10] and the
+ * image contains the values {2, 5, 11}, the maximum will be 5, since 11 is outside of the range.
+ * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite
+ * values, so enforcing an upper bound is beneficial. */
+float maximum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound);
+
+/* --------------------------------------------------------------------
+ * Minimum Reductions.
+ */
+
+/* Computes the minimum luminance of all pixels in the given texture, using the given luminance
+ * coefficients to compute the luminance. */
+float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* Computes the minimum float of all pixels in the given float texture, limited to the given range.
+ * Values outside of the given range are ignored. If non of the pixel values are in the range, the
+ * upper bound of the range is returned. For instance, if the given range is [-10, 10] and the
+ * image contains the values {-11, 2, 5}, the minimum will be 2, since -11 is outside of the range.
+ * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite
+ * values, so enforcing a lower bound is beneficial. */
+float minimum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound);
+
} // namespace blender::realtime_compositor
diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
index 3266ccd14eb..9672431992d 100644
--- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
+++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
@@ -134,6 +134,34 @@ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coef
return sum;
}
+float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_sum_log_luminance");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float sum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return sum;
+}
+
+float4 sum_color(Context &context, GPUTexture *texture)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_sum_color");
+ GPU_shader_bind(shader);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_RGBA32F);
+ const float4 sum = float4(reduced_value);
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return sum;
+}
+
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
@@ -202,4 +230,80 @@ float sum_luminance_squared_difference(Context &context,
return sum;
}
+/* --------------------------------------------------------------------
+ * Maximum Reductions.
+ */
+
+float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_maximum_luminance");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float maximum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return maximum;
+}
+
+float maximum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_maximum_float_in_range");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "lower_bound", lower_bound);
+ GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float maximum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return maximum;
+}
+
+/* --------------------------------------------------------------------
+ * Minimum Reductions.
+ */
+
+float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_minimum_luminance");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float minimum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return minimum;
+}
+
+float minimum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_minimum_float_in_range");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "lower_bound", lower_bound);
+ GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float minimum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return minimum;
+}
+
} // namespace blender::realtime_compositor
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index f95c0700a47..c84852788fd 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -453,6 +453,11 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD
if (id == nullptr) {
return IDWALK_RET_NOP;
}
+ if (!ID_TYPE_IS_COW(GS(id->name))) {
+ /* No need to go further if the id never had a cow copy in the depsgraph. This function is
+ * only concerned with keeping the mapping between original and COW ids intact. */
+ return IDWALK_RET_NOP;
+ }
DepsgraphNodeBuilder *builder = static_cast<DepsgraphNodeBuilder *>(cb_data->user_data);
ID *id_cow_self = cb_data->id_self;
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 4636011e18b..11998860ef3 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -191,8 +191,8 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
bool is_neg_scale = is_negative_m4(dob->mat);
SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE);
- copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
- invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat);
+ copy_m4_m4(data->temp_dupli_object.object_to_world, dob->mat);
+ invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.object_to_world);
data->next_object = &data->temp_dupli_object;
BLI_assert(deg::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id));
return true;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index a5b29ae56a9..62a9158928d 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -284,7 +284,7 @@ void invalidate_tagged_evaluated_transform(ID *id)
switch (id_type) {
case ID_OB: {
Object *object = (Object *)id;
- copy_vn_fl((float *)object->obmat, 16, NAN);
+ copy_vn_fl((float *)object->object_to_world, 16, NAN);
break;
}
default:
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index a645bd6b6af..4010b491141 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -71,7 +71,7 @@ set(SRC
intern/draw_attributes.cc
intern/draw_cache_impl_curve.cc
intern/draw_cache_impl_curves.cc
- intern/draw_cache_impl_gpencil.c
+ intern/draw_cache_impl_gpencil.cc
intern/draw_cache_impl_lattice.c
intern/draw_cache_impl_mesh.cc
intern/draw_cache_impl_particles.c
@@ -95,6 +95,7 @@ set(SRC
intern/draw_manager_text.cc
intern/draw_manager_texture.c
intern/draw_pbvh.cc
+ intern/draw_pointcloud.cc
intern/draw_select_buffer.c
intern/draw_shader.cc
intern/draw_texture_pool.cc
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index eee6a5a7cb5..05e62764bb1 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -182,7 +182,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
}
}
- const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool do_cull = (draw_ctx->v3d &&
(draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING));
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 942ab5502c7..eb111610706 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -403,7 +403,7 @@ static bool eevee_lightprobes_culling_test(Object *ob)
const float max[3] = {1.0f, 1.0f, 1.0f};
BKE_boundbox_init_from_minmax(&bbox, min, max);
- copy_m4_m4(tmp, ob->obmat);
+ copy_m4_m4(tmp, ob->object_to_world);
normalize_v3(tmp[2]);
mul_v3_fl(tmp[2], probe->distinf);
@@ -445,7 +445,7 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
/* Debug Display */
DRWCallBuffer *grp = vedata->stl->g_data->planar_display_shgrp;
if (grp && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
- DRW_buffer_add_entry(grp, &pinfo->num_planar, ob->obmat);
+ DRW_buffer_add_entry(grp, &pinfo->num_planar, ob->object_to_world);
}
pinfo->num_planar++;
@@ -488,30 +488,30 @@ void EEVEE_lightprobes_grid_data_from_object(Object *ob, EEVEE_LightGrid *egrid,
mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
/* Matrix converting world space to cell ranges. */
- invert_m4_m4(egrid->mat, ob->obmat);
+ invert_m4_m4(egrid->mat, ob->object_to_world);
/* First cell. */
copy_v3_fl(egrid->corner, -1.0f);
add_v3_v3(egrid->corner, half_cell_dim);
- mul_m4_v3(ob->obmat, egrid->corner);
+ mul_m4_v3(ob->object_to_world, egrid->corner);
/* Opposite neighbor cell. */
copy_v3_fl3(egrid->increment_x, cell_dim[0], 0.0f, 0.0f);
add_v3_v3(egrid->increment_x, half_cell_dim);
add_v3_fl(egrid->increment_x, -1.0f);
- mul_m4_v3(ob->obmat, egrid->increment_x);
+ mul_m4_v3(ob->object_to_world, egrid->increment_x);
sub_v3_v3(egrid->increment_x, egrid->corner);
copy_v3_fl3(egrid->increment_y, 0.0f, cell_dim[1], 0.0f);
add_v3_v3(egrid->increment_y, half_cell_dim);
add_v3_fl(egrid->increment_y, -1.0f);
- mul_m4_v3(ob->obmat, egrid->increment_y);
+ mul_m4_v3(ob->object_to_world, egrid->increment_y);
sub_v3_v3(egrid->increment_y, egrid->corner);
copy_v3_fl3(egrid->increment_z, 0.0f, 0.0f, cell_dim[2]);
add_v3_v3(egrid->increment_z, half_cell_dim);
add_v3_fl(egrid->increment_z, -1.0f);
- mul_m4_v3(ob->obmat, egrid->increment_z);
+ mul_m4_v3(ob->object_to_world, egrid->increment_z);
sub_v3_v3(egrid->increment_z, egrid->corner);
/* Visibility bias */
@@ -527,7 +527,7 @@ void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprob
LightProbe *probe = (LightProbe *)ob->data;
/* Update transforms */
- copy_v3_v3(eprobe->position, ob->obmat[3]);
+ copy_v3_v3(eprobe->position, ob->object_to_world[3]);
/* Attenuation */
eprobe->attenuation_type = probe->attenuation_type;
@@ -535,7 +535,7 @@ void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprob
unit_m4(eprobe->attenuationmat);
scale_m4_fl(eprobe->attenuationmat, probe->distinf);
- mul_m4_m4m4(eprobe->attenuationmat, ob->obmat, eprobe->attenuationmat);
+ mul_m4_m4m4(eprobe->attenuationmat, ob->object_to_world, eprobe->attenuationmat);
invert_m4(eprobe->attenuationmat);
/* Parallax */
@@ -550,7 +550,7 @@ void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprob
scale_m4_fl(eprobe->parallaxmat, probe->distinf);
}
- mul_m4_m4m4(eprobe->parallaxmat, ob->obmat, eprobe->parallaxmat);
+ mul_m4_m4m4(eprobe->parallaxmat, ob->object_to_world, eprobe->parallaxmat);
invert_m4(eprobe->parallaxmat);
}
@@ -566,8 +566,8 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob,
vis_test->cached = false;
/* Computing mtx : matrix that mirror position around object's XY plane. */
- normalize_m4_m4(normat, ob->obmat); /* object > world */
- invert_m4_m4(imat, normat); /* world > object */
+ normalize_m4_m4(normat, ob->object_to_world); /* object > world */
+ invert_m4_m4(imat, normat); /* world > object */
/* XY reflection plane */
imat[0][2] = -imat[0][2];
imat[1][2] = -imat[1][2];
@@ -576,38 +576,38 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob,
mul_m4_m4m4(eplanar->mtx, normat, imat); /* world > object > mirrored obj > world */
/* Compute clip plane equation / normal. */
- copy_v3_v3(eplanar->plane_equation, ob->obmat[2]);
+ copy_v3_v3(eplanar->plane_equation, ob->object_to_world[2]);
normalize_v3(eplanar->plane_equation); /* plane normal */
- eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->obmat[3]);
+ eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->object_to_world[3]);
eplanar->clipsta = probe->clipsta;
/* Compute XY clip planes. */
- normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]);
- normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]);
+ normalize_v3_v3(eplanar->clip_vec_x, ob->object_to_world[0]);
+ normalize_v3_v3(eplanar->clip_vec_y, ob->object_to_world[1]);
float vec[3] = {0.0f, 0.0f, 0.0f};
vec[0] = 1.0f;
vec[1] = 0.0f;
vec[2] = 0.0f;
- mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */
eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec);
vec[0] = 0.0f;
vec[1] = 1.0f;
vec[2] = 0.0f;
- mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */
eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec);
vec[0] = -1.0f;
vec[1] = 0.0f;
vec[2] = 0.0f;
- mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */
eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec);
vec[0] = 0.0f;
vec[1] = -1.0f;
vec[2] = 0.0f;
- mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ mul_m4_v3(ob->object_to_world, vec); /* Point on the edge */
eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
/* Facing factors */
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 312305a31f7..f8250f9520d 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -132,7 +132,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
const float light_threshold = draw_ctx->scene->eevee.light_threshold;
/* Position */
- copy_v3_v3(evli->position, ob->obmat[3]);
+ copy_v3_v3(evli->position, ob->object_to_world[3]);
/* Color */
copy_v3_v3(evli->color, &la->r);
@@ -153,7 +153,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
evli->invsqrdist_volume = 1.0f / max_ff(1e-4f, square_f(att_radius_volume));
/* Vectors */
- normalize_m4_m4_ex(mat, ob->obmat, scale);
+ normalize_m4_m4_ex(mat, ob->object_to_world, scale);
copy_v3_v3(evli->forwardvec, mat[2]);
normalize_v3(evli->forwardvec);
negate_v3(evli->forwardvec);
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index b5f81f3a307..b134d7f6dc6 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -810,7 +810,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
if (ob->sculpt && ob->sculpt->pbvh) {
@@ -924,17 +924,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata,
if (matcache.depth_grp) {
*matcache.depth_grp_p = DRW_shgroup_hair_create_sub(
ob, psys, md, matcache.depth_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat);
}
if (matcache.shading_grp) {
*matcache.shading_grp_p = DRW_shgroup_hair_create_sub(
ob, psys, md, matcache.shading_grp, matcache.shading_gpumat);
- DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat);
}
if (matcache.shadow_grp) {
*matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(
ob, psys, md, matcache.shadow_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat);
*cast_shadow = true;
}
@@ -954,16 +951,13 @@ void EEVEE_object_curves_cache_populate(EEVEE_Data *vedata,
if (matcache.depth_grp) {
*matcache.depth_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.depth_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat);
}
if (matcache.shading_grp) {
*matcache.shading_grp_p = DRW_shgroup_curves_create_sub(
ob, matcache.shading_grp, matcache.shading_gpumat);
- DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat);
}
if (matcache.shadow_grp) {
*matcache.shadow_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.shadow_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat);
*cast_shadow = true;
}
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index a3ca19c88e1..9f7fb1c154c 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -292,7 +292,7 @@ void EEVEE_motion_blur_curves_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata)
int mb_step = effects->motion_blur_step;
/* Store transform. */
- copy_m4_m4(mb_data->obmat[mb_step], ob->obmat);
+ copy_m4_m4(mb_data->obmat[mb_step], ob->object_to_world);
EEVEE_HairMotionData *mb_curves = EEVEE_motion_blur_curves_data_get(mb_data);
@@ -362,7 +362,7 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
if (mb_data) {
int mb_step = effects->motion_blur_step;
/* Store transform. */
- copy_m4_m4(mb_data->obmat[mb_step], ob->obmat);
+ copy_m4_m4(mb_data->obmat[mb_step], ob->object_to_world);
EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(mb_data);
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index 9e571b1d15b..1cf3c7c6da1 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -153,7 +153,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
for (int i = 0; i < 8; i++) {
float vec[3];
copy_v3_v3(vec, bb->vec[i]);
- mul_m4_v3(ob->obmat, vec);
+ mul_m4_v3(ob->object_to_world, vec);
minmax_v3v3_v3(min, max, vec);
}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 05b2bafdb3a..872696a8b7c 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -299,7 +299,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
}
float size[3];
- mat4_to_size(size, ob->obmat);
+ mat4_to_size(size, ob->object_to_world);
/* Check if any of the axes have 0 length. (see T69070) */
const float epsilon = 1e-8f;
if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) {
diff --git a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl
index 90272400915..5af317b7398 100644
--- a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl
@@ -96,7 +96,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod)
/* Mix all colors to get the corner color. */
vec4 col3 = (col + col1 + col2) / 3.0;
- vec2 mix_fac = uv_border * 0.5;
+ vec2 mix_fac = saturate(uv_border * 0.5);
return mix(mix(col, col2, mix_fac.x), mix(col1, col3, mix_fac.x), mix_fac.y);
}
else if (any(border)) {
@@ -108,7 +108,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod)
uv = cubemap_face_coord(cubevec.xyz, face);
coord = vec3(uv, cubevec.w * 6.0 + face);
- float mix_fac = max(uv_border.x, uv_border.y) * 0.5;
+ float mix_fac = saturate(max(uv_border.x, uv_border.y) * 0.5);
return mix(col, textureLod(tex, coord, lod), mix_fac);
}
else {
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
index 51a351babd3..5f04cdcebfa 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
@@ -95,7 +95,11 @@ void main()
weights = dof_layer_weight(cocs) * dof_sample_weight(cocs);
/* Filter NaNs. */
- weights = select(weights, vec4(0.0), equal(cocs, vec4(0.0)));
+ for (int i = 0; i < 4; i++) {
+ if (isnan(weights[i]) || isinf(weights[i])) {
+ weights[i] = 0.0;
+ }
+ }
color1 = colors[0] * weights[0];
color2 = colors[1] * weights[1];
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index 062a40f35c2..ccf6d6e2042 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -30,7 +30,7 @@ void main()
vec3 world_pos = pos;
#elif defined(POINTCLOUD_SHADER)
pointcloud_get_pos_and_radius(pointPosition, pointRadius);
- pointID = gl_VertexID;
+ pointID = pointcloud_get_point_id();
#else
vec3 world_pos = point_object_to_world(pos);
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
index 8f49c7bd265..7a22b2c53d7 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
@@ -37,7 +37,7 @@ void main()
vec3 world_pos = pos;
#elif defined(POINTCLOUD_SHADER)
pointcloud_get_pos_and_radius(pointPosition, pointRadius);
- pointID = gl_VertexID;
+ pointID = pointcloud_get_point_id();
#else
vec3 world_pos = point_object_to_world(pos);
#endif
diff --git a/source/blender/draw/engines/eevee_next/eevee_light.cc b/source/blender/draw/engines/eevee_next/eevee_light.cc
index 8a5de15229d..aa8268dbaa7 100644
--- a/source/blender/draw/engines/eevee_next/eevee_light.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_light.cc
@@ -58,7 +58,7 @@ void Light::sync(/* ShadowModule &shadows , */ const Object *ob, float threshold
this->influence_radius_invsqr_volume = 1.0f / square_f(max_ff(influence_radius_volume, 1e-8f));
this->color = float3(&la->r) * la->energy;
- normalize_m4_m4_ex(this->object_mat.ptr(), ob->obmat, scale);
+ normalize_m4_m4_ex(this->object_mat.ptr(), ob->object_to_world, scale);
/* Make sure we have consistent handedness (in case of negatively scaled Z axis). */
float3 cross = math::cross(float3(this->_right), float3(this->_up));
if (math::dot(cross, float3(this->_back)) < 0.0f) {
diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
index e6b37b4ad47..0242f732f27 100644
--- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
@@ -182,7 +182,7 @@ PassMain::Sub *ForwardPipeline::prepass_transparent_add(const Object *ob,
if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
state |= DRW_STATE_CULL_BACK;
}
- float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_);
+ float sorting_value = math::dot(float3(ob->object_to_world[3]), camera_forward_);
PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
pass->state_set(state);
pass->material_set(*inst_.manager, gpumat);
@@ -197,7 +197,7 @@ PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob,
if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
state |= DRW_STATE_CULL_BACK;
}
- float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_);
+ float sorting_value = math::dot(float3(ob->object_to_world[3]), camera_forward_);
PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
pass->state_set(state);
pass->material_set(*inst_.manager, gpumat);
diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc
index 08cda6f47cf..cbd735ec29c 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sync.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc
@@ -248,17 +248,17 @@ static void gpencil_stroke_sync(bGPDlayer * /*gpl*/,
return;
}
+ GPUBatch *geom = DRW_cache_gpencil_get(iter.ob, iter.cfra);
+
if (show_fill) {
- GPUBatch *geom = DRW_cache_gpencil_fills_get(iter.ob, iter.cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
gpencil_drawcall_add(iter, geom, material, vfirst, vcount, false);
}
if (show_stroke) {
- GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter.ob, iter.cfra);
/* Start one vert before to have gl_InstanceID > 0 (see shader). */
- int vfirst = gps->runtime.stroke_start - 1;
+ int vfirst = gps->runtime.stroke_start * 3;
/* Include "potential" cyclic vertex and start adj vertex (see shader). */
int vcount = gps->totpoints + 1 + 1;
gpencil_drawcall_add(iter, geom, material, vfirst, vcount, true);
diff --git a/source/blender/draw/engines/eevee_next/eevee_velocity.cc b/source/blender/draw/engines/eevee_next/eevee_velocity.cc
index b9a78e8547e..52401c8003e 100644
--- a/source/blender/draw/engines/eevee_next/eevee_velocity.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_velocity.cc
@@ -106,16 +106,16 @@ bool VelocityModule::step_object_sync(Object *ob,
vel.obj.ofs[step_] = object_steps_usage[step_]++;
vel.obj.resource_id = resource_handle.resource_index();
vel.id = (ID *)ob->data;
- object_steps[step_]->get_or_resize(vel.obj.ofs[step_]) = ob->obmat;
+ object_steps[step_]->get_or_resize(vel.obj.ofs[step_]) = ob->object_to_world;
if (step_ == STEP_CURRENT) {
/* Replace invalid steps. Can happen if object was hidden in one of those steps. */
if (vel.obj.ofs[STEP_PREVIOUS] == -1) {
vel.obj.ofs[STEP_PREVIOUS] = object_steps_usage[STEP_PREVIOUS]++;
- object_steps[STEP_PREVIOUS]->get_or_resize(vel.obj.ofs[STEP_PREVIOUS]) = ob->obmat;
+ object_steps[STEP_PREVIOUS]->get_or_resize(vel.obj.ofs[STEP_PREVIOUS]) = ob->object_to_world;
}
if (vel.obj.ofs[STEP_NEXT] == -1) {
vel.obj.ofs[STEP_NEXT] = object_steps_usage[STEP_NEXT]++;
- object_steps[STEP_NEXT]->get_or_resize(vel.obj.ofs[STEP_NEXT]) = ob->obmat;
+ object_steps[STEP_NEXT]->get_or_resize(vel.obj.ofs[STEP_NEXT]) = ob->object_to_world;
}
}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl
index 38debf14eda..87a5bf71c45 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl
@@ -16,30 +16,18 @@ void main()
float hardness;
vec2 thickness;
- gl_Position = gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- /* TODO */
- vec4(1024.0, 1024.0, 1.0 / 1024.0, 1.0 / 1024.0),
- interp.P,
- interp.N,
- g_color,
- strength,
- g_uvs,
- sspos,
- aspect,
- thickness,
- hardness);
+ gl_Position = gpencil_vertex(
+ /* TODO */
+ vec4(1024.0, 1024.0, 1.0 / 1024.0, 1.0 / 1024.0),
+ interp.P,
+ interp.N,
+ g_color,
+ strength,
+ g_uvs,
+ sspos,
+ aspect,
+ thickness,
+ hardness);
#ifdef MAT_VELOCITY
/* GPencil do not support deformation motion blur. */
vec3 lP_curr = transform_point(ModelMatrixInverse, interp.P);
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index a41918e7e0d..06bf531cded 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -39,9 +39,9 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob)
tgp_ob->layers.first = tgp_ob->layers.last = NULL;
tgp_ob->vfx.first = tgp_ob->vfx.last = NULL;
- tgp_ob->camera_z = dot_v3v3(pd->camera_z_axis, ob->obmat[3]);
+ tgp_ob->camera_z = dot_v3v3(pd->camera_z_axis, ob->object_to_world[3]);
tgp_ob->is_drawmode3d = (gpd->draw_mode == GP_DRAWMODE_3D) || pd->draw_depth_only;
- tgp_ob->object_scale = mat4_to_scale(ob->obmat);
+ tgp_ob->object_scale = mat4_to_scale(ob->object_to_world);
/* Check if any material with holdout flag enabled. */
tgp_ob->do_mat_holdout = false;
@@ -71,7 +71,7 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob)
add_v3_fl(size, 1e-8f);
rescale_m4(mat, size);
/* BBox space to World. */
- mul_m4_m4m4(mat, ob->obmat, mat);
+ mul_m4_m4m4(mat, ob->object_to_world, mat);
if (DRW_view_is_persp_get(NULL)) {
/* BBox center to camera vector. */
sub_v3_v3v3(tgp_ob->plane_normal, pd->camera_pos, mat[3]);
@@ -96,9 +96,9 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob)
unit_m4(tgp_ob->plane_mat);
copy_v3_v3(tgp_ob->plane_mat[2], tgp_ob->plane_normal);
orthogonalize_m4(tgp_ob->plane_mat, 2);
- mul_mat3_m4_v3(ob->obmat, size);
+ mul_mat3_m4_v3(ob->object_to_world, size);
float radius = len_v3(size);
- mul_m4_v3(ob->obmat, center);
+ mul_m4_v3(ob->object_to_world, center);
rescale_m4(tgp_ob->plane_mat, (float[3]){radius, radius, radius});
copy_v3_v3(tgp_ob->plane_mat[3], center);
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index e54ac99a888..07b72c97875 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -387,20 +387,20 @@ void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob)
}
else if (la->type == LA_AREA) {
/* Simulate area lights using a spot light. */
- normalize_m4_m4(mat, ob->obmat);
+ normalize_m4_m4(mat, ob->object_to_world);
invert_m4(mat);
gp_light->type = GP_LIGHT_TYPE_SPOT;
gp_light->spot_size = cosf(M_PI_2);
gp_light->spot_blend = (1.0f - gp_light->spot_size) * 1.0f;
}
else if (la->type == LA_SUN) {
- normalize_v3_v3(gp_light->forward, ob->obmat[2]);
+ normalize_v3_v3(gp_light->forward, ob->object_to_world[2]);
gp_light->type = GP_LIGHT_TYPE_SUN;
}
else {
gp_light->type = GP_LIGHT_TYPE_POINT;
}
- copy_v4_v4(gp_light->position, ob->obmat[3]);
+ copy_v4_v4(gp_light->position, ob->object_to_world[3]);
copy_v3_v3(gp_light->color, &la->r);
mul_v3_fl(gp_light->color, la->energy * light_power_get(la));
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index b24e4c605e4..78e658d35eb 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -342,7 +342,6 @@ typedef struct gpIterPopulateData {
int stroke_index_offset;
/* Infos for call batching. */
struct GPUBatch *geom;
- bool instancing;
int vfirst, vcount;
} gpIterPopulateData;
@@ -352,12 +351,7 @@ static void gpencil_drawcall_flush(gpIterPopulateData *iter)
{
#if !DISABLE_BATCHING
if (iter->geom != NULL) {
- if (iter->instancing) {
- DRW_shgroup_call_instance_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount);
- }
- else {
- DRW_shgroup_call_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount);
- }
+ DRW_shgroup_call_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount);
}
#endif
@@ -367,25 +361,22 @@ static void gpencil_drawcall_flush(gpIterPopulateData *iter)
}
/* Group draw-calls that are consecutive and with the same type. Reduces GPU driver overhead. */
-static void gpencil_drawcall_add(
- gpIterPopulateData *iter, struct GPUBatch *geom, bool instancing, int v_first, int v_count)
+static void gpencil_drawcall_add(gpIterPopulateData *iter,
+ struct GPUBatch *geom,
+ int v_first,
+ int v_count)
{
#if DISABLE_BATCHING
- if (instancing) {
- DRW_shgroup_call_instance_range(iter->grp, iter->ob, geom, v_first, v_count);
- }
- else {
- DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count);
- }
+ DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count);
+ return;
#endif
int last = iter->vfirst + iter->vcount;
/* Interrupt draw-call grouping if the sequence is not consecutive. */
- if ((geom != iter->geom) || (v_first - last > 3)) {
+ if ((geom != iter->geom) || (v_first - last > 0)) {
gpencil_drawcall_flush(iter);
}
iter->geom = geom;
- iter->instancing = instancing;
if (iter->vfirst == -1) {
iter->vfirst = v_first;
}
@@ -516,22 +507,33 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl,
bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW);
+ GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_get(iter->ob, show_fill) :
+ DRW_cache_gpencil_get(iter->ob, iter->pd->cfra);
+ if (geom != iter->geom) {
+ gpencil_drawcall_flush(iter);
+
+ GPUVertBuf *position_tx = do_sbuffer ?
+ DRW_cache_gpencil_sbuffer_position_buffer_get(iter->ob,
+ show_fill) :
+ DRW_cache_gpencil_position_buffer_get(iter->ob, iter->pd->cfra);
+ GPUVertBuf *color_tx = do_sbuffer ?
+ DRW_cache_gpencil_sbuffer_color_buffer_get(iter->ob, show_fill) :
+ DRW_cache_gpencil_color_buffer_get(iter->ob, iter->pd->cfra);
+ DRW_shgroup_buffer_texture(iter->grp, "gp_pos_tx", position_tx);
+ DRW_shgroup_buffer_texture(iter->grp, "gp_col_tx", color_tx);
+ }
+
if (show_fill) {
- GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_fill_get(iter->ob) :
- DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
- gpencil_drawcall_add(iter, geom, false, vfirst, vcount);
+ gpencil_drawcall_add(iter, geom, vfirst, vcount);
}
if (show_stroke) {
- GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_stroke_get(iter->ob) :
- DRW_cache_gpencil_strokes_get(iter->ob, iter->pd->cfra);
- /* Start one vert before to have gl_InstanceID > 0 (see shader). */
- int vfirst = gps->runtime.stroke_start - 1;
- /* Include "potential" cyclic vertex and start adj vertex (see shader). */
- int vcount = gps->totpoints + 1 + 1;
- gpencil_drawcall_add(iter, geom, true, vfirst, vcount);
+ int vfirst = gps->runtime.stroke_start * 3;
+ bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2);
+ int vcount = (gps->totpoints + (int)is_cyclic) * 2 * 3;
+ gpencil_drawcall_add(iter, geom, vfirst, vcount);
}
iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1;
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index a7d8570dbaa..9b1129e77be 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -96,7 +96,7 @@ static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *it
float winmat[4][4], persmat[4][4];
float blur_size[2] = {fx->radius[0], fx->radius[1]};
DRW_view_persmat_get(NULL, persmat, false);
- const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3]));
if (fx->flag & FX_BLUR_DOF_MODE) {
/* Compute circle of confusion size. */
@@ -108,7 +108,7 @@ static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *it
DRW_view_winmat_get(NULL, winmat, false);
const float *vp_size = DRW_viewport_size_get();
float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
- float scale = mat4_to_scale(ob->obmat);
+ float scale = mat4_to_scale(ob->object_to_world);
float distance_factor = world_pixel_scale * scale * winmat[1][1] * vp_size[1] / w;
mul_v2_fl(blur_size, distance_factor);
}
@@ -175,11 +175,11 @@ static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter
const float *vp_size = DRW_viewport_size_get();
const float *vp_size_inv = DRW_viewport_invert_size_get();
- const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3]));
/* Modify by distance to camera and object scale. */
float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
- float scale = mat4_to_scale(ob->obmat);
+ float scale = mat4_to_scale(ob->object_to_world);
float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
mul_v2_fl(offset, distance_factor);
mul_v2_v2(offset, vp_size_inv);
@@ -248,8 +248,8 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat
mul_v2_v2(pixel_size, vp_size_inv);
/* Fixed pixelisation center from object center. */
- const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
- mul_v3_m4v3(ob_center, persmat, ob->obmat[3]);
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3]));
+ mul_v3_m4v3(ob_center, persmat, ob->object_to_world[3]);
mul_v3_fl(ob_center, 1.0f / w);
const bool use_antialiasing = ((fx->flag & FX_PIXEL_FILTER_NEAREST) == 0);
@@ -260,7 +260,7 @@ static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxDat
/* Modify by distance to camera and object scale. */
float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
- float scale = mat4_to_scale(ob->obmat);
+ float scale = mat4_to_scale(ob->object_to_world);
mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w);
/* Center to texel */
@@ -310,7 +310,9 @@ static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData
const float *vp_size_inv = DRW_viewport_invert_size_get();
const float ratio = vp_size_inv[1] / vp_size_inv[0];
- copy_v3_v3(rot_center, (use_obj_pivot && fx->object) ? fx->object->obmat[3] : ob->obmat[3]);
+ copy_v3_v3(rot_center,
+ (use_obj_pivot && fx->object) ? fx->object->object_to_world[3] :
+ ob->object_to_world[3]);
const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center));
mul_v3_m4v3(rot_center, persmat, rot_center);
@@ -318,7 +320,7 @@ static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData
/* Modify by distance to camera and object scale. */
float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
- float scale = mat4_to_scale(ob->obmat);
+ float scale = mat4_to_scale(ob->object_to_world);
float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
mul_v2_fl(offset, distance_factor);
mul_v2_v2(offset, vp_size_inv);
@@ -485,13 +487,13 @@ static void gpencil_vfx_wave(WaveShaderFxData *fx, Object *ob, gpIterVfxData *it
const float *vp_size = DRW_viewport_size_get();
const float *vp_size_inv = DRW_viewport_invert_size_get();
- const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
- mul_v3_m4v3(wave_center, persmat, ob->obmat[3]);
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->object_to_world[3]));
+ mul_v3_m4v3(wave_center, persmat, ob->object_to_world[3]);
mul_v3_fl(wave_center, 1.0f / w);
/* Modify by distance to camera and object scale. */
float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
- float scale = mat4_to_scale(ob->obmat);
+ float scale = mat4_to_scale(ob->object_to_world);
float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
wave_center[0] = wave_center[0] * 0.5f + 0.5f;
@@ -542,7 +544,7 @@ static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *UNUSED(ob), gpIterV
DRW_view_persmat_get(NULL, persmat, false);
const float *vp_size = DRW_viewport_size_get();
- copy_v3_v3(swirl_center, fx->object->obmat[3]);
+ copy_v3_v3(swirl_center, fx->object->object_to_world[3]);
const float w = fabsf(mul_project_m4_v3_zfac(persmat, swirl_center));
mul_v3_m4v3(swirl_center, persmat, swirl_center);
@@ -550,7 +552,7 @@ static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *UNUSED(ob), gpIterV
/* Modify by distance to camera and object scale. */
float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
- float scale = mat4_to_scale(fx->object->obmat);
+ float scale = mat4_to_scale(fx->object->object_to_world);
float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
mul_v2_fl(swirl_center, 0.5f);
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_shared.h b/source/blender/draw/engines/gpencil/gpencil_shader_shared.h
index 4c621e955b9..3f0f73e7c13 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_shared.h
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_shared.h
@@ -41,6 +41,9 @@ enum gpLightType {
GP_LIGHT_TYPE_AMBIENT = 3u,
};
+#define GP_IS_STROKE_VERTEX_BIT (1 << 30)
+#define GP_VERTEX_ID_SHIFT 2
+
/* Avoid compiler funkiness with enum types not being strongly typed in C. */
#ifndef GPU_SHADER
# define gpMaterialFlag uint
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 7ddfdc5f65c..642939136c8 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -1,92 +1,4 @@
-/* Must match C declaration. */
-struct gpMaterial {
- vec4 stroke_color;
- vec4 fill_color;
- vec4 fill_mix_color;
- vec4 fill_uv_rot_scale;
- vec4 fill_uv_offset;
- /* Put float/int at the end to avoid padding error */
- /* Some drivers are completely messing the alignment or the fetches here.
- * We are forced to pack these into vec4 otherwise we only get 0.0 as value. */
- vec4 gp_mat_packed_1;
- // float stroke_texture_mix;
- // float stroke_u_scale;
- // float fill_texture_mix;
- // int gp_flag;
- /* Please ensure 16 byte alignment (multiple of vec4). */
-};
-
-#define MATERIAL(m) materials[m + gpMaterialOffset]
-
-#define stroke_texture_mix gp_mat_packed_1.x
-#define stroke_u_scale gp_mat_packed_1.y
-#define fill_texture_mix gp_mat_packed_1.z
-#define GP_FLAG(m) floatBitsToInt(MATERIAL(m).gp_mat_packed_1.w)
-
-/* flag */
-#define GP_STROKE_ALIGNMENT_STROKE 1
-#define GP_STROKE_ALIGNMENT_OBJECT 2
-#define GP_STROKE_ALIGNMENT_FIXED 3
-#define GP_STROKE_ALIGNMENT 0x3
-#define GP_STROKE_OVERLAP (1 << 2)
-#define GP_STROKE_TEXTURE_USE (1 << 3)
-#define GP_STROKE_TEXTURE_STENCIL (1 << 4)
-#define GP_STROKE_TEXTURE_PREMUL (1 << 5)
-#define GP_STROKE_DOTS (1 << 6)
-#define GP_STROKE_HOLDOUT (1 << 7)
-#define GP_FILL_HOLDOUT (1 << 8)
-#define GP_FILL_TEXTURE_USE (1 << 10)
-#define GP_FILL_TEXTURE_PREMUL (1 << 11)
-#define GP_FILL_TEXTURE_CLIP (1 << 12)
-#define GP_FILL_GRADIENT_USE (1 << 13)
-#define GP_FILL_GRADIENT_RADIAL (1 << 14)
-/* High bits are used to pass material ID to fragment shader. */
-#define GP_MATID_SHIFT 16
-
-/* Multiline defines can crash blender with certain GPU drivers. */
-/* clang-format off */
-#define GP_FILL_FLAGS (GP_FILL_TEXTURE_USE | GP_FILL_TEXTURE_PREMUL | GP_FILL_TEXTURE_CLIP | GP_FILL_GRADIENT_USE | GP_FILL_GRADIENT_RADIAL | GP_FILL_HOLDOUT)
-/* clang-format on */
-
-#define GP_FLAG_TEST(flag, val) (((flag) & (val)) != 0)
-
-/* Must match C declaration. */
-struct gpLight {
- vec4 color_type;
- vec4 right;
- vec4 up;
- vec4 forward;
- vec4 position;
- /* Please ensure 16 byte alignment (multiple of vec4). */
-};
-
-#define spot_size right.w
-#define spot_blend up.w
-
-#define GP_LIGHT_TYPE_POINT 0.0
-#define GP_LIGHT_TYPE_SPOT 1.0
-#define GP_LIGHT_TYPE_SUN 2.0
-#define GP_LIGHT_TYPE_AMBIENT 3.0
-
-#ifdef GP_MATERIAL_BUFFER_LEN
-
-layout(std140) uniform gpMaterialBlock
-{
- gpMaterial materials[GP_MATERIAL_BUFFER_LEN];
-};
-
-#endif
-
-#ifdef GPENCIL_LIGHT_BUFFER_LEN
-
-layout(std140) uniform gpLightBlock
-{
- gpLight lights[GPENCIL_LIGHT_BUFFER_LEN];
-};
-
-#endif
-
/* Must match eGPLayerBlendModes */
#define MODE_REGULAR 0
#define MODE_HARDLIGHT 1
@@ -149,510 +61,3 @@ void blend_mode_output(
break;
}
}
-
-#ifndef USE_GPU_SHADER_CREATE_INFO
-
-IN_OUT ShaderStageInterface
-{
- vec4 finalColorMul;
- vec4 finalColorAdd;
- vec3 finalPos;
- vec2 finalUvs;
- noperspective float strokeThickness;
- noperspective float unclampedThickness;
- noperspective float strokeHardeness;
- flat vec2 strokeAspect;
- flat vec2 strokePt1;
- flat vec2 strokePt2;
- flat int matFlag;
- flat float depth;
-};
-
-#endif
-
-#ifdef GPU_FRAGMENT_SHADER
-
-# define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0))
-
-float stroke_round_cap_mask(vec2 p1, vec2 p2, vec2 aspect, float thickness, float hardfac)
-{
- /* We create our own uv space to avoid issues with triangulation and linear
- * interpolation artifacts. */
- vec2 line = p2.xy - p1.xy;
- vec2 pos = gl_FragCoord.xy - p1.xy;
- float line_len = length(line);
- float half_line_len = line_len * 0.5;
- /* Normalize */
- line = (line_len > 0.0) ? (line / line_len) : vec2(1.0, 0.0);
- /* Create a uv space that englobe the whole segment into a capsule. */
- vec2 uv_end;
- uv_end.x = max(abs(dot(line, pos) - half_line_len) - half_line_len, 0.0);
- uv_end.y = dot(vec2(-line.y, line.x), pos);
- /* Divide by stroke radius. */
- uv_end /= thickness;
- uv_end *= aspect;
-
- float dist = clamp(1.0 - length(uv_end) * 2.0, 0.0, 1.0);
- if (hardfac > 0.999) {
- return step(1e-8, dist);
- }
- else {
- /* Modulate the falloff profile */
- float hardness = 1.0 - hardfac;
- dist = pow(dist, mix(0.01, 10.0, hardness));
- return smoothstep(0.0, 1.0, dist);
- }
-}
-
-#endif
-
-uniform vec2 sizeViewport;
-uniform vec2 sizeViewportInv;
-
-/* Per Object */
-uniform bool strokeOrder3d;
-uniform int gpMaterialOffset;
-uniform float thicknessScale;
-uniform float thicknessWorldScale;
-#define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
-
-#ifdef GPU_VERTEX_SHADER
-
-/* Per Layer */
-uniform float thicknessOffset;
-uniform float vertexColorOpacity;
-uniform vec4 layerTint;
-uniform float layerOpacity; /* Used for onion skin. */
-uniform float strokeIndexOffset = 0.0;
-
-/* All of these attributes are quad loaded the same way
- * as GL_LINES_ADJACENCY would feed a geometry shader:
- * - ma reference the previous adjacency point.
- * - ma1 reference the current line first point.
- * - ma2 reference the current line second point.
- * - ma3 reference the next adjacency point.
- * Note that we are rendering quad instances and not using any index buffer (except for fills).
- */
-/* x is material index, y is stroke_id, z is point_id, w is aspect & rotation & hardness packed. */
-in ivec4 ma;
-in ivec4 ma1;
-in ivec4 ma2;
-in ivec4 ma3;
-/* Position contains thickness in 4th component. */
-in vec4 pos; /* Prev adj vert */
-in vec4 pos1; /* Current edge */
-in vec4 pos2; /* Current edge */
-in vec4 pos3; /* Next adj vert */
-/* xy is UV for fills, z is U of stroke, w is strength. */
-in vec4 uv1;
-in vec4 uv2;
-in vec4 col1;
-in vec4 col2;
-in vec4 fcol1;
-/* WARNING: Max attribute count is actually 14 because OSX OpenGL implementation
- * considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536) */
-# define stroke_id1 ma1.y
-# define point_id1 ma1.z
-# define thickness1 pos1.w
-# define thickness2 pos2.w
-# define strength1 uv1.w
-# define strength2 uv2.w
-/* Packed! need to be decoded. */
-# define hardness1 ma1.w
-# define hardness2 ma2.w
-# define uvrot1 ma1.w
-# define aspect1 ma1.w
-
-vec2 decode_aspect(int packed_data)
-{
- float asp = float(uint(packed_data) & 0x1FFu) * (1.0 / 255.0);
- return (asp > 1.0) ? vec2(1.0, (asp - 1.0)) : vec2(asp, 1.0);
-}
-
-float decode_uvrot(int packed_data)
-{
- uint udata = uint(packed_data);
- float uvrot = 1e-8 + float((udata & 0x1FE00u) >> 9u) * (1.0 / 255.0);
- return ((udata & 0x20000u) != 0u) ? -uvrot : uvrot;
-}
-
-float decode_hardness(int packed_data)
-{
- return float((uint(packed_data) & 0x3FC0000u) >> 18u) * (1.0 / 255.0);
-}
-
-void discard_vert()
-{
- /* We set the vertex at the camera origin to generate 0 fragments. */
- gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
-}
-
-vec2 project_to_screenspace(vec4 v)
-{
- return ((v.xy / v.w) * 0.5 + 0.5) * sizeViewport;
-}
-
-vec2 rotate_90deg(vec2 v)
-{
- /* Counter Clock-Wise. */
- return vec2(-v.y, v.x);
-}
-
-mat4 model_matrix_get()
-{
- return ModelMatrix;
-}
-
-vec3 transform_point(mat4 m, vec3 v)
-{
- return (m * vec4(v, 1.0)).xyz;
-}
-
-vec2 safe_normalize(vec2 v)
-{
- float len_sqr = dot(v, v);
- if (len_sqr > 0.0) {
- return v / sqrt(len_sqr);
- }
- else {
- return vec2(1.0, 0.0);
- }
-}
-
-vec2 safe_normalize_len(vec2 v, out float len)
-{
- len = sqrt(dot(v, v));
- if (len > 0.0) {
- return v / len;
- }
- else {
- return vec2(1.0, 0.0);
- }
-}
-
-float stroke_thickness_modulate(float thickness)
-{
- /* Modify stroke thickness by object and layer factors. */
- thickness *= thicknessScale;
- thickness += thicknessOffset;
- thickness = max(1.0, thickness);
-
- if (thicknessIsScreenSpace) {
- /* Multiply offset by view Z so that offset is constant in screenspace.
- * (e.i: does not change with the distance to camera) */
- thickness *= gl_Position.w;
- }
- else {
- /* World space point size. */
- thickness *= thicknessWorldScale * drw_view.winmat[1][1] * sizeViewport.y;
- }
- return thickness;
-}
-
-float clamp_small_stroke_thickness(float thickness)
-{
- /* To avoid aliasing artifacts, we clamp the line thickness and
- * reduce its opacity in the fragment shader. */
- float min_thickness = gl_Position.w * 1.3;
- thickness = max(min_thickness, thickness);
-
- return thickness;
-}
-
-# ifdef GP_MATERIAL_BUFFER_LEN
-void color_output(vec4 stroke_col, vec4 vert_col, float vert_strength, float mix_tex)
-{
- /* Mix stroke with other colors. */
- vec4 mixed_col = stroke_col;
- mixed_col.rgb = mix(mixed_col.rgb, vert_col.rgb, vert_col.a * vertexColorOpacity);
- mixed_col.rgb = mix(mixed_col.rgb, layerTint.rgb, layerTint.a);
- mixed_col.a *= vert_strength * layerOpacity;
- /**
- * This is what the fragment shader looks like.
- * out = col * finalColorMul + col.a * finalColorAdd.
- * finalColorMul is how much of the texture color to keep.
- * finalColorAdd is how much of the mixed color to add.
- * Note that we never add alpha. This is to keep the texture act as a stencil.
- * We do however, modulate the alpha (reduce it).
- */
- /* We add the mixed color. This is 100% mix (no texture visible). */
- finalColorMul = vec4(mixed_col.aaa, mixed_col.a);
- finalColorAdd = vec4(mixed_col.rgb * mixed_col.a, 0.0);
- /* Then we blend according to the texture mix factor.
- * Note that we keep the alpha modulation. */
- finalColorMul.rgb *= mix_tex;
- finalColorAdd.rgb *= 1.0 - mix_tex;
-}
-# endif
-
-void stroke_vertex()
-{
- int m = ma1.x;
- bool is_dot = false;
- bool is_squares = false;
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- if (m != -1) {
- is_dot = GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_ALIGNMENT);
- is_squares = !GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_DOTS);
- }
-# endif
-
- /* Special Case. Stroke with single vert are rendered as dots. Do not discard them. */
- if (!is_dot && ma.x == -1 && ma2.x == -1) {
- is_dot = true;
- is_squares = false;
- }
-
- /* Endpoints, we discard the vertices. */
- if (ma1.x == -1 || (!is_dot && ma2.x == -1)) {
- discard_vert();
- return;
- }
-
- mat4 model_mat = model_matrix_get();
-
- /* Avoid using a vertex attribute for quad positioning. */
- float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
- float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
-
- bool use_curr = is_dot || (x == -1.0);
-
- vec3 wpos_adj = transform_point(model_mat, (use_curr) ? pos.xyz : pos3.xyz);
- vec3 wpos1 = transform_point(model_mat, pos1.xyz);
- vec3 wpos2 = transform_point(model_mat, pos2.xyz);
-
- vec4 ndc_adj = point_world_to_ndc(wpos_adj);
- vec4 ndc1 = point_world_to_ndc(wpos1);
- vec4 ndc2 = point_world_to_ndc(wpos2);
-
- gl_Position = (use_curr) ? ndc1 : ndc2;
- finalPos = (use_curr) ? wpos1 : wpos2;
-
- vec2 ss_adj = project_to_screenspace(ndc_adj);
- vec2 ss1 = project_to_screenspace(ndc1);
- vec2 ss2 = project_to_screenspace(ndc2);
- /* Screenspace Lines tangents. */
- float line_len;
- vec2 line = safe_normalize_len(ss2 - ss1, line_len);
- vec2 line_adj = safe_normalize((use_curr) ? (ss1 - ss_adj) : (ss_adj - ss2));
-
- float thickness = abs((use_curr) ? thickness1 : thickness2);
- thickness = stroke_thickness_modulate(thickness);
- float clampedThickness = clamp_small_stroke_thickness(thickness);
-
- finalUvs = vec2(x, y) * 0.5 + 0.5;
- strokeHardeness = decode_hardness(use_curr ? hardness1 : hardness2);
-
- if (is_dot) {
-# ifdef GP_MATERIAL_BUFFER_LEN
- int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT;
- /* For one point strokes use object alignment. */
- if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) {
- alignement = GP_STROKE_ALIGNMENT_OBJECT;
- }
-# endif
-
- vec2 x_axis;
-# ifdef GP_MATERIAL_BUFFER_LEN
- if (alignement == GP_STROKE_ALIGNMENT_STROKE) {
- x_axis = (ma2.x == -1) ? line_adj : line;
- }
- else if (alignement == GP_STROKE_ALIGNMENT_FIXED) {
- /* Default for no-material drawing. */
- x_axis = vec2(1.0, 0.0);
- }
- else
-# endif
- { /* GP_STROKE_ALIGNMENT_OBJECT */
- vec4 ndc_x = point_world_to_ndc(wpos1 + model_mat[0].xyz);
- vec2 ss_x = project_to_screenspace(ndc_x);
- x_axis = safe_normalize(ss_x - ss1);
- }
-
- /* Rotation: Encoded as Cos + Sin sign. */
- float uv_rot = decode_uvrot(uvrot1);
- float rot_sin = sqrt(max(0.0, 1.0 - uv_rot * uv_rot)) * sign(uv_rot);
- float rot_cos = abs(uv_rot);
- x_axis = mat2(rot_cos, -rot_sin, rot_sin, rot_cos) * x_axis;
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- if (is_dot) {
- float alignment_cos = MATERIAL(m).fill_uv_offset.z;
- float alignment_sin = MATERIAL(m).fill_uv_offset.w;
- x_axis = mat2(alignment_cos, -alignment_sin, alignment_sin, alignment_cos) * x_axis;
- }
-# endif
-
- vec2 y_axis = rotate_90deg(x_axis);
-
- strokeAspect = decode_aspect(aspect1);
-
- x *= strokeAspect.x;
- y *= strokeAspect.y;
-
- /* Invert for vertex shader. */
- strokeAspect = 1.0 / strokeAspect;
-
- gl_Position.xy += (x * x_axis + y * y_axis) * sizeViewportInv.xy * clampedThickness;
-
- strokePt1 = ss1;
- strokePt2 = ss1 + x_axis * 0.5;
- strokeThickness = (is_squares) ? 1e18 : (clampedThickness / gl_Position.w);
- unclampedThickness = (is_squares) ? 1e18 : (thickness / gl_Position.w);
- }
- else {
- bool is_stroke_start = (ma.x == -1 && x == -1);
- bool is_stroke_end = (ma3.x == -1 && x == 1);
-
- /* Mitter tangent vector. */
- vec2 miter_tan = safe_normalize(line_adj + line);
- float miter_dot = dot(miter_tan, line_adj);
- /* Break corners after a certain angle to avoid really thick corners. */
- const float miter_limit = 0.5; /* cos(60°) */
- bool miter_break = (miter_dot < miter_limit);
- miter_tan = (miter_break || is_stroke_start || is_stroke_end) ? line : (miter_tan / miter_dot);
-
- vec2 miter = rotate_90deg(miter_tan);
-
- strokePt1.xy = ss1;
- strokePt2.xy = ss2;
- strokeThickness = clampedThickness / gl_Position.w;
- unclampedThickness = thickness / gl_Position.w;
- strokeAspect = vec2(1.0);
-
- vec2 screen_ofs = miter * y;
-
- /* Reminder: we packed the cap flag into the sign of strength and thickness sign. */
- if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) ||
- (miter_break && !is_stroke_start && !is_stroke_end)) {
- screen_ofs += line * x;
- }
-
- gl_Position.xy += screen_ofs * sizeViewportInv.xy * clampedThickness;
-
- finalUvs.x = (use_curr) ? uv1.z : uv2.z;
-# ifdef GP_MATERIAL_BUFFER_LEN
- finalUvs.x *= MATERIAL(m).stroke_u_scale;
-# endif
- }
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- vec4 vert_col = (use_curr) ? col1 : col2;
- float vert_strength = abs((use_curr) ? strength1 : strength2);
- vec4 stroke_col = MATERIAL(m).stroke_color;
- float mix_tex = MATERIAL(m).stroke_texture_mix;
-
- /* Special case: We don't use vertex color if material Holdout. */
- if (GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_HOLDOUT)) {
- vert_col = vec4(0.0);
- }
-
- color_output(stroke_col, vert_col, vert_strength, mix_tex);
-
- matFlag = GP_FLAG(m) & ~GP_FILL_FLAGS;
-# endif
-
- if (strokeOrder3d) {
- /* Use the fragment depth (see fragment shader). */
- depth = -1.0;
- }
-# ifdef GP_MATERIAL_BUFFER_LEN
- else if (GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_OVERLAP)) {
- /* Use the index of the point as depth.
- * This means the stroke can overlap itself. */
- depth = (point_id1 + strokeIndexOffset + 1.0) * 0.0000002;
- }
-# endif
- else {
- /* Use the index of first point of the stroke as depth.
- * We render using a greater depth test this means the stroke
- * cannot overlap itself.
- * We offset by one so that the fill can be overlapped by its stroke.
- * The offset is ok since we pad the strokes data because of adjacency infos. */
- depth = (stroke_id1 + strokeIndexOffset + 1.0) * 0.0000002;
- }
-}
-
-void fill_vertex()
-{
- mat4 model_mat = model_matrix_get();
-
- vec3 wpos = transform_point(model_mat, pos1.xyz);
- gl_Position = point_world_to_ndc(wpos);
- finalPos = wpos;
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- int m = ma1.x;
-
- vec4 fill_col = MATERIAL(m).fill_color;
- float mix_tex = MATERIAL(m).fill_texture_mix;
-
- /* Special case: We don't modulate alpha in gradient mode. */
- if (GP_FLAG_TEST(GP_FLAG(m), GP_FILL_GRADIENT_USE)) {
- fill_col.a = 1.0;
- }
-
- /* Decode fill opacity. */
- vec4 fcol_decode = vec4(fcol1.rgb, floor(fcol1.a / 10.0));
- float fill_opacity = fcol1.a - (fcol_decode.a * 10);
- fcol_decode.a /= 10000.0;
-
- /* Special case: We don't use vertex color if material Holdout. */
- if (GP_FLAG_TEST(GP_FLAG(m), GP_FILL_HOLDOUT)) {
- fcol_decode = vec4(0.0);
- }
-
- /* Apply opacity. */
- fill_col.a *= fill_opacity;
- /* If factor is > 1 force opacity. */
- if (fill_opacity > 1.0) {
- fill_col.a += fill_opacity - 1.0;
- }
-
- fill_col.a = clamp(fill_col.a, 0.0, 1.0);
-
- color_output(fill_col, fcol_decode, 1.0, mix_tex);
-
- matFlag = GP_FLAG(m) & GP_FILL_FLAGS;
- matFlag |= m << GP_MATID_SHIFT;
-
- vec2 loc = MATERIAL(m).fill_uv_offset.xy;
- mat2x2 rot_scale = mat2x2(MATERIAL(m).fill_uv_rot_scale.xy, MATERIAL(m).fill_uv_rot_scale.zw);
- finalUvs = rot_scale * uv1.xy + loc;
-# endif
-
- strokeHardeness = 1.0;
- strokeThickness = 1e18;
- unclampedThickness = 1e20;
- strokeAspect = vec2(1.0);
- strokePt1 = strokePt2 = vec2(0.0);
-
- if (strokeOrder3d) {
- /* Use the fragment depth (see fragment shader). */
- depth = -1.0;
- /* We still offset the fills a little to avoid overlaps */
- gl_Position.z += 0.000002;
- }
- else {
- /* Use the index of first point of the stroke as depth. */
- depth = (stroke_id1 + strokeIndexOffset) * 0.0000002;
- }
-}
-
-void gpencil_vertex()
-{
- /* Trick to detect if a drawcall is stroke or fill.
- * This does mean that we need to draw an empty stroke segment before starting
- * to draw the real stroke segments. */
- bool is_fill = (gl_InstanceID == 0);
-
- if (!is_fill) {
- stroke_vertex();
- }
- else {
- fill_vertex();
- }
-}
-
-#endif
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index 8ed03b23809..2e7544cea29 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -31,23 +31,11 @@ void main()
vec4 vert_color;
vec3 vert_N;
+ ivec4 ma1 = floatBitsToInt(texelFetch(gp_pos_tx, gpencil_stroke_point_id() * 3 + 1));
gpMaterial gp_mat = materials[ma1.x + gpMaterialOffset];
gpMaterialFlag gp_flag = floatBitsToUint(gp_mat._flag);
- gl_Position = gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- vec4(viewportSize, 1.0 / viewportSize),
+ gl_Position = gpencil_vertex(vec4(viewportSize, 1.0 / viewportSize),
gp_flag,
gp_mat._alignment_rot,
gp_interp.pos,
@@ -60,7 +48,7 @@ void main()
gp_interp.thickness,
gp_interp.hardness);
- if (GPENCIL_IS_STROKE_VERTEX) {
+ if (gpencil_is_stroke_vertex()) {
if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) {
gp_interp.uv.x *= gp_mat._stroke_u_scale;
}
@@ -83,7 +71,7 @@ void main()
/* Use the index of the point as depth.
* This means the stroke can overlap itself. */
float point_index = float(ma1.z);
- gp_interp.depth = (point_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
+ gp_interp.depth = (point_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
}
else {
/* Use the index of first point of the stroke as depth.
@@ -92,10 +80,13 @@ void main()
* We offset by one so that the fill can be overlapped by its stroke.
* The offset is ok since we pad the strokes data because of adjacency infos. */
float stroke_index = float(ma1.y);
- gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
+ gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
}
}
else {
+ int stroke_point_id = gpencil_stroke_point_id();
+ vec4 uv1 = texelFetch(gp_pos_tx, stroke_point_id * 3 + 2);
+ vec4 fcol1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 1);
vec4 fill_col = gp_mat.fill_color;
/* Special case: We don't modulate alpha in gradient mode. */
@@ -137,7 +128,7 @@ void main()
else {
/* Use the index of first point of the stroke as depth. */
float stroke_index = float(ma1.y);
- gp_interp.depth = (stroke_index + gpStrokeIndexOffset) * 0.0000002;
+ gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
}
}
}
diff --git a/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh b/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh
index edd51e71242..da2776254e6 100644
--- a/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh
+++ b/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh
@@ -22,10 +22,10 @@ GPU_SHADER_CREATE_INFO(gpencil_geometry)
.do_static_compilation(true)
.define("GP_LIGHT")
.typedef_source("gpencil_defines.h")
- .sampler(0, ImageType::FLOAT_2D, "gpFillTexture")
- .sampler(1, ImageType::FLOAT_2D, "gpStrokeTexture")
- .sampler(2, ImageType::DEPTH_2D, "gpSceneDepthTexture")
- .sampler(3, ImageType::FLOAT_2D, "gpMaskTexture")
+ .sampler(2, ImageType::FLOAT_2D, "gpFillTexture")
+ .sampler(3, ImageType::FLOAT_2D, "gpStrokeTexture")
+ .sampler(4, ImageType::DEPTH_2D, "gpSceneDepthTexture")
+ .sampler(5, ImageType::FLOAT_2D, "gpMaskTexture")
.uniform_buf(4, "gpMaterial", "materials[GPENCIL_MATERIAL_BUFFER_LEN]", Frequency::BATCH)
.uniform_buf(3, "gpLight", "lights[GPENCIL_LIGHT_BUFFER_LEN]", Frequency::BATCH)
.push_constant(Type::VEC2, "viewportSize")
diff --git a/source/blender/draw/engines/overlay/overlay_armature.cc b/source/blender/draw/engines/overlay/overlay_armature.cc
index 0cf9d91804a..8c9587e7a9a 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.cc
+++ b/source/blender/draw/engines/overlay/overlay_armature.cc
@@ -441,7 +441,7 @@ static void drw_shgroup_bone_octahedral(ArmatureDrawContext *ctx,
const float outline_color[4])
{
BoneInstanceData inst_data;
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat);
if (ctx->solid) {
OVERLAY_bone_instance_data_set_color(&inst_data, bone_color);
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color);
@@ -461,7 +461,7 @@ static void drw_shgroup_bone_box(ArmatureDrawContext *ctx,
const float outline_color[4])
{
BoneInstanceData inst_data;
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat);
if (ctx->solid) {
OVERLAY_bone_instance_data_set_color(&inst_data, bone_color);
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color);
@@ -479,9 +479,9 @@ static void drw_shgroup_bone_wire(ArmatureDrawContext *ctx,
const float color[4])
{
float head[3], tail[3];
- mul_v3_m4v3(head, ctx->ob->obmat, bone_mat[3]);
+ mul_v3_m4v3(head, ctx->ob->object_to_world, bone_mat[3]);
add_v3_v3v3(tail, bone_mat[3], bone_mat[1]);
- mul_m4_v3(ctx->ob->obmat, tail);
+ mul_m4_v3(ctx->ob->object_to_world, tail);
DRW_buffer_add_entry(ctx->wire, head, color);
DRW_buffer_add_entry(ctx->wire, tail, color);
@@ -496,9 +496,9 @@ static void drw_shgroup_bone_stick(ArmatureDrawContext *ctx,
const float col_tail[4])
{
float head[3], tail[3];
- mul_v3_m4v3(head, ctx->ob->obmat, bone_mat[3]);
+ mul_v3_m4v3(head, ctx->ob->object_to_world, bone_mat[3]);
add_v3_v3v3(tail, bone_mat[3], bone_mat[1]);
- mul_m4_v3(ctx->ob->obmat, tail);
+ mul_m4_v3(ctx->ob->object_to_world, tail);
DRW_buffer_add_entry(ctx->stick, head, tail, col_wire, col_bone, col_head, col_tail);
}
@@ -517,11 +517,11 @@ static void drw_shgroup_bone_envelope_distance(ArmatureDrawContext *ctx,
mul_m4_v4(bone_mat, head_sph);
mul_m4_v4(bone_mat, tail_sph);
mul_m4_v4(bone_mat, xaxis);
- mul_m4_v4(ctx->ob->obmat, head_sph);
- mul_m4_v4(ctx->ob->obmat, tail_sph);
- mul_m4_v4(ctx->ob->obmat, xaxis);
+ mul_m4_v4(ctx->ob->object_to_world, head_sph);
+ mul_m4_v4(ctx->ob->object_to_world, tail_sph);
+ mul_m4_v4(ctx->ob->object_to_world, xaxis);
sub_v3_v3(xaxis, head_sph);
- float obscale = mat4_to_scale(ctx->ob->obmat);
+ float obscale = mat4_to_scale(ctx->ob->object_to_world);
head_sph[3] = *radius_head * obscale;
head_sph[3] += *distance * obscale;
tail_sph[3] = *radius_tail * obscale;
@@ -544,10 +544,10 @@ static void drw_shgroup_bone_envelope(ArmatureDrawContext *ctx,
mul_m4_v4(bone_mat, head_sph);
mul_m4_v4(bone_mat, tail_sph);
mul_m4_v4(bone_mat, xaxis);
- mul_m4_v4(ctx->ob->obmat, head_sph);
- mul_m4_v4(ctx->ob->obmat, tail_sph);
- mul_m4_v4(ctx->ob->obmat, xaxis);
- float obscale = mat4_to_scale(ctx->ob->obmat);
+ mul_m4_v4(ctx->ob->object_to_world, head_sph);
+ mul_m4_v4(ctx->ob->object_to_world, tail_sph);
+ mul_m4_v4(ctx->ob->object_to_world, xaxis);
+ float obscale = mat4_to_scale(ctx->ob->object_to_world);
head_sph[3] = *radius_head * obscale;
tail_sph[3] = *radius_tail * obscale;
@@ -651,7 +651,7 @@ static void drw_shgroup_bone_custom_solid_mesh(ArmatureDrawContext *ctx,
DRWCallBuffer *buf;
if (surf || edges || ledges) {
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat);
}
if (surf && ctx->custom_solid) {
@@ -692,7 +692,7 @@ static void drw_shgroup_bone_custom_mesh_wire(ArmatureDrawContext *ctx,
if (geom) {
DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, geom);
BoneInstanceData inst_data;
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat);
OVERLAY_bone_instance_data_set_color_hint(&inst_data, color);
OVERLAY_bone_instance_data_set_color(&inst_data, color);
DRW_buffer_add_entry_struct(buf, inst_data.mat);
@@ -724,7 +724,7 @@ static void drw_shgroup_custom_bone_curve(ArmatureDrawContext *ctx,
if (ledges) {
BoneInstanceData inst_data;
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat);
DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, ledges);
OVERLAY_bone_instance_data_set_color_hint(&inst_data, outline_color);
@@ -785,7 +785,7 @@ static void drw_shgroup_bone_custom_empty(ArmatureDrawContext *ctx,
{
const float final_color[4] = {color[0], color[1], color[2], 1.0f};
float mat[4][4];
- mul_m4_m4m4(mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(mat, ctx->ob->object_to_world, bone_mat);
switch (custom->empty_drawtype) {
case OB_PLAINAXES:
@@ -811,7 +811,7 @@ static void drw_shgroup_bone_point(ArmatureDrawContext *ctx,
const float outline_color[4])
{
BoneInstanceData inst_data;
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, bone_mat);
if (ctx->point_solid) {
OVERLAY_bone_instance_data_set_color(&inst_data, bone_color);
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color);
@@ -829,7 +829,7 @@ static void drw_shgroup_bone_axes(ArmatureDrawContext *ctx,
const float color[4])
{
float mat[4][4];
- mul_m4_m4m4(mat, ctx->ob->obmat, bone_mat);
+ mul_m4_m4m4(mat, ctx->ob->object_to_world, bone_mat);
/* Move to bone tail. */
add_v3_v3(mat[3], mat[1]);
OVERLAY_empty_shape(ctx->extras, mat, 0.25f, OB_ARROWS, color);
@@ -842,8 +842,8 @@ static void drw_shgroup_bone_relationship_lines_ex(ArmatureDrawContext *ctx,
const float color[4])
{
float s[3], e[3];
- mul_v3_m4v3(s, ctx->ob->obmat, start);
- mul_v3_m4v3(e, ctx->ob->obmat, end);
+ mul_v3_m4v3(s, ctx->ob->object_to_world, start);
+ mul_v3_m4v3(e, ctx->ob->object_to_world, end);
/* reverse order to have less stipple overlap */
OVERLAY_extra_line_dashed(ctx->extras, s, e, color);
}
@@ -1909,7 +1909,7 @@ static void draw_bone_degrees_of_freedom(ArmatureDrawContext *ctx, bPoseChannel
mul_m4_m4m4(posetrans, posetrans, tmp);
/* into world space. */
- mul_m4_m4m4(inst_data.mat, ctx->ob->obmat, posetrans);
+ mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world, posetrans);
if ((pchan->ikflag & BONE_IK_XLIMIT) && (pchan->ikflag & BONE_IK_ZLIMIT)) {
bone_instance_data_set_angle_minmax(
@@ -2079,7 +2079,7 @@ static void draw_bone_name(ArmatureDrawContext *ctx,
float *head = pchan ? pchan->pose_head : eBone->head;
float *tail = pchan ? pchan->pose_tail : eBone->tail;
mid_v3_v3v3(vec, head, tail);
- mul_m4_v3(ctx->ob->obmat, vec);
+ mul_m4_v3(ctx->ob->object_to_world, vec);
DRW_text_cache_add(dt,
vec,
@@ -2177,7 +2177,8 @@ static bool pchan_culling_test_envelope(const DRWView *view,
BoundSphere bsphere;
pchan_culling_calc_bsphere(ob, pchan, &bsphere);
bsphere.radius += max_ff(pchan->bone->rad_head, pchan->bone->rad_tail) *
- mat4_to_size_max_axis(ob->obmat) * mat4_to_size_max_axis(pchan->disp_mat);
+ mat4_to_size_max_axis(ob->object_to_world) *
+ mat4_to_size_max_axis(pchan->disp_mat);
return DRW_culling_sphere_test(view, &bsphere);
}
@@ -2188,13 +2189,13 @@ static bool pchan_culling_test_bbone(const DRWView *view,
const bArmature *arm = static_cast<bArmature *>(ob->data);
BLI_assert(arm->drawtype == ARM_B_BONE);
UNUSED_VARS_NDEBUG(arm);
- const float ob_scale = mat4_to_size_max_axis(ob->obmat);
+ const float ob_scale = mat4_to_size_max_axis(ob->object_to_world);
const Mat4 *bbones_mat = (const Mat4 *)pchan->draw_data->bbone_matrix;
for (int i = pchan->bone->segments; i--; bbones_mat++) {
BoundSphere bsphere;
float size[3];
mat4_to_size(size, bbones_mat->mat);
- mul_v3_m4v3(bsphere.center, ob->obmat, bbones_mat->mat[3]);
+ mul_v3_m4v3(bsphere.center, ob->object_to_world, bbones_mat->mat[3]);
bsphere.radius = len_v3(size) * ob_scale;
if (DRW_culling_sphere_test(view, &bsphere)) {
return true;
diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.cc b/source/blender/draw/engines/overlay/overlay_edit_text.cc
index ebadaa530e4..d1bca705ae6 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_text.cc
+++ b/source/blender/draw/engines/overlay/overlay_edit_text.cc
@@ -119,7 +119,7 @@ static void edit_text_cache_populate_select(OVERLAY_Data *vedata, Object *ob)
add_v2_v2(box[3], &sb->x);
}
v2_quad_corners_to_mat4(box, final_mat);
- mul_m4_m4m4(final_mat, ob->obmat, final_mat);
+ mul_m4_m4m4(final_mat, ob->object_to_world, final_mat);
DRW_shgroup_call_obmat(pd->edit_text_selection_grp, geom, final_mat);
}
@@ -134,7 +134,7 @@ static void edit_text_cache_populate_cursor(OVERLAY_Data *vedata, Object *ob)
float mat[4][4];
v2_quad_corners_to_mat4(cursor, mat);
- mul_m4_m4m4(mat, ob->obmat, mat);
+ mul_m4_m4m4(mat, ob->object_to_world, mat);
struct GPUBatch *geom = DRW_cache_quad_get();
DRW_shgroup_call_obmat(pd->edit_text_cursor_grp, geom, mat);
@@ -162,7 +162,7 @@ static void edit_text_cache_populate_boxes(OVERLAY_Data *vedata, Object *ob)
vecs[3][1] -= tb->h;
for (int j = 0; j < 4; j++) {
- mul_v3_m4v3(vecs[j], ob->obmat, vecs[j]);
+ mul_v3_m4v3(vecs[j], ob->object_to_world, vecs[j]);
}
for (int j = 0; j < 4; j++) {
OVERLAY_extra_line_dashed(cb, vecs[j], vecs[(j + 1) % 4], color);
diff --git a/source/blender/draw/engines/overlay/overlay_extra.cc b/source/blender/draw/engines/overlay/overlay_extra.cc
index 114123ab36e..27afe49a17b 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.cc
+++ b/source/blender/draw/engines/overlay/overlay_extra.cc
@@ -331,7 +331,7 @@ void OVERLAY_empty_cache_populate(OVERLAY_Data *vedata, Object *ob)
case OB_EMPTY_CONE:
case OB_ARROWS:
DRW_object_wire_theme_get(ob, view_layer, &color);
- OVERLAY_empty_shape(cb, ob->obmat, ob->empty_drawsize, ob->empty_drawtype, color);
+ OVERLAY_empty_shape(cb, ob->object_to_world, ob->empty_drawsize, ob->empty_drawtype, color);
break;
case OB_EMPTY_IMAGE:
OVERLAY_image_empty_cache_populate(vedata, ob);
@@ -372,7 +372,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb,
case OB_BOUND_BOX:
size_to_mat4(tmp, size);
copy_v3_v3(tmp[3], center);
- mul_m4_m4m4(tmp, ob->obmat, tmp);
+ mul_m4_m4m4(tmp, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_cube, color, tmp);
break;
case OB_BOUND_SPHERE:
@@ -380,7 +380,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb,
size[1] = size[2] = size[0];
size_to_mat4(tmp, size);
copy_v3_v3(tmp[3], center);
- mul_m4_m4m4(tmp, ob->obmat, tmp);
+ mul_m4_m4m4(tmp, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_sphere, color, tmp);
break;
case OB_BOUND_CYLINDER:
@@ -388,7 +388,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb,
size[1] = size[0];
size_to_mat4(tmp, size);
copy_v3_v3(tmp[3], center);
- mul_m4_m4m4(tmp, ob->obmat, tmp);
+ mul_m4_m4m4(tmp, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_cylinder, color, tmp);
break;
case OB_BOUND_CONE:
@@ -399,7 +399,7 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb,
/* Cone batch has base at 0 and is pointing towards +Y. */
swap_v3_v3(tmp[1], tmp[2]);
tmp[3][2] -= size[2];
- mul_m4_m4m4(tmp, ob->obmat, tmp);
+ mul_m4_m4m4(tmp, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_cone, color, tmp);
break;
case OB_BOUND_CAPSULE:
@@ -408,14 +408,14 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb,
scale_m4_fl(tmp, size[0]);
copy_v2_v2(tmp[3], center);
tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]);
- mul_m4_m4m4(final_mat, ob->obmat, tmp);
+ mul_m4_m4m4(final_mat, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_capsule_cap, color, final_mat);
negate_v3(tmp[2]);
tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]);
- mul_m4_m4m4(final_mat, ob->obmat, tmp);
+ mul_m4_m4m4(final_mat, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_capsule_cap, color, final_mat);
tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f);
- mul_m4_m4m4(final_mat, ob->obmat, tmp);
+ mul_m4_m4m4(final_mat, ob->object_to_world, tmp);
DRW_buffer_add_entry(cb->empty_capsule_body, color, final_mat);
break;
}
@@ -489,7 +489,7 @@ static void OVERLAY_texture_space(OVERLAY_ExtraCallBuffers *cb, Object *ob, cons
unit_m4(mat);
}
- mul_m4_m4m4(mat, ob->obmat, mat);
+ mul_m4_m4m4(mat, ob->object_to_world, mat);
DRW_buffer_add_entry(cb->empty_cube, color, mat);
}
@@ -511,7 +511,7 @@ static void OVERLAY_forcefield(OVERLAY_ExtraCallBuffers *cb, Object *ob, ViewLay
};
} instdata;
- copy_m4_m4(instdata.mat, ob->obmat);
+ copy_m4_m4(instdata.mat, ob->object_to_world);
instdata.size_x = instdata.size_y = instdata.size_z = ob->empty_drawsize;
switch (pd->forcefield) {
@@ -531,16 +531,16 @@ static void OVERLAY_forcefield(OVERLAY_ExtraCallBuffers *cb, Object *ob, ViewLay
instdata.size_x = instdata.size_y = instdata.size_z = pd->f_strength;
float pos[4];
BKE_where_on_path(ob, 0.0f, pos, nullptr, nullptr, nullptr, nullptr);
- copy_v3_v3(instdata.pos, ob->obmat[3]);
+ copy_v3_v3(instdata.pos, ob->object_to_world[3]);
translate_m4(instdata.mat, pos[0], pos[1], pos[2]);
DRW_buffer_add_entry(cb->field_curve, color, &instdata);
BKE_where_on_path(ob, 1.0f, pos, nullptr, nullptr, nullptr, nullptr);
- copy_v3_v3(instdata.pos, ob->obmat[3]);
+ copy_v3_v3(instdata.pos, ob->object_to_world[3]);
translate_m4(instdata.mat, pos[0], pos[1], pos[2]);
DRW_buffer_add_entry(cb->field_sphere_limit, color, &instdata);
/* Restore */
- copy_v3_v3(instdata.pos, ob->obmat[3]);
+ copy_v3_v3(instdata.pos, ob->object_to_world[3]);
}
break;
}
@@ -625,7 +625,7 @@ void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob)
};
} instdata;
- copy_m4_m4(instdata.mat, ob->obmat);
+ copy_m4_m4(instdata.mat, ob->object_to_world);
/* FIXME / TODO: clip_end has no meaning nowadays.
* In EEVEE, Only clip_sta is used shadow-mapping.
* Clip end is computed automatically based on light power.
@@ -708,7 +708,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob)
};
} instdata;
- copy_m4_m4(instdata.mat, ob->obmat);
+ copy_m4_m4(instdata.mat, ob->object_to_world);
switch (prb->type) {
case LIGHTPROBE_TYPE_CUBE:
@@ -720,15 +720,15 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob)
if (show_influence) {
char shape = (prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) ? OB_CUBE : OB_EMPTY_SPHERE;
float f = 1.0f - prb->falloff;
- OVERLAY_empty_shape(cb, ob->obmat, prb->distinf, shape, color_p);
- OVERLAY_empty_shape(cb, ob->obmat, prb->distinf * f, shape, color_p);
+ OVERLAY_empty_shape(cb, ob->object_to_world, prb->distinf, shape, color_p);
+ OVERLAY_empty_shape(cb, ob->object_to_world, prb->distinf * f, shape, color_p);
}
if (show_parallax) {
char shape = (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) ? OB_CUBE : OB_EMPTY_SPHERE;
float dist = ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) ? prb->distpar :
prb->distinf;
- OVERLAY_empty_shape(cb, ob->obmat, dist, shape, color_p);
+ OVERLAY_empty_shape(cb, ob->object_to_world, dist, shape, color_p);
}
break;
case LIGHTPROBE_TYPE_GRID:
@@ -738,8 +738,8 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob)
if (show_influence) {
float f = 1.0f - prb->falloff;
- OVERLAY_empty_shape(cb, ob->obmat, 1.0 + prb->distinf, OB_CUBE, color_p);
- OVERLAY_empty_shape(cb, ob->obmat, 1.0 + prb->distinf * f, OB_CUBE, color_p);
+ OVERLAY_empty_shape(cb, ob->object_to_world, 1.0 + prb->distinf, OB_CUBE, color_p);
+ OVERLAY_empty_shape(cb, ob->object_to_world, 1.0 + prb->distinf * f, OB_CUBE, color_p);
}
/* Data dots */
@@ -777,7 +777,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob)
zero_v3(instdata.mat[2]);
DRW_buffer_add_entry(cb->empty_cube, color_p, &instdata);
- normalize_m4_m4(instdata.mat, ob->obmat);
+ normalize_m4_m4(instdata.mat, ob->object_to_world);
OVERLAY_empty_shape(cb, instdata.mat, ob->empty_drawsize, OB_SINGLE_ARROW, color_p);
break;
}
@@ -797,7 +797,7 @@ void OVERLAY_speaker_cache_populate(OVERLAY_Data *vedata, Object *ob)
float *color_p;
DRW_object_wire_theme_get(ob, view_layer, &color_p);
- DRW_buffer_add_entry(cb->speaker, color_p, ob->obmat);
+ DRW_buffer_add_entry(cb->speaker, color_p, ob->object_to_world);
}
/** \} */
@@ -890,7 +890,7 @@ static void camera_view3d_reconstruction(
float object_imat[4][4];
invert_m4_m4(object_imat, object_mat);
- mul_m4_m4m4(tracking_object_mat, ob->obmat, object_imat);
+ mul_m4_m4m4(tracking_object_mat, ob->object_to_world, object_imat);
}
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
@@ -1132,14 +1132,17 @@ void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob)
DRW_object_wire_theme_get(ob, view_layer, &color_p);
copy_v4_v4(instdata.color, color_p);
- normalize_m4_m4(instdata.mat, ob->obmat);
+ normalize_m4_m4(instdata.mat, ob->object_to_world);
/* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here. */
if (is_selection_camera_stereo) {
copy_v3_fl(scale, 1.0f);
}
else {
- copy_v3_fl3(scale, len_v3(ob->obmat[0]), len_v3(ob->obmat[1]), len_v3(ob->obmat[2]));
+ copy_v3_fl3(scale,
+ len_v3(ob->object_to_world[0]),
+ len_v3(ob->object_to_world[1]),
+ len_v3(ob->object_to_world[2]));
/* Avoid division by 0. */
if (ELEM(0.0f, scale[0], scale[1], scale[2])) {
return;
@@ -1255,7 +1258,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) {
float *parent_pos = ob->runtime.parent_display_origin;
- OVERLAY_extra_line_dashed(cb, parent_pos, ob->obmat[3], relation_color);
+ OVERLAY_extra_line_dashed(cb, parent_pos, ob->object_to_world[3], relation_color);
}
/* Drawing the hook lines. */
@@ -1263,9 +1266,9 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
if (md->type == eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData *)md;
float center[3];
- mul_v3_m4v3(center, ob->obmat, hmd->cent);
+ mul_v3_m4v3(center, ob->object_to_world, hmd->cent);
if (hmd->object) {
- OVERLAY_extra_line_dashed(cb, hmd->object->obmat[3], center, relation_color);
+ OVERLAY_extra_line_dashed(cb, hmd->object->object_to_world[3], center, relation_color);
}
OVERLAY_extra_point(cb, center, relation_color);
}
@@ -1275,10 +1278,12 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
Object *rbc_ob1 = ob->rigidbody_constraint->ob1;
Object *rbc_ob2 = ob->rigidbody_constraint->ob2;
if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) {
- OVERLAY_extra_line_dashed(cb, rbc_ob1->obmat[3], ob->obmat[3], relation_color);
+ OVERLAY_extra_line_dashed(
+ cb, rbc_ob1->object_to_world[3], ob->object_to_world[3], relation_color);
}
if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) {
- OVERLAY_extra_line_dashed(cb, rbc_ob2->obmat[3], ob->obmat[3], relation_color);
+ OVERLAY_extra_line_dashed(
+ cb, rbc_ob2->object_to_world[3], ob->object_to_world[3], relation_color);
}
}
@@ -1307,7 +1312,8 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
}
if (camob) {
- OVERLAY_extra_line_dashed(cb, camob->obmat[3], ob->obmat[3], constraint_color);
+ OVERLAY_extra_line_dashed(
+ cb, camob->object_to_world[3], ob->object_to_world[3], constraint_color);
}
}
else {
@@ -1330,7 +1336,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
else {
unit_m4(ct->matrix);
}
- OVERLAY_extra_line_dashed(cb, ct->matrix[3], ob->obmat[3], constraint_color);
+ OVERLAY_extra_line_dashed(cb, ct->matrix[3], ob->object_to_world[3], constraint_color);
}
BKE_constraint_targets_flush(curcon, &targets, true);
@@ -1387,7 +1393,7 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
copy_v3_v3(voxel_cubemat[3], min);
/* move small cube into the domain (otherwise its centered on vertex of domain object) */
translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f);
- mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat);
+ mul_m4_m4m4(voxel_cubemat, ob->object_to_world, voxel_cubemat);
DRW_buffer_add_entry(cb->empty_cube, color, voxel_cubemat);
}
@@ -1493,15 +1499,15 @@ static void OVERLAY_object_center(OVERLAY_ExtraCallBuffers *cb,
const bool is_library = ID_REAL_USERS(&ob->id) > 1 || ID_IS_LINKED(ob);
BKE_view_layer_synced_ensure(scene, view_layer);
if (ob == BKE_view_layer_active_object_get(view_layer)) {
- DRW_buffer_add_entry(cb->center_active, ob->obmat[3]);
+ DRW_buffer_add_entry(cb->center_active, ob->object_to_world[3]);
}
else if (ob->base_flag & BASE_SELECTED) {
DRWCallBuffer *cbuf = (is_library) ? cb->center_selected_lib : cb->center_selected;
- DRW_buffer_add_entry(cbuf, ob->obmat[3]);
+ DRW_buffer_add_entry(cbuf, ob->object_to_world[3]);
}
else if (pd->v3d_flag & V3D_DRAW_CENTERS) {
DRWCallBuffer *cbuf = (is_library) ? cb->center_deselected_lib : cb->center_deselected;
- DRW_buffer_add_entry(cbuf, ob->obmat[3]);
+ DRW_buffer_add_entry(cbuf, ob->object_to_world[3]);
}
}
@@ -1513,7 +1519,7 @@ static void OVERLAY_object_name(Object *ob, int theme_id)
UI_GetThemeColor4ubv(theme_id, color);
DRW_text_cache_add(dt,
- ob->obmat[3],
+ ob->object_to_world[3],
ob->id.name + 2,
strlen(ob->id.name + 2),
10,
@@ -1571,7 +1577,7 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
/* Helpers for when we're transforming origins. */
if (draw_xform) {
const float color_xform[4] = {0.15f, 0.15f, 0.15f, 0.7f};
- DRW_buffer_add_entry(cb->origin_xform, color_xform, ob->obmat);
+ DRW_buffer_add_entry(cb->origin_xform, color_xform, ob->object_to_world);
}
/* don't show object extras in set's */
if (!from_dupli) {
@@ -1591,7 +1597,7 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
OVERLAY_collision(cb, ob, color);
}
if (ob->dtx & OB_AXIS) {
- DRW_buffer_add_entry(cb->empty_axes, color, ob->obmat);
+ DRW_buffer_add_entry(cb->empty_axes, color, ob->object_to_world);
}
if (draw_volume) {
OVERLAY_volume_extra(cb, vedata, ob, md, scene, color);
diff --git a/source/blender/draw/engines/overlay/overlay_facing.cc b/source/blender/draw/engines/overlay/overlay_facing.cc
index 825036ecd05..44dab0f0a42 100644
--- a/source/blender/draw/engines/overlay/overlay_facing.cc
+++ b/source/blender/draw/engines/overlay/overlay_facing.cc
@@ -43,7 +43,7 @@ void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob)
}
const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
diff --git a/source/blender/draw/engines/overlay/overlay_fade.cc b/source/blender/draw/engines/overlay/overlay_fade.cc
index d6fd4f9127a..b9523a4eac9 100644
--- a/source/blender/draw/engines/overlay/overlay_fade.cc
+++ b/source/blender/draw/engines/overlay/overlay_fade.cc
@@ -53,7 +53,7 @@ void OVERLAY_fade_cache_populate(OVERLAY_Data *vedata, Object *ob)
}
const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.cc b/source/blender/draw/engines/overlay/overlay_gpencil.cc
index 30765b30ce6..f5988d91e72 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.cc
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.cc
@@ -243,7 +243,7 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
copy_v3_v3(col_grid, gpd->grid.color);
col_grid[3] = max_ff(v3d->overlay.gpencil_grid_opacity, 0.01f);
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
/* Rotate and scale except align to cursor. */
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
@@ -286,7 +286,7 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
copy_v3_v3(mat[3], cursor->location);
}
else if (ts->gpencil_v3d_align & GP_PROJECT_VIEWSPACE) {
- copy_v3_v3(mat[3], ob->obmat[3]);
+ copy_v3_v3(mat[3], ob->object_to_world[3]);
}
translate_m4(mat, gpd->grid.offset[0], gpd->grid.offset[1], 0.0f);
@@ -397,7 +397,7 @@ static void overlay_gpencil_draw_stroke_color_name(bGPDlayer * /*gpl*/,
UI_GetThemeColor4ubv(theme_id, color);
float fpt[3];
- mul_v3_m4v3(fpt, ob->obmat, &pt->x);
+ mul_v3_m4v3(fpt, ob->object_to_world, &pt->x);
struct DRWTextStore *dt = DRW_text_cache_ensure();
DRW_text_cache_add(dt,
diff --git a/source/blender/draw/engines/overlay/overlay_image.cc b/source/blender/draw/engines/overlay/overlay_image.cc
index f42867622e4..7b99bd6bd18 100644
--- a/source/blender/draw/engines/overlay/overlay_image.cc
+++ b/source/blender/draw/engines/overlay/overlay_image.cc
@@ -392,7 +392,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob)
float image_aspect[2];
overlay_image_calc_aspect(ima, size, image_aspect);
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
mul_v3_fl(mat[0], image_aspect[0] * 0.5f * ob->empty_drawsize);
mul_v3_fl(mat[1], image_aspect[1] * 0.5f * ob->empty_drawsize);
madd_v3_v3fl(mat[3], mat[0], ob->ima_ofs[0] * 2.0f + 1.0f);
diff --git a/source/blender/draw/engines/overlay/overlay_lattice.cc b/source/blender/draw/engines/overlay/overlay_lattice.cc
index 7b59aa78c89..72c3335d871 100644
--- a/source/blender/draw/engines/overlay/overlay_lattice.cc
+++ b/source/blender/draw/engines/overlay/overlay_lattice.cc
@@ -52,7 +52,7 @@ void OVERLAY_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob)
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false);
- OVERLAY_extra_wire(cb, geom, ob->obmat, color);
+ OVERLAY_extra_wire(cb, geom, ob->object_to_world, color);
}
void OVERLAY_edit_lattice_draw(OVERLAY_Data *vedata)
diff --git a/source/blender/draw/engines/overlay/overlay_metaball.cc b/source/blender/draw/engines/overlay/overlay_metaball.cc
index 2fc6910fe44..dd0a862337e 100644
--- a/source/blender/draw/engines/overlay/overlay_metaball.cc
+++ b/source/blender/draw/engines/overlay/overlay_metaball.cc
@@ -45,10 +45,10 @@ static void metaball_instance_data_set(
BoneInstanceData *data, Object *ob, const float *pos, const float radius, const float color[4])
{
/* Bone point radius is 0.05. Compensate for that. */
- mul_v3_v3fl(data->mat[0], ob->obmat[0], radius / 0.05f);
- mul_v3_v3fl(data->mat[1], ob->obmat[1], radius / 0.05f);
- mul_v3_v3fl(data->mat[2], ob->obmat[2], radius / 0.05f);
- mul_v3_m4v3(data->mat[3], ob->obmat, pos);
+ mul_v3_v3fl(data->mat[0], ob->object_to_world[0], radius / 0.05f);
+ mul_v3_v3fl(data->mat[1], ob->object_to_world[1], radius / 0.05f);
+ mul_v3_v3fl(data->mat[2], ob->object_to_world[2], radius / 0.05f);
+ mul_v3_m4v3(data->mat[3], ob->object_to_world, pos);
/* WATCH: Reminder, alpha is wire-size. */
OVERLAY_bone_instance_data_set_color(data, color);
}
diff --git a/source/blender/draw/engines/overlay/overlay_mode_transfer.cc b/source/blender/draw/engines/overlay/overlay_mode_transfer.cc
index 5222abfc743..79ac92a187c 100644
--- a/source/blender/draw/engines/overlay/overlay_mode_transfer.cc
+++ b/source/blender/draw/engines/overlay/overlay_mode_transfer.cc
@@ -85,7 +85,7 @@ void OVERLAY_mode_transfer_cache_populate(OVERLAY_Data *vedata, Object *ob)
}
const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc
index 5ea02376b67..c2df665eba3 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.cc
+++ b/source/blender/draw/engines/overlay/overlay_outline.cc
@@ -43,7 +43,7 @@ static void gpencil_depth_plane(Object *ob, float r_plane[4])
add_v3_fl(size, 1e-8f);
rescale_m4(mat, size);
/* BBox space to World. */
- mul_m4_m4m4(mat, ob->obmat, mat);
+ mul_m4_m4m4(mat, ob->object_to_world, mat);
/* BBox center in world space. */
copy_v3_v3(center, mat[3]);
/* View Vector. */
@@ -138,6 +138,7 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
GPUShader *sh_curves = OVERLAY_shader_outline_prepass_curves();
+
pd->outlines_curves_grp = grp = DRW_shgroup_create(sh_curves, psl->outlines_prepass_ps);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
@@ -172,7 +173,6 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
typedef struct iterData {
Object *ob;
DRWShadingGroup *stroke_grp;
- DRWShadingGroup *fill_grp;
int cfra;
float plane[4];
} iterData;
@@ -188,17 +188,22 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl,
const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D);
- float object_scale = mat4_to_scale(iter->ob->obmat);
+ float object_scale = mat4_to_scale(iter->ob->object_to_world);
/* Negate thickness sign to tag that strokes are in screen space.
* Convert to world units (by default, 1 meter = 2000 pixels). */
float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f);
+ GPUVertBuf *position_tx = DRW_cache_gpencil_position_buffer_get(iter->ob, iter->cfra);
+ GPUVertBuf *color_tx = DRW_cache_gpencil_color_buffer_get(iter->ob, iter->cfra);
+
DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp);
DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", is_stroke_order_3d);
DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", object_scale);
DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", float(gpl->line_change));
DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", thickness_scale);
DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane);
+ DRW_shgroup_buffer_texture(grp, "gp_pos_tx", position_tx);
+ DRW_shgroup_buffer_texture(grp, "gp_col_tx", color_tx);
}
static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/,
@@ -219,20 +224,19 @@ static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/,
return;
}
+ struct GPUBatch *geom = DRW_cache_gpencil_get(iter->ob, iter->cfra);
+
if (show_fill) {
- struct GPUBatch *geom = DRW_cache_gpencil_fills_get(iter->ob, iter->cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
- DRW_shgroup_call_range(iter->fill_grp, iter->ob, geom, vfirst, vcount);
+ DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
}
if (show_stroke) {
- struct GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter->ob, iter->cfra);
- /* Start one vert before to have gl_InstanceID > 0 (see shader). */
- int vfirst = gps->runtime.stroke_start - 1;
- /* Include "potential" cyclic vertex and start adj vertex (see shader). */
- int vcount = gps->totpoints + 1 + 1;
- DRW_shgroup_call_instance_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
+ int vfirst = gps->runtime.stroke_start * 3;
+ bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2);
+ int vcount = (gps->totpoints + (int)is_cyclic) * 2 * 3;
+ DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
}
}
@@ -247,7 +251,6 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
iterData iter{};
iter.ob = ob;
iter.stroke_grp = pd->outlines_gpencil_grp;
- iter.fill_grp = DRW_shgroup_create_sub(pd->outlines_gpencil_grp);
iter.cfra = pd->cfra;
if (gpd->draw_mode == GP_DRAWMODE_2D) {
@@ -280,6 +283,18 @@ static void OVERLAY_outline_curves(OVERLAY_PrivateData *pd, Object *ob)
DRW_shgroup_curves_create_sub(ob, shgroup, nullptr);
}
+static void OVERLAY_outline_pointcloud(OVERLAY_PrivateData *pd, Object *ob)
+{
+ if (pd->wireframe_mode) {
+ /* Looks bad in this case. Could be relaxed if we draw a
+ * wireframe of some sort in the future. */
+ return;
+ }
+
+ DRWShadingGroup *shgroup = pd->outlines_ptcloud_grp;
+ DRW_shgroup_pointcloud_create_sub(ob, shgroup, nullptr);
+}
+
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
@@ -311,9 +326,8 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
return;
}
- if (ob->type == OB_POINTCLOUD && pd->wireframe_mode) {
- /* Looks bad in this case. Could be relaxed if we draw a
- * wireframe of some sort in the future. */
+ if (ob->type == OB_POINTCLOUD) {
+ OVERLAY_outline_pointcloud(pd, ob);
return;
}
@@ -336,18 +350,12 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
}
if (geom) {
- shgroup = (ob->type == OB_POINTCLOUD) ? pd->outlines_ptcloud_grp : pd->outlines_grp;
+ shgroup = pd->outlines_grp;
}
}
if (shgroup && geom) {
- if (ob->type == OB_POINTCLOUD) {
- /* Draw range to avoid drawcall batching messing up the instance attribute. */
- DRW_shgroup_call_instance_range(shgroup, ob, geom, 0, 0);
- }
- else {
- DRW_shgroup_call(shgroup, geom, ob);
- }
+ DRW_shgroup_call(shgroup, geom, ob);
}
if (init_dupli) {
diff --git a/source/blender/draw/engines/overlay/overlay_sculpt.cc b/source/blender/draw/engines/overlay/overlay_sculpt.cc
index 8f142d68350..3377aa5394b 100644
--- a/source/blender/draw/engines/overlay/overlay_sculpt.cc
+++ b/source/blender/draw/engines/overlay/overlay_sculpt.cc
@@ -37,7 +37,7 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob)
struct GPUBatch *sculpt_overlays;
PBVH *pbvh = ob->sculpt->pbvh;
- const bool use_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+ const bool use_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d);
if (!pbvh) {
/* It is possible to have SculptSession without PBVH. This happens, for example, when toggling
diff --git a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc
index 1bba2a366a5..68de5dcd11d 100644
--- a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc
+++ b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc
@@ -64,7 +64,7 @@ void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object)
".selection_curve_float";
bool is_point_domain;
- GPUTexture **texture = DRW_curves_texture_for_evaluated_attribute(
+ GPUVertBuf **texture = DRW_curves_texture_for_evaluated_attribute(
curves, name, &is_point_domain);
if (texture == nullptr) {
return;
@@ -78,7 +78,7 @@ void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object)
}
DRW_shgroup_uniform_bool_copy(grp, "is_point_domain", is_point_domain);
- DRW_shgroup_uniform_texture(grp, "selection_tx", *texture);
+ DRW_shgroup_buffer_texture(grp, "selection_tx", *texture);
}
void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata)
diff --git a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc
index d57ea08d888..fd1657b3d59 100644
--- a/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc
+++ b/source/blender/draw/engines/overlay/overlay_viewer_attribute.cc
@@ -81,18 +81,16 @@ static void populate_cache_for_instance(Object &object,
break;
}
case OB_POINTCLOUD: {
- DRWShadingGroup *sub_grp = DRW_shgroup_create_sub(
- pd.viewer_attribute_instance_pointcloud_grp);
+ DRWShadingGroup *sub_grp = DRW_shgroup_pointcloud_create_sub(
+ &object, pd.viewer_attribute_pointcloud_grp, nullptr);
DRW_shgroup_uniform_vec4_copy(sub_grp, "ucolor", color);
- GPUBatch *batch = DRW_cache_pointcloud_surface_get(&object);
- DRW_shgroup_call_instance_range(sub_grp, &object, batch, 0, 0);
break;
}
case OB_CURVES_LEGACY: {
DRWShadingGroup *sub_grp = DRW_shgroup_create_sub(pd.viewer_attribute_instance_grp);
DRW_shgroup_uniform_vec4_copy(sub_grp, "ucolor", color);
GPUBatch *batch = DRW_cache_curve_edge_wire_get(&object);
- DRW_shgroup_call_obmat(sub_grp, batch, object.obmat);
+ DRW_shgroup_call_obmat(sub_grp, batch, object.object_to_world);
break;
}
case OB_CURVES: {
@@ -123,9 +121,11 @@ static void populate_cache_for_geometry(Object &object,
case OB_POINTCLOUD: {
PointCloud *pointcloud = static_cast<PointCloud *>(object.data);
if (pointcloud->attributes().contains(".viewer")) {
- GPUBatch *batch = DRW_cache_pointcloud_surface_viewer_attribute_get(&object);
- DRW_shgroup_uniform_float_copy(pd.viewer_attribute_pointcloud_grp, "opacity", opacity);
- DRW_shgroup_call_instance_range(pd.viewer_attribute_pointcloud_grp, &object, batch, 0, 0);
+ GPUVertBuf **vertbuf = DRW_pointcloud_evaluated_attribute(pointcloud, ".viewer");
+ DRWShadingGroup *grp = DRW_shgroup_pointcloud_create_sub(
+ &object, pd.viewer_attribute_pointcloud_grp, nullptr);
+ DRW_shgroup_uniform_float_copy(grp, "opacity", opacity);
+ DRW_shgroup_buffer_texture_ref(grp, "attribute_tx", vertbuf);
}
break;
}
@@ -135,7 +135,7 @@ static void populate_cache_for_geometry(Object &object,
if (curves.attributes().contains(".viewer")) {
GPUBatch *batch = DRW_cache_curve_edge_wire_viewer_attribute_get(&object);
DRW_shgroup_uniform_float_copy(pd.viewer_attribute_curve_grp, "opacity", opacity);
- DRW_shgroup_call_obmat(pd.viewer_attribute_curve_grp, batch, object.obmat);
+ DRW_shgroup_call_obmat(pd.viewer_attribute_curve_grp, batch, object.object_to_world);
}
break;
}
@@ -144,13 +144,13 @@ static void populate_cache_for_geometry(Object &object,
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
if (curves.attributes().contains(".viewer")) {
bool is_point_domain;
- GPUTexture **texture = DRW_curves_texture_for_evaluated_attribute(
+ GPUVertBuf **texture = DRW_curves_texture_for_evaluated_attribute(
curves_id, ".viewer", &is_point_domain);
DRWShadingGroup *grp = DRW_shgroup_curves_create_sub(
&object, pd.viewer_attribute_curves_grp, nullptr);
DRW_shgroup_uniform_float_copy(pd.viewer_attribute_curves_grp, "opacity", opacity);
DRW_shgroup_uniform_bool_copy(grp, "is_point_domain", is_point_domain);
- DRW_shgroup_uniform_texture(grp, "color_tx", *texture);
+ DRW_shgroup_buffer_texture(grp, "color_tx", *texture);
}
break;
}
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.cc b/source/blender/draw/engines/overlay/overlay_wireframe.cc
index bff1bf46923..7053d0039cf 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.cc
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.cc
@@ -132,12 +132,12 @@ static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, Part
if (collection != nullptr) {
sub_v3_v3(dupli_mat[3], collection->instance_offset);
}
- mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat);
+ mul_m4_m4m4(dupli_mat, dupli_parent->object_to_world, dupli_mat);
}
else {
- copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
+ copy_m4_m4(dupli_mat, dupli_object->ob->object_to_world);
invert_m4(dupli_mat);
- mul_m4_m4m4(dupli_mat, ob->obmat, dupli_mat);
+ mul_m4_m4m4(dupli_mat, ob->object_to_world, dupli_mat);
}
}
else {
@@ -217,7 +217,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
}
if (geom) {
- OVERLAY_extra_wire(cb, geom, ob->obmat, color);
+ OVERLAY_extra_wire(cb, geom, ob->object_to_world, color);
}
}
@@ -230,12 +230,12 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
if (dupli->wire_shgrp == cb->extra_loose_points) {
float *color;
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
- OVERLAY_extra_loose_points(cb, dupli->wire_geom, ob->obmat, color);
+ OVERLAY_extra_loose_points(cb, dupli->wire_geom, ob->object_to_world, color);
}
else if (dupli->wire_shgrp == cb->extra_wire) {
float *color;
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
- OVERLAY_extra_wire(cb, dupli->wire_geom, ob->obmat, color);
+ OVERLAY_extra_wire(cb, dupli->wire_geom, ob->object_to_world, color);
}
else {
DRW_shgroup_call(dupli->wire_shgrp, dupli->wire_geom, ob);
@@ -264,7 +264,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob);
if (geom) {
- OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
+ OVERLAY_extra_loose_points(cb, geom, ob->object_to_world, color);
}
return;
}
@@ -276,7 +276,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
/* Don't do that in edit Mesh mode, unless there is a modifier preview. */
if (use_wire && (!is_mesh || (!is_edit_mode || has_edit_mesh_cage))) {
const bool is_sculpt_mode = ((ob->mode & OB_MODE_SCULPT) != 0) && (ob->sculpt != nullptr);
- const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI);
const bool instance_parent_in_edit_mode = is_instance ? DRW_object_is_in_edit_mode(
@@ -318,14 +318,14 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
if (is_mesh_verts_only) {
geom = DRW_cache_mesh_all_verts_get(ob);
if (geom) {
- OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
+ OVERLAY_extra_loose_points(cb, geom, ob->object_to_world, color);
shgrp = cb->extra_loose_points;
}
}
else {
geom = DRW_cache_mesh_loose_edges_get(ob);
if (geom) {
- OVERLAY_extra_wire(cb, geom, ob->obmat, color);
+ OVERLAY_extra_wire(cb, geom, ob->object_to_world, color);
shgrp = cb->extra_wire;
}
}
diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh
index 20d4797b76f..6a0bd03f030 100644
--- a/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh
+++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_viewer_attribute_info.hh
@@ -27,7 +27,7 @@ GPU_SHADER_CREATE_INFO(overlay_viewer_attribute_pointcloud)
.fragment_source("overlay_viewer_attribute_frag.glsl")
.fragment_out(0, Type::VEC4, "out_color")
.fragment_out(1, Type::VEC4, "lineOutput")
- .vertex_in(3, Type::VEC4, "attribute_value")
+ .sampler(3, ImageType::FLOAT_BUFFER, "attribute_tx")
.vertex_out(overlay_viewer_attribute_iface)
.additional_info("overlay_viewer_attribute_common", "draw_pointcloud");
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
index 7d8fb0c2cb8..851e0884354 100644
--- a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
@@ -34,20 +34,7 @@ void main()
float unused_strength;
vec2 unused_uv;
- gl_Position = gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- vec4(sizeViewport, sizeViewportInv),
+ gl_Position = gpencil_vertex(vec4(sizeViewport, sizeViewportInv),
world_pos,
unused_N,
unused_color,
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl
index e706e8f9033..e7b7cafd898 100644
--- a/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/overlay_viewer_attribute_pointcloud_vert.glsl
@@ -6,5 +6,5 @@ void main()
{
vec3 world_pos = pointcloud_get_pos();
gl_Position = point_world_to_ndc(world_pos);
- finalColor = attribute_value;
+ finalColor = pointcloud_get_customdata_vec4(attribute_tx);
}
diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c
index 026a1f52ac1..07e2a42b808 100644
--- a/source/blender/draw/engines/select/select_engine.c
+++ b/source/blender/draw/engines/select/select_engine.c
@@ -205,7 +205,7 @@ static void select_cache_populate(void *vedata, Object *ob)
struct Mesh *me = ob->data;
if (e_data.context.select_mode & SCE_SELECT_FACE) {
struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->object_to_world);
}
else if (ob->dt >= OB_SOLID) {
#ifdef USE_CAGE_OCCLUSION
@@ -213,17 +213,17 @@ static void select_cache_populate(void *vedata, Object *ob)
#else
struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me);
#endif
- DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->object_to_world);
}
if (e_data.context.select_mode & SCE_SELECT_EDGE) {
struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
- DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->object_to_world);
}
if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->object_to_world);
}
return;
}
@@ -231,7 +231,7 @@ static void select_cache_populate(void *vedata, Object *ob)
float min[3], max[3];
select_id_object_min_max(ob, min, max);
- if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->obmat, min, max)) {
+ if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->object_to_world, min, max)) {
if (sel_data == NULL) {
sel_data = (SELECTID_ObjectData *)DRW_drawdata_ensure(
&ob->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), NULL, NULL);
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index fecdad5802c..15a16539a26 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -27,6 +27,7 @@
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
+#include "DNA_pointcloud_types.h"
#include "ED_paint.h"
@@ -266,7 +267,7 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_active = (ob == draw_ctx->obact);
- const bool is_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+ const bool is_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool is_render = DRW_state_is_image_render() && (draw_ctx->v3d == NULL);
const bool is_texpaint_mode = is_active && (wpd->ctx_mode == CTX_MODE_PAINT_TEXTURE);
@@ -418,7 +419,7 @@ void workbench_cache_populate(void *ved, Object *ob)
return;
}
- if (ELEM(ob->type, OB_MESH, OB_POINTCLOUD)) {
+ if (ob->type == OB_MESH) {
bool use_sculpt_pbvh, use_texpaint_mode, draw_shadow, has_transp_mat = false;
eV3DShadingColorType color_type = workbench_color_type_get(
wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, &draw_shadow);
@@ -442,6 +443,12 @@ void workbench_cache_populate(void *ved, Object *ob)
DRWShadingGroup *grp = workbench_material_hair_setup(wpd, ob, CURVES_MATERIAL_NR, color_type);
DRW_shgroup_curves_create_sub(ob, grp, NULL);
}
+ else if (ob->type == OB_POINTCLOUD) {
+ int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
+ DRWShadingGroup *grp = workbench_material_ptcloud_setup(
+ wpd, ob, POINTCLOUD_MATERIAL_NR, color_type);
+ DRW_shgroup_pointcloud_create_sub(ob, grp, NULL);
+ }
else if (ob->type == OB_VOLUME) {
if (wpd->shading.type != OB_WIRE) {
int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 492bce1e571..4aedaf443b9 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -511,6 +511,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
#define workbench_image_hair_setup(wpd, ob, mat_nr, ima, iuser, interp) \
workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_DATATYPE_HAIR)
+#define workbench_material_ptcloud_setup(wpd, ob, mat_nr, color_type) \
+ workbench_material_setup_ex(wpd, ob, mat_nr, color_type, WORKBENCH_DATATYPE_POINTCLOUD, 0)
+#define workbench_image_ptcloud_setup(wpd, ob, mat_nr, ima, iuser, interp) \
+ workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_DATATYPE_POINTCLOUD)
+
/* workbench_data.c */
void workbench_private_data_alloc(WORKBENCH_StorageList *stl);
diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c
index 0b34e849049..eb4d546648a 100644
--- a/source/blender/draw/engines/workbench/workbench_shadow.c
+++ b/source/blender/draw/engines/workbench/workbench_shadow.c
@@ -172,7 +172,7 @@ static const BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_Private
{
if (oed->shadow_bbox_dirty || wpd->shadow_changed) {
float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat);
+ mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->object_to_world);
/* Get AABB in shadow space. */
INIT_MINMAX(oed->shadow_min, oed->shadow_max);
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index ce7773e7439..7c6df93f5a3 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -237,7 +237,7 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata,
/* Combined texture to object, and object to world transform. */
float texture_to_world[4][4];
- mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object);
+ mul_m4_m4m4(texture_to_world, ob->object_to_world, grid->texture_to_object);
if (use_slice) {
float invviewmat[4][4];
@@ -291,7 +291,7 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata,
/* Compute density scale. */
const float density_scale = volume->display.density *
- BKE_volume_density_scale(volume, ob->obmat);
+ BKE_volume_density_scale(volume, ob->object_to_world);
DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture);
/* TODO: implement shadow texture, see manta_smoke_calc_transparency. */
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 8c6a51442e1..00ac2563c43 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -899,8 +899,6 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob)
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_get(ob);
- case OB_POINTCLOUD:
- return DRW_cache_pointcloud_surface_get(ob);
default:
return NULL;
}
@@ -959,8 +957,6 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob,
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
- case OB_POINTCLOUD:
- return DRW_cache_pointcloud_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
default:
return NULL;
}
@@ -3006,24 +3002,6 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob)
/** \name PointCloud
* \{ */
-GPUBatch *DRW_cache_pointcloud_get_dots(Object *object)
-{
- BLI_assert(object->type == OB_POINTCLOUD);
- return DRW_pointcloud_batch_cache_get_dots(object);
-}
-
-GPUBatch *DRW_cache_pointcloud_surface_get(Object *object)
-{
- BLI_assert(object->type == OB_POINTCLOUD);
- return DRW_pointcloud_batch_cache_get_surface(object);
-}
-
-GPUBatch *DRW_cache_pointcloud_surface_viewer_attribute_get(Object *object)
-{
- BLI_assert(object->type == OB_POINTCLOUD);
- return DRW_pointcloud_batch_cache_get_surface_viewer_attribute(object);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -3308,6 +3286,9 @@ void drw_batch_cache_generate_requested(Object *ob)
case OB_CURVES:
DRW_curves_batch_cache_create_requested(ob);
break;
+ case OB_POINTCLOUD:
+ DRW_pointcloud_batch_cache_create_requested(ob);
+ break;
/* TODO: all cases. */
default:
break;
@@ -3358,7 +3339,9 @@ void DRW_batch_cache_free_old(Object *ob, int ctime)
case OB_CURVES:
DRW_curves_batch_cache_free_old((Curves *)ob->data, ctime);
break;
- /* TODO: all cases. */
+ case OB_POINTCLOUD:
+ DRW_pointcloud_batch_cache_free_old((PointCloud *)ob->data, ctime);
+ break;
default:
break;
}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 058f28f094d..772cf3b12a5 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -13,6 +13,7 @@ extern "C" {
struct GPUBatch;
struct GPUMaterial;
+struct GPUVertBuf;
struct ModifierData;
struct Object;
struct PTCacheEdit;
@@ -224,12 +225,6 @@ struct GPUBatch **DRW_cache_curves_surface_shaded_get(struct Object *ob,
struct GPUBatch *DRW_cache_curves_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_curves_edge_detection_get(struct Object *ob, bool *r_is_manifold);
-/* PointCloud */
-
-struct GPUBatch *DRW_cache_pointcloud_get_dots(struct Object *obj);
-struct GPUBatch *DRW_cache_pointcloud_surface_get(struct Object *obj);
-struct GPUBatch *DRW_cache_pointcloud_surface_viewer_attribute_get(struct Object *obj);
-
/* Volume */
typedef struct DRWVolumeGrid {
@@ -257,14 +252,17 @@ struct GPUBatch *DRW_cache_volume_selection_surface_get(struct Object *ob);
/* GPencil */
-struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
-struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_get(struct Object *ob, int cfra);
+struct GPUVertBuf *DRW_cache_gpencil_position_buffer_get(struct Object *ob, int cfra);
+struct GPUVertBuf *DRW_cache_gpencil_color_buffer_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_curve_points_get(struct Object *ob, int cfra);
-struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob);
-struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob);
+struct GPUBatch *DRW_cache_gpencil_sbuffer_get(struct Object *ob, bool show_fill);
+struct GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(struct Object *ob,
+ bool show_fill);
+struct GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(struct Object *ob, bool show_fill);
int DRW_gpencil_material_count_get(struct bGPdata *gpd);
struct GPUBatch *DRW_cache_gpencil_face_wireframe_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index c6e8539121f..5aa2203ca68 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -80,6 +80,7 @@ void DRW_batch_cache_free_old(struct Object *ob, int ctime);
*/
void DRW_mesh_batch_cache_free_old(struct Mesh *me, int ctime);
void DRW_curves_batch_cache_free_old(struct Curves *curves, int ctime);
+void DRW_pointcloud_batch_cache_free_old(struct PointCloud *pointcloud, int ctime);
/** \} */
@@ -131,7 +132,7 @@ int DRW_curves_material_count_get(struct Curves *curves);
* \return A pointer to location where the texture will be
* stored, which will be filled by #DRW_shgroup_curves_create_sub.
*/
-struct GPUTexture **DRW_curves_texture_for_evaluated_attribute(struct Curves *curves,
+struct GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(struct Curves *curves,
const char *name,
bool *r_is_point_domain);
@@ -147,12 +148,11 @@ void DRW_curves_batch_cache_create_requested(struct Object *ob);
int DRW_pointcloud_material_count_get(struct PointCloud *pointcloud);
+struct GPUVertBuf **DRW_pointcloud_evaluated_attribute(struct PointCloud *pointcloud,
+ const char *name);
struct GPUBatch *DRW_pointcloud_batch_cache_get_dots(struct Object *ob);
-struct GPUBatch *DRW_pointcloud_batch_cache_get_surface(struct Object *ob);
-struct GPUBatch *DRW_pointcloud_batch_cache_get_surface_viewer_attribute(struct Object *ob);
-struct GPUBatch **DRW_cache_pointcloud_surface_shaded_get(struct Object *ob,
- struct GPUMaterial **gpumat_array,
- uint gpumat_array_len);
+
+void DRW_pointcloud_batch_cache_create_requested(struct Object *ob);
/** \} */
diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc
index 85dd9ca8695..c36b90ec32e 100644
--- a/source/blender/draw/intern/draw_cache_impl_curves.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curves.cc
@@ -88,13 +88,11 @@ static void curves_discard_attributes(CurvesEvalCache &curves_cache)
{
for (const int i : IndexRange(GPU_MAX_ATTR)) {
GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_attributes_buf[i]);
- DRW_TEXTURE_FREE_SAFE(curves_cache.proc_attributes_tex[i]);
}
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
for (const int j : IndexRange(GPU_MAX_ATTR)) {
GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].attributes_buf[j]);
- DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].attributes_tex[j]);
}
drw_attributes_clear(&curves_cache.final[i].attr_used);
@@ -107,17 +105,12 @@ static void curves_batch_cache_clear_data(CurvesEvalCache &curves_cache)
GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_point_buf);
GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_length_buf);
GPU_VERTBUF_DISCARD_SAFE(curves_cache.data_edit_points);
- DRW_TEXTURE_FREE_SAFE(curves_cache.point_tex);
- DRW_TEXTURE_FREE_SAFE(curves_cache.length_tex);
GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_buf);
GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_seg_buf);
- DRW_TEXTURE_FREE_SAFE(curves_cache.strand_tex);
- DRW_TEXTURE_FREE_SAFE(curves_cache.strand_seg_tex);
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].proc_buf);
- DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].proc_tex);
for (const int j : IndexRange(MAX_THICKRES)) {
GPU_BATCH_DISCARD_SAFE(curves_cache.final[i].proc_hairs[j]);
}
@@ -286,21 +279,6 @@ static void curves_batch_cache_ensure_procedural_pos(const Curves &curves,
cache.strands_len};
curves_batch_cache_fill_segments_proc_pos(curves, posTime_data, hairLength_data);
-
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache.proc_point_buf);
- cache.point_tex = GPU_texture_create_from_vertbuf("hair_point", cache.proc_point_buf);
- }
-
- if (gpu_material && cache.proc_length_buf != nullptr && cache.length_tex) {
- ListBase gpu_attrs = GPU_material_attributes(gpu_material);
- LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) {
- if (attr->type == CD_HAIRLENGTH) {
- GPU_vertbuf_use(cache.proc_length_buf);
- cache.length_tex = GPU_texture_create_from_vertbuf("hair_length", cache.proc_length_buf);
- break;
- }
- }
}
}
@@ -363,12 +341,6 @@ static void curves_batch_cache_ensure_procedural_final_attr(CurvesEvalCache &cac
/* Those are points! not line segments. */
GPU_vertbuf_data_alloc(final_cache.attributes_buf[index],
final_cache.strands_res * cache.strands_len);
-
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(final_cache.attributes_buf[index]);
-
- final_cache.attributes_tex[index] = GPU_texture_create_from_vertbuf(
- name, final_cache.attributes_buf[index]);
}
static void curves_batch_ensure_attribute(const Curves &curves,
@@ -379,7 +351,6 @@ static void curves_batch_ensure_attribute(const Curves &curves,
{
using namespace blender;
GPU_VERTBUF_DISCARD_SAFE(cache.proc_attributes_buf[index]);
- DRW_TEXTURE_FREE_SAFE(cache.proc_attributes_tex[index]);
char sampler_name[32];
drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name);
@@ -414,13 +385,9 @@ static void curves_batch_ensure_attribute(const Curves &curves,
attribute.materialize(vbo_span);
- GPU_vertbuf_use(attr_vbo);
- cache.proc_attributes_tex[index] = GPU_texture_create_from_vertbuf(sampler_name, attr_vbo);
-
/* Existing final data may have been for a different attribute (with a different name or domain),
* free the data. */
GPU_VERTBUF_DISCARD_SAFE(cache.final[subdiv].attributes_buf[index]);
- DRW_TEXTURE_FREE_SAFE(cache.final[subdiv].attributes_tex[index]);
/* Ensure final data for points. */
if (request.domain == ATTR_DOMAIN_POINT) {
@@ -466,19 +433,11 @@ static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves,
GPU_vertbuf_attr_get_raw_data(cache.proc_strand_seg_buf, seg_id, &seg_step);
curves_batch_cache_fill_strands_data(curves, data_step, seg_step);
-
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache.proc_strand_buf);
- cache.strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache.proc_strand_buf);
-
- GPU_vertbuf_use(cache.proc_strand_seg_buf);
- cache.strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg",
- cache.proc_strand_seg_buf);
}
static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &cache, int subdiv)
{
- /* Same format as point_tex. */
+ /* Same format as proc_point_buf. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
@@ -489,12 +448,6 @@ static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &c
/* Those are points! not line segments. */
GPU_vertbuf_data_alloc(cache.final[subdiv].proc_buf,
cache.final[subdiv].strands_res * cache.strands_len);
-
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache.final[subdiv].proc_buf);
-
- cache.final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc",
- cache.final[subdiv].proc_buf);
}
static void curves_batch_cache_fill_segments_indices(const Curves &curves,
@@ -583,7 +536,6 @@ static bool curves_ensure_attributes(const Curves &curves,
/* Some new attributes have been added, free all and start over. */
for (const int i : IndexRange(GPU_MAX_ATTR)) {
GPU_VERTBUF_DISCARD_SAFE(cache.curves_cache.proc_attributes_buf[i]);
- DRW_TEXTURE_FREE_SAFE(cache.curves_cache.proc_attributes_tex[i]);
}
drw_attributes_merge(&final_cache.attr_used, &attrs_needed, cache.render_mutex);
}
@@ -631,7 +583,7 @@ bool curves_ensure_procedural_data(Curves *curves,
}
/* Refreshed if active layer or custom data changes. */
- if ((*r_hair_cache)->strand_tex == nullptr) {
+ if ((*r_hair_cache)->proc_strand_buf == nullptr) {
curves_batch_cache_ensure_procedural_strand_data(*curves, cache.curves_cache);
}
@@ -689,7 +641,7 @@ static void request_attribute(Curves &curves, const char *name)
drw_attributes_merge(&final_cache.attr_used, &attributes, cache.render_mutex);
}
-GPUTexture **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
+GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
const char *name,
bool *r_is_point_domain)
{
@@ -715,10 +667,10 @@ GPUTexture **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
switch (final_cache.attr_used.requests[request_i].domain) {
case ATTR_DOMAIN_POINT:
*r_is_point_domain = true;
- return &final_cache.attributes_tex[request_i];
+ return &final_cache.attributes_buf[request_i];
case ATTR_DOMAIN_CURVE:
*r_is_point_domain = false;
- return &cache.curves_cache.proc_attributes_tex[request_i];
+ return &cache.curves_cache.proc_attributes_buf[request_i];
default:
BLI_assert_unreachable();
return nullptr;
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.cc
index 7a43c7ee2e6..3d6d2631186 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc
@@ -23,12 +23,14 @@
#include "DEG_depsgraph_query.h"
#include "BLI_hash.h"
+#include "BLI_math_vec_types.hh"
#include "BLI_polyfill_2d.h"
#include "draw_cache.h"
#include "draw_cache_impl.h"
#include "../engines/gpencil/gpencil_defines.h"
+#include "../engines/gpencil/gpencil_shader_shared.h"
#define BEZIER_HANDLE (1 << 3)
#define COLOR_SHIFT 5
@@ -41,11 +43,13 @@ typedef struct GpencilBatchCache {
/** Instancing Data */
GPUVertBuf *vbo;
GPUVertBuf *vbo_col;
- /** Fill Topology */
+ /** Indices in material order, then stroke order with fill first.
+ * Strokes can be individually rendered using `gps->runtime.stroke_start` and
+ * `gps->runtime.fill_start`. */
GPUIndexBuf *ibo;
- /** Instancing Batches */
- GPUBatch *stroke_batch;
- GPUBatch *fill_batch;
+ /** Batches */
+ GPUBatch *geom_batch;
+ /** Stroke lines only */
GPUBatch *lines_batch;
/** Edit Mode */
@@ -97,7 +101,8 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
GpencilBatchCache *cache = gpd->runtime.gpencil_cache;
if (!cache) {
- cache = gpd->runtime.gpencil_cache = MEM_callocN(sizeof(*cache), __func__);
+ cache = gpd->runtime.gpencil_cache = (GpencilBatchCache *)MEM_callocN(sizeof(*cache),
+ __func__);
}
else {
memset(cache, 0, sizeof(*cache));
@@ -116,8 +121,7 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
}
GPU_BATCH_DISCARD_SAFE(cache->lines_batch);
- GPU_BATCH_DISCARD_SAFE(cache->fill_batch);
- GPU_BATCH_DISCARD_SAFE(cache->stroke_batch);
+ GPU_BATCH_DISCARD_SAFE(cache->geom_batch);
GPU_VERTBUF_DISCARD_SAFE(cache->vbo);
GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo);
@@ -172,9 +176,10 @@ void DRW_gpencil_batch_cache_free(bGPdata *gpd)
/* MUST match the format below. */
typedef struct gpStrokeVert {
- int32_t mat, stroke_id, point_id, packed_asp_hard_rot;
/** Position and thickness packed in the same attribute. */
float pos[3], thickness;
+ /** Material Index, Stroke Index, Point Index, Packed aspect + hardness + rotation. */
+ int32_t mat, stroke_id, point_id, packed_asp_hard_rot;
/** UV and strength packed in the same attribute. */
float uv_fill[2], u_stroke, strength;
} gpStrokeVert;
@@ -183,12 +188,9 @@ static GPUVertFormat *gpencil_stroke_format(void)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT);
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT);
GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- /* IMPORTANT: This means having only 4 attributes
- * to fit into GPU module limit of 16 attributes. */
- GPU_vertformat_multiload_enable(&format, 4);
}
return &format;
}
@@ -238,9 +240,6 @@ static GPUVertFormat *gpencil_color_format(void)
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "fcol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- /* IMPORTANT: This means having only 4 attributes
- * to fit into GPU module limit of 16 attributes. */
- GPU_vertformat_multiload_enable(&format, 4);
}
return &format;
}
@@ -295,7 +294,8 @@ BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float har
return packed;
}
-static void gpencil_buffer_add_point(gpStrokeVert *verts,
+static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo,
+ gpStrokeVert *verts,
gpColorVert *cols,
const bGPDstroke *gps,
const bGPDspoint *pt,
@@ -319,7 +319,7 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts,
vert->strength = (round_cap0) ? pt->strength : -pt->strength;
vert->u_stroke = pt->uv_fac;
- vert->stroke_id = gps->runtime.stroke_start;
+ vert->stroke_id = gps->runtime.vertex_start;
vert->point_id = v;
vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f);
/* Tag endpoint material to -1 so they get discarded by vertex shader. */
@@ -329,27 +329,36 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts,
vert->packed_asp_hard_rot = pack_rotation_aspect_hardness(
pt->uv_rot, aspect_ratio, gps->hardeness);
+
+ if (!is_endpoint) {
+ /* Issue a Quad per point. */
+ /* The attribute loading uses a different shader and will undo this bit packing. */
+ int v_mat = (v << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT;
+ GPU_indexbuf_add_tri_verts(ibo, v_mat + 0, v_mat + 1, v_mat + 2);
+ GPU_indexbuf_add_tri_verts(ibo, v_mat + 2, v_mat + 1, v_mat + 3);
+ }
}
-static void gpencil_buffer_add_stroke(gpStrokeVert *verts,
+static void gpencil_buffer_add_stroke(GPUIndexBufBuilder *ibo,
+ gpStrokeVert *verts,
gpColorVert *cols,
const bGPDstroke *gps)
{
const bGPDspoint *pts = gps->points;
int pts_len = gps->totpoints;
bool is_cyclic = gpencil_stroke_is_cyclic(gps);
- int v = gps->runtime.stroke_start;
+ int v = gps->runtime.vertex_start;
/* First point for adjacency (not drawn). */
int adj_idx = (is_cyclic) ? (pts_len - 1) : min_ii(pts_len - 1, 1);
- gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[adj_idx], v++, true);
for (int i = 0; i < pts_len; i++) {
- gpencil_buffer_add_point(verts, cols, gps, &pts[i], v++, false);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[i], v++, false);
}
/* Draw line to first point to complete the loop for cyclic strokes. */
if (is_cyclic) {
- gpencil_buffer_add_point(verts, cols, gps, &pts[0], v, false);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[0], v, false);
/* UV factor needs to be adjusted for the last point to not be equal to the UV factor of the
* first point. It should be the factor of the last point plus the distance from the last point
* to the first.
@@ -360,16 +369,20 @@ static void gpencil_buffer_add_stroke(gpStrokeVert *verts,
}
/* Last adjacency point (not drawn). */
adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2);
- gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[adj_idx], v++, true);
}
static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps)
{
int tri_len = gps->tot_triangles;
- int v = gps->runtime.stroke_start;
+ int v = gps->runtime.vertex_start + 1;
for (int i = 0; i < tri_len; i++) {
uint *tri = gps->triangles[i].verts;
- GPU_indexbuf_add_tri_verts(ibo, v + tri[0], v + tri[1], v + tri[2]);
+ /* The attribute loading uses a different shader and will undo this bit packing. */
+ GPU_indexbuf_add_tri_verts(ibo,
+ (v + tri[0]) << GP_VERTEX_ID_SHIFT,
+ (v + tri[1]) << GP_VERTEX_ID_SHIFT,
+ (v + tri[2]) << GP_VERTEX_ID_SHIFT);
}
}
@@ -379,10 +392,10 @@ static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl),
void *thunk)
{
gpIterData *iter = (gpIterData *)thunk;
- gpencil_buffer_add_stroke(iter->verts, iter->cols, gps);
if (gps->tot_triangles > 0) {
gpencil_buffer_add_fill(&iter->ibo, gps);
}
+ gpencil_buffer_add_stroke(&iter->ibo, iter->verts, iter->cols, gps);
}
static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
@@ -391,12 +404,15 @@ static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
void *thunk)
{
gpIterData *iter = (gpIterData *)thunk;
-
- /* Store first index offset */
- gps->runtime.stroke_start = iter->vert_len;
+ int stroke_vert_len = gps->totpoints + gpencil_stroke_is_cyclic(gps);
+ gps->runtime.vertex_start = iter->vert_len;
+ /* Add additional padding at the start and end. */
+ iter->vert_len += 1 + stroke_vert_len + 1;
+ /* Store first index offset. */
gps->runtime.fill_start = iter->tri_len;
- iter->vert_len += gps->totpoints + 2 + gpencil_stroke_is_cyclic(gps);
iter->tri_len += gps->tot_triangles;
+ gps->runtime.stroke_start = iter->tri_len;
+ iter->tri_len += stroke_vert_len * 2;
}
static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra)
@@ -406,7 +422,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
if (cache->vbo == NULL) {
/* Should be discarded together. */
BLI_assert(cache->vbo == NULL && cache->ibo == NULL);
- BLI_assert(cache->fill_batch == NULL && cache->stroke_batch == NULL);
+ BLI_assert(cache->geom_batch == NULL);
/* TODO/PERF: Could be changed to only do it if needed.
* For now it's simpler to assume we always need it
* since multiple viewport could or could not need it.
@@ -415,29 +431,29 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
bool do_onion = true;
/* First count how many vertices and triangles are needed for the whole object. */
- gpIterData iter = {
- .gpd = gpd,
- .verts = NULL,
- .ibo = {0},
- .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
- .tri_len = 0,
- .curve_len = 0,
- };
+ gpIterData iter = {};
+ iter.gpd = gpd;
+ iter.verts = NULL;
+ iter.ibo = {0};
+ iter.vert_len = 0;
+ iter.tri_len = 0;
+ iter.curve_len = 0;
BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra);
+ GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
/* Create VBOs. */
GPUVertFormat *format = gpencil_stroke_format();
GPUVertFormat *format_col = gpencil_color_format();
- cache->vbo = GPU_vertbuf_create_with_format(format);
- cache->vbo_col = GPU_vertbuf_create_with_format(format_col);
+ cache->vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag);
+ cache->vbo_col = GPU_vertbuf_create_with_format_ex(format_col, vbo_flag);
/* Add extra space at the end of the buffer because of quad load. */
GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2);
GPU_vertbuf_data_alloc(cache->vbo_col, iter.vert_len + 2);
iter.verts = (gpStrokeVert *)GPU_vertbuf_get_data(cache->vbo);
iter.cols = (gpColorVert *)GPU_vertbuf_get_data(cache->vbo_col);
/* Create IBO. */
- GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
+ GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, 0xFFFFFFFFu);
/* Fill buffers with data. */
BKE_gpencil_visible_stroke_advanced_iter(
@@ -452,33 +468,39 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
/* Finish the IBO. */
cache->ibo = GPU_indexbuf_build(&iter.ibo);
-
/* Create the batches */
- cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
- GPU_batch_vertbuf_add(cache->fill_batch, cache->vbo_col);
- cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
- GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0);
- GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo_col, 0);
+ cache->geom_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
+ /* Allow creation of buffer texture. */
+ GPU_vertbuf_use(cache->vbo);
+ GPU_vertbuf_use(cache->vbo_col);
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
cache->is_dirty = false;
}
}
-GPUBatch *DRW_cache_gpencil_strokes_get(Object *ob, int cfra)
+GPUBatch *DRW_cache_gpencil_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+
+ return cache->geom_batch;
+}
+
+GPUVertBuf *DRW_cache_gpencil_position_buffer_get(Object *ob, int cfra)
{
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
gpencil_batches_ensure(ob, cache, cfra);
- return cache->stroke_batch;
+ return cache->vbo;
}
-GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra)
+GPUVertBuf *DRW_cache_gpencil_color_buffer_get(Object *ob, int cfra)
{
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
gpencil_batches_ensure(ob, cache, cfra);
- return cache->fill_batch;
+ return cache->vbo_col;
}
static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl),
@@ -489,7 +511,7 @@ static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl),
gpIterData *iter = (gpIterData *)thunk;
int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps);
- int start = gps->runtime.stroke_start + 1;
+ int start = gps->runtime.vertex_start + 1;
int end = start + pts_len;
for (int i = start; i < end; i++) {
GPU_indexbuf_add_generic_vert(&iter->ibo, i);
@@ -508,10 +530,9 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
if (cache->lines_batch == NULL) {
GPUVertBuf *vbo = cache->vbo;
- gpIterData iter = {
- .gpd = ob->data,
- .ibo = {0},
- };
+ gpIterData iter = {};
+ iter.gpd = (bGPdata *)ob->data;
+ iter.ibo = {0};
uint vert_len = GPU_vertbuf_get_vertex_len(vbo);
GPU_indexbuf_init_ex(&iter.ibo, GPU_PRIM_LINE_STRIP, vert_len, vert_len);
@@ -540,7 +561,7 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob)
Brush *brush = gpd->runtime.sbuffer_brush;
/* Convert the sbuffer to a bGPDstroke. */
if (gpd->runtime.sbuffer_gps == NULL) {
- bGPDstroke *gps = MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer");
+ bGPDstroke *gps = (bGPDstroke *)MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer");
gps->totpoints = gpd->runtime.sbuffer_used;
gps->mat_nr = max_ii(0, gpd->runtime.matid - 1);
gps->flag = gpd->runtime.sbuffer_sflag;
@@ -553,7 +574,9 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob)
gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2);
gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND;
- gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */
+ gps->runtime.vertex_start = 0;
+ gps->runtime.fill_start = 0;
+ gps->runtime.stroke_start = 0;
copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill);
/* Caps. */
gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type;
@@ -563,17 +586,17 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob)
return gpd->runtime.sbuffer_gps;
}
-static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_fill)
+static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill)
{
- tGPspoint *tpoints = gpd->runtime.sbuffer;
+ tGPspoint *tpoints = (tGPspoint *)gpd->runtime.sbuffer;
bGPDstroke *gps = gpd->runtime.sbuffer_gps;
int vert_len = gpd->runtime.sbuffer_used;
/* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */
BLI_assert(gps != NULL);
- if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) {
- gps->points = MEM_mallocN(vert_len * sizeof(*gps->points), __func__);
+ if (gpd->runtime.sbuffer_batch == NULL) {
+ gps->points = (bGPDspoint *)MEM_mallocN(vert_len * sizeof(*gps->points), __func__);
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
@@ -596,36 +619,25 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_
/* Calc uv data along the stroke. */
BKE_gpencil_stroke_uv_update(gps);
+ int tri_len = gps->tot_triangles + (gps->totpoints + gpencil_stroke_is_cyclic(gps)) * 2;
+ /* Create IBO. */
+ GPUIndexBufBuilder ibo_builder;
+ GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, tri_len, 0xFFFFFFFFu);
/* Create VBO. */
+ GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
GPUVertFormat *format = gpencil_stroke_format();
GPUVertFormat *format_color = gpencil_color_format();
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format);
- GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(format_color);
- /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag);
+ GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format_ex(format_color, vbo_flag);
+ /* Add extra space at the start and end the buffer because of quad load and cyclic. */
GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2);
GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2);
gpStrokeVert *verts = (gpStrokeVert *)GPU_vertbuf_get_data(vbo);
gpColorVert *cols = (gpColorVert *)GPU_vertbuf_get_data(vbo_col);
- /* Fill buffers with data. */
- gpencil_buffer_add_stroke(verts, cols, gps);
-
- GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
- GPU_batch_instbuf_add_ex(batch, vbo, true);
- GPU_batch_instbuf_add_ex(batch, vbo_col, true);
-
- gpd->runtime.sbuffer_stroke_batch = batch;
-
- MEM_freeN(gps->points);
- }
-
- if (do_fill && (gpd->runtime.sbuffer_fill_batch == NULL)) {
- /* Create IBO. */
- GPUIndexBufBuilder ibo_builder;
- GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len);
-
- if (gps->tot_triangles > 0) {
- float(*tpoints2d)[2] = MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__);
+ /* Create fill indices. */
+ if (do_fill && gps->tot_triangles > 0) {
+ float(*tpoints2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__);
/* Triangulate in 2D. */
for (int i = 0; i < vert_len; i++) {
copy_v2_v2(tpoints2d[i], tpoints[i].m_xy);
@@ -633,51 +645,72 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_
/* Compute directly inside the IBO data buffer. */
/* OPTI: This is a bottleneck if the stroke is very long. */
BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data);
- /* Add stroke start offset. */
+ /* Add stroke start offset and shift. */
for (int i = 0; i < gps->tot_triangles * 3; i++) {
- ibo_builder.data[i] += gps->runtime.stroke_start;
+ ibo_builder.data[i] = (ibo_builder.data[i] + 1) << GP_VERTEX_ID_SHIFT;
}
/* HACK since we didn't use the builder API to avoid another malloc and copy,
* we need to set the number of indices manually. */
ibo_builder.index_len = gps->tot_triangles * 3;
+ ibo_builder.index_min = 0;
+ /* For this case, do not allow index compaction to avoid yet another preprocessing step. */
+ ibo_builder.index_max = 0xFFFFFFFFu - 1u;
+
+ gps->runtime.stroke_start = gps->tot_triangles;
MEM_freeN(tpoints2d);
}
- GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder);
- GPUVertBuf *vbo = gpd->runtime.sbuffer_stroke_batch->inst[0];
- GPUVertBuf *vbo_col = gpd->runtime.sbuffer_stroke_batch->inst[1];
+ /* Fill buffers with data. */
+ gpencil_buffer_add_stroke(&ibo_builder, verts, cols, gps);
- GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, ibo, GPU_BATCH_OWNS_INDEX);
- GPU_batch_vertbuf_add(batch, vbo_col);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS,
+ gpencil_dummy_buffer_get(),
+ GPU_indexbuf_build(&ibo_builder),
+ GPU_BATCH_OWNS_INDEX);
- gpd->runtime.sbuffer_fill_batch = batch;
+ gpd->runtime.sbuffer_position_buf = vbo;
+ gpd->runtime.sbuffer_color_buf = vbo_col;
+ gpd->runtime.sbuffer_batch = batch;
+
+ MEM_freeN(gps->points);
}
}
-GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(Object *ob)
+GPUBatch *DRW_cache_gpencil_sbuffer_get(Object *ob, bool show_fill)
{
bGPdata *gpd = (bGPdata *)ob->data;
- gpencil_sbuffer_stroke_ensure(gpd, true, false);
+ /* Fill batch also need stroke batch to be created (vbo is shared). */
+ gpencil_sbuffer_stroke_ensure(gpd, show_fill);
- return gpd->runtime.sbuffer_stroke_batch;
+ return gpd->runtime.sbuffer_batch;
}
-GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(Object *ob)
+GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob, bool show_fill)
{
bGPdata *gpd = (bGPdata *)ob->data;
/* Fill batch also need stroke batch to be created (vbo is shared). */
- gpencil_sbuffer_stroke_ensure(gpd, true, true);
+ gpencil_sbuffer_stroke_ensure(gpd, show_fill);
- return gpd->runtime.sbuffer_fill_batch;
+ return gpd->runtime.sbuffer_position_buf;
+}
+
+GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob, bool show_fill)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ /* Fill batch also need stroke batch to be created (vbo is shared). */
+ gpencil_sbuffer_stroke_ensure(gpd, show_fill);
+
+ return gpd->runtime.sbuffer_color_buf;
}
void DRW_cache_gpencil_sbuffer_clear(Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
MEM_SAFE_FREE(gpd->runtime.sbuffer_gps);
- GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_fill_batch);
- GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_stroke_batch);
+ GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_batch);
+ GPU_VERTBUF_DISCARD_SAFE(gpd->runtime.sbuffer_position_buf);
+ GPU_VERTBUF_DISCARD_SAFE(gpd->runtime.sbuffer_color_buf);
}
/** \} */
@@ -728,7 +761,7 @@ static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl,
{
gpEditIterData *iter = (gpEditIterData *)thunk;
const int v_len = gps->totpoints;
- const int v = gps->runtime.stroke_start + 1;
+ const int v = gps->runtime.vertex_start + 1;
MDeformVert *dvert = ((iter->vgindex > -1) && gps->dvert) ? gps->dvert : NULL;
gpEditVert *vert_ptr = iter->verts + v;
@@ -743,9 +776,12 @@ static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl,
vert_ptr->weight = gpencil_point_edit_weight(dvert, i, iter->vgindex);
vert_ptr++;
}
- /* Draw line to first point to complete the loop for cyclic strokes. */
- vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len);
- vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex);
+
+ if (gpencil_stroke_is_cyclic(gps)) {
+ /* Draw line to first point to complete the loop for cyclic strokes. */
+ vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len);
+ vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex);
+ }
}
static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl,
@@ -876,14 +912,13 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
/* Curve Handles and Points for Editing. */
if (cache->edit_curve_vbo == NULL) {
- gpIterData iterdata = {
- .gpd = gpd,
- .verts = NULL,
- .ibo = {0},
- .vert_len = 0,
- .tri_len = 0,
- .curve_len = 0,
- };
+ gpIterData iterdata = {};
+ iterdata.gpd = gpd;
+ iterdata.verts = NULL;
+ iterdata.ibo = {0};
+ iterdata.vert_len = 0;
+ iterdata.tri_len = 0;
+ iterdata.curve_len = 0;
/* Create VBO. */
GPUVertFormat *format = gpencil_edit_curve_format();
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc
index 5ce658abfe4..031de3e4ef2 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc
@@ -1889,7 +1889,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
is_editmode,
is_paint_mode,
is_mode_active,
- ob->obmat,
+ ob->object_to_world,
false,
true,
scene,
@@ -1906,7 +1906,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
is_editmode,
is_paint_mode,
is_mode_active,
- ob->obmat,
+ ob->object_to_world,
false,
false,
scene,
@@ -1922,7 +1922,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
is_editmode,
is_paint_mode,
is_mode_active,
- ob->obmat,
+ ob->object_to_world,
true,
false,
do_cage,
@@ -1943,7 +1943,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
is_editmode,
is_paint_mode,
is_mode_active,
- ob->obmat,
+ ob->object_to_world,
true,
false,
scene,
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index 9c1784b1de2..8facea4333f 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -173,13 +173,9 @@ static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
/* TODO: more granular update tagging. */
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_length_buf);
- DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex);
- DRW_TEXTURE_FREE_SAFE(hair_cache->length_tex);
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf);
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_seg_buf);
- DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex);
- DRW_TEXTURE_FREE_SAFE(hair_cache->strand_seg_tex);
for (int i = 0; i < MAX_MTFACE; i++) {
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]);
@@ -192,7 +188,6 @@ static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
for (int i = 0; i < MAX_HAIR_SUBDIV; i++) {
GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf);
- DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex);
for (int j = 0; j < MAX_THICKRES; j++) {
GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]);
}
@@ -810,7 +805,7 @@ static int particle_batch_cache_fill_strands_data(ParticleSystem *psys,
static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache,
int subdiv)
{
- /* Same format as point_tex. */
+ /* Same format as proc_point_buf. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
@@ -823,12 +818,6 @@ static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCach
/* Those are points! not line segments. */
GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf,
cache->final[subdiv].strands_res * cache->strands_len);
-
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache->final[subdiv].proc_buf);
-
- cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("part_proc",
- cache->final[subdiv].proc_buf);
}
static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit,
@@ -1034,14 +1023,6 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
MEM_freeN(parent_mcol);
}
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache->proc_strand_buf);
- cache->strand_tex = GPU_texture_create_from_vertbuf("part_strand", cache->proc_strand_buf);
-
- GPU_vertbuf_use(cache->proc_strand_seg_buf);
- cache->strand_seg_tex = GPU_texture_create_from_vertbuf("part_strand_seg",
- cache->proc_strand_seg_buf);
-
for (int i = 0; i < cache->num_uv_layers; i++) {
GPU_vertbuf_use(cache->proc_uv_buf[i]);
cache->uv_tex[i] = GPU_texture_create_from_vertbuf("part_uv", cache->proc_uv_buf[i]);
@@ -1107,7 +1088,7 @@ static void particle_batch_cache_ensure_procedural_indices(PTCacheEdit *edit,
static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit,
ParticleSystem *psys,
ParticleHairCache *cache,
- GPUMaterial *gpu_material)
+ GPUMaterial *UNUSED(gpu_material))
{
if (cache->proc_point_buf == NULL) {
/* initialize vertex format */
@@ -1149,22 +1130,6 @@ static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit,
psys->childcache, child_count, &pos_step, &length_step);
}
}
-
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache->proc_point_buf);
- cache->point_tex = GPU_texture_create_from_vertbuf("part_point", cache->proc_point_buf);
- }
-
- /* Checking hair length separately, only allocating gpu memory when needed. */
- if (gpu_material && cache->proc_length_buf != NULL && cache->length_tex == NULL) {
- ListBase gpu_attrs = GPU_material_attributes(gpu_material);
- LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) {
- if (attr->type == CD_HAIRLENGTH) {
- GPU_vertbuf_use(cache->proc_length_buf);
- cache->length_tex = GPU_texture_create_from_vertbuf("hair_length", cache->proc_length_buf);
- break;
- }
- }
}
}
@@ -1722,7 +1687,7 @@ bool particles_ensure_procedural_data(Object *object,
/* Refreshed on combing and simulation. */
if ((*r_hair_cache)->proc_point_buf == NULL ||
- (gpu_material && (*r_hair_cache)->length_tex == NULL)) {
+ (gpu_material && (*r_hair_cache)->proc_length_buf == NULL)) {
ensure_seg_pt_count(source.edit, source.psys, &cache->hair);
particle_batch_cache_ensure_procedural_pos(
source.edit, source.psys, &cache->hair, gpu_material);
@@ -1730,7 +1695,7 @@ bool particles_ensure_procedural_data(Object *object,
}
/* Refreshed if active layer or custom data changes. */
- if ((*r_hair_cache)->strand_tex == NULL) {
+ if ((*r_hair_cache)->proc_strand_buf == NULL) {
particle_batch_cache_ensure_procedural_strand_data(
source.edit, source.psys, source.md, &cache->hair);
}
diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.cc b/source/blender/draw/intern/draw_cache_impl_pointcloud.cc
index 98531637e57..d64fc581942 100644
--- a/source/blender/draw/intern/draw_cache_impl_pointcloud.cc
+++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.cc
@@ -23,30 +23,64 @@
#include "BKE_pointcloud.h"
#include "GPU_batch.h"
+#include "GPU_material.h"
-#include "draw_cache_impl.h" /* own include */
+#include "draw_attributes.h"
+#include "draw_cache_impl.h"
+#include "draw_cache_inline.h"
+#include "draw_pointcloud_private.hh" /* own include */
-/* ---------------------------------------------------------------------- */
-/* PointCloud GPUBatch Cache */
+using namespace blender;
-struct PointCloudBatchCache {
- GPUVertBuf *pos; /* Position and radius. */
- GPUVertBuf *geom; /* Instanced geometry for each point in the cloud (small sphere). */
- GPUVertBuf *attr_viewer;
- GPUIndexBuf *geom_indices;
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name GPUBatch cache management
+ * \{ */
+
+struct PointCloudBatchCache {
+ /* Dot primitive types. */
GPUBatch *dots;
+ /* Triangle primitive types. */
GPUBatch *surface;
GPUBatch **surface_per_mat;
- GPUBatch *surface_viewer_attribute;
+ /* Triangles indices to draw the points. */
+ GPUIndexBuf *geom_indices;
+
+ /* Position and radius. */
+ GPUVertBuf *pos_rad;
+ /* Active attribute in 3D view. */
+ GPUVertBuf *attr_viewer;
+ /* Requested attributes */
+ GPUVertBuf *attributes_buf[GPU_MAX_ATTR];
+
+ /** Attributes currently being drawn or about to be drawn. */
+ DRW_Attributes attr_used;
+ /**
+ * Attributes that were used at some point. This is used for garbage collection, to remove
+ * attributes that are not used in shaders anymore due to user edits.
+ */
+ DRW_Attributes attr_used_over_time;
+
+ /**
+ * The last time in seconds that the `attr_used` and `attr_used_over_time` were exactly the same.
+ * If the delta between this time and the current scene time is greater than the timeout set in
+ * user preferences (`U.vbotimeout`) then garbage collection is performed.
+ */
+ int last_attr_matching_time;
/* settings to determine if cache is invalid */
bool is_dirty;
int mat_len;
-};
-/* GPUBatch cache management. */
+ /**
+ * The draw cache extraction is currently not multi-threaded for multiple objects, but if it was,
+ * some locking would be necessary because multiple objects can use the same object data with
+ * different materials, etc. This is a placeholder to make multi-threading easier in the future.
+ */
+ std::mutex render_mutex;
+};
static PointCloudBatchCache *pointcloud_batch_cache_get(PointCloud &pointcloud)
{
@@ -71,7 +105,7 @@ static void pointcloud_batch_cache_init(PointCloud &pointcloud)
PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
if (!cache) {
- cache = MEM_cnew<PointCloudBatchCache>(__func__);
+ cache = MEM_new<PointCloudBatchCache>(__func__);
pointcloud.batch_cache = cache;
}
else {
@@ -100,6 +134,15 @@ void DRW_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode)
}
}
+static void pointcloud_discard_attributes(PointCloudBatchCache &cache)
+{
+ for (const int j : IndexRange(GPU_MAX_ATTR)) {
+ GPU_VERTBUF_DISCARD_SAFE(cache.attributes_buf[j]);
+ }
+
+ drw_attributes_clear(&cache.attr_used);
+}
+
static void pointcloud_batch_cache_clear(PointCloud &pointcloud)
{
PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
@@ -109,8 +152,7 @@ static void pointcloud_batch_cache_clear(PointCloud &pointcloud)
GPU_BATCH_DISCARD_SAFE(cache->dots);
GPU_BATCH_DISCARD_SAFE(cache->surface);
- GPU_VERTBUF_DISCARD_SAFE(cache->pos);
- GPU_VERTBUF_DISCARD_SAFE(cache->geom);
+ GPU_VERTBUF_DISCARD_SAFE(cache->pos_rad);
GPU_VERTBUF_DISCARD_SAFE(cache->attr_viewer);
GPU_INDEXBUF_DISCARD_SAFE(cache->geom_indices);
@@ -119,8 +161,9 @@ static void pointcloud_batch_cache_clear(PointCloud &pointcloud)
GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
}
}
- GPU_BATCH_DISCARD_SAFE(cache->surface_viewer_attribute);
MEM_SAFE_FREE(cache->surface_per_mat);
+
+ pointcloud_discard_attributes(*cache);
}
void DRW_pointcloud_batch_cache_validate(PointCloud *pointcloud)
@@ -137,61 +180,35 @@ void DRW_pointcloud_batch_cache_free(PointCloud *pointcloud)
MEM_SAFE_FREE(pointcloud->batch_cache);
}
-static void pointcloud_batch_cache_ensure_pos(const PointCloud &pointcloud,
- PointCloudBatchCache &cache)
+void DRW_pointcloud_batch_cache_free_old(PointCloud *pointcloud, int ctime)
{
- using namespace blender;
- if (cache.pos != nullptr) {
+ PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud);
+ if (!cache) {
return;
}
- const bke::AttributeAccessor attributes = pointcloud.attributes();
- const VArraySpan<float3> positions = attributes.lookup<float3>("position", ATTR_DOMAIN_POINT);
- const VArray<float> radii = attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
- /* From the opengl wiki:
- * Note that size does not have to exactly match the size used by the vertex shader. If the
- * vertex shader has fewer components than the attribute provides, then the extras are ignored.
- * If the vertex shader has more components than the array provides, the extras are given
- * values from the vector (0, 0, 0, 1) for the missing XYZW components. */
- if (radii) {
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
- cache.pos = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(cache.pos, positions.size());
- const VArraySpan<float> radii_span(radii);
- MutableSpan<float4> vbo_data{static_cast<float4 *>(GPU_vertbuf_get_data(cache.pos)),
- pointcloud.totpoint};
- threading::parallel_for(vbo_data.index_range(), 4096, [&](IndexRange range) {
- for (const int i : range) {
- vbo_data[i].x = positions[i].x;
- vbo_data[i].y = positions[i].y;
- vbo_data[i].z = positions[i].z;
- /* TODO(fclem): remove multiplication. Here only for keeping the size correct for now. */
- vbo_data[i].w = radii_span[i] * 100.0f;
- }
- });
+ bool do_discard = false;
+
+ if (drw_attributes_overlap(&cache->attr_used_over_time, &cache->attr_used)) {
+ cache->last_attr_matching_time = ctime;
}
- else {
- static GPUVertFormat format = {0};
- static uint pos;
- if (format.attr_len == 0) {
- pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
- cache.pos = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(cache.pos, positions.size());
- GPU_vertbuf_attr_fill(cache.pos, pos, positions.data());
+
+ if (ctime - cache->last_attr_matching_time > U.vbotimeout) {
+ do_discard = true;
+ }
+
+ drw_attributes_clear(&cache->attr_used_over_time);
+
+ if (do_discard) {
+ pointcloud_discard_attributes(*cache);
}
}
-static const float half_octahedron_normals[5][3] = {
- {0.0f, 0.0f, 1.0f},
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f},
- {-1.0f, 0.0f, 0.0f},
- {0.0f, -1.0f, 0.0f},
-};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name PointCloud extraction
+ * \{ */
static const uint half_octahedron_tris[4][3] = {
{0, 1, 2},
@@ -200,130 +217,236 @@ static const uint half_octahedron_tris[4][3] = {
{0, 4, 1},
};
-static void pointcloud_batch_cache_ensure_geom(PointCloudBatchCache &cache)
+static void pointcloud_extract_indices(const PointCloud &pointcloud, PointCloudBatchCache &cache)
{
- if (cache.geom != nullptr) {
- return;
+ /** \note: Avoid modulo by non-power-of-two in shader. */
+ uint32_t vertid_max = pointcloud.totpoint * 32;
+ uint32_t index_len = pointcloud.totpoint * ARRAY_SIZE(half_octahedron_tris);
+
+ GPUIndexBufBuilder builder;
+ GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, index_len, vertid_max);
+
+ for (int p = 0; p < pointcloud.totpoint; p++) {
+ for (int i = 0; i < ARRAY_SIZE(half_octahedron_tris); i++) {
+ GPU_indexbuf_add_tri_verts(&builder,
+ half_octahedron_tris[i][0] + p * 32,
+ half_octahedron_tris[i][1] + p * 32,
+ half_octahedron_tris[i][2] + p * 32);
+ }
}
+ GPU_indexbuf_build_in_place(&builder, cache.geom_indices);
+}
+
+static void pointcloud_extract_position_and_radius(const PointCloud &pointcloud,
+ PointCloudBatchCache &cache)
+{
+ using namespace blender;
+
+ const bke::AttributeAccessor attributes = pointcloud.attributes();
+ const VArraySpan<float3> positions = attributes.lookup<float3>("position", ATTR_DOMAIN_POINT);
+ const VArray<float> radii = attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
static GPUVertFormat format = {0};
- static uint pos;
if (format.attr_len == 0) {
- pos = GPU_vertformat_attr_add(&format, "pos_inst", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- GPU_vertformat_alias_add(&format, "nor");
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
- cache.geom = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(cache.geom, ARRAY_SIZE(half_octahedron_normals));
-
- GPU_vertbuf_attr_fill(cache.geom, pos, half_octahedron_normals);
-
- GPUIndexBufBuilder builder;
- GPU_indexbuf_init(&builder,
- GPU_PRIM_TRIS,
- ARRAY_SIZE(half_octahedron_tris),
- ARRAY_SIZE(half_octahedron_normals));
+ GPUUsageType usage_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
+ GPU_vertbuf_init_with_format_ex(cache.pos_rad, &format, usage_flag);
- for (int i = 0; i < ARRAY_SIZE(half_octahedron_tris); i++) {
- GPU_indexbuf_add_tri_verts(&builder, UNPACK3(half_octahedron_tris[i]));
+ GPU_vertbuf_data_alloc(cache.pos_rad, positions.size());
+ MutableSpan<float4> vbo_data{static_cast<float4 *>(GPU_vertbuf_get_data(cache.pos_rad)),
+ pointcloud.totpoint};
+ if (radii) {
+ const VArraySpan<float> radii_span(radii);
+ threading::parallel_for(vbo_data.index_range(), 4096, [&](IndexRange range) {
+ for (const int i : range) {
+ vbo_data[i].x = positions[i].x;
+ vbo_data[i].y = positions[i].y;
+ vbo_data[i].z = positions[i].z;
+ /* TODO(fclem): remove multiplication. Here only for keeping the size correct for now. */
+ vbo_data[i].w = radii_span[i] * 100.0f;
+ }
+ });
+ }
+ else {
+ threading::parallel_for(vbo_data.index_range(), 4096, [&](IndexRange range) {
+ for (const int i : range) {
+ vbo_data[i].x = positions[i].x;
+ vbo_data[i].y = positions[i].y;
+ vbo_data[i].z = positions[i].z;
+ vbo_data[i].w = 1.0f;
+ }
+ });
}
-
- cache.geom_indices = GPU_indexbuf_build(&builder);
}
-static void pointcloud_batch_cache_ensure_attribute_overlay(const PointCloud &pointcloud,
- PointCloudBatchCache &cache)
+static void pointcloud_extract_attribute(const PointCloud &pointcloud,
+ PointCloudBatchCache &cache,
+ const DRW_AttributeRequest &request,
+ int index)
{
using namespace blender;
- if (cache.attr_viewer != nullptr) {
- return;
- }
+
+ GPUVertBuf *&attr_buf = cache.attributes_buf[index];
const bke::AttributeAccessor attributes = pointcloud.attributes();
- const VArray<ColorGeometry4f> colors = attributes.lookup_or_default<ColorGeometry4f>(
- ".viewer", ATTR_DOMAIN_POINT, {1.0f, 0.0f, 1.0f, 1.0f});
+
+ /* TODO(@kevindietrich): float4 is used for scalar attributes as the implicit conversion done
+ * by OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following
+ * the Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a
+ * similar texture state swizzle to map the attribute correctly as for volume attributes, so we
+ * can control the conversion ourselves. */
+ VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
+ request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f});
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "attribute_value", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "attr", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
- cache.attr_viewer = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(cache.attr_viewer, pointcloud.totpoint);
+ GPUUsageType usage_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
+ GPU_vertbuf_init_with_format_ex(attr_buf, &format, usage_flag);
+ GPU_vertbuf_data_alloc(attr_buf, pointcloud.totpoint);
+
MutableSpan<ColorGeometry4f> vbo_data{
- static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(cache.attr_viewer)),
- pointcloud.totpoint};
- colors.materialize(vbo_data);
+ static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(attr_buf)), pointcloud.totpoint};
+ attribute.materialize(vbo_data);
}
-GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob)
-{
- PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
- PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
+/** \} */
- if (cache->dots == nullptr) {
- pointcloud_batch_cache_ensure_pos(pointcloud, *cache);
- cache->dots = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, nullptr);
- }
+/* -------------------------------------------------------------------- */
+/** \name Private API
+ * \{ */
- return cache->dots;
+GPUVertBuf *pointcloud_position_and_radius_get(PointCloud *pointcloud)
+{
+ PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud);
+ DRW_vbo_request(nullptr, &cache->pos_rad);
+ return cache->pos_rad;
}
-GPUBatch *DRW_pointcloud_batch_cache_get_surface(Object *ob)
+GPUBatch **pointcloud_surface_shaded_get(PointCloud *pointcloud,
+ GPUMaterial **gpu_materials,
+ int mat_len)
{
- PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
- PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
+ PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud);
+ DRW_Attributes attrs_needed;
+ drw_attributes_clear(&attrs_needed);
+
+ for (GPUMaterial *gpu_material : Span<GPUMaterial *>(gpu_materials, mat_len)) {
+ ListBase gpu_attrs = GPU_material_attributes(gpu_material);
+ LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) {
+ const char *name = gpu_attr->name;
+
+ int layer_index;
+ eCustomDataType type;
+ eAttrDomain domain = ATTR_DOMAIN_POINT;
+ if (!drw_custom_data_match_attribute(&pointcloud->pdata, name, &layer_index, &type)) {
+ continue;
+ }
- if (cache->surface == nullptr) {
- pointcloud_batch_cache_ensure_pos(pointcloud, *cache);
- pointcloud_batch_cache_ensure_geom(*cache);
+ drw_attributes_add_request(&attrs_needed, name, type, layer_index, domain);
+ }
+ }
- cache->surface = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices);
- GPU_batch_instbuf_add_ex(cache->surface, cache->pos, false);
+ if (!drw_attributes_overlap(&cache->attr_used, &attrs_needed)) {
+ /* Some new attributes have been added, free all and start over. */
+ for (const int i : IndexRange(GPU_MAX_ATTR)) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->attributes_buf[i]);
+ }
+ drw_attributes_merge(&cache->attr_used, &attrs_needed, cache->render_mutex);
}
+ drw_attributes_merge(&cache->attr_used_over_time, &attrs_needed, cache->render_mutex);
+
+ DRW_batch_request(&cache->surface_per_mat[0]);
+ return cache->surface_per_mat;
+}
- return cache->surface;
+GPUBatch *pointcloud_surface_get(PointCloud *pointcloud)
+{
+ PointCloudBatchCache *cache = pointcloud_batch_cache_get(*pointcloud);
+ return DRW_batch_request(&cache->surface);
}
-GPUBatch *DRW_pointcloud_batch_cache_get_surface_viewer_attribute(Object *ob)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name API
+ * \{ */
+
+GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob)
{
PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
+ return DRW_batch_request(&cache->dots);
+}
- if (cache->surface_viewer_attribute == nullptr) {
- pointcloud_batch_cache_ensure_pos(pointcloud, *cache);
- pointcloud_batch_cache_ensure_geom(*cache);
- pointcloud_batch_cache_ensure_attribute_overlay(pointcloud, *cache);
+GPUVertBuf **DRW_pointcloud_evaluated_attribute(PointCloud *pointcloud, const char *name)
+{
+ PointCloudBatchCache &cache = *pointcloud_batch_cache_get(*pointcloud);
+
+ int layer_index;
+ eCustomDataType type;
+ eAttrDomain domain = ATTR_DOMAIN_POINT;
+ if (drw_custom_data_match_attribute(&pointcloud->pdata, name, &layer_index, &type)) {
+ DRW_Attributes attributes{};
+ drw_attributes_add_request(&attributes, name, type, layer_index, domain);
+ drw_attributes_merge(&cache.attr_used, &attributes, cache.render_mutex);
+ }
- cache->surface_viewer_attribute = GPU_batch_create(
- GPU_PRIM_TRIS, cache->geom, cache->geom_indices);
- GPU_batch_instbuf_add_ex(cache->surface_viewer_attribute, cache->attr_viewer, false);
- GPU_batch_instbuf_add_ex(cache->surface_viewer_attribute, cache->pos, false);
+ int request_i = -1;
+ for (const int i : IndexRange(cache.attr_used.num_requests)) {
+ if (STREQ(cache.attr_used.requests[i].attribute_name, name)) {
+ request_i = i;
+ break;
+ }
+ }
+ if (request_i == -1) {
+ return nullptr;
}
+ return &cache.attributes_buf[request_i];
+}
- return cache->surface_viewer_attribute;
+int DRW_pointcloud_material_count_get(PointCloud *pointcloud)
+{
+ return max_ii(1, pointcloud->totcol);
}
-GPUBatch **DRW_cache_pointcloud_surface_shaded_get(Object *ob,
- struct GPUMaterial ** /*gpumat_array*/,
- uint gpumat_array_len)
+void DRW_pointcloud_batch_cache_create_requested(Object *ob)
{
- PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
- PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
- BLI_assert(cache->mat_len == gpumat_array_len);
- UNUSED_VARS(gpumat_array_len);
+ PointCloud *pointcloud = static_cast<PointCloud *>(ob->data);
+ PointCloudBatchCache &cache = *pointcloud_batch_cache_get(*pointcloud);
- if (cache->surface_per_mat[0] == nullptr) {
- pointcloud_batch_cache_ensure_pos(pointcloud, *cache);
- pointcloud_batch_cache_ensure_geom(*cache);
+ if (DRW_batch_requested(cache.dots, GPU_PRIM_POINTS)) {
+ DRW_vbo_request(cache.dots, &cache.pos_rad);
+ }
- cache->surface_per_mat[0] = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices);
- GPU_batch_instbuf_add_ex(cache->surface_per_mat[0], cache->pos, false);
+ if (DRW_batch_requested(cache.surface, GPU_PRIM_TRIS)) {
+ DRW_ibo_request(cache.surface, &cache.geom_indices);
+ DRW_vbo_request(cache.surface, &cache.pos_rad);
+ }
+ for (int i = 0; i < cache.mat_len; i++) {
+ if (DRW_batch_requested(cache.surface_per_mat[i], GPU_PRIM_TRIS)) {
+ /* TODO(fclem): Per material ranges. */
+ DRW_ibo_request(cache.surface_per_mat[i], &cache.geom_indices);
+ }
}
+ for (int j = 0; j < cache.attr_used.num_requests; j++) {
+ DRW_vbo_request(nullptr, &cache.attributes_buf[j]);
- return cache->surface_per_mat;
-}
+ if (DRW_vbo_requested(cache.attributes_buf[j])) {
+ pointcloud_extract_attribute(*pointcloud, cache, cache.attr_used.requests[j], j);
+ }
+ }
-int DRW_pointcloud_material_count_get(PointCloud *pointcloud)
-{
- return max_ii(1, pointcloud->totcol);
+ if (DRW_ibo_requested(cache.geom_indices)) {
+ pointcloud_extract_indices(*pointcloud, cache);
+ }
+
+ if (DRW_vbo_requested(cache.pos_rad)) {
+ pointcloud_extract_position_and_radius(*pointcloud, cache);
+ }
}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_command.cc b/source/blender/draw/intern/draw_command.cc
index 882eda9b31d..10dd63e05dc 100644
--- a/source/blender/draw/intern/draw_command.cc
+++ b/source/blender/draw/intern/draw_command.cc
@@ -30,6 +30,11 @@ void ShaderBind::execute(RecordingState &state) const
}
}
+void FramebufferBind::execute() const
+{
+ GPU_framebuffer_bind(framebuffer);
+}
+
void ResourceBind::execute() const
{
if (slot == -1) {
@@ -229,6 +234,11 @@ std::string ShaderBind::serialize() const
return std::string(".shader_bind(") + GPU_shader_get_name(shader) + ")";
}
+std::string FramebufferBind::serialize() const
+{
+ return std::string(".framebuffer_bind(") + GPU_framebuffer_get_name(framebuffer) + ")";
+}
+
std::string ResourceBind::serialize() const
{
switch (type) {
diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh
index 5307a242e39..ab180cc60b1 100644
--- a/source/blender/draw/intern/draw_command.hh
+++ b/source/blender/draw/intern/draw_command.hh
@@ -88,6 +88,7 @@ enum class Type : uint8_t {
DispatchIndirect,
Draw,
DrawIndirect,
+ FramebufferBind,
PushConstant,
ResourceBind,
ShaderBind,
@@ -118,6 +119,13 @@ struct ShaderBind {
std::string serialize() const;
};
+struct FramebufferBind {
+ GPUFrameBuffer *framebuffer;
+
+ void execute() const;
+ std::string serialize() const;
+};
+
struct ResourceBind {
eGPUSamplerState sampler;
int slot;
@@ -473,10 +481,8 @@ class DrawMultiBuf {
uint vertex_first,
ResourceHandle handle)
{
- /* Unsupported for now. Use PassSimple. */
- BLI_assert(vertex_first == 0 || vertex_first == -1);
- BLI_assert(vertex_len == -1);
- UNUSED_VARS_NDEBUG(vertex_len, vertex_first);
+ /* Custom draw-calls cannot be batched and will produce one group per draw. */
+ const bool custom_group = (vertex_first != 0 || vertex_first != -1 || vertex_len != -1);
instance_len = instance_len != -1 ? instance_len : 1;
@@ -493,8 +499,14 @@ class DrawMultiBuf {
bool inverted = handle.has_inverted_handedness();
- if (group_id == uint(-1)) {
+ DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++);
+ draw.resource_handle = handle.raw;
+ draw.instance_len = instance_len;
+ draw.group_id = group_id;
+
+ if (group_id == uint(-1) || custom_group) {
uint new_group_id = group_count_++;
+ draw.group_id = new_group_id;
DrawGroup &group = group_buf_.get_or_resize(new_group_id);
group.next = cmd.group_first;
@@ -503,11 +515,16 @@ class DrawMultiBuf {
group.gpu_batch = batch;
group.front_proto_len = 0;
group.back_proto_len = 0;
+ group.vertex_len = vertex_len;
+ group.vertex_first = vertex_first;
+ /* Custom group are not to be registered in the group_ids_. */
+ if (!custom_group) {
+ group_id = new_group_id;
+ }
/* For serialization only. */
(inverted ? group.back_proto_len : group.front_proto_len)++;
/* Append to list. */
cmd.group_first = new_group_id;
- group_id = new_group_id;
}
else {
DrawGroup &group = group_buf_[group_id];
@@ -516,11 +533,6 @@ class DrawMultiBuf {
/* For serialization only. */
(inverted ? group.back_proto_len : group.front_proto_len)++;
}
-
- DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++);
- draw.group_id = group_id;
- draw.resource_handle = handle.raw;
- draw.instance_len = instance_len;
}
void bind(RecordingState &state,
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index b5e9b3ee8bd..07d245e7dfe 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -88,6 +88,14 @@ void DRW_curves_ubos_pool_free(struct CurvesUniformBufPool *pool);
void DRW_curves_update(void);
void DRW_curves_free(void);
+/* draw_pointcloud.cc */
+
+struct DRWShadingGroup *DRW_shgroup_pointcloud_create_sub(struct Object *object,
+ struct DRWShadingGroup *shgrp_parent,
+ struct GPUMaterial *gpu_material);
+void DRW_pointcloud_init(void);
+void DRW_pointcloud_free(void);
+
/* draw_volume.cc */
/**
diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc
index a61769e7a63..ee9ed4666e0 100644
--- a/source/blender/draw/intern/draw_curves.cc
+++ b/source/blender/draw/intern/draw_curves.cc
@@ -129,25 +129,25 @@ void DRW_curves_ubos_pool_free(CurvesUniformBufPool *pool)
static void drw_curves_cache_shgrp_attach_resources(DRWShadingGroup *shgrp,
CurvesEvalCache *cache,
- GPUTexture *tex,
+ GPUVertBuf *point_buf,
const int subdiv)
{
- DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", tex);
- DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex);
- DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
+ DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", point_buf);
+ DRW_shgroup_buffer_texture(shgrp, "hairStrandBuffer", cache->proc_strand_buf);
+ DRW_shgroup_buffer_texture(shgrp, "hairStrandSegBuffer", cache->proc_strand_seg_buf);
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
}
static void drw_curves_cache_update_compute(CurvesEvalCache *cache,
const int subdiv,
const int strands_len,
- GPUVertBuf *buffer,
- GPUTexture *tex)
+ GPUVertBuf *output_buf,
+ GPUVertBuf *input_buf)
{
GPUShader *shader = curves_eval_shader_get(CURVES_EVAL_CATMULL_ROM);
DRWShadingGroup *shgrp = DRW_shgroup_create(shader, g_tf_pass);
- drw_curves_cache_shgrp_attach_resources(shgrp, cache, tex, subdiv);
- DRW_shgroup_vertex_buffer(shgrp, "posTime", buffer);
+ drw_curves_cache_shgrp_attach_resources(shgrp, cache, input_buf, subdiv);
+ DRW_shgroup_vertex_buffer(shgrp, "posTime", output_buf);
const int max_strands_per_call = GPU_max_work_group_count(0);
int strands_start = 0;
@@ -169,7 +169,7 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int su
}
drw_curves_cache_update_compute(
- cache, subdiv, strands_len, cache->final[subdiv].proc_buf, cache->point_tex);
+ cache, subdiv, strands_len, cache->final[subdiv].proc_buf, cache->proc_point_buf);
const DRW_Attributes &attrs = cache->final[subdiv].attr_used;
for (int i = 0; i < attrs.num_requests; i++) {
@@ -182,13 +182,13 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int su
subdiv,
strands_len,
cache->final[subdiv].attributes_buf[i],
- cache->proc_attributes_tex[i]);
+ cache->proc_attributes_buf[i]);
}
}
static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache,
- GPUVertBuf *vbo,
- GPUTexture *tex,
+ GPUVertBuf *output_buf,
+ GPUVertBuf *input_buf,
const int subdiv,
const int final_points_len)
{
@@ -196,14 +196,14 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache,
DRWShadingGroup *tf_shgrp = nullptr;
if (GPU_transform_feedback_support()) {
- tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, g_tf_pass, vbo);
+ tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, g_tf_pass, output_buf);
}
else {
tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
CurvesEvalCall *pr_call = MEM_new<CurvesEvalCall>(__func__);
pr_call->next = g_tf_calls;
- pr_call->vbo = vbo;
+ pr_call->vbo = output_buf;
pr_call->shgrp = tf_shgrp;
pr_call->vert_len = final_points_len;
g_tf_calls = pr_call;
@@ -213,7 +213,7 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache,
}
BLI_assert(tf_shgrp != nullptr);
- drw_curves_cache_shgrp_attach_resources(tf_shgrp, cache, tex, subdiv);
+ drw_curves_cache_shgrp_attach_resources(tf_shgrp, cache, input_buf, subdiv);
DRW_shgroup_call_procedural_points(tf_shgrp, nullptr, final_points_len);
}
@@ -225,7 +225,7 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, c
}
drw_curves_cache_update_transform_feedback(
- cache, cache->final[subdiv].proc_buf, cache->point_tex, subdiv, final_points_len);
+ cache, cache->final[subdiv].proc_buf, cache->proc_point_buf, subdiv, final_points_len);
const DRW_Attributes &attrs = cache->final[subdiv].attr_used;
for (int i = 0; i < attrs.num_requests; i++) {
@@ -236,7 +236,7 @@ static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, c
drw_curves_cache_update_transform_feedback(cache,
cache->final[subdiv].attributes_buf[i],
- cache->proc_attributes_tex[i],
+ cache->proc_attributes_buf[i],
subdiv,
final_points_len);
}
@@ -346,9 +346,9 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
1.0f);
}
- DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_tex);
- if (curves_cache->length_tex) {
- DRW_shgroup_uniform_texture(shgrp, "hairLen", curves_cache->length_tex);
+ DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_buf);
+ if (curves_cache->proc_length_buf) {
+ DRW_shgroup_buffer_texture(shgrp, "hairLen", curves_cache->proc_length_buf);
}
const DRW_Attributes &attrs = curves_cache->final[subdiv].attr_used;
@@ -359,18 +359,18 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name);
if (request.domain == ATTR_DOMAIN_CURVE) {
- if (!curves_cache->proc_attributes_tex[i]) {
+ if (!curves_cache->proc_attributes_buf[i]) {
continue;
}
- DRW_shgroup_uniform_texture(shgrp, sampler_name, curves_cache->proc_attributes_tex[i]);
+ DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->proc_attributes_buf[i]);
}
else {
- if (!curves_cache->final[subdiv].attributes_tex[i]) {
+ if (!curves_cache->final[subdiv].attributes_buf[i]) {
continue;
}
- DRW_shgroup_uniform_texture(
- shgrp, sampler_name, curves_cache->final[subdiv].attributes_tex[i]);
+ DRW_shgroup_buffer_texture(
+ shgrp, sampler_name, curves_cache->final[subdiv].attributes_buf[i]);
}
/* Some attributes may not be used in the shader anymore and were not garbage collected yet, so
@@ -390,10 +390,15 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final[subdiv].strands_res, 1);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
- DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->obmat);
+ DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->object_to_world);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
+ if (gpu_material) {
+ /* \note: This needs to happen before the drawcall to allow correct attribute extraction.
+ * (see T101896) */
+ DRW_shgroup_add_material_resources(shgrp, gpu_material);
+ }
/* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass
* culling test. */
GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1];
diff --git a/source/blender/draw/intern/draw_curves_private.h b/source/blender/draw/intern/draw_curves_private.h
index a74878ec674..715706fd7a6 100644
--- a/source/blender/draw/intern/draw_curves_private.h
+++ b/source/blender/draw/intern/draw_curves_private.h
@@ -34,7 +34,6 @@ typedef enum CurvesEvalShader {
typedef struct CurvesEvalFinalCache {
/* Output of the subdivision stage: vertex buffer sized to subdiv level. */
GPUVertBuf *proc_buf;
- GPUTexture *proc_tex;
/** Just contains a huge index buffer used to draw the final curves. */
GPUBatch *proc_hairs[MAX_THICKRES];
@@ -61,35 +60,29 @@ typedef struct CurvesEvalFinalCache {
/* Output of the subdivision stage: vertex buffers sized to subdiv level. This is only attributes
* on point domain. */
GPUVertBuf *attributes_buf[GPU_MAX_ATTR];
- GPUTexture *attributes_tex[GPU_MAX_ATTR];
} CurvesEvalFinalCache;
/* Curves procedural display: Evaluation is done on the GPU. */
typedef struct CurvesEvalCache {
/* Input control point positions combined with parameter data. */
GPUVertBuf *proc_point_buf;
- GPUTexture *point_tex;
/* Editmode data (such as selection flags) used by overlay_edit_curve_point.glsl */
GPUVertBuf *data_edit_points;
/** Info of control points strands (segment count and base index) */
GPUVertBuf *proc_strand_buf;
- GPUTexture *strand_tex;
/* Curve length data. */
GPUVertBuf *proc_length_buf;
- GPUTexture *length_tex;
GPUVertBuf *proc_strand_seg_buf;
- GPUTexture *strand_seg_tex;
CurvesEvalFinalCache final[MAX_HAIR_SUBDIV];
/* For point attributes, which need subdivision, these buffers contain the input data.
* For curve domain attributes, which do not need subdivision, these are the final data. */
GPUVertBuf *proc_attributes_buf[GPU_MAX_ATTR];
- GPUTexture *proc_attributes_tex[GPU_MAX_ATTR];
int strands_len;
int elems_len;
diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc
index 4e44967e5e9..c5261f26f76 100644
--- a/source/blender/draw/intern/draw_hair.cc
+++ b/source/blender/draw/intern/draw_hair.cc
@@ -105,9 +105,9 @@ static void drw_hair_particle_cache_shgrp_attach_resources(DRWShadingGroup *shgr
ParticleHairCache *cache,
const int subdiv)
{
- DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", cache->point_tex);
- DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex);
- DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
+ DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", cache->proc_point_buf);
+ DRW_shgroup_buffer_texture(shgrp, "hairStrandBuffer", cache->proc_strand_buf);
+ DRW_shgroup_buffer_texture(shgrp, "hairStrandSegBuffer", cache->proc_strand_seg_buf);
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
}
@@ -216,12 +216,12 @@ void DRW_hair_duplimat_get(Object *object,
if (collection != nullptr) {
sub_v3_v3(dupli_mat[3], collection->instance_offset);
}
- mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat);
+ mul_m4_m4m4(dupli_mat, dupli_parent->object_to_world, dupli_mat);
}
else {
- copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
+ copy_m4_m4(dupli_mat, dupli_object->ob->object_to_world);
invert_m4(dupli_mat);
- mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
+ mul_m4_m4m4(dupli_mat, object->object_to_world, dupli_mat);
}
}
else {
@@ -280,9 +280,9 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
float hair_rad_tip = part->rad_tip * part->rad_scale * 0.5f;
bool hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0;
- DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
- if (hair_cache->length_tex) {
- DRW_shgroup_uniform_texture(shgrp, "l", hair_cache->length_tex);
+ DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_buf);
+ if (hair_cache->proc_length_buf) {
+ DRW_shgroup_buffer_texture(shgrp, "l", hair_cache->proc_length_buf);
}
DRW_shgroup_uniform_block(shgrp, "drw_curves", *g_dummy_curves_info);
@@ -293,6 +293,11 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
+ if (gpu_material) {
+ /* \note: This needs to happen before the drawcall to allow correct attribute extraction.
+ * (see T101896) */
+ DRW_shgroup_add_material_resources(shgrp, gpu_material);
+ }
/* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass
* culling test. */
GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index c7e9e1e22de..a3019ab5aa5 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -29,7 +29,6 @@ struct ParticleSystem;
typedef struct ParticleHairFinalCache {
/* Output of the subdivision stage: vertex buff sized to subdiv level. */
GPUVertBuf *proc_buf;
- GPUTexture *proc_tex;
/* Just contains a huge index buffer used to draw the final hair. */
GPUBatch *proc_hairs[MAX_THICKRES];
@@ -44,18 +43,14 @@ typedef struct ParticleHairCache {
/* Hair Procedural display: Interpolation is done on the GPU. */
GPUVertBuf *proc_point_buf; /* Input control points */
- GPUTexture *point_tex;
/** Infos of control points strands (segment count and base index) */
GPUVertBuf *proc_strand_buf;
- GPUTexture *strand_tex;
/* Hair Length */
GPUVertBuf *proc_length_buf;
- GPUTexture *length_tex;
GPUVertBuf *proc_strand_seg_buf;
- GPUTexture *strand_seg_tex;
GPUVertBuf *proc_uv_buf[MAX_MTFACE];
GPUTexture *uv_tex[MAX_MTFACE];
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index da77845feb4..4fcfec833eb 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1690,6 +1690,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DRW_globals_update();
drw_debug_init();
+ DRW_pointcloud_init();
DRW_curves_init(DST.vmempool);
DRW_volume_init(DST.vmempool);
DRW_smoke_init(DST.vmempool);
@@ -1959,20 +1960,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
DST.buffer_finish_called = false;
}
-/* Callback function for RE_engine_update_render_passes to ensure all
- * render passes are registered. */
-static void draw_render_result_ensure_pass_cb(void *user_data,
- struct Scene *UNUSED(scene),
- struct ViewLayer *view_layer,
- const char *name,
- int channels,
- const char *chanid,
- eNodeSocketDatatype UNUSED(type))
-{
- RenderEngine *engine = user_data;
- RE_engine_add_pass(engine, name, channels, chanid, view_layer->name);
-}
-
void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
@@ -2023,10 +2010,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* set default viewport */
GPU_viewport(0, 0, size[0], size[1]);
- /* Update the render passes. This needs to be done before acquiring the render result. */
- RE_engine_update_render_passes(
- engine, scene, view_layer, draw_render_result_ensure_pass_cb, engine);
-
/* Init render result. */
RenderResult *render_result = RE_engine_begin_result(engine,
0,
@@ -2071,6 +2054,7 @@ void DRW_render_object_iter(
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
+ DRW_pointcloud_init();
DRW_curves_init(DST.vmempool);
DRW_volume_init(DST.vmempool);
DRW_smoke_init(DST.vmempool);
@@ -2131,6 +2115,7 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
drw_manager_init(&DST, NULL, NULL);
+ DRW_pointcloud_init();
DRW_curves_init(DST.vmempool);
DRW_volume_init(DST.vmempool);
DRW_smoke_init(DST.vmempool);
@@ -2166,6 +2151,7 @@ void DRW_cache_restart(void)
DST.buffer_finish_called = false;
+ DRW_pointcloud_init();
DRW_curves_init(DST.vmempool);
DRW_volume_init(DST.vmempool);
DRW_smoke_init(DST.vmempool);
@@ -2491,6 +2477,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
/* Init engines */
drw_engines_init();
+ DRW_pointcloud_init();
DRW_curves_init(DST.vmempool);
DRW_volume_init(DST.vmempool);
DRW_smoke_init(DST.vmempool);
@@ -2672,6 +2659,7 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
/* Init engines */
drw_engines_init();
+ DRW_pointcloud_init();
DRW_curves_init(DST.vmempool);
DRW_volume_init(DST.vmempool);
DRW_smoke_init(DST.vmempool);
@@ -2813,7 +2801,7 @@ void DRW_draw_depth_object(
GPU_matrix_projection_set(rv3d->winmat);
GPU_matrix_set(rv3d->viewmat);
- GPU_matrix_mul(object->obmat);
+ GPU_matrix_mul(object->object_to_world);
/* Setup frame-buffer. */
GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport);
@@ -2833,11 +2821,11 @@ void DRW_draw_depth_object(
const bool use_clipping_planes = RV3D_CLIPPING_ENABLED(v3d, rv3d);
if (use_clipping_planes) {
GPU_clip_distances(6);
- ED_view3d_clipping_local(rv3d, object->obmat);
+ ED_view3d_clipping_local(rv3d, object->object_to_world);
for (int i = 0; i < 6; i++) {
copy_v4_v4(planes.world[i], rv3d->clip_local[i]);
}
- copy_m4_m4(planes.ModelMatrix, object->obmat);
+ copy_m4_m4(planes.ModelMatrix, object->object_to_world);
}
drw_batch_cache_validate(object);
@@ -3086,6 +3074,7 @@ void DRW_engines_free(void)
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
DRW_shaders_free();
+ DRW_pointcloud_free();
DRW_curves_free();
DRW_volume_free();
DRW_shape_cache_free();
diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc
index 981206e56fe..4aa27e2288c 100644
--- a/source/blender/draw/intern/draw_manager_data.cc
+++ b/source/blender/draw/intern/draw_manager_data.cc
@@ -589,7 +589,7 @@ void DRW_shgroup_buffer_texture(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf *vertex_buffer)
{
- int location = GPU_shader_get_ssbo(shgroup->shader, name);
+ int location = GPU_shader_get_texture_binding(shgroup->shader, name);
if (location == -1) {
return;
}
@@ -606,7 +606,7 @@ void DRW_shgroup_buffer_texture_ref(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf **vertex_buffer)
{
- int location = GPU_shader_get_ssbo(shgroup->shader, name);
+ int location = GPU_shader_get_texture_binding(shgroup->shader, name);
if (location == -1) {
return;
}
@@ -724,8 +724,8 @@ static void drw_call_culling_init(DRWCullingState *cull, Object *ob)
float corner[3];
/* Get BoundSphere center and radius from the BoundBox. */
mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]);
- mul_v3_m4v3(corner, ob->obmat, bbox->vec[0]);
- mul_m4_v3(ob->obmat, cull->bsphere.center);
+ mul_v3_m4v3(corner, ob->object_to_world, bbox->vec[0]);
+ mul_m4_v3(ob->object_to_world, cull->bsphere.center);
cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner);
/* Bypass test for very large objects (see T67319). */
@@ -1017,7 +1017,7 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : obmat, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : obmat, ob);
drw_command_draw(shgroup, geom, handle);
/* Culling data. */
@@ -1042,7 +1042,7 @@ void DRW_shgroup_call_range(
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob);
drw_command_draw_range(shgroup, geom, handle, v_sta, v_num);
}
@@ -1053,7 +1053,7 @@ void DRW_shgroup_call_instance_range(
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob);
drw_command_draw_intance_range(shgroup, geom, handle, i_sta, i_num);
}
@@ -1099,7 +1099,7 @@ static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob);
drw_command_draw_procedural(shgroup, geom, handle, vert_count);
}
@@ -1149,7 +1149,7 @@ void DRW_shgroup_call_procedural_indirect(DRWShadingGroup *shgroup,
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob);
drw_command_draw_indirect(shgroup, geom, handle, indirect_buf);
}
@@ -1159,7 +1159,7 @@ void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, Object *ob, GPUBatch *
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob);
drw_command_draw_instance(shgroup, geom, handle, count, false);
}
@@ -1173,7 +1173,7 @@ void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup,
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, nullptr, DST.select_id);
}
- DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : nullptr, ob);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->object_to_world : nullptr, ob);
GPUBatch *batch = DRW_temp_batch_instance_request(
DST.vmempool->idatalist, nullptr, inst_attributes, geom);
drw_command_draw_instance(shgroup, batch, handle, 0, true);
@@ -1283,7 +1283,7 @@ static void drw_sculpt_get_frustum_planes(Object *ob, float planes[6][4])
* 4x4 matrix is done by multiplying with the transpose inverse.
* The inverse cancels out here since we transform by inverse(obmat). */
float tmat[4][4];
- transpose_m4_m4(tmat, ob->obmat);
+ transpose_m4_m4(tmat, ob->object_to_world);
for (int i = 0; i < 6; i++) {
mul_m4_v4(tmat, planes[i]);
}
@@ -1361,7 +1361,7 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd)
if (SCULPT_DEBUG_BUFFERS) {
int debug_node_nr = 0;
- DRW_debug_modelmat(scd->ob->obmat);
+ DRW_debug_modelmat(scd->ob->object_to_world);
BKE_pbvh_draw_debug_cb(
pbvh,
(void (*)(PBVHNode * n, void *d, const float min[3], const float max[3], PBVHNodeFlags f))
diff --git a/source/blender/draw/intern/draw_manager_text.cc b/source/blender/draw/intern/draw_manager_text.cc
index 100ef528bc8..239f6fcca73 100644
--- a/source/blender/draw/intern/draw_manager_text.cc
+++ b/source/blender/draw/intern/draw_manager_text.cc
@@ -305,11 +305,11 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
mid_v3_v3v3(vmid, v1_clip, v2_clip);
- mul_m4_v3(ob->obmat, vmid);
+ mul_m4_v3(ob->object_to_world, vmid);
if (do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
+ mul_mat3_m4_v3(ob->object_to_world, v1);
+ mul_mat3_m4_v3(ob->object_to_world, v2);
}
if (unit->system) {
@@ -373,7 +373,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
float angle;
mid_v3_v3v3(vmid, v1_clip, v2_clip);
- mul_m4_v3(ob->obmat, vmid);
+ mul_m4_v3(ob->object_to_world, vmid);
if (use_coords) {
copy_v3_v3(no_a, poly_normals[BM_elem_index_get(l_a->f)]);
@@ -443,16 +443,16 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
n += 3;
if (do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
- mul_mat3_m4_v3(ob->obmat, v3);
+ mul_mat3_m4_v3(ob->object_to_world, v1);
+ mul_mat3_m4_v3(ob->object_to_world, v2);
+ mul_mat3_m4_v3(ob->object_to_world, v3);
}
area += area_tri_v3(v1, v2, v3);
}
mul_v3_fl(vmid, 1.0f / float(n));
- mul_m4_v3(ob->obmat, vmid);
+ mul_m4_v3(ob->object_to_world, vmid);
if (unit->system) {
numstr_len = BKE_unit_value_as_string(
@@ -522,9 +522,9 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
copy_v3_v3(v2_local, v2);
if (do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
- mul_mat3_m4_v3(ob->obmat, v3);
+ mul_mat3_m4_v3(ob->object_to_world, v1);
+ mul_mat3_m4_v3(ob->object_to_world, v2);
+ mul_mat3_m4_v3(ob->object_to_world, v3);
}
float angle = angle_v3v3v3(v1, v2, v3);
@@ -535,7 +535,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
(is_rad) ? angle : RAD2DEGF(angle),
(is_rad) ? "r" : "°");
interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
- mul_m4_v3(ob->obmat, fvec);
+ mul_m4_v3(ob->object_to_world, fvec);
DRW_text_cache_add(dt, fvec, numstr, numstr_len, 0, 0, txt_flag, col);
}
}
@@ -566,7 +566,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
copy_v3_v3(v1, v->co);
}
- mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->object_to_world, v1);
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, 0, txt_flag, col);
@@ -595,7 +595,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
mid_v3_v3v3(vmid, v1_clip, v2_clip);
- mul_m4_v3(ob->obmat, vmid);
+ mul_m4_v3(ob->object_to_world, vmid);
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
DRW_text_cache_add(
@@ -629,7 +629,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
BM_face_calc_center_median(f, v1);
}
- mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->object_to_world, v1);
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, 0, txt_flag, col);
diff --git a/source/blender/draw/intern/draw_pass.hh b/source/blender/draw/intern/draw_pass.hh
index 24dfdd1b97b..892dfdddfcf 100644
--- a/source/blender/draw/intern/draw_pass.hh
+++ b/source/blender/draw/intern/draw_pass.hh
@@ -14,8 +14,7 @@
* #Pass. Use many #PassSub along with a main #Pass to reduce the overhead and allow groupings of
* commands. \note The draw call order inside a batch of multiple draw with the exact same state is
* not guaranteed and is not even deterministic. Use a #PassSimple or #PassSortable if ordering is
- * needed. \note As of now, it is also quite limited in the type of draw command it can record
- * (no custom vertex count, no custom first vertex).
+ * needed. Custom vertex count and custom first vertex will effectively disable batching.
*
* `PassSimple`:
* Does not have the overhead of #PassMain but does not have the culling and batching optimization.
@@ -192,6 +191,12 @@ class PassBase {
void shader_set(GPUShader *shader);
/**
+ * Bind a framebuffer. This is equivalent to a deferred GPU_framebuffer_bind() call.
+ * \note Changes the global GPU state (outside of DRW).
+ */
+ void framebuffer_set(GPUFrameBuffer *framebuffer);
+
+ /**
* Bind a material shader along with its associated resources. Any following bind() or
* push_constant() call will use its interface.
* IMPORTANT: Assumes material is compiled and can be used (no compilation error).
@@ -743,6 +748,11 @@ template<class T> inline void PassBase<T>::shader_set(GPUShader *shader)
create_command(Type::ShaderBind).shader_bind = {shader};
}
+template<class T> inline void PassBase<T>::framebuffer_set(GPUFrameBuffer *framebuffer)
+{
+ create_command(Type::FramebufferBind).framebuffer_bind = {framebuffer};
+}
+
template<class T> inline void PassBase<T>::material_set(Manager &manager, GPUMaterial *material)
{
GPUPass *gpupass = GPU_material_get_pass(material);
diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc
index 38fb6d55245..b25bb42a8a5 100644
--- a/source/blender/draw/intern/draw_pbvh.cc
+++ b/source/blender/draw/intern/draw_pbvh.cc
@@ -951,6 +951,14 @@ struct PBVHBatches {
void create_index_faces(PBVH_GPU_Args *args)
{
+ int *mat_index = static_cast<int *>(
+ CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
+
+ if (mat_index && args->totprim) {
+ int poly_index = args->mlooptri[args->prim_indices[0]].poly;
+ material_index = mat_index[poly_index];
+ }
+
/* Calculate number of edges*/
int edge_count = 0;
for (int i = 0; i < args->totprim; i++) {
@@ -959,6 +967,7 @@ struct PBVHBatches {
if (args->hide_poly && args->hide_poly[lt->poly]) {
continue;
}
+
int r_edges[3];
BKE_mesh_looptri_get_real_edges(args->me, lt, r_edges);
@@ -1030,6 +1039,14 @@ struct PBVHBatches {
void create_index_grids(PBVH_GPU_Args *args)
{
+ int *mat_index = static_cast<int *>(
+ CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
+
+ if (mat_index && args->totprim) {
+ int poly_index = BKE_subdiv_ccg_grid_to_face_index(args->subdiv_ccg, args->grid_indices[0]);
+ material_index = mat_index[poly_index];
+ }
+
needs_tri_index = true;
int gridsize = args->ccg_key.grid_size;
int totgrid = args->totprim;
diff --git a/source/blender/draw/intern/draw_pointcloud.cc b/source/blender/draw/intern/draw_pointcloud.cc
new file mode 100644
index 00000000000..582dc690cee
--- /dev/null
+++ b/source/blender/draw/intern/draw_pointcloud.cc
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2017 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup draw
+ *
+ * \brief Contains procedural GPU hair drawing methods.
+ */
+
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_pointcloud_types.h"
+
+#include "BKE_curves.hh"
+#include "BKE_geometry_set.hh"
+
+#include "GPU_batch.h"
+#include "GPU_capabilities.h"
+#include "GPU_compute.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+#include "GPU_vertex_buffer.h"
+
+#include "DRW_gpu_wrapper.hh"
+#include "DRW_render.h"
+
+#include "draw_attributes.h"
+#include "draw_cache_impl.h"
+#include "draw_common.h"
+#include "draw_manager.h"
+#include "draw_pointcloud_private.hh"
+
+static GPUVertBuf *g_dummy_vbo = nullptr;
+
+void DRW_pointcloud_init()
+{
+ if (g_dummy_vbo == nullptr) {
+ /* initialize vertex format */
+ GPUVertFormat format = {0};
+ uint dummy_id = GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ g_dummy_vbo = GPU_vertbuf_create_with_format_ex(
+ &format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY);
+
+ const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_vertbuf_data_alloc(g_dummy_vbo, 1);
+ GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert);
+ }
+}
+
+DRWShadingGroup *DRW_shgroup_pointcloud_create_sub(Object *object,
+ DRWShadingGroup *shgrp_parent,
+ GPUMaterial *gpu_material)
+{
+ PointCloud &pointcloud = *static_cast<PointCloud *>(object->data);
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
+
+ /* Fix issue with certain driver not drawing anything if there is no texture bound to
+ * "ac", "au", "u" or "c". */
+ DRW_shgroup_buffer_texture(shgrp, "u", g_dummy_vbo);
+ DRW_shgroup_buffer_texture(shgrp, "au", g_dummy_vbo);
+ DRW_shgroup_buffer_texture(shgrp, "c", g_dummy_vbo);
+ DRW_shgroup_buffer_texture(shgrp, "ac", g_dummy_vbo);
+
+ GPUVertBuf *pos_rad_buf = pointcloud_position_and_radius_get(&pointcloud);
+ DRW_shgroup_buffer_texture(shgrp, "ptcloud_pos_rad_tx", pos_rad_buf);
+
+ if (gpu_material != nullptr) {
+
+ // const DRW_Attributes &attrs = cache->attr_used;
+ // for (int i = 0; i < attrs.num_requests; i++) {
+ // const DRW_AttributeRequest &request = attrs.requests[i];
+
+ // char sampler_name[32];
+ // /* \note reusing curve attribute function. */
+ // drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name);
+
+ // GPUTexture *attribute_buf = DRW_pointcloud_evaluated_attribute(&pointcloud);
+ // if (!cache->attributes_buf[i]) {
+ // continue;
+ // }
+ // DRW_shgroup_buffer_texture_ref(shgrp, sampler_name, attribute_buf);
+ // }
+
+ /* Only single material supported for now. */
+ GPUBatch **geom = pointcloud_surface_shaded_get(&pointcloud, &gpu_material, 1);
+ DRW_shgroup_call(shgrp, geom[0], object);
+ }
+ else {
+ GPUBatch *geom = pointcloud_surface_get(&pointcloud);
+ DRW_shgroup_call(shgrp, geom, object);
+ }
+ return shgrp;
+}
+
+void DRW_pointcloud_free()
+{
+ GPU_VERTBUF_DISCARD_SAFE(g_dummy_vbo);
+}
diff --git a/source/blender/draw/intern/draw_pointcloud_private.hh b/source/blender/draw/intern/draw_pointcloud_private.hh
new file mode 100644
index 00000000000..9422d7fbc99
--- /dev/null
+++ b/source/blender/draw/intern/draw_pointcloud_private.hh
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2021 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup draw
+ */
+
+#pragma once
+
+struct PointCloud;
+struct GPUBatch;
+struct GPUVertBuf;
+struct GPUMaterial;
+
+GPUVertBuf *pointcloud_position_and_radius_get(PointCloud *pointcloud);
+GPUBatch **pointcloud_surface_shaded_get(PointCloud *pointcloud,
+ GPUMaterial **gpu_materials,
+ int mat_len);
+GPUBatch *pointcloud_surface_get(PointCloud *pointcloud);
diff --git a/source/blender/draw/intern/draw_resource.hh b/source/blender/draw/intern/draw_resource.hh
index 2df38e32ed2..b116d7fe183 100644
--- a/source/blender/draw/intern/draw_resource.hh
+++ b/source/blender/draw/intern/draw_resource.hh
@@ -31,7 +31,7 @@
inline void ObjectMatrices::sync(const Object &object)
{
- model = object.obmat;
+ model = object.object_to_world;
model_inverse = object.imat;
}
diff --git a/source/blender/draw/intern/draw_volume.cc b/source/blender/draw/intern/draw_volume.cc
index 2b4b0e3c089..5c1ce7c3111 100644
--- a/source/blender/draw/intern/draw_volume.cc
+++ b/source/blender/draw/intern/draw_volume.cc
@@ -127,7 +127,7 @@ static DRWShadingGroup *drw_volume_object_grids_init(Object *ob,
grp = DRW_shgroup_create_sub(grp);
- volume_infos.density_scale = BKE_volume_density_scale(volume, ob->obmat);
+ volume_infos.density_scale = BKE_volume_density_scale(volume, ob->object_to_world);
volume_infos.color_mul = float4(1.0f);
volume_infos.temperature_mul = 1.0f;
volume_infos.temperature_bias = 0.0f;
diff --git a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
index 123c493b572..def841b07aa 100644
--- a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
@@ -90,10 +90,15 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos)
#ifdef GPU_VERTEX_SHADER
-/* Trick to detect if a drawcall is stroke or fill.
- * This does mean that we need to draw an empty stroke segment before starting
- * to draw the real stroke segments. */
-# define GPENCIL_IS_STROKE_VERTEX (gl_InstanceID != 0)
+int gpencil_stroke_point_id()
+{
+ return (gl_VertexID & ~GP_IS_STROKE_VERTEX_BIT) >> GP_VERTEX_ID_SHIFT;
+}
+
+bool gpencil_is_stroke_vertex()
+{
+ return flag_test(gl_VertexID, GP_IS_STROKE_VERTEX_BIT);
+}
/**
* Returns value of gl_Position.
@@ -120,20 +125,7 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos)
* WARNING: Max attribute count is actually 14 because OSX OpenGL implementation
* considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536)
*/
-vec4 gpencil_vertex(ivec4 ma,
- ivec4 ma1,
- ivec4 ma2,
- ivec4 ma3,
- vec4 pos,
- vec4 pos1,
- vec4 pos2,
- vec4 pos3,
- vec4 uv1,
- vec4 uv2,
- vec4 col1,
- vec4 col2,
- vec4 fcol1,
- vec4 viewport_size,
+vec4 gpencil_vertex(vec4 viewport_size,
gpMaterialFlag material_flags,
vec2 alignment_rot,
/* World Position. */
@@ -155,6 +147,24 @@ vec4 gpencil_vertex(ivec4 ma,
/* Stroke hardness. */
out float out_hardness)
{
+ int stroke_point_id = (gl_VertexID & ~GP_IS_STROKE_VERTEX_BIT) >> GP_VERTEX_ID_SHIFT;
+
+ /* Attribute Loading. */
+ vec4 pos = texelFetch(gp_pos_tx, (stroke_point_id - 1) * 3 + 0);
+ vec4 pos1 = texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 0);
+ vec4 pos2 = texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 0);
+ vec4 pos3 = texelFetch(gp_pos_tx, (stroke_point_id + 2) * 3 + 0);
+ ivec4 ma = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id - 1) * 3 + 1));
+ ivec4 ma1 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 1));
+ ivec4 ma2 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 1));
+ ivec4 ma3 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 2) * 3 + 1));
+ vec4 uv1 = texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 2);
+ vec4 uv2 = texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 2);
+
+ vec4 col1 = texelFetch(gp_col_tx, (stroke_point_id + 0) * 2 + 0);
+ vec4 col2 = texelFetch(gp_col_tx, (stroke_point_id + 1) * 2 + 0);
+ vec4 fcol1 = texelFetch(gp_col_tx, (stroke_point_id + 0) * 2 + 1);
+
# define thickness1 pos1.w
# define thickness2 pos2.w
# define strength1 uv1.w
@@ -167,7 +177,7 @@ vec4 gpencil_vertex(ivec4 ma,
vec4 out_ndc;
- if (GPENCIL_IS_STROKE_VERTEX) {
+ if (gpencil_is_stroke_vertex()) {
bool is_dot = flag_test(material_flags, GP_STROKE_ALIGNMENT);
bool is_squares = !flag_test(material_flags, GP_STROKE_DOTS);
@@ -177,13 +187,6 @@ vec4 gpencil_vertex(ivec4 ma,
is_squares = false;
}
- /* Endpoints, we discard the vertices. */
- if (ma1.x == -1 || (!is_dot && ma2.x == -1)) {
- /* We set the vertex at the camera origin to generate 0 fragments. */
- out_ndc = vec4(0.0, 0.0, -3e36, 0.0);
- return out_ndc;
- }
-
/* Avoid using a vertex attribute for quad positioning. */
float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
@@ -336,8 +339,7 @@ vec4 gpencil_vertex(ivec4 ma,
out_N = safe_normalize(N);
/* Decode fill opacity. */
- out_color = vec4(fcol1.rgb, floor(fcol1.a / 10.0));
- out_color.a /= 10000.0;
+ out_color = vec4(fcol1.rgb, floor(fcol1.a / 10.0) / 10000.0);
/* We still offset the fills a little to avoid overlaps */
out_ndc.z += 0.000002;
@@ -355,20 +357,7 @@ vec4 gpencil_vertex(ivec4 ma,
return out_ndc;
}
-vec4 gpencil_vertex(ivec4 ma,
- ivec4 ma1,
- ivec4 ma2,
- ivec4 ma3,
- vec4 pos,
- vec4 pos1,
- vec4 pos2,
- vec4 pos3,
- vec4 uv1,
- vec4 uv2,
- vec4 col1,
- vec4 col2,
- vec4 fcol1,
- vec4 viewport_size,
+vec4 gpencil_vertex(vec4 viewport_size,
out vec3 out_P,
out vec3 out_N,
out vec4 out_color,
@@ -379,20 +368,7 @@ vec4 gpencil_vertex(ivec4 ma,
out vec2 out_thickness,
out float out_hardness)
{
- return gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- viewport_size,
+ return gpencil_vertex(viewport_size,
0u,
vec2(1.0, 0.0),
out_P,
diff --git a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl
index dd725ad327f..8725e036435 100644
--- a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl
@@ -2,16 +2,10 @@
/* NOTE: To be used with UNIFORM_RESOURCE_ID and INSTANCED_ATTR as define. */
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
-#ifndef DRW_SHADER_SHARED_H
-
-in vec4 pos; /* Position and radius. */
-
-/* ---- Instanced attribs ---- */
-
-in vec3 pos_inst;
-in vec3 nor;
-
-#endif
+int pointcloud_get_point_id()
+{
+ return gl_VertexID / 32;
+}
mat3 pointcloud_get_facing_matrix(vec3 p)
{
@@ -25,8 +19,10 @@ mat3 pointcloud_get_facing_matrix(vec3 p)
/* Returns world center position and radius. */
void pointcloud_get_pos_and_radius(out vec3 outpos, out float outradius)
{
- outpos = point_object_to_world(pos.xyz);
- outradius = dot(abs(mat3(ModelMatrix) * pos.www), vec3(1.0 / 3.0));
+ int id = pointcloud_get_point_id();
+ vec4 pos_rad = texelFetch(ptcloud_pos_rad_tx, id);
+ outpos = point_object_to_world(pos_rad.xyz);
+ outradius = dot(abs(mat3(ModelMatrix) * pos_rad.www), vec3(1.0 / 3.0));
}
/* Return world position and normal. */
@@ -38,15 +34,67 @@ void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor)
mat3 facing_mat = pointcloud_get_facing_matrix(p);
+ /** \note: Avoid modulo by non-power-of-two in shader. See Index buffer setup. */
+ int vert_id = gl_VertexID % 32;
+ vec3 pos_inst = vec3(0.0);
+
+ switch (vert_id) {
+ case 0:
+ pos_inst.z = 1.0;
+ break;
+ case 1:
+ pos_inst.x = 1.0;
+ break;
+ case 2:
+ pos_inst.y = 1.0;
+ break;
+ case 3:
+ pos_inst.x = -1.0;
+ break;
+ case 4:
+ pos_inst.y = -1.0;
+ break;
+ }
+
/* TODO(fclem): remove multiplication here. Here only for keeping the size correct for now. */
radius *= 0.01;
- outpos = p + (facing_mat * pos_inst) * radius;
- outnor = facing_mat * nor;
+ outnor = facing_mat * pos_inst;
+ outpos = p + outnor * radius;
}
-vec3 pointcloud_get_pos(void)
+vec3 pointcloud_get_pos()
{
vec3 outpos, outnor;
pointcloud_get_pos_and_nor(outpos, outnor);
return outpos;
}
+
+float pointcloud_get_customdata_float(const samplerBuffer cd_buf)
+{
+ int id = pointcloud_get_point_id();
+ return texelFetch(cd_buf, id).r;
+}
+
+vec2 pointcloud_get_customdata_vec2(const samplerBuffer cd_buf)
+{
+ int id = pointcloud_get_point_id();
+ return texelFetch(cd_buf, id).rg;
+}
+
+vec3 pointcloud_get_customdata_vec3(const samplerBuffer cd_buf)
+{
+ int id = pointcloud_get_point_id();
+ return texelFetch(cd_buf, id).rgb;
+}
+
+vec4 pointcloud_get_customdata_vec4(const samplerBuffer cd_buf)
+{
+ int id = pointcloud_get_point_id();
+ return texelFetch(cd_buf, id).rgba;
+}
+
+vec2 pointcloud_get_barycentric(void)
+{
+ /* TODO: To be implemented. */
+ return vec2(0.0);
+}
diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh
index 7b500f66a68..23892a39062 100644
--- a/source/blender/draw/intern/shaders/draw_view_info.hh
+++ b/source/blender/draw/intern/shaders/draw_view_info.hh
@@ -112,9 +112,7 @@ GPU_SHADER_CREATE_INFO(draw_hair)
.additional_info("draw_modelmat", "draw_resource_id");
GPU_SHADER_CREATE_INFO(draw_pointcloud)
- .vertex_in(0, Type::VEC4, "pos")
- .vertex_in(1, Type::VEC3, "pos_inst")
- .vertex_in(2, Type::VEC3, "nor")
+ .sampler(0, ImageType::FLOAT_BUFFER, "ptcloud_pos_rad_tx", Frequency::BATCH)
.additional_info("draw_modelmat_instanced_attr", "draw_resource_id_uniform");
GPU_SHADER_CREATE_INFO(draw_volume).additional_info("draw_modelmat", "draw_resource_id_uniform");
@@ -122,26 +120,15 @@ GPU_SHADER_CREATE_INFO(draw_volume).additional_info("draw_modelmat", "draw_resou
GPU_SHADER_CREATE_INFO(draw_gpencil)
.typedef_source("gpencil_shader_shared.h")
.define("DRW_GPENCIL_INFO")
- .vertex_in(0, Type::IVEC4, "ma")
- .vertex_in(1, Type::IVEC4, "ma1")
- .vertex_in(2, Type::IVEC4, "ma2")
- .vertex_in(3, Type::IVEC4, "ma3")
- .vertex_in(4, Type::VEC4, "pos")
- .vertex_in(5, Type::VEC4, "pos1")
- .vertex_in(6, Type::VEC4, "pos2")
- .vertex_in(7, Type::VEC4, "pos3")
- .vertex_in(8, Type::VEC4, "uv1")
- .vertex_in(9, Type::VEC4, "uv2")
- .vertex_in(10, Type::VEC4, "col1")
- .vertex_in(11, Type::VEC4, "col2")
- .vertex_in(12, Type::VEC4, "fcol1")
+ .sampler(0, ImageType::FLOAT_BUFFER, "gp_pos_tx")
+ .sampler(1, ImageType::FLOAT_BUFFER, "gp_col_tx")
/* Per Object */
.push_constant(Type::FLOAT, "gpThicknessScale") /* TODO(fclem): Replace with object info. */
.push_constant(Type::FLOAT, "gpThicknessWorldScale") /* TODO(fclem): Same as above. */
.define("gpThicknessIsScreenSpace", "(gpThicknessWorldScale < 0.0)")
/* Per Layer */
.push_constant(Type::FLOAT, "gpThicknessOffset")
- .additional_info("draw_modelmat", "draw_resource_id_uniform", "draw_object_infos");
+ .additional_info("draw_modelmat", "draw_object_infos");
/** \} */
diff --git a/source/blender/draw/tests/draw_pass_test.cc b/source/blender/draw/tests/draw_pass_test.cc
index 394ca8bd3cf..95ab8fa2ef1 100644
--- a/source/blender/draw/tests/draw_pass_test.cc
+++ b/source/blender/draw/tests/draw_pass_test.cc
@@ -181,12 +181,19 @@ static void test_draw_pass_multi_draw()
pass.draw_procedural(GPU_PRIM_LINES, 1, -1, -1, {5});
pass.draw_procedural(GPU_PRIM_POINTS, 6, -1, -1, {5});
pass.draw_procedural(GPU_PRIM_TRIS, 3, -1, -1, {6});
+ /* Custom calls should use their own group and never be batched. */
+ pass.draw_procedural(GPU_PRIM_TRIS, 2, 2, 2, {7});
+ pass.draw_procedural(GPU_PRIM_TRIS, 2, 2, 2, {8});
std::string result = pass.serialize();
std::stringstream expected;
expected << ".test.multi_draw" << std::endl;
expected << " .shader_bind(gpu_shader_3D_image_color)" << std::endl;
expected << " .draw_multi(3)" << std::endl;
+ expected << " .group(id=4, len=2)" << std::endl;
+ expected << " .proto(instance_len=2, resource_id=8, front_face)" << std::endl;
+ expected << " .group(id=3, len=2)" << std::endl;
+ expected << " .proto(instance_len=2, resource_id=7, front_face)" << std::endl;
expected << " .group(id=2, len=1)" << std::endl;
expected << " .proto(instance_len=1, resource_id=5, front_face)" << std::endl;
expected << " .group(id=1, len=15)" << std::endl;
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index 23c1d68b4d6..4a83bb4c800 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -161,11 +161,11 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
}
/* Result must be in world-space. */
- mul_m4_v3(ob_eval->obmat, mpv->co);
+ mul_m4_v3(ob_eval->object_to_world, mpv->co);
}
else {
/* World-space object location. */
- copy_v3_v3(mpv->co, ob_eval->obmat[3]);
+ copy_v3_v3(mpv->co, ob_eval->object_to_world[3]);
}
float mframe = (float)(cframe);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index c9957b38853..96a9604a6f5 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1044,12 +1044,12 @@ static float *visualkey_get_values(
Object *ob = ptr->data;
/* Loc code is specific... */
if (strstr(identifier, "location")) {
- copy_v3_v3(buffer, ob->obmat[3]);
+ copy_v3_v3(buffer, ob->object_to_world[3]);
*r_count = 3;
return buffer;
}
- copy_m4_m4(tmat, ob->obmat);
+ copy_m4_m4(tmat, ob->object_to_world);
rotmode = ob->rotmode;
}
else if (ptr->type == &RNA_PoseBone) {
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 17484b2b0b7..fbdb375b8a6 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -181,13 +181,13 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
const View3DCursor *curs = &scene->cursor;
copy_v3_v3(newbone->tail, curs->location);
- sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
+ sub_v3_v3v3(newbone->tail, newbone->tail, obedit->object_to_world[3]);
if (a == 1) {
newbone->tail[0] = -newbone->tail[0];
}
- copy_m3_m4(mat, obedit->obmat);
+ copy_m3_m4(mat, obedit->object_to_world);
invert_m3_m3(imat, mat);
mul_m3_v3(imat, newbone->tail);
@@ -1569,7 +1569,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
copy_v3_v3(curs, CTX_data_scene(C)->cursor.location);
/* Get inverse point for head and orientation for tail */
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
mul_m4_v3(obedit->imat, curs);
if (rv3d && (U.flag & USER_ADD_VIEWALIGNED)) {
@@ -1579,7 +1579,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
unit_m3(obmat);
}
- copy_m3_m4(viewmat, obedit->obmat);
+ copy_m3_m4(viewmat, obedit->object_to_world);
mul_m3_m3m3(totmat, obmat, viewmat);
invert_m3_m3(imat, totmat);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 9e828ebd501..810279f1b6c 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -113,7 +113,7 @@ void ED_armature_origin_set(
/* Find the center-point. */
if (centermode == 2) {
copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_v3(ob->imat, cent);
}
else {
@@ -154,7 +154,7 @@ void ED_armature_origin_set(
/* Adjust object location for new center-point. */
if (centermode && (is_editmode == false)) {
- mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
+ mul_mat3_m4_v3(ob->object_to_world, cent); /* omit translation part */
add_v3_v3(ob->loc, cent);
}
}
@@ -282,14 +282,14 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
axis_flip = true;
}
- copy_m3_m4(imat, ob->obmat);
+ copy_m3_m4(imat, ob->object_to_world);
invert_m3(imat);
if (type == CALC_ROLL_CURSOR) { /* Cursor */
float cursor_local[3];
const View3DCursor *cursor = &scene->cursor;
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
copy_v3_v3(cursor_local, cursor->location);
mul_m4_v3(ob->imat, cursor_local);
@@ -730,7 +730,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
ebp = points.first;
/* Get points - cursor (tail) */
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
/* Create a bone */
@@ -767,7 +767,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
float dist_sq_a, dist_sq_b;
/* get cursor location */
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
/* get distances */
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 9f1883ccac0..fccf2964868 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -289,7 +289,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
/* Inverse transform for all selected armatures in this object,
* See #object_join_exec for detailed comment on why the safe version is used. */
- invert_m4_m4_safe_ortho(oimat, ob_active->obmat);
+ invert_m4_m4_safe_ortho(oimat, ob_active->object_to_world);
/* Get edit-bones of active armature to add edit-bones to */
ED_armature_to_edit(arm);
@@ -321,7 +321,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
// BASACT->flag &= ~OB_MODE_POSE;
/* Find the difference matrix */
- mul_m4_m4m4(mat, oimat, ob_iter->obmat);
+ mul_m4_m4m4(mat, oimat, ob_iter->object_to_world);
/* Copy bones and posechannels from the object to the edit armature */
for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 6b8f790d30f..3ee0510ca7f 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -1601,8 +1601,8 @@ static const EnumPropertyItem prop_similar_types[] = {
static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone)
{
float v1[3], v2[3];
- mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
- mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
+ mul_v3_mat3_m4v3(v1, ob->object_to_world, ebone->head);
+ mul_v3_mat3_m4v3(v2, ob->object_to_world, ebone->tail);
return len_squared_v3v3(v1, v2);
}
@@ -1650,8 +1650,8 @@ static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_
copy_v3_v3(v1, ebone->head);
copy_v3_v3(v2, ebone->tail);
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
+ mul_m4_v3(ob->object_to_world, v1);
+ mul_m4_v3(ob->object_to_world, v2);
sub_v3_v3v3(r_dir, v1, v2);
normalize_v3(r_dir);
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 6155aac621d..3c9c8cf05b3 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -365,8 +365,8 @@ static void add_verts_to_dgroups(ReportList *reports,
copy_v3_v3(tip[j], bone->arm_tail);
}
- mul_m4_v3(par->obmat, root[j]);
- mul_m4_v3(par->obmat, tip[j]);
+ mul_m4_v3(par->object_to_world, root[j]);
+ mul_m4_v3(par->object_to_world, tip[j]);
/* set selected */
if (wpmode) {
@@ -414,7 +414,7 @@ static void add_verts_to_dgroups(ReportList *reports,
if (!vertsfilled) {
copy_v3_v3(verts[i], mesh_verts[i].co);
}
- mul_m4_v3(ob->obmat, verts[i]);
+ mul_m4_v3(ob->object_to_world, verts[i]);
}
/* compute the weights based on gathered vertices and bones */
@@ -438,7 +438,7 @@ static void add_verts_to_dgroups(ReportList *reports,
root,
tip,
selected,
- mat4_to_scale(par->obmat));
+ mat4_to_scale(par->object_to_world));
}
/* only generated in some cases but can call anyway */
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 09174aa5e47..0465606e694 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -703,11 +703,11 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
newBone->inherit_scale_mode = eBone->inherit_scale_mode;
if (eBone == arm->act_edbone) {
- /* don't change active selection, this messes up separate which uses
- * editmode toggle and can separate active bone which is de-selected originally */
+ /* Don't change active selection, this messes up separate which uses
+ * edit-mode toggle and can separate active bone which is de-selected originally. */
- /* important, editbones can be active with only 1 point selected */
- /* newBone->flag |= BONE_SELECTED; */
+ /* important, edit-bones can be active with only 1 point selected */
+ /* `newBone->flag |= BONE_SELECTED;` */
arm->act_bone = newBone;
}
newBone->roll = 0.0f;
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 567977e51c4..dfb9e8a79fa 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -1788,11 +1788,11 @@ void ED_mesh_deform_bind_callback(Object *object,
mmd_orig->bindcagecos = (float *)mdb.cagecos;
mmd_orig->verts_num = mdb.verts_num;
mmd_orig->cage_verts_num = mdb.cage_verts_num;
- copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat);
+ copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->object_to_world);
/* transform bindcagecos to world space */
for (a = 0; a < mdb.cage_verts_num; a++) {
- mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3);
+ mul_m4_v3(mmd_orig->object->object_to_world, mmd_orig->bindcagecos + a * 3);
}
/* free */
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 9ed963f0c66..51071815823 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -77,10 +77,10 @@ static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Objec
/* apply current transform from parent (not yet destroyed),
* then calculate new parent inverse matrix
*/
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ BKE_object_apply_mat4(ob, ob->object_to_world, false, false);
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
}
}
@@ -361,7 +361,7 @@ static void applyarmature_reset_constraints(bPose *pose, const bool use_selected
}
}
-/* set the current pose as the restpose */
+/* Set the current pose as the rest-pose. */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -404,10 +404,10 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
}
}
- /* Get editbones of active armature to alter */
+ /* Get edit-bones of active armature to alter. */
ED_armature_to_edit(arm);
- /* get pose of active object and move it out of posemode */
+ /* Get pose of active object and move it out of pose-mode. */
pose = ob->pose;
if (use_selected) {
@@ -429,11 +429,11 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
}
}
- /* convert editbones back to bones, and then free the edit-data */
+ /* Convert edit-bones back to bones, and then free the edit-data. */
ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
- /* flush positions of posebones */
+ /* Flush positions of pose-bones. */
BKE_pose_where_is(depsgraph, scene, ob);
/* fix parenting of objects which are bone-parented */
diff --git a/source/blender/editors/asset/ED_asset_list.h b/source/blender/editors/asset/ED_asset_list.h
index b54f81004f2..3d2aaa3bda1 100644
--- a/source/blender/editors/asset/ED_asset_list.h
+++ b/source/blender/editors/asset/ED_asset_list.h
@@ -23,6 +23,7 @@ struct wmNotifier;
*/
void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference,
const struct bContext *C);
+bool ED_assetlist_is_loaded(const struct AssetLibraryReference *library_reference);
void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference,
const struct bContext *C);
void ED_assetlist_clear(const struct AssetLibraryReference *library_reference, struct bContext *C);
diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc
index b641c9d6ffc..fc71882d88f 100644
--- a/source/blender/editors/asset/intern/asset_list.cc
+++ b/source/blender/editors/asset/intern/asset_list.cc
@@ -355,7 +355,7 @@ void AssetListStorage::fetch_library(const AssetLibraryReference &library_refere
void AssetListStorage::destruct()
{
- global_storage().~AssetListMap();
+ global_storage().clear();
}
AssetList *AssetListStorage::lookup_list(const AssetLibraryReference &library_ref)
@@ -427,6 +427,18 @@ void ED_assetlist_storage_fetch(const AssetLibraryReference *library_reference,
AssetListStorage::fetch_library(*library_reference, *C);
}
+bool ED_assetlist_is_loaded(const AssetLibraryReference *library_reference)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (!list) {
+ return false;
+ }
+ if (list->needsRefetch()) {
+ return false;
+ }
+ return true;
+}
+
void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference,
const bContext *C)
{
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 61e92f0a1c3..2b6cce25bb7 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -4999,7 +4999,7 @@ bool ed_editnurb_spin(
invert_m3_m3(persinv, persmat);
/* imat and center and size */
- copy_m3_m4(bmat, obedit->obmat);
+ copy_m3_m4(bmat, obedit->object_to_world);
invert_m3_m3(imat, bmat);
axis_angle_to_mat3(cmat, axis, M_PI_4);
@@ -5095,7 +5095,7 @@ static int spin_exec(bContext *C, wmOperator *op)
continue;
}
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
mul_m4_v3(obedit->imat, cent);
if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) {
@@ -5574,7 +5574,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
RNA_float_get_array(op->ptr, "location", location);
- invert_m4_m4(imat, obedit->obmat);
+ invert_m4_m4(imat, obedit->object_to_world);
mul_m4_v3(imat, location);
if (ed_editcurve_addvert(cu, editnurb, v3d, location)) {
@@ -5614,10 +5614,10 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_curve_nurb_vert_selected_find(cu, vc.v3d, &nu, &bezt, &bp);
if (bezt) {
- mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]);
+ mul_v3_m4v3(location, vc.obedit->object_to_world, bezt->vec[1]);
}
else if (bp) {
- mul_v3_m4v3(location, vc.obedit->obmat, bp->vec);
+ mul_v3_m4v3(location, vc.obedit->object_to_world, bp->vec);
}
else {
copy_v3_v3(location, vc.scene->cursor.location);
@@ -5662,8 +5662,8 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* get the plane */
float plane[4];
/* only normalize to avoid precision errors */
- normalize_v3_v3(plane, vc.obedit->obmat[2]);
- plane[3] = -dot_v3v3(plane, vc.obedit->obmat[3]);
+ normalize_v3_v3(plane, vc.obedit->object_to_world[2]);
+ plane[3] = -dot_v3v3(plane, vc.obedit->object_to_world[3]);
if (fabsf(dot_v3v3(view_dir, plane)) < eps) {
/* can't project on an aligned plane. */
@@ -6924,7 +6924,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
/* Inverse transform for all selected curves in this object,
* See #object_join_exec for detailed comment on why the safe version is used. */
- invert_m4_m4_safe_ortho(imat, ob_active->obmat);
+ invert_m4_m4_safe_ortho(imat, ob_active->object_to_world);
Curve *cu_active = ob_active->data;
@@ -6936,7 +6936,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
if (cu->nurb.first) {
/* watch it: switch order here really goes wrong */
- mul_m4_m4m4(cmat, imat, ob_iter->obmat);
+ mul_m4_m4m4(cmat, imat, ob_iter->object_to_world);
/* Compensate for different bevel depth. */
bool do_radius = false;
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 7632f1b1e64..1e91e2f48fc 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -148,7 +148,7 @@ static void stroke_elem_pressure_set(const struct CurveDrawData *cdd,
const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) -
stroke_elem_radius_from_pressure(cdd, selem->pressure);
madd_v3_v3fl(selem->location_local, selem->normal_local, adjust);
- mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local);
+ mul_v3_m4v3(selem->location_world, cdd->vc.obedit->object_to_world, selem->location_local);
}
selem->pressure = pressure;
}
@@ -249,7 +249,7 @@ static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd,
if (!is_zero_v3(r_normal_world)) {
copy_v3_v3(r_normal_local, r_normal_world);
- mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local);
+ mul_transposed_mat3_m4_v3(cdd->vc.obedit->object_to_world, r_normal_local);
normalize_v3(r_normal_local);
}
else {
@@ -367,7 +367,7 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C),
/* scale to edit-mode space */
GPU_matrix_push();
- GPU_matrix_mul(obedit->obmat);
+ GPU_matrix_mul(obedit->object_to_world);
BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
@@ -445,7 +445,7 @@ static void curve_draw_event_add(wmOperator *op, const wmEvent *event)
struct CurveDrawData *cdd = op->customdata;
Object *obedit = cdd->vc.obedit;
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool);
@@ -758,7 +758,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
const bool is_3d = (cu->flag & CU_3D) != 0;
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) {
curve_draw_stroke_from_operator(op);
@@ -1073,8 +1073,8 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (CU_IS_2D(cu)) {
/* 2D overrides other options */
- plane_co = obedit->obmat[3];
- plane_no = obedit->obmat[2];
+ plane_co = obedit->object_to_world[3];
+ plane_no = obedit->object_to_world[2];
cdd->project.use_plane = true;
}
else {
diff --git a/source/blender/editors/curve/editcurve_pen.c b/source/blender/editors/curve/editcurve_pen.c
index f71173f951e..b57ce6fc7cf 100644
--- a/source/blender/editors/curve/editcurve_pen.c
+++ b/source/blender/editors/curve/editcurve_pen.c
@@ -152,8 +152,8 @@ static void update_location_for_2d_curve(const ViewContext *vc, float location[3
/* Get the plane. */
float plane[4];
/* Only normalize to avoid precision errors. */
- normalize_v3_v3(plane, vc->obedit->obmat[2]);
- plane[3] = -dot_v3v3(plane, vc->obedit->obmat[3]);
+ normalize_v3_v3(plane, vc->obedit->object_to_world[2]);
+ plane[3] = -dot_v3v3(plane, vc->obedit->object_to_world[3]);
if (fabsf(dot_v3v3(view_dir, plane)) < eps) {
/* Can't project on an aligned plane. */
@@ -173,7 +173,7 @@ static void update_location_for_2d_curve(const ViewContext *vc, float location[3
}
float imat[4][4];
- invert_m4_m4(imat, vc->obedit->obmat);
+ invert_m4_m4(imat, vc->obedit->object_to_world);
mul_m4_v3(imat, location);
if (CU_IS_2D(cu)) {
@@ -186,7 +186,7 @@ static void screenspace_to_worldspace(const ViewContext *vc,
const float depth[3],
float r_pos_3d[3])
{
- mul_v3_m4v3(r_pos_3d, vc->obedit->obmat, depth);
+ mul_v3_m4v3(r_pos_3d, vc->obedit->object_to_world, depth);
ED_view3d_win_to_3d(vc->v3d, vc->region, r_pos_3d, pos_2d, r_pos_3d);
update_location_for_2d_curve(vc, r_pos_3d);
}
@@ -1082,7 +1082,7 @@ static void extrude_points_from_selected_vertices(const ViewContext *vc,
float location[3];
if (sel_exists) {
- mul_v3_m4v3(location, vc->obedit->obmat, center);
+ mul_v3_m4v3(location, vc->obedit->object_to_world, center);
}
else {
copy_v3_v3(location, vc->scene->cursor.location);
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 9c0c580f699..da742dd0c61 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -1517,7 +1517,7 @@ static void nurb_bezt_direction_worldspace_get(Object *ob,
{
float rsmat[3][3];
BKE_nurb_bezt_calc_normal(nu, bezt, r_dir);
- copy_m3_m4(rsmat, ob->obmat);
+ copy_m3_m4(rsmat, ob->object_to_world);
mul_m3_v3(rsmat, r_dir);
normalize_v3(r_dir);
}
@@ -1526,7 +1526,7 @@ static void nurb_bpoint_direction_worldspace_get(Object *ob, Nurb *nu, BPoint *b
{
float rsmat[3][3];
BKE_nurb_bpoint_calc_normal(nu, bp, r_dir);
- copy_m3_m4(rsmat, ob->obmat);
+ copy_m3_m4(rsmat, ob->object_to_world);
mul_m3_v3(rsmat, r_dir);
normalize_v3(r_dir);
}
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index 38b2b2071b8..1d2b1264477 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -435,7 +435,7 @@ static bke::CurvesGeometry particles_to_curves(Object &object, ParticleSystem &p
bke::CurvesGeometry curves(points_num, curves_num);
curves.offsets_for_write().copy_from(curve_offsets);
- const float4x4 object_to_world_mat = object.obmat;
+ const float4x4 object_to_world_mat = object.object_to_world;
const float4x4 world_to_object_mat = object_to_world_mat.inverted();
MutableSpan<float3> positions = curves.positions_for_write();
@@ -497,7 +497,7 @@ static int curves_convert_from_particle_system_exec(bContext *C, wmOperator * /*
Object *ob_new = BKE_object_add(&bmain, &scene, &view_layer, OB_CURVES, psys_eval->name);
Curves *curves_id = static_cast<Curves *>(ob_new->data);
- BKE_object_apply_mat4(ob_new, ob_from_orig->obmat, true, false);
+ BKE_object_apply_mat4(ob_new, ob_from_orig->object_to_world, true, false);
bke::CurvesGeometry::wrap(curves_id->geometry) = particles_to_curves(*ob_from_eval, *psys_eval);
DEG_relations_tag_update(&bmain);
diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c
index 1ac4ce0bcdf..465c72dd44f 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_presets.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c
@@ -114,7 +114,7 @@ void ED_gizmo_draw_preset_facemap(
}
GPU_matrix_push();
- GPU_matrix_mul(ob->obmat);
+ GPU_matrix_mul(ob->object_to_world);
ED_draw_object_facemap(depsgraph, ob, color, facemap);
GPU_matrix_pop();
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 677bf1bb392..2fd58a9cee0 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -13,9 +13,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_math_geom.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c
index 5f5a4b41b27..2b7e09b7f05 100644
--- a/source/blender/editors/gpencil/gpencil_armature.c
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -329,8 +329,8 @@ static void gpencil_add_verts_to_dgroups(
copy_v3_v3(tip[j], bone->arm_tail);
}
- mul_m4_v3(ob_arm->obmat, root[j]);
- mul_m4_v3(ob_arm->obmat, tip[j]);
+ mul_m4_v3(ob_arm->object_to_world, root[j]);
+ mul_m4_v3(ob_arm->object_to_world, tip[j]);
selected[j] = 1;
@@ -364,7 +364,7 @@ static void gpencil_add_verts_to_dgroups(
/* transform stroke points to global space */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
copy_v3_v3(verts[i], &pt->x);
- mul_m4_v3(ob->obmat, verts[i]);
+ mul_m4_v3(ob->object_to_world, verts[i]);
}
/* loop groups and assign weight */
diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.cc b/source/blender/editors/gpencil/gpencil_bake_animation.cc
index 1535fd614fe..4ef2cf9ffd6 100644
--- a/source/blender/editors/gpencil/gpencil_bake_animation.cc
+++ b/source/blender/editors/gpencil/gpencil_bake_animation.cc
@@ -222,7 +222,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
ob_gpencil = ED_gpencil_add_object(C, scene->cursor.location, local_view_bits);
float invmat[4][4];
- invert_m4_m4(invmat, ob_gpencil->obmat);
+ invert_m4_m4(invmat, ob_gpencil->object_to_world);
bGPdata *gpd_dst = (bGPdata *)ob_gpencil->data;
gpd_dst->draw_mode = GP_DRAWMODE_2D;
@@ -323,7 +323,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
bGPDspoint *pt = &gps->points[j];
pt->runtime.idx_orig = 0;
pt->runtime.pt_orig = nullptr;
- mul_m4_v3(ob_eval->obmat, &pt->x);
+ mul_m4_v3(ob_eval->object_to_world, &pt->x);
mul_m4_v3(invmat, &pt->x);
}
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index c6d7eb294fb..0417694d7bd 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -2914,8 +2914,8 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
float offset_global[3];
float offset_local[3];
- sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
- copy_m3_m4(bmat, ob_active->obmat);
+ sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->object_to_world[3]);
+ copy_m3_m4(bmat, ob_active->object_to_world);
/* Inverse transform for all selected curves in this object,
* See #object_join_exec for detailed comment on why the safe version is used. */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 6181b9810e3..f9b40a4c79b 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3848,7 +3848,12 @@ static int gpencil_stroke_start_set_exec(bContext *C, wmOperator *op)
for (int i = 0; i < gps->totpoints; i++) {
pt = &gps->points[i];
if (pt->flag & GP_SPOINT_SELECT) {
- BKE_gpencil_stroke_start_set(gps, i);
+ if (i == gps->totpoints - 1) {
+ BKE_gpencil_stroke_flip(gps);
+ }
+ else {
+ BKE_gpencil_stroke_start_set(gps, i);
+ }
BKE_gpencil_stroke_geometry_update(gpd, gps);
changed = true;
break;
@@ -4157,7 +4162,7 @@ static int gpencil_stroke_outline_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *cam_ob = scene->camera;
if (cam_ob != NULL) {
- invert_m4_m4(viewmat, cam_ob->obmat);
+ invert_m4_m4(viewmat, cam_ob->object_to_world);
}
break;
}
@@ -4224,7 +4229,7 @@ static int gpencil_stroke_outline_exec(bContext *C, wmOperator *op)
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
- gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
/* Stroke. */
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index b94b413edc2..5c88e719b8c 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -317,7 +317,7 @@ static void add_endpoint_radius_help(tGPDfill *tgpf,
/* Rotate to object rotation. */
sub_v3_v3(&pt->x, endpoint);
- mul_mat3_m4_v3(tgpf->ob->obmat, &pt->x);
+ mul_mat3_m4_v3(tgpf->ob->object_to_world, &pt->x);
add_v3_v3(&pt->x, endpoint);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_mesh.cc b/source/blender/editors/gpencil/gpencil_mesh.cc
index d847fbe2aea..2b01fce5bf8 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.cc
+++ b/source/blender/editors/gpencil/gpencil_mesh.cc
@@ -299,7 +299,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
angle,
thickness,
offset,
- ob_eval->obmat,
+ ob_eval->object_to_world,
frame_offset,
use_seams,
use_faces,
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index a82288e3377..d2ed1720bf8 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -936,7 +936,7 @@ static bGPDstroke *gpencil_stroke_to_outline(tGPsdata *p, bGPDstroke *gps)
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
- gps_duplicate->thickness *= mat4_to_scale(p->ob->obmat);
+ gps_duplicate->thickness *= mat4_to_scale(p->ob->object_to_world);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
/* Stroke. */
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 9b934876ebb..515bdeb6188 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -671,7 +671,7 @@ static bool gpencil_brush_pinch_apply(tGP_BrushEditData *gso,
/* 1) Make this point relative to the cursor/midpoint (dvec) */
float fpt[3];
- mul_v3_m4v3(fpt, gso->object->obmat, &pt->x);
+ mul_v3_m4v3(fpt, gso->object->object_to_world, &pt->x);
sub_v3_v3v3(vec, fpt, gso->dvec);
/* 2) Shrink the distance by pulling the point towards the midpoint
@@ -743,7 +743,7 @@ static bool gpencil_brush_twist_apply(tGP_BrushEditData *gso,
/* Rotate point */
float fpt[3];
- mul_v3_m4v3(fpt, gso->object->obmat, &pt->x);
+ mul_v3_m4v3(fpt, gso->object->object_to_world, &pt->x);
sub_v3_v3v3(vec, fpt, gso->dvec); /* make relative to center
* (center is stored in dvec) */
mul_m3_v3(rmat, vec);
@@ -1037,7 +1037,7 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
*/
for (i = 0, pt = new_stroke->points; i < new_stroke->totpoints; i++, pt++) {
/* Rotate around center new position */
- mul_mat3_m4_v3(gso->object->obmat, &pt->x); /* only rotation component */
+ mul_mat3_m4_v3(gso->object->object_to_world, &pt->x); /* only rotation component */
/* assume that the delta can just be applied, and then everything works */
add_v3_v3(&pt->x, delta);
@@ -1172,7 +1172,7 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->object = ob;
if (ob) {
float matrix[4][4];
- copy_m4_m4(matrix, ob->obmat);
+ copy_m4_m4(matrix, ob->object_to_world);
zero_axis_bias_m4(matrix);
invert_m4_m4(gso->inv_mat, matrix);
gso->vrgroup = gso->gpd->vertex_group_active_index - 1;
@@ -1202,6 +1202,9 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->automasking_strokes = BLI_ghash_ptr_new(__func__);
}
else {
+ if (gso->automasking_strokes != NULL) {
+ BLI_ghash_free(gso->automasking_strokes, NULL, NULL);
+ }
gso->automasking_strokes = NULL;
}
/* save mask */
@@ -1292,6 +1295,10 @@ static void gpencil_sculpt_brush_exit(bContext *C, wmOperator *op)
}
default:
+ if (gso->stroke_customdata != NULL) {
+ BLI_ghash_free(gso->stroke_customdata, NULL, NULL);
+ gso->stroke_customdata = NULL;
+ }
break;
}
@@ -2075,6 +2082,20 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const
if (gso->brush == NULL) {
gso->brush = gso->brush_prev;
}
+ Brush *brush = gso->brush;
+ if (brush->gpencil_settings->sculpt_mode_flag &
+ (GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
+ GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) {
+ if (gso->automasking_strokes == NULL) {
+ gso->automasking_strokes = BLI_ghash_ptr_new(__func__);
+ }
+ }
+ else {
+ if (gso->automasking_strokes != NULL) {
+ BLI_ghash_free(gso->automasking_strokes, NULL, NULL);
+ }
+ gso->automasking_strokes = NULL;
+ }
}
else {
if (gso->brush_prev != NULL) {
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index cc13f667e48..7d814b43196 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -900,7 +900,7 @@ void ED_gpencil_drawing_reference_get(const Scene *scene,
}
else {
/* use object location */
- copy_v3_v3(r_vec, ob->obmat[3]);
+ copy_v3_v3(r_vec, ob->object_to_world[3]);
/* Apply layer offset. */
bGPdata *gpd = ob->data;
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
@@ -984,7 +984,7 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene,
/* if object, apply object rotation */
if (ob && (ob->type == OB_GPENCIL)) {
float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
/* move origin to cursor */
if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
@@ -1206,7 +1206,7 @@ void ED_gpencil_project_point_to_plane(const Scene *scene,
/* if object, apply object rotation */
if (ob && (ob->type == OB_GPENCIL)) {
float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
if (gpl != NULL) {
add_v3_v3(mat[3], gpl->location);
@@ -1233,7 +1233,7 @@ void ED_gpencil_project_point_to_plane(const Scene *scene,
/* move origin to object */
if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
- copy_v3_v3(mat[3], ob->obmat[3]);
+ copy_v3_v3(mat[3], ob->object_to_world[3]);
}
mul_mat3_m4_v3(mat, plane_normal);
@@ -1365,16 +1365,16 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata
if (gpl->parent != NULL) {
/* calculate new matrix */
if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
- invert_m4_m4(cur_mat, gpl->parent->obmat);
- copy_v3_v3(gpl_loc, obact->obmat[3]);
+ invert_m4_m4(cur_mat, gpl->parent->object_to_world);
+ copy_v3_v3(gpl_loc, obact->object_to_world[3]);
}
else if (gpl->partype == PARBONE) {
bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
if (pchan) {
float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
+ mul_m4_m4m4(tmp_mat, gpl->parent->object_to_world, pchan->pose_mat);
invert_m4_m4(cur_mat, tmp_mat);
- copy_v3_v3(gpl_loc, obact->obmat[3]);
+ copy_v3_v3(gpl_loc, obact->object_to_world[3]);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c
index 51cb08cf592..0144ffa07c7 100644
--- a/source/blender/editors/gpencil/gpencil_uv.c
+++ b/source/blender/editors/gpencil/gpencil_uv.c
@@ -138,7 +138,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op)
opdata->array_loc = NULL;
opdata->array_rot = NULL;
opdata->array_scale = NULL;
- opdata->ob_scale = mat4_to_scale(opdata->ob->obmat);
+ opdata->ob_scale = mat4_to_scale(opdata->ob->object_to_world);
opdata->vinit_rotation[0] = 1.0f;
opdata->vinit_rotation[1] = 0.0f;
@@ -158,7 +158,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op)
float r_center[3];
gpencil_stroke_center(gps, r_center);
/* Add object location. */
- add_v3_v3(r_center, opdata->ob->obmat[3]);
+ add_v3_v3(r_center, opdata->ob->object_to_world[3]);
add_v3_v3(center, r_center);
i++;
}
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index c8ffbb9acb1..b97cd6a9099 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -345,12 +345,14 @@ typedef enum {
ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */
} eUVPackIsland_MarginMethod;
+/** See also #UnwrapOptions. */
struct UVPackIsland_Params {
uint rotate : 1;
uint only_selected_uvs : 1;
uint only_selected_faces : 1;
uint use_seams : 1;
uint correct_aspect : 1;
+ bool ignore_pinned; /* Ignore islands which have any pinned UVs. */
eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */
float margin; /* Additional space to add around each island. */
};
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 2a1941f0d9e..1098266331f 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -784,6 +784,9 @@ void UI_block_set_search_only(uiBlock *block, bool search_only);
* Can be called with C==NULL.
*/
void UI_block_free(const struct bContext *C, uiBlock *block);
+
+void UI_block_listen(const uiBlock *block, const struct wmRegionListenerParams *listener_params);
+
/**
* Can be called with C==NULL.
*/
@@ -1683,6 +1686,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name);
* Adds a hint to the button which draws right aligned, grayed out and never clipped.
*/
void UI_but_hint_drawstr_set(uiBut *but, const char *string);
+void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number);
void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
@@ -2524,6 +2528,7 @@ void uiTemplateNodeView(uiLayout *layout,
struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocket *input);
+void uiTemplateNodeAssetMenuItems(uiLayout *layout, struct bContext *C, const char *catalog_path);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
/**
* Button to quickly show texture in Properties Editor texture tab.
@@ -2788,7 +2793,8 @@ typedef struct uiPropertySplitWrapper {
uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout);
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
-void uiItemL_ex(uiLayout *layout, const char *name, int icon, bool highlight, bool redalert);
+struct uiBut *uiItemL_ex(
+ uiLayout *layout, const char *name, int icon, bool highlight, bool redalert);
/**
* Helper to add a label and creates a property split layout if needed.
*/
@@ -3195,9 +3201,6 @@ void UI_interface_tag_script_reload(void);
/* Support click-drag motion which presses the button and closes a popover (like a menu). */
#define USE_UI_POPOVER_ONCE
-void UI_block_views_listen(const uiBlock *block,
- const struct wmRegionListenerParams *listener_params);
-
bool UI_view_item_is_active(const uiViewItemHandle *item_handle);
bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle);
/**
diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh
index 6c756984203..fc03b0218c0 100644
--- a/source/blender/editors/include/UI_interface.hh
+++ b/source/blender/editors/include/UI_interface.hh
@@ -35,6 +35,7 @@ struct ContextPathItem {
std::string name;
/* #BIFIconID */
int icon;
+ int icon_indicator_number;
};
void context_path_add_generic(Vector<ContextPathItem> &path,
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index a1a98a4b08c..9669e242dac 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -27,6 +27,12 @@ typedef struct IconFile {
int index;
} IconFile;
+typedef struct IconTextOverlay {
+ char text[5];
+} IconTextOverlay;
+
+#define UI_NO_ICON_OVERLAY_TEXT NULL
+
#define ICON_DEFAULT_HEIGHT 16
#define ICON_DEFAULT_WIDTH 16
@@ -105,7 +111,8 @@ void UI_icon_draw_ex(float x,
float alpha,
float desaturate,
const uchar mono_color[4],
- bool mono_border);
+ bool mono_border,
+ const struct IconTextOverlay *text_overlay);
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
@@ -124,6 +131,9 @@ int UI_icon_from_library(const struct ID *id);
int UI_icon_from_object_mode(int mode);
int UI_icon_color_from_collection(const struct Collection *collection);
+void UI_icon_text_overlay_init_from_count(struct IconTextOverlay *text_overlay,
+ const int icon_indicator_number);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_depth.c b/source/blender/editors/interface/eyedroppers/eyedropper_depth.c
index 3fb5a74944b..c6d950112b9 100644
--- a/source/blender/editors/interface/eyedroppers/eyedropper_depth.c
+++ b/source/blender/editors/interface/eyedroppers/eyedropper_depth.c
@@ -162,7 +162,7 @@ static void depthdropper_depth_sample_pt(bContext *C,
View3D *v3d = area->spacedata.first;
RegionView3D *rv3d = region->regiondata;
/* weak, we could pass in some reference point */
- const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
+ const float *view_co = v3d->camera ? v3d->camera->object_to_world[3] : rv3d->viewinv[3];
const int mval[2] = {m_xy[0] - region->winrct.xmin, m_xy[1] - region->winrct.ymin};
copy_v2_v2_int(ddr->name_pos, mval);
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 422fc34aa50..331d1581db5 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -3474,6 +3474,7 @@ void UI_block_free(const bContext *C, uiBlock *block)
BLI_freelistN(&block->saferct);
BLI_freelistN(&block->color_pickers.list);
+ BLI_freelistN(&block->dynamic_listeners);
ui_block_free_button_groups(block);
ui_block_free_views(block);
@@ -3481,6 +3482,20 @@ void UI_block_free(const bContext *C, uiBlock *block)
MEM_freeN(block);
}
+void UI_block_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
+{
+ /* Don't need to let invisible blocks (old blocks from previous redraw) listen. */
+ if (!block->active) {
+ return;
+ }
+
+ LISTBASE_FOREACH (uiBlockDynamicListener *, listener, &block->dynamic_listeners) {
+ listener->listener_func(listener_params);
+ }
+
+ ui_block_views_listen(block, listener_params);
+}
+
void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
{
ARegion *region = CTX_wm_region(C);
@@ -6452,6 +6467,11 @@ void UI_but_hint_drawstr_set(uiBut *but, const char *string)
ui_but_add_shortcut(but, string, false);
}
+void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number)
+{
+ UI_icon_text_overlay_init_from_count(&but->icon_overlay_text, indicator_number);
+}
+
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
{
but->flag |= UI_BUT_NODE_LINK;
diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc
index e8f552e26a3..74a07d6edc8 100644
--- a/source/blender/editors/interface/interface_context_path.cc
+++ b/source/blender/editors/interface/interface_context_path.cc
@@ -17,6 +17,8 @@
#include "UI_interface.hh"
#include "UI_resources.h"
+#include "RNA_prototypes.h"
+
#include "WM_api.h"
namespace blender::ui {
@@ -41,7 +43,13 @@ void context_path_add_generic(Vector<ContextPathItem> &path,
static_cast<BIFIconID>(RNA_struct_ui_icon(rna_ptr.type)) :
icon_override;
- path.append({name, int(icon)});
+ if (&rna_type == &RNA_NodeTree) {
+ ID *id = (ID *)ptr;
+ path.append({name, int(icon), ID_REAL_USERS(id)});
+ }
+ else {
+ path.append({name, int(icon), 1});
+ }
}
/* -------------------------------------------------------------------- */
@@ -60,7 +68,9 @@ void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path)
if (i > 0) {
uiItemL(sub_row, "", ICON_RIGHTARROW_THIN);
}
- uiItemL(sub_row, context_path[i].name.c_str(), context_path[i].icon);
+ uiBut *but = uiItemL_ex(
+ sub_row, context_path[i].name.c_str(), context_path[i].icon, false, false);
+ UI_but_icon_indicator_number_set(but, context_path[i].icon_indicator_number);
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index a45721e2c64..a5c786358d6 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3519,7 +3519,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
{
- /* label and roundbox can overlap real buttons (backdrops...) */
+ /* Label and round-box can overlap real buttons (backdrops...). */
if (ELEM(actbut->type,
UI_BTYPE_LABEL,
UI_BTYPE_SEPR,
@@ -3551,7 +3551,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
{
- /* label and roundbox can overlap real buttons (backdrops...) */
+ /* Label and round-box can overlap real buttons (backdrops...). */
if (ELEM(actbut->type,
UI_BTYPE_LABEL,
UI_BTYPE_SEPR,
@@ -3894,7 +3894,7 @@ static void ui_do_but_textedit(
}
if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) {
if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
- strcmp(ime_data->str_result, "\xE3\x80\x82") == 0) {
+ STREQ(ime_data->str_result, "\xE3\x80\x82")) {
/* Convert Ideographic Full Stop (U+3002) to decimal point when entering numbers. */
ui_textedit_insert_ascii(but, data, '.');
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index deb3d84ae66..9a4f98ebcd6 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -415,8 +415,15 @@ static void vicon_collection_color_draw(
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(
- x, y, ICON_OUTLINER_COLLECTION, aspect, 1.0f, 0.0f, collection_color->color, true);
+ UI_icon_draw_ex(x,
+ y,
+ ICON_OUTLINER_COLLECTION,
+ aspect,
+ 1.0f,
+ 0.0f,
+ collection_color->color,
+ true,
+ UI_NO_ICON_OVERLAY_TEXT);
}
# define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \
@@ -444,7 +451,8 @@ static void vicon_strip_color_draw(
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true);
+ UI_icon_draw_ex(
+ x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true, UI_NO_ICON_OVERLAY_TEXT);
}
# define DEF_ICON_STRIP_COLOR_DRAW(index, color) \
@@ -472,8 +480,15 @@ static void vicon_strip_color_draw_library_data_indirect(
{
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(
- x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false);
+ UI_icon_draw_ex(x,
+ y,
+ ICON_LIBRARY_DATA_DIRECT,
+ aspect,
+ ICON_INDIRECT_DATA_ALPHA * alpha,
+ 0.0f,
+ NULL,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
static void vicon_strip_color_draw_library_data_override_noneditable(
@@ -488,7 +503,8 @@ static void vicon_strip_color_draw_library_data_override_noneditable(
ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f,
0.0f,
NULL,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/* Dynamically render icon instead of rendering a plain color to a texture/buffer
@@ -1716,9 +1732,47 @@ static void icon_draw_texture(float x,
int ih,
float alpha,
const float rgb[3],
- bool with_border)
-{
- if (g_icon_draw_cache.enabled) {
+ bool with_border,
+ const IconTextOverlay *text_overlay)
+{
+ const float zoom_factor = w / UI_DPI_ICON_SIZE;
+ float text_width = 0.0f;
+
+ /* No need to show if too zoomed out, otherwise it just adds noise. */
+ const bool show_indicator = (text_overlay && text_overlay->text[0] != '\0') &&
+ (zoom_factor > 0.7f);
+
+ if (show_indicator) {
+ /* Handle the little numbers on top of the icon. */
+ uchar text_color[4];
+ UI_GetThemeColor3ubv(TH_TEXT, text_color);
+ text_color[3] = 255;
+
+ uiFontStyle fstyle_small = *UI_FSTYLE_WIDGET;
+ fstyle_small.points *= zoom_factor;
+ fstyle_small.points *= 0.8f;
+
+ rcti text_rect = {
+ .xmax = x + UI_UNIT_X * zoom_factor,
+ .xmin = x,
+ .ymax = y,
+ .ymin = y,
+ };
+
+ UI_fontstyle_draw(&fstyle_small,
+ &text_rect,
+ text_overlay->text,
+ sizeof(text_overlay->text),
+ text_color,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_RIGHT,
+ });
+ text_width = (float)UI_fontstyle_string_width(&fstyle_small, text_overlay->text) / UI_UNIT_X /
+ zoom_factor;
+ }
+
+ /* Draw the actual icon. */
+ if (!show_indicator && g_icon_draw_cache.enabled) {
icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1735,7 +1789,7 @@ static void icon_draw_texture(float x,
GPUTexture *texture = with_border ? icongltex.tex[1] : icongltex.tex[0];
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON);
GPU_shader_bind(shader);
const int img_binding = GPU_shader_get_texture_binding(shader, "image");
@@ -1752,6 +1806,7 @@ static void icon_draw_texture(float x,
GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2});
GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h});
+ GPU_shader_uniform_1f(shader, "text_width", text_width);
GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false);
@@ -1786,7 +1841,8 @@ static void icon_draw_size(float x,
int draw_size,
const float desaturate,
const uchar mono_rgba[4],
- const bool mono_border)
+ const bool mono_border,
+ const IconTextOverlay *text_overlay)
{
bTheme *btheme = UI_GetTheme();
const float fdraw_size = (float)draw_size;
@@ -1874,7 +1930,8 @@ static void icon_draw_size(float x,
di->data.texture.h,
alpha,
NULL,
- false);
+ false,
+ text_overlay);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
/* Monochrome icon that uses text or theme color. */
@@ -1908,7 +1965,8 @@ static void icon_draw_size(float x,
di->data.texture.h + 2 * border_texel,
color[3],
color,
- with_border);
+ with_border,
+ text_overlay);
}
else if (di->type == ICON_TYPE_BUFFER) {
@@ -2425,17 +2483,27 @@ int UI_icon_color_from_collection(const Collection *collection)
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
{
- UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false);
+ icon_draw_size(x,
+ y,
+ icon_id,
+ aspect,
+ alpha,
+ ICON_SIZE_PREVIEW,
+ size,
+ false,
+ NULL,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_ex(float x,
@@ -2445,7 +2513,8 @@ void UI_icon_draw_ex(float x,
float alpha,
float desaturate,
const uchar mono_color[4],
- const bool mono_border)
+ const bool mono_border,
+ const IconTextOverlay *text_overlay)
{
const int draw_size = get_draw_size(ICON_SIZE_ICON);
icon_draw_size(x,
@@ -2457,7 +2526,19 @@ void UI_icon_draw_ex(float x,
draw_size,
desaturate,
mono_color,
- mono_border);
+ mono_border,
+ text_overlay);
+}
+
+void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay,
+ const int icon_indicator_number)
+{
+ /* The icon indicator is used as an aggregator, no need to show if it is 1. */
+ if (icon_indicator_number < 2) {
+ text_overlay->text[0] = '\0';
+ return;
+ }
+ BLI_str_format_integer_unit(text_overlay->text, icon_indicator_number);
}
/* ********** Alert Icons ********** */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 6ef7d346418..982ac1753e1 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -23,6 +23,7 @@ struct ARegion;
struct AnimationEvalContext;
struct CurveMapping;
struct CurveProfile;
+struct IconTextOverlay;
struct ID;
struct ImBuf;
struct Main;
@@ -275,6 +276,9 @@ struct uiBut {
uiButPushedStateFunc pushed_state_func;
const void *pushed_state_arg;
+ /** Little indicator (e.g., counter) displayed on top of some icons. */
+ struct IconTextOverlay icon_overlay_text;
+
/* pointer back */
uiBlock *block;
};
@@ -473,6 +477,12 @@ typedef enum uiButtonGroupFlag {
} uiButtonGroupFlag;
ENUM_OPERATORS(uiButtonGroupFlag, UI_BUTTON_GROUP_PANEL_HEADER);
+typedef struct uiBlockDynamicListener {
+ struct uiBlockDynamicListener *next, *prev;
+
+ void (*listener_func)(const struct wmRegionListenerParams *params);
+} uiBlockDynamicListener;
+
struct uiBlock {
uiBlock *next, *prev;
@@ -495,6 +505,8 @@ struct uiBlock {
* state that is persistent over redraws (e.g. collapsed tree-view items). */
ListBase views;
+ ListBase dynamic_listeners; /* #uiBlockDynamicListener */
+
char name[UI_MAX_NAME_STR];
float winmat[4][4];
@@ -1536,6 +1548,8 @@ void ui_interface_tag_script_reload_queries(void);
/* interface_view.cc */
void ui_block_free_views(struct uiBlock *block);
+void ui_block_views_listen(const uiBlock *block,
+ const struct wmRegionListenerParams *listener_params);
uiViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block,
const uiViewHandle *new_view);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index c906a5b36f1..a456cef7be6 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -3235,7 +3235,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
return but;
}
-void uiItemL_ex(
+uiBut *uiItemL_ex(
uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert)
{
uiBut *but = uiItemL_(layout, name, icon);
@@ -3248,6 +3248,8 @@ void uiItemL_ex(
if (redalert) {
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
+
+ return but;
}
void uiItemL(uiLayout *layout, const char *name, int icon)
@@ -5812,6 +5814,14 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
}
+ if (mt->listener) {
+ /* Forward the menu type listener to the block we're drawing in. */
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBlockDynamicListener *listener = MEM_mallocN(sizeof(*listener), "uiBlockDynamicListener");
+ listener->listener_func = mt->listener;
+ BLI_addtail(&block->dynamic_listeners, listener);
+ }
+
if (layout->context) {
CTX_store_set(C, layout->context);
}
diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc
index e089642963d..2d06dd2c465 100644
--- a/source/blender/editors/interface/interface_ops.cc
+++ b/source/blender/editors/interface/interface_ops.cc
@@ -1859,8 +1859,7 @@ static void edittranslation_find_po_file(const char *root,
/* First, full lang code. */
BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng);
- BLI_path_join(path, maxlen, root, uilng);
- BLI_path_append(path, maxlen, tstr);
+ BLI_path_join(path, maxlen, root, uilng, tstr);
if (BLI_is_file(path)) {
return;
}
diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc
index 7a69e2f9b2f..24d8281aad8 100644
--- a/source/blender/editors/interface/interface_panel.cc
+++ b/source/blender/editors/interface/interface_panel.cc
@@ -1112,7 +1112,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style,
0.7f,
0.0f,
title_color,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
@@ -1140,7 +1141,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style,
1.0f,
0.0f,
title_color,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc
index 569f657a544..0d19390d508 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.cc
+++ b/source/blender/editors/interface/interface_region_menu_popup.cc
@@ -10,6 +10,7 @@
#include <cstdarg>
#include <cstdlib>
#include <cstring>
+#include <functional>
#include "MEM_guardedalloc.h"
@@ -166,28 +167,80 @@ struct uiPopupMenu {
uiBut *but;
ARegion *butregion;
+ /* Menu hash is created from this, to keep a memory of recently opened menus. */
+ const char *title;
+
int mx, my;
bool popup, slideout;
- uiMenuCreateFunc menu_func;
- void *menu_arg;
+ std::function<void(bContext *C, uiLayout *layout)> menu_func;
};
+/**
+ * \param title: Optional. If set, it will be used to store recently opened menus so they can be
+ * opened with the mouse over the last chosen entry again.
+ */
+static void ui_popup_menu_create_block(bContext *C,
+ uiPopupMenu *pup,
+ const char *title,
+ const char *block_name)
+{
+ const uiStyle *style = UI_style_get_dpi();
+
+ pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN);
+ if (!pup->but) {
+ pup->block->flag |= UI_BLOCK_IS_FLIP | UI_BLOCK_NO_FLIP;
+ }
+ if (title && title[0]) {
+ pup->block->flag |= UI_BLOCK_POPUP_MEMORY;
+ pup->block->puphash = ui_popup_menu_hash(title);
+ }
+ pup->layout = UI_block_layout(
+ pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
+
+ /* NOTE: this intentionally differs from the menu & sub-menu default because many operators
+ * use popups like this to select one of their options -
+ * where having invoke doesn't make sense.
+ * When the menu was opened from a button, use invoke still for compatibility. This used to be
+ * the default and changing now could cause issues. */
+ const wmOperatorCallContext opcontext = pup->but ? WM_OP_INVOKE_REGION_WIN :
+ WM_OP_EXEC_REGION_WIN;
+
+ uiLayoutSetOperatorContext(pup->layout, opcontext);
+
+ if (pup->but) {
+ if (pup->but->context) {
+ uiLayoutContextCopy(pup->layout, pup->but->context);
+ }
+ }
+}
+
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
uiPopupMenu *pup = static_cast<uiPopupMenu *>(arg_pup);
- if (pup->menu_func) {
- pup->block->handle = handle;
- pup->menu_func(C, pup->layout, pup->menu_arg);
- pup->block->handle = nullptr;
+ int minwidth = 0;
+
+ if (!pup->layout) {
+ ui_popup_menu_create_block(C, pup, pup->title, __func__);
+
+ if (pup->menu_func) {
+ pup->block->handle = handle;
+ pup->menu_func(C, pup->layout);
+ pup->block->handle = nullptr;
+ }
+
+ if (uiLayoutGetUnitsX(pup->layout) != 0.0f) {
+ /* Use the minimum width from the layout if it's set. */
+ minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X;
+ }
+
+ pup->layout = nullptr;
}
/* Find block minimum width. */
- int minwidth;
- if (uiLayoutGetUnitsX(pup->layout) != 0.0f) {
- /* Use the minimum width from the layout if it's set. */
- minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X;
+ if (minwidth) {
+ /* Skip. */
}
else if (pup->but) {
/* Minimum width to enforce. */
@@ -236,7 +289,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
if (pup->popup) {
- int offset[2];
+ int offset[2] = {0, 0};
uiBut *but_activate = nullptr;
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
@@ -244,36 +297,42 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
UI_block_direction_set(block, direction);
/* offset the mouse position, possibly based on earlier selection */
- uiBut *bt;
- if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) {
- /* position mouse on last clicked item, at 0.8*width of the
- * button, so it doesn't overlap the text too much, also note
- * the offset is negative because we are inverse moving the
- * block to be under the mouse */
- offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
- offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
-
- if (ui_but_is_editable(bt)) {
- but_activate = bt;
- }
- }
- else {
- /* position mouse at 0.8*width of the button and below the tile
- * on the first item */
- offset[0] = 0;
- LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
- offset[0] = min_ii(offset[0],
- -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect)));
+ if (!handle->refresh) {
+ uiBut *bt;
+ if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) {
+ /* position mouse on last clicked item, at 0.8*width of the
+ * button, so it doesn't overlap the text too much, also note
+ * the offset is negative because we are inverse moving the
+ * block to be under the mouse */
+ offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
+ offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
+
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ }
}
+ else {
+ /* position mouse at 0.8*width of the button and below the tile
+ * on the first item */
+ offset[0] = 0;
+ LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
+ offset[0] = min_ii(offset[0],
+ -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect)));
+ }
- offset[1] = 2.1 * UI_UNIT_Y;
+ offset[1] = 2.1 * UI_UNIT_Y;
- LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
- if (ui_but_is_editable(but_iter)) {
- but_activate = but_iter;
- break;
+ LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
+ if (ui_but_is_editable(but_iter)) {
+ but_activate = but_iter;
+ break;
+ }
}
}
+ copy_v2_v2_int(handle->prev_bounds_offset, offset);
+ }
+ else {
+ copy_v2_v2_int(offset, handle->prev_bounds_offset);
}
/* in rare cases this is needed since moving the popup
@@ -312,27 +371,35 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
return pup->block;
}
-uiPopupBlockHandle *ui_popup_menu_create(
- bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
+static void ui_block_free_func_POPUP(void *arg_pup)
+{
+ uiPopupMenu *pup = static_cast<uiPopupMenu *>(arg_pup);
+ MEM_delete(pup);
+}
+
+static uiPopupBlockHandle *ui_popup_menu_create(
+ bContext *C,
+ ARegion *butregion,
+ uiBut *but,
+ const char *title,
+ std::function<void(bContext *, uiLayout *)> menu_func)
{
wmWindow *window = CTX_wm_window(C);
- const uiStyle *style = UI_style_get_dpi();
- uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__);
- pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS_PULLDOWN);
- pup->block->flag |= UI_BLOCK_NUMSELECT; /* Default menus to numeric-selection. */
- pup->layout = UI_block_layout(
- pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
- pup->slideout = but ? ui_block_is_menu(but->block) : false;
- pup->but = but;
- uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
+ uiPopupMenu *pup = MEM_new<uiPopupMenu>(__func__);
+ pup->title = title;
+ /* menu is created from a callback */
+ pup->menu_func = menu_func;
+ if (but) {
+ pup->slideout = ui_block_is_menu(but->block);
+ pup->but = but;
+ }
if (!but) {
/* no button to start from, means we are a popup */
pup->mx = window->eventstate->xy[0];
pup->my = window->eventstate->xy[1];
pup->popup = true;
- pup->block->flag |= UI_BLOCK_NO_FLIP;
}
/* some enums reversing is strange, currently we have no good way to
* reverse some enum's but not others, so reverse all so the first menu
@@ -346,17 +413,10 @@ uiPopupBlockHandle *ui_popup_menu_create(
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
#endif
- if (but->context) {
- uiLayoutContextCopy(pup->layout, but->context);
- }
}
- /* menu is created from a callback */
- pup->menu_func = menu_func;
- pup->menu_arg = arg;
-
uiPopupBlockHandle *handle = ui_popup_block_create(
- C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr);
+ C, butregion, but, nullptr, ui_block_func_POPUP, pup, ui_block_free_func_POPUP);
if (!but) {
handle->popup = true;
@@ -365,68 +425,73 @@ uiPopupBlockHandle *ui_popup_menu_create(
WM_event_add_mousemove(window);
}
- MEM_freeN(pup);
-
return handle;
}
+uiPopupBlockHandle *ui_popup_menu_create(
+ bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
+{
+ return ui_popup_menu_create(
+ C, butregion, but, nullptr, [menu_func, arg](bContext *C, uiLayout *layout) {
+ menu_func(C, layout, arg);
+ });
+}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Popup Menu API with begin & end
* \{ */
+static void create_title_button(uiLayout *layout, const char *title, int icon)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ char titlestr[256];
+
+ if (icon) {
+ BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
+ uiDefIconTextBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ icon,
+ titlestr,
+ 0,
+ 0,
+ 200,
+ UI_UNIT_Y,
+ nullptr,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ }
+ else {
+ uiBut *but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, "");
+ but->drawflag = UI_BUT_TEXT_LEFT;
+ }
+
+ uiItemS(layout);
+}
+
+/* Used to directly create a popup menu that is not refreshed on redraw. */
uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
const char *title,
const char *block_name,
int icon)
{
- const uiStyle *style = UI_style_get_dpi();
- uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__);
+ uiPopupMenu *pup = MEM_new<uiPopupMenu>(__func__);
- pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN);
- pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP;
- pup->block->puphash = ui_popup_menu_hash(title);
- pup->layout = UI_block_layout(
- pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
+ pup->title = title;
- /* NOTE: this intentionally differs from the menu & sub-menu default because many operators
- * use popups like this to select one of their options -
- * where having invoke doesn't make sense */
- uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
+ ui_popup_menu_create_block(C, pup, title, block_name);
/* create in advance so we can let buttons point to retval already */
pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__);
- /* create title button */
if (title[0]) {
- char titlestr[256];
-
- if (icon) {
- BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
- uiDefIconTextBut(pup->block,
- UI_BTYPE_LABEL,
- 0,
- icon,
- titlestr,
- 0,
- 0,
- 200,
- UI_UNIT_Y,
- nullptr,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
- else {
- uiBut *but = uiDefBut(
- pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, "");
- but->drawflag = UI_BUT_TEXT_LEFT;
- }
-
- uiItemS(pup->layout);
+ create_title_button(pup->layout, title, icon);
}
return pup;
@@ -465,7 +530,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
WM_event_add_mousemove(window);
- MEM_freeN(pup);
+ MEM_delete(pup);
}
bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup)
@@ -477,7 +542,7 @@ bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup)
UI_block_layout_resolve(pup->block, nullptr, nullptr);
MEM_freeN(pup->block->handle);
UI_block_free(C, pup->block);
- MEM_freeN(pup);
+ MEM_delete(pup);
return false;
}
@@ -541,6 +606,20 @@ void UI_popup_menu_reports(bContext *C, ReportList *reports)
}
}
+static void ui_popup_menu_create_from_menutype(bContext *C,
+ MenuType *mt,
+ const char *title,
+ const int icon)
+{
+ uiPopupBlockHandle *handle = ui_popup_menu_create(
+ C, nullptr, nullptr, title, [mt, title, icon](bContext *C, uiLayout *layout) -> void {
+ create_title_button(layout, title, icon);
+ ui_item_menutype_func(C, layout, mt);
+ });
+
+ handle->can_refresh = true;
+}
+
int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
{
MenuType *mt = WM_menutype_find(idname, true);
@@ -554,14 +633,21 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
/* cancel but allow event to pass through, just like operators do */
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
+ /* For now always recreate menus on redraw that were invoked with this function. Maybe we want to
+ * make that optional somehow. */
+ const bool allow_refresh = true;
- uiPopupMenu *pup = UI_popup_menu_begin(
- C, CTX_IFACE_(mt->translation_context, mt->label), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- UI_menutype_draw(C, mt, layout);
-
- UI_popup_menu_end(C, pup);
+ const char *title = CTX_IFACE_(mt->translation_context, mt->label);
+ if (allow_refresh) {
+ ui_popup_menu_create_from_menutype(C, mt, title, ICON_NONE);
+ }
+ else {
+ /* If no refresh is needed, create the block directly. */
+ uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+ UI_menutype_draw(C, mt, layout);
+ UI_popup_menu_end(C, pup);
+ }
return OPERATOR_INTERFACE;
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6ba80e2e0d9..1bad9b34a72 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1420,21 +1420,25 @@ static void widget_draw_icon(
/* to indicate draggable */
if (ui_but_drag_is_draggable(but) && (but->flag & UI_ACTIVE)) {
- UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else if (but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) {
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else if (!((but->icon != ICON_NONE) && UI_but_is_tool(but))) {
if (has_theme) {
alpha *= 0.8f;
}
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else {
const bTheme *btheme = UI_GetTheme();
const float desaturate = 1.0 - btheme->tui.icon_saturation;
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, desaturate, color, has_theme, &but->icon_overlay_text);
}
}
@@ -5426,7 +5430,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
GPU_blend(GPU_BLEND_ALPHA);
/* XXX scale weak get from fstyle? */
- UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
+ UI_icon_draw_ex(
+ xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false, UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/interface/views/interface_view.cc b/source/blender/editors/interface/views/interface_view.cc
index c568a8cab74..71974b4d2f9 100644
--- a/source/blender/editors/interface/views/interface_view.cc
+++ b/source/blender/editors/interface/views/interface_view.cc
@@ -81,7 +81,7 @@ void ui_block_free_views(uiBlock *block)
}
}
-void UI_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
+void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
{
ARegion *region = listener_params->region;
diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc
index 888a8340d51..1c6d1747516 100644
--- a/source/blender/editors/mesh/editface.cc
+++ b/source/blender/editors/mesh/editface.cc
@@ -383,7 +383,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
return ok;
}
- copy_m3_m4(bmat, ob->obmat);
+ copy_m3_m4(bmat, ob->object_to_world);
const Span<MVert> verts = me->verts();
const Span<MPoly> polys = me->polys();
@@ -403,7 +403,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
const MLoop *ml = &loops[poly.loopstart];
for (int b = 0; b < poly.totloop; b++, ml++) {
mul_v3_m3v3(vec, bmat, verts[ml->v].co);
- add_v3_v3v3(vec, vec, ob->obmat[3]);
+ add_v3_v3v3(vec, vec, ob->object_to_world[3]);
minmax_v3v3_v3(r_min, r_max, vec);
}
diff --git a/source/blender/editors/mesh/editmesh_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c
index f5090c0143d..ad900c997f8 100644
--- a/source/blender/editors/mesh/editmesh_add_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_add_gizmo.c
@@ -316,7 +316,7 @@ static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op)
PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
if (RNA_property_is_set(op->ptr, prop_matrix)) {
RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]);
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
mul_m4_m4m4(matrix, obedit->imat, matrix);
}
else {
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 3284cd70646..85801668510 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -244,7 +244,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
Object *obedit = objects[ob_index];
- float scale = mat4_to_scale(obedit->obmat);
+ float scale = mat4_to_scale(obedit->object_to_world);
opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (em->bm->totvertsel > 0) {
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 5c5a12b3e64..aab33678bec 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -314,9 +314,9 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
copy_v3_v3(plane_co_local, plane_co);
copy_v3_v3(plane_no_local, plane_no);
- invert_m4_m4(imat, obedit->obmat);
+ invert_m4_m4(imat, obedit->object_to_world);
mul_m4_v3(imat, plane_co_local);
- mul_transposed_mat3_m4_v3(obedit->obmat, plane_no_local);
+ mul_transposed_mat3_m4_v3(obedit->object_to_world, plane_no_local);
BMOperator bmop;
EDBM_op_init(
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 55e9c32e41b..9df3a521cfa 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -55,8 +55,8 @@ static void edbm_extrude_edge_exclude_mirror(
float mtx[4][4];
if (mmd->mirror_ob) {
float imtx[4][4];
- invert_m4_m4(imtx, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, imtx, obedit->obmat);
+ invert_m4_m4(imtx, mmd->mirror_ob->object_to_world);
+ mul_m4_m4m4(mtx, imtx, obedit->object_to_world);
}
BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
@@ -293,7 +293,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- copy_m3_m4(tmat, obedit->obmat);
+ copy_m3_m4(tmat, obedit->object_to_world);
invert_m3(tmat);
mul_v3_m3v3(offset_local, tmat, offset);
@@ -736,7 +736,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
}
mul_v3_fl(local_center, 1.0f / (float)local_verts_len);
- mul_m4_v3(vc.obedit->obmat, local_center);
+ mul_m4_v3(vc.obedit->object_to_world, local_center);
mul_v3_fl(local_center, (float)local_verts_len);
add_v3_v3(center, local_center);
@@ -761,7 +761,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
continue;
}
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
float local_center[3];
@@ -823,7 +823,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
/* center */
copy_v3_v3(ofs, local_center);
- mul_m4_v3(vc.obedit->obmat, ofs); /* view space */
+ mul_m4_v3(vc.obedit->object_to_world, ofs); /* view space */
ED_view3d_win_to_3d_int(vc.v3d, vc.region, ofs, event->mval, ofs);
mul_m4_v3(vc.obedit->imat, ofs); /* back in object space */
diff --git a/source/blender/editors/mesh/editmesh_extrude_screw.c b/source/blender/editors/mesh/editmesh_extrude_screw.c
index be2d04b14a1..9d0bcfe4e90 100644
--- a/source/blender/editors/mesh/editmesh_extrude_screw.c
+++ b/source/blender/editors/mesh/editmesh_extrude_screw.c
@@ -102,11 +102,11 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
continue;
}
- copy_v3_v3(nor, obedit->obmat[2]);
+ copy_v3_v3(nor, obedit->object_to_world[2]);
/* calculate dvec */
- mul_v3_m4v3(v1_co_global, obedit->obmat, v1->co);
- mul_v3_m4v3(v2_co_global, obedit->obmat, v2->co);
+ mul_v3_m4v3(v1_co_global, obedit->object_to_world, v1->co);
+ mul_v3_m4v3(v2_co_global, obedit->object_to_world, v2->co);
sub_v3_v3v3(dvec, v1_co_global, v2_co_global);
mul_v3_fl(dvec, 1.0f / steps);
@@ -126,7 +126,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
dvec,
turns * steps,
DEG2RADF(360.0f * turns),
- obedit->obmat,
+ obedit->object_to_world,
false)) {
continue;
}
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c
index 1b9c98db5eb..756d7f73d10 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin.c
@@ -77,7 +77,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op)
d,
steps,
-angle,
- obedit->obmat,
+ obedit->object_to_world,
use_normal_flip,
dupli,
use_auto_merge)) {
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 687f06c8dcf..19e23f4f212 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -362,7 +362,7 @@ static void gizmo_mesh_spin_init_refresh(const bContext *C, wmGizmoGroup *gzgrou
}
if (totsel) {
mul_v3_fl(select_center, 1.0f / totsel);
- mul_m4_v3(obedit->obmat, select_center);
+ mul_m4_v3(obedit->object_to_world, select_center);
copy_v3_v3(ggd->data.select_center, select_center);
ggd->data.use_select_center = true;
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 068e6215c26..fa4ae7f984c 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -136,7 +136,7 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
Object *obedit = objects[ob_index];
- float scale = mat4_to_scale(obedit->obmat);
+ float scale = mat4_to_scale(obedit->object_to_world);
opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (em->bm->totvertsel > 0) {
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index a147594b25b..369162e80a3 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -586,9 +586,9 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd,
float axis[3];
float arc_angle;
- const float inverse_average_scale = 1 /
- (kcd->curr.ob->obmat[0][0] + kcd->curr.ob->obmat[1][1] +
- kcd->curr.ob->obmat[2][2]);
+ const float inverse_average_scale = 1 / (kcd->curr.ob->object_to_world[0][0] +
+ kcd->curr.ob->object_to_world[1][1] +
+ kcd->curr.ob->object_to_world[2][2]);
const float px_scale =
3.0f * inverse_average_scale *
@@ -1194,7 +1194,7 @@ static void knife_bm_tri_cagecos_get_worldspace(const KnifeTool_OpData *kcd,
knife_bm_tri_cagecos_get(kcd, ob_index, tri_index, cos);
const Object *ob = kcd->objects[ob_index];
for (int i = 0; i < 3; i++) {
- mul_m4_v3(ob->obmat, cos[i]);
+ mul_m4_v3(ob->object_to_world, cos[i]);
}
}
@@ -1744,7 +1744,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob
}
float cageco_ws[3];
- mul_v3_m4v3(cageco_ws, ob->obmat, cageco);
+ mul_v3_m4v3(cageco_ws, ob->object_to_world, cageco);
kfv = new_knife_vert(kcd, v->co, cageco_ws);
kfv->v = v;
@@ -2657,14 +2657,14 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
if (cagecos) {
for (int i = 0; i < em->bm->totvert; i++) {
copy_v3_v3(ws, cagecos[i]);
- mul_m4_v3(ob->obmat, ws);
+ mul_m4_v3(ob->object_to_world, ws);
minmax_v3v3_v3(min, max, ws);
}
}
else {
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
copy_v3_v3(ws, v->co);
- mul_m4_v3(ob->obmat, ws);
+ mul_m4_v3(ob->object_to_world, ws);
minmax_v3v3_v3(min, max, ws);
}
}
@@ -5072,7 +5072,7 @@ void EDBM_mesh_knife(ViewContext *vc,
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
float cent[3], cent_ss[2];
BM_face_calc_point_in_face(f, cent);
- mul_m4_v3(ob->obmat, cent);
+ mul_m4_v3(ob->object_to_world, cent);
knife_project_v2(kcd, cent, cent_ss);
if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
@@ -5113,7 +5113,7 @@ void EDBM_mesh_knife(ViewContext *vc,
if (found) {
float cent[3], cent_ss[2];
BM_face_calc_point_in_face(f, cent);
- mul_m4_v3(ob->obmat, cent);
+ mul_m4_v3(ob->object_to_world, cent);
knife_project_v2(kcd, cent, cent_ss);
if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
edbm_mesh_knife_point_isect(polys, cent_ss)) {
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 494e0ff4a27..9a91d7836fe 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -88,7 +88,7 @@ typedef struct RingSelOpData {
static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
{
RingSelOpData *lcd = arg;
- EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->obmat);
+ EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->object_to_world);
}
static void edgering_select(RingSelOpData *lcd)
diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c
index bf9664fa10d..63e37b18827 100644
--- a/source/blender/editors/mesh/editmesh_polybuild.c
+++ b/source/blender/editors/mesh/editmesh_polybuild.c
@@ -124,7 +124,7 @@ static int edbm_polybuild_transform_at_cursor_invoke(bContext *C,
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
if (!ele_act) {
@@ -192,7 +192,7 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C,
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
if (!ele_act) {
@@ -286,7 +286,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
@@ -294,7 +294,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
if (ele_act == NULL || ele_act->head.htype == BM_FACE) {
/* Just add vert */
copy_v3_v3(center, vc.scene->cursor.location);
- mul_v3_m4v3(center, vc.obedit->obmat, center);
+ mul_v3_m4v3(center, vc.obedit->object_to_world, center);
ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
@@ -309,7 +309,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
BMFace *f_reference = e_act->l ? e_act->l->f : NULL;
mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
- mul_m4_v3(vc.obedit->obmat, center);
+ mul_m4_v3(vc.obedit->object_to_world, center);
ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) {
@@ -364,7 +364,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL;
- mul_v3_m4v3(center, vc.obedit->obmat, v_act->co);
+ mul_v3_m4v3(center, vc.obedit->object_to_world, v_act->co);
ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
@@ -386,7 +386,7 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
}
else {
/* Just add edge */
- mul_m4_v3(vc.obedit->obmat, center);
+ mul_m4_v3(vc.obedit->object_to_world, center);
ED_view3d_win_to_3d_int(vc.v3d, vc.region, v_act->co, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
@@ -464,7 +464,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C,
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ invert_m4_m4(vc.obedit->imat, vc.obedit->object_to_world);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
@@ -475,7 +475,7 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C,
if (ele_act->head.htype == BM_EDGE) {
BMEdge *e_act = (BMEdge *)ele_act;
mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
- mul_m4_v3(vc.obedit->obmat, center);
+ mul_m4_v3(vc.obedit->object_to_world, center);
ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c
index cf73e579700..732f39e4123 100644
--- a/source/blender/editors/mesh/editmesh_preselect_elem.c
+++ b/source/blender/editors/mesh/editmesh_preselect_elem.c
@@ -243,7 +243,7 @@ static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_P
}
if (e_pair[1] != NULL) {
- mul_v3_m4v3(center, vc->obedit->obmat, v_act->co);
+ mul_v3_m4v3(center, vc->obedit->object_to_world, v_act->co);
ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
mul_m4_v3(vc->obedit->imat, center);
@@ -311,7 +311,7 @@ static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_P
psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris), __func__);
psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__);
mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
- mul_m4_v3(vc->obedit->obmat, center);
+ mul_m4_v3(vc->obedit->object_to_world, center);
ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
mul_m4_v3(vc->obedit->imat, center);
diff --git a/source/blender/editors/mesh/editmesh_select.cc b/source/blender/editors/mesh/editmesh_select.cc
index 76d0bab8a52..2ef2772d404 100644
--- a/source/blender/editors/mesh/editmesh_select.cc
+++ b/source/blender/editors/mesh/editmesh_select.cc
@@ -1060,7 +1060,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
float imat3[3][3];
ED_view3d_viewcontext_init_object(vc, obedit);
- copy_m3_m4(imat3, obedit->obmat);
+ copy_m3_m4(imat3, obedit->object_to_world);
invert_m3(imat3);
const float(*coords)[3] = nullptr;
@@ -1085,7 +1085,8 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
for (uint j = 0; j < 2; j++) {
BMVert *v = *((&e->v1) + j);
float point[3];
- mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
+ mul_v3_m4v3(
+ point, obedit->object_to_world, coords ? coords[BM_elem_index_get(v)] : v->co);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
if (dist_sq_test < dist_sq_best_vert) {
@@ -1114,7 +1115,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
else {
mid_v3_v3v3(point, e->v1->co, e->v2->co);
}
- mul_m4_v3(obedit->obmat, point);
+ mul_m4_v3(obedit->object_to_world, point);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
if (dist_sq_test < dist_sq_best_edge) {
@@ -1139,7 +1140,8 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
float point[3];
- mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
+ mul_v3_m4v3(
+ point, obedit->object_to_world, coords ? coords[BM_elem_index_get(v)] : v->co);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
if (dist_sq_test < dist_sq_best_vert) {
@@ -1169,7 +1171,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
else {
mid_v3_v3v3(point, e->v1->co, e->v2->co);
}
- mul_m4_v3(obedit->obmat, point);
+ mul_m4_v3(obedit->object_to_world, point);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
if (dist_sq_test < dist_sq_best_edge) {
@@ -1198,7 +1200,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
else {
BM_face_calc_center_median(f, point);
}
- mul_m4_v3(obedit->obmat, point);
+ mul_m4_v3(obedit->object_to_world, point);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
if (dist_sq_test < dist_sq_best_face) {
@@ -4947,7 +4949,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op)
{
float vertex_world[3];
- mul_v3_m4v3(vertex_world, obedit->obmat, v_act->co);
+ mul_v3_m4v3(vertex_world, obedit->object_to_world, v_act->co);
value = dot_v3v3(axis_vector, vertex_world);
}
@@ -4977,7 +4979,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) {
float v_iter_world[3];
- mul_v3_m4v3(v_iter_world, obedit_iter->obmat, v->co);
+ mul_v3_m4v3(v_iter_world, obedit_iter->object_to_world, v->co);
const float value_iter = dot_v3v3(axis_vector, v_iter_world);
switch (sign) {
case SELECT_AXIS_ALIGN:
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index 47c76b7709b..9469639718f 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -137,7 +137,7 @@ static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4])
copy_v3_v3(normal, face->no);
mul_transposed_mat3_m4_v3(ob->imat, normal);
normalize_v3(normal);
- mul_v3_m4v3(co, ob->obmat, BM_FACE_FIRST_LOOP(face)->v->co);
+ mul_v3_m4v3(co, ob->object_to_world, BM_FACE_FIRST_LOOP(face)->v->co);
plane_from_point_normal_v3(r_plane, co, normal);
}
@@ -206,7 +206,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em->bm;
Material ***material_array = NULL;
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
int custom_data_offset = 0;
if (bm->totfacesel == 0) {
@@ -214,7 +214,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
}
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
switch (type) {
case SIMFACE_MATERIAL: {
@@ -335,7 +335,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
int custom_data_offset;
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
bool has_custom_data_layer = false;
switch (type) {
@@ -559,8 +559,8 @@ static void edge_pos_direction_worldspace_get(Object *ob, BMEdge *edge, float *r
copy_v3_v3(v1, edge->v1->co);
copy_v3_v3(v2, edge->v2->co);
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
+ mul_m4_v3(ob->object_to_world, v1);
+ mul_m4_v3(ob->object_to_world, v2);
sub_v3_v3v3(r_dir, v1, v2);
normalize_v3(r_dir);
@@ -586,8 +586,8 @@ static float edge_length_squared_worldspace_get(Object *ob, BMEdge *edge)
{
float v1[3], v2[3];
- mul_v3_mat3_m4v3(v1, ob->obmat, edge->v1->co);
- mul_v3_mat3_m4v3(v2, ob->obmat, edge->v2->co);
+ mul_v3_mat3_m4v3(v1, ob->object_to_world, edge->v1->co);
+ mul_v3_mat3_m4v3(v2, ob->object_to_world, edge->v2->co);
return len_squared_v3v3(v1, v2);
}
@@ -705,7 +705,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
}
float ob_m3[3][3], ob_m3_inv[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
invert_m3_m3(ob_m3_inv, ob_m3);
BMEdge *edge; /* Mesh edge. */
@@ -812,7 +812,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
}
float ob_m3[3][3], ob_m3_inv[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
invert_m3_m3(ob_m3_inv, ob_m3);
BMEdge *edge; /* Mesh edge. */
@@ -1028,7 +1028,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
BLI_bitmap *defbase_selected = NULL;
int defbase_len = 0;
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
if (bm->totvertsel == 0) {
continue;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 9f3ef8af17d..9f5c0d74ced 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -3356,7 +3356,7 @@ static bool merge_target(BMEditMesh *em,
if (use_cursor) {
vco = scene->cursor.location;
copy_v3_v3(co, vco);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_v3(ob->imat, co);
}
else {
@@ -6684,7 +6684,7 @@ static void sort_bmelem_flag(bContext *C,
int coidx = (action == SRT_VIEW_ZAXIS) ? 2 : 0;
/* Apply the view matrix to the object matrix. */
- mul_m4_m4m4(mat, rv3d->viewmat, ob->obmat);
+ mul_m4_m4m4(mat, rv3d->viewmat, ob->object_to_world);
if (totelem[0]) {
pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock");
@@ -6753,7 +6753,7 @@ static void sort_bmelem_flag(bContext *C,
copy_v3_v3(cur, scene->cursor.location);
- invert_m4_m4(mat, ob->obmat);
+ invert_m4_m4(mat, ob->object_to_world);
mul_m4_v3(mat, cur);
if (totelem[0]) {
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 4fc44f01ea0..10acfc96ca8 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1858,7 +1858,7 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
ED_view3d_win_to_segment_clipped(depsgraph, region, v3d, mval_f, origin, end, false);
- invert_m4_m4(invmat, obedit->obmat);
+ invert_m4_m4(invmat, obedit->object_to_world);
mul_m4_v3(invmat, origin);
copy_v3_v3(co1, e->v1->co);
diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc
index 122b8fa7d89..b468360ff9b 100644
--- a/source/blender/editors/mesh/mesh_data.cc
+++ b/source/blender/editors/mesh/mesh_data.cc
@@ -787,7 +787,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
if (me->edit_mesh) {
/* Tag edges as sharp according to smooth threshold if needed,
- * to preserve autosmooth shading. */
+ * to preserve auto-smooth shading. */
if (me->flag & ME_AUTOSMOOTH) {
BM_edges_sharp_from_angle_set(me->edit_mesh->bm, me->smoothresh);
}
@@ -796,7 +796,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
}
else {
/* Tag edges as sharp according to smooth threshold if needed,
- * to preserve autosmooth shading. */
+ * to preserve auto-smooth shading. */
if (me->flag & ME_AUTOSMOOTH) {
const Span<MVert> verts = me->verts();
MutableSpan<MEdge> edges = me->edges_for_write();
diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc
index 4d75ab7f041..147c26e521f 100644
--- a/source/blender/editors/mesh/meshtools.cc
+++ b/source/blender/editors/mesh/meshtools.cc
@@ -132,7 +132,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
float cmat[4][4];
/* Watch this: switch matrix multiplication order really goes wrong. */
- mul_m4_m4m4(cmat, imat, ob_src->obmat);
+ mul_m4_m4m4(cmat, imat, ob_src->object_to_world);
/* transform vertex coordinates into new space */
for (a = 0; a < me->totvert; a++, mvert++) {
@@ -386,7 +386,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
* NOTE: This doesn't apply recursive parenting. */
if (join_parent) {
ob->parent = nullptr;
- BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false);
+ BKE_object_apply_mat4_ex(ob, ob->object_to_world, ob->parent, ob->parentinv, false);
}
/* that way the active object is always selected */
@@ -594,7 +594,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* Inverse transform for all selected meshes in this object,
* See #object_join_exec for detailed comment on why the safe version is used. */
- invert_m4_m4_safe_ortho(imat, ob->obmat);
+ invert_m4_m4_safe_ortho(imat, ob->object_to_world);
/* Add back active mesh first.
* This allows to keep things similar as they were, as much as possible
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc
index 3ce39b695e0..6075e4250eb 100644
--- a/source/blender/editors/object/object_add.cc
+++ b/source/blender/editors/object/object_add.cc
@@ -322,7 +322,7 @@ void ED_object_base_init_transform_on_add(Object *object, const float loc[3], co
copy_v3_v3(object->rot, rot);
}
- BKE_object_to_mat4(object, object->obmat);
+ BKE_object_to_mat4(object, object->object_to_world);
}
float ED_object_new_primitive_matrix(bContext *C,
@@ -342,14 +342,14 @@ float ED_object_new_primitive_matrix(bContext *C,
invert_m3(rmat);
/* inverse transform for initial rotation and object */
- copy_m3_m4(mat, obedit->obmat);
+ copy_m3_m4(mat, obedit->object_to_world);
mul_m3_m3m3(cmat, rmat, mat);
invert_m3_m3(imat, cmat);
copy_m4_m3(r_primmat, imat);
/* center */
copy_v3_v3(r_primmat[3], loc);
- sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->obmat[3]);
+ sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->object_to_world[3]);
invert_m3_m3(imat, mat);
mul_m3_v3(imat, r_primmat[3]);
@@ -2084,7 +2084,7 @@ static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op)
Object *curves_ob = ED_object_add_type(
C, OB_CURVES, nullptr, nullptr, nullptr, false, local_view_bits);
- BKE_object_apply_mat4(curves_ob, surface_ob->obmat, false, false);
+ BKE_object_apply_mat4(curves_ob, surface_ob->object_to_world, false, false);
/* Set surface object. */
Curves *curves_id = static_cast<Curves *>(curves_ob->data);
@@ -2561,8 +2561,8 @@ static void make_object_duplilist_real(bContext *C,
id_us_min((ID *)ob_dst->instance_collection);
ob_dst->instance_collection = nullptr;
- copy_m4_m4(ob_dst->obmat, dob->mat);
- BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
+ copy_m4_m4(ob_dst->object_to_world, dob->mat);
+ BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world, false, false);
BLI_ghash_insert(dupli_gh, dob, ob_dst);
if (parent_gh) {
@@ -3017,7 +3017,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
float loc[3], size[3], rot[3][3], eul[3];
float matrix[4][4];
- mat4_to_loc_rot_size(loc, rot, size, ob->obmat);
+ mat4_to_loc_rot_size(loc, rot, size, ob->object_to_world);
mat3_to_eul(eul, rot);
Object *ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits);
@@ -3556,11 +3556,62 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/** \name Duplicate Object Operator
* \{ */
+static void object_add_sync_base_collection(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new)
+{
+ if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) {
+ BKE_collection_object_add_from(bmain, scene, base_src->object, object_new);
+ }
+ else {
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, object_new);
+ }
+}
+
+static void object_add_sync_local_view(Base *base_src, Base *base_new)
+{
+ base_new->local_view_bits = base_src->local_view_bits;
+}
+
+static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new)
+{
+ /* 1) duplis should end up in same collection as the original
+ * 2) Rigid Body sim participants MUST always be part of a collection...
+ */
+ /* XXX: is 2) really a good measure here? */
+ if (object_src->rigidbody_object || object_src->rigidbody_constraint) {
+ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+ if (BKE_collection_has_object(collection, object_src)) {
+ BKE_collection_object_add(bmain, collection, object_new);
+ }
+ }
+ }
+}
+
/**
* - Assumes `id.new` is correct.
* - Leaves selection of base/object unaltered.
* - Sets #ID.newid pointers.
*/
+static void object_add_duplicate_internal(Main *bmain,
+ Object *ob,
+ const eDupli_ID_Flags dupflag,
+ const eLibIDDuplicateFlags duplicate_options,
+ Object **r_ob_new)
+{
+ if (ob->mode & OB_MODE_POSE) {
+ return;
+ }
+
+ Object *obn = static_cast<Object *>(
+ ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)));
+ if (r_ob_new) {
+ *r_ob_new = obn;
+ }
+ DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ return;
+}
+
static Base *object_add_duplicate_internal(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -3569,49 +3620,25 @@ static Base *object_add_duplicate_internal(Main *bmain,
const eLibIDDuplicateFlags duplicate_options,
Object **r_ob_new)
{
- Base *base, *basen = nullptr;
- Object *obn;
-
- if (ob->mode & OB_MODE_POSE) {
- /* nothing? */
+ Object *object_new = nullptr;
+ object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new);
+ if (r_ob_new) {
+ *r_ob_new = object_new;
+ }
+ if (object_new == nullptr) {
+ return nullptr;
}
- else {
- obn = static_cast<Object *>(
- ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)));
- if (r_ob_new) {
- *r_ob_new = obn;
- }
- DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- BKE_view_layer_synced_ensure(scene, view_layer);
- base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) {
- BKE_collection_object_add_from(bmain, scene, ob, obn);
- }
- else {
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
- BKE_collection_object_add(bmain, layer_collection->collection, obn);
- }
-
- BKE_view_layer_synced_ensure(scene, view_layer);
- basen = BKE_view_layer_base_find(view_layer, obn);
- if (base != nullptr && basen != nullptr) {
- basen->local_view_bits = base->local_view_bits;
- }
- /* 1) duplis should end up in same collection as the original
- * 2) Rigid Body sim participants MUST always be part of a collection...
- */
- /* XXX: is 2) really a good measure here? */
- if (ob->rigidbody_object || ob->rigidbody_constraint) {
- LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
- if (BKE_collection_has_object(collection, ob)) {
- BKE_collection_object_add(bmain, collection, obn);
- }
- }
- }
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ Base *base_src = BKE_view_layer_base_find(view_layer, ob);
+ object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new);
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ Base *base_new = BKE_view_layer_base_find(view_layer, object_new);
+ if (base_src && base_new) {
+ object_add_sync_local_view(base_src, base_new);
}
- return basen;
+ object_add_sync_rigid_body(bmain, ob, object_new);
+ return base_new;
}
Base *ED_object_add_duplicate(
@@ -3665,70 +3692,70 @@ static int duplicate_exec(bContext *C, wmOperator *op)
* we also want to remap pointers between those... */
BKE_main_id_newptr_and_tag_clear(bmain);
- /* Do not do collection re-syncs for each object; will do it once afterwards.
- * However this means we can't get to new duplicated Base's immediately, will
- * have to process them after the sync. */
- BKE_layer_collection_resync_forbid();
-
/* Duplicate the selected objects, remember data needed to process
- * after the sync (the base of the original object, and the copy of the
- * original object). */
- blender::Vector<std::pair<Base *, Object *>> source_bases_new_objects;
- Object *ob_new_active = nullptr;
+ * after the sync. */
+ struct DuplicateObjectLink {
+ Base *base_src = nullptr;
+ Object *object_new = nullptr;
+
+ DuplicateObjectLink(Base *base_src) : base_src(base_src)
+ {
+ }
+ };
+ blender::Vector<DuplicateObjectLink> object_base_links;
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
- Object *ob_new = nullptr;
+ object_base_links.append(DuplicateObjectLink(base));
+ }
+ CTX_DATA_END;
+
+ bool new_objects_created = false;
+ for (DuplicateObjectLink &link : object_base_links) {
object_add_duplicate_internal(bmain,
- scene,
- view_layer,
- base->object,
+ link.base_src->object,
dupflag,
LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID,
- &ob_new);
- if (ob_new == nullptr) {
- continue;
- }
- source_bases_new_objects.append({base, ob_new});
-
- /* note that this is safe to do with this context iterator,
- * the list is made in advance */
- ED_object_base_select(base, BA_DESELECT);
-
- /* new object will become active */
- BKE_view_layer_synced_ensure(scene, view_layer);
- if (BKE_view_layer_active_base_get(view_layer) == base) {
- ob_new_active = ob_new;
+ &link.object_new);
+ if (link.object_new) {
+ new_objects_created = true;
}
}
- CTX_DATA_END;
- BKE_layer_collection_resync_allow();
- if (source_bases_new_objects.is_empty()) {
+ if (!new_objects_created) {
return OPERATOR_CANCELLED;
}
- /* Sync the collection now, after everything is duplicated. */
- BKE_main_collection_sync(bmain);
+ /* Sync that could tag the view_layer out of sync. */
+ for (DuplicateObjectLink &link : object_base_links) {
+ /* note that this is safe to do with this context iterator,
+ * the list is made in advance */
+ ED_object_base_select(link.base_src, BA_DESELECT);
+ if (link.object_new) {
+ object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new);
+ object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new);
+ }
+ }
- /* After sync we can get to the new Base data, process it here. */
- for (const auto &item : source_bases_new_objects) {
- Object *ob_new = item.second;
- Base *base_source = item.first;
- BKE_view_layer_synced_ensure(scene, view_layer);
- Base *base_new = BKE_view_layer_base_find(view_layer, ob_new);
- if (base_new == nullptr) {
+ /* Sync the view layer. Everything else should not tag the view_layer out of sync. */
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ const Base *active_base = BKE_view_layer_active_base_get(view_layer);
+ for (DuplicateObjectLink &link : object_base_links) {
+ if (!link.object_new) {
continue;
}
+
+ Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new);
+ BLI_assert(base_new);
ED_object_base_select(base_new, BA_SELECT);
- if (ob_new == ob_new_active) {
+ if (active_base == link.base_src) {
ED_object_base_activate(C, base_new);
}
- if (base_new->object->data) {
- DEG_id_tag_update(static_cast<ID *>(base_new->object->data), 0);
+
+ if (link.object_new->data) {
+ DEG_id_tag_update(static_cast<ID *>(link.object_new->data), 0);
}
- /* #object_add_duplicate_internal will not have done this, since
- * before the collection sync it would not have found the new base yet. */
- base_new->local_view_bits = base_source->local_view_bits;
+
+ object_add_sync_local_view(link.base_src, base_new);
}
/* Note that this will also clear newid pointers and tags. */
@@ -3844,8 +3871,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op)
PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
if (RNA_property_is_set(op->ptr, prop_matrix)) {
Object *ob_add = basen->object;
- RNA_property_float_get_array(op->ptr, prop_matrix, &ob_add->obmat[0][0]);
- BKE_object_apply_mat4(ob_add, ob_add->obmat, true, true);
+ RNA_property_float_get_array(op->ptr, prop_matrix, &ob_add->object_to_world[0][0]);
+ BKE_object_apply_mat4(ob_add, ob_add->object_to_world, true, true);
DEG_id_tag_update(&ob_add->id, ID_RECALC_TRANSFORM);
}
@@ -3942,7 +3969,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op)
float mat_dst_unit[4][4];
float final_delta[4][4];
- normalize_m4_m4(mat_src_unit, ob->obmat);
+ normalize_m4_m4(mat_src_unit, ob->object_to_world);
normalize_m4_m4(mat_dst_unit, matrix);
invert_m4(mat_src_unit);
mul_m4_m4m4(final_delta, mat_dst_unit, mat_src_unit);
@@ -4097,7 +4124,7 @@ static int object_join_exec(bContext *C, wmOperator *op)
* If the zero scale is removed, the data on this axis remains un-scaled
* (something that wouldn't work for #invert_m4_m4_safe). */
float imat_test[4][4];
- if (!invert_m4_m4(imat_test, ob->obmat)) {
+ if (!invert_m4_m4(imat_test, ob->object_to_world)) {
BKE_report(op->reports,
RPT_WARNING,
"Active object final transform has one or more zero scaled axes");
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 781866db6a0..d05badc8fee 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -1518,10 +1518,10 @@ static int bake(const BakeAPIRender *bkr,
highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false);
/* Low-poly to high-poly transformation matrix. */
- copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
+ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->object_to_world);
invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
- highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
+ highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->object_to_world);
i++;
}
@@ -1540,18 +1540,19 @@ static int bake(const BakeAPIRender *bkr,
pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num,
"bake pixels high poly");
- if (!RE_bake_pixels_populate_from_objects(me_low_eval,
- pixel_array_low,
- pixel_array_high,
- highpoly,
- tot_highpoly,
- targets.pixels_num,
- ob_cage != NULL,
- bkr->cage_extrusion,
- bkr->max_ray_distance,
- ob_low_eval->obmat,
- (ob_cage ? ob_cage->obmat : ob_low_eval->obmat),
- me_cage_eval)) {
+ if (!RE_bake_pixels_populate_from_objects(
+ me_low_eval,
+ pixel_array_low,
+ pixel_array_high,
+ highpoly,
+ tot_highpoly,
+ targets.pixels_num,
+ ob_cage != NULL,
+ bkr->cage_extrusion,
+ bkr->max_ray_distance,
+ ob_low_eval->object_to_world,
+ (ob_cage ? ob_cage->object_to_world : ob_low_eval->object_to_world),
+ me_cage_eval)) {
BKE_report(reports, RPT_ERROR, "Error handling selected objects");
goto cleanup;
}
@@ -1629,7 +1630,7 @@ static int bake(const BakeAPIRender *bkr,
targets.result,
me_low_eval,
bkr->normal_swizzle,
- ob_low_eval->obmat);
+ ob_low_eval->object_to_world);
}
else {
/* From multi-resolution. */
@@ -1655,7 +1656,7 @@ static int bake(const BakeAPIRender *bkr,
targets.result,
(me_nores) ? me_nores : me_low_eval,
bkr->normal_swizzle,
- ob_low_eval->obmat);
+ ob_low_eval->object_to_world);
if (md) {
BKE_id_free(NULL, &me_nores->id);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index fa9ded0f989..1386da5dbde 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -2327,14 +2327,14 @@ static bool get_new_constraint_target(
/* Since by default, IK targets the tip of the last bone,
* use the tip of the active PoseChannel if adding a target for an IK Constraint. */
if (con_type == CONSTRAINT_TYPE_KINEMATIC) {
- mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail);
+ mul_v3_m4v3(obt->loc, obact->object_to_world, pchanact->pose_tail);
}
else {
- mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head);
+ mul_v3_m4v3(obt->loc, obact->object_to_world, pchanact->pose_head);
}
}
else {
- copy_v3_v3(obt->loc, obact->obmat[3]);
+ copy_v3_v3(obt->loc, obact->object_to_world[3]);
}
/* restore, BKE_object_add sets active */
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 27659042f50..63093692e43 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -535,7 +535,7 @@ static int add_hook_object(const bContext *C,
ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
/* transform cent to global coords for loc */
- mul_v3_m4v3(ob->loc, obedit->obmat, cent);
+ mul_v3_m4v3(ob->loc, obedit->object_to_world, cent);
}
md = obedit->modifiers.first;
@@ -556,13 +556,13 @@ static int add_hook_object(const bContext *C,
unit_m4(pose_mat);
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
if (mode == OBJECT_ADDHOOK_NEWOB) {
/* pass */
}
else {
/* may overwrite with pose-bone location, below */
- mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
+ mul_v3_m4v3(cent, obedit->imat, ob->object_to_world[3]);
}
if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
@@ -576,7 +576,7 @@ static int add_hook_object(const bContext *C,
pchan_act = BKE_pose_channel_active_if_layer_visible(ob);
if (LIKELY(pchan_act)) {
invert_m4_m4(pose_mat, pchan_act->pose_mat);
- mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
+ mul_v3_m4v3(cent, ob->object_to_world, pchan_act->pose_mat[3]);
mul_v3_m4v3(cent, obedit->imat, cent);
}
}
@@ -588,16 +588,16 @@ static int add_hook_object(const bContext *C,
copy_v3_v3(hmd->cent, cent);
/* matrix calculus */
- /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
+ /* vert x (obmat x hook->imat) x hook->object_to_world x ob->imat */
/* (parentinv ) */
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
BKE_object_transform_copy(object_eval, ob);
BKE_object_where_is_calc(depsgraph, scene_eval, object_eval);
- invert_m4_m4(object_eval->imat, object_eval->obmat);
+ invert_m4_m4(object_eval->imat, object_eval->object_to_world);
/* apparently this call goes from right to left... */
- mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->obmat);
+ mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->object_to_world);
DEG_relations_tag_update(bmain);
@@ -834,10 +834,10 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op)
}
/* recenter functionality */
- copy_m3_m4(bmat, ob->obmat);
+ copy_m3_m4(bmat, ob->object_to_world);
invert_m3_m3(imat, bmat);
- sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
+ sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->object_to_world[3]);
mul_m3_v3(imat, hmd->cent);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 5da19d76259..10068def991 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -272,7 +272,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
/* inverse parent matrix */
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
else {
ob->partype = PARVERT1;
@@ -280,7 +280,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
/* inverse parent matrix */
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
}
}
@@ -401,7 +401,7 @@ void ED_object_parent_clear(Object *ob, const int type)
/* remove parent, and apply the parented transform
* result as object's local transforms */
ob->parent = NULL;
- BKE_object_apply_mat4(ob, ob->obmat, true, false);
+ BKE_object_apply_mat4(ob, ob->object_to_world, true, false);
break;
}
case CLEAR_PARENT_INVERSE: {
@@ -584,7 +584,7 @@ bool ED_object_parent_set(ReportList *reports,
if (keep_transform) {
/* Was removed because of bug T23577,
* but this can be handy in some cases too T32616, so make optional. */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ BKE_object_apply_mat4(ob, ob->object_to_world, false, false);
}
/* Set the parent (except for follow-path constraint option). */
@@ -706,7 +706,7 @@ bool ED_object_parent_set(ReportList *reports,
BKE_constraint_target_matrix_get(
depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
- sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
+ sub_v3_v3v3(vec, ob->object_to_world[3], cmat[3]);
copy_v3_v3(ob->loc, vec);
}
@@ -729,7 +729,7 @@ bool ED_object_parent_set(ReportList *reports,
ob->partype = PAROBJECT;
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
else if (is_armature_parent && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
if (partype == PAR_ARMATURE) {
@@ -747,7 +747,7 @@ bool ED_object_parent_set(ReportList *reports,
ob->partype = PAROBJECT;
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
else if ((ob->type == OB_GPENCIL) && (par->type == OB_LATTICE)) {
/* Add Lattice modifier */
@@ -758,12 +758,12 @@ bool ED_object_parent_set(ReportList *reports,
ob->partype = PAROBJECT;
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
else {
/* calculate inverse parent matrix */
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
}
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -772,7 +772,7 @@ bool ED_object_parent_set(ReportList *reports,
static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
{
- const float *co_find = child->obmat[3];
+ const float *co_find = child->object_to_world[3];
if (is_tri) {
KDTreeNearest_3d nearest[3];
int tot;
@@ -1186,7 +1186,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
}
if (type == CLEAR_TRACK_KEEP_TRANSFORM) {
- BKE_object_apply_mat4(ob, ob->obmat, true, true);
+ BKE_object_apply_mat4(ob, ob->object_to_world, true, true);
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc
index 8358bf632d3..c653610d6fe 100644
--- a/source/blender/editors/object/object_remesh.cc
+++ b/source/blender/editors/object/object_remesh.cc
@@ -296,7 +296,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion * /*ar*/, void *arg)
uint pos3d = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_matrix_push();
- GPU_matrix_mul(cd->active_object->obmat);
+ GPU_matrix_mul(cd->active_object->object_to_world);
/* Draw Rect */
immUniformColor4f(0.9f, 0.9f, 0.9f, 0.8f);
@@ -494,7 +494,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
float view_normal[3] = {0.0f, 0.0f, 1.0f};
/* Calculate the view normal. */
- invert_m4_m4(active_object->imat, active_object->obmat);
+ invert_m4_m4(active_object->imat, active_object->object_to_world);
copy_m3_m4(mat, rv3d->viewinv);
mul_m3_v3(mat, view_normal);
copy_m3_m4(mat, active_object->imat);
@@ -535,7 +535,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
/* Project the selected face in the previous step of the Bounding Box. */
for (int i = 0; i < 4; i++) {
float preview_plane_world_space[3];
- mul_v3_m4v3(preview_plane_world_space, active_object->obmat, cd->preview_plane[i]);
+ mul_v3_m4v3(preview_plane_world_space, active_object->object_to_world, cd->preview_plane[i]);
ED_view3d_project_v2(region, preview_plane_world_space, preview_plane_proj[i]);
}
@@ -582,7 +582,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
/* Invert object scale. */
float scale[3];
- mat4_to_size(scale, active_object->obmat);
+ mat4_to_size(scale, active_object->object_to_world);
invert_v3(scale);
size_to_mat4(scale_mat, scale);
@@ -593,7 +593,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
/* Scale the text to constant viewport size. */
float text_pos_word_space[3];
- mul_v3_m4v3(text_pos_word_space, active_object->obmat, text_pos);
+ mul_v3_m4v3(text_pos_word_space, active_object->object_to_world, text_pos);
const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos_word_space);
scale_m4_fl(scale_mat, pixelsize * 0.5f);
mul_m4_m4_post(cd->text_mat, scale_mat);
diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc
index 6604e3da4d2..a863e9ac324 100644
--- a/source/blender/editors/object/object_transform.cc
+++ b/source/blender/editors/object/object_transform.cc
@@ -527,9 +527,9 @@ static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Ob
LISTBASE_FOREACH (Object *, ob_child, &bmain->objects) {
if (ob_child->parent == ob) {
Object *ob_child_eval = DEG_get_evaluated_object(depsgraph, ob_child);
- BKE_object_apply_mat4(ob_child_eval, ob_child_eval->obmat, true, false);
+ BKE_object_apply_mat4(ob_child_eval, ob_child_eval->object_to_world, true, false);
BKE_object_workob_calc_parent(depsgraph, scene, ob_child_eval, &workob);
- invert_m4_m4(ob_child->parentinv, workob.obmat);
+ invert_m4_m4(ob_child->parentinv, workob.object_to_world);
/* Copy result of BKE_object_apply_mat4(). */
BKE_object_transform_copy(ob_child, ob_child_eval);
/* Make sure evaluated object is in a consistent state with the original one.
@@ -660,11 +660,11 @@ static int apply_objects_internal(bContext *C,
if (do_multi_user) {
obact = CTX_data_active_object(C);
- invert_m4_m4(obact_invmat, obact->obmat);
+ invert_m4_m4(obact_invmat, obact->object_to_world);
Object workob;
BKE_object_workob_calc_parent(depsgraph, scene, obact, &workob);
- copy_m4_m4(obact_parent, workob.obmat);
+ copy_m4_m4(obact_parent, workob.object_to_world);
copy_m4_m4(obact_parentinv, obact->parentinv);
if (apply_objects_internal_need_single_user(C)) {
@@ -989,7 +989,7 @@ static int apply_objects_internal(bContext *C,
float _obmat[4][4], _iobmat[4][4];
float _mat[4][4];
- copy_m4_m4(_obmat, ob->obmat);
+ copy_m4_m4(_obmat, ob->object_to_world);
invert_m4_m4(_iobmat, _obmat);
copy_m4_m4(_mat, _obmat);
@@ -1075,7 +1075,7 @@ static int visual_transform_apply_exec(bContext *C, wmOperator * /*op*/)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
BKE_object_where_is_calc(depsgraph, scene, ob_eval);
- BKE_object_apply_mat4(ob_eval, ob_eval->obmat, true, true);
+ BKE_object_apply_mat4(ob_eval, ob_eval->object_to_world, true, true);
BKE_object_transform_copy(ob, ob_eval);
/* update for any children that may get moved */
@@ -1274,7 +1274,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (centermode == ORIGIN_TO_CURSOR) {
copy_v3_v3(cent, cursor);
- invert_m4_m4(obedit->imat, obedit->obmat);
+ invert_m4_m4(obedit->imat, obedit->object_to_world);
mul_m4_v3(obedit->imat, cent);
}
else {
@@ -1342,7 +1342,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (centermode == ORIGIN_TO_CURSOR) {
copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_v3(ob->imat, cent);
}
@@ -1363,7 +1363,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
INIT_MINMAX(min, max);
BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true);
mid_v3_v3v3(cent, min, max);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_v3(ob->imat, cent);
}
@@ -1554,7 +1554,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (centermode == ORIGIN_TO_GEOMETRY) {
zero_v3(gpcenter);
BKE_gpencil_centroid_3d(gpd, gpcenter);
- add_v3_v3(gpcenter, ob->obmat[3]);
+ add_v3_v3(gpcenter, ob->object_to_world[3]);
}
if (centermode == ORIGIN_TO_CURSOR) {
copy_v3_v3(gpcenter, cursor);
@@ -1566,8 +1566,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
float offset_local[3];
int i;
- sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
- copy_m3_m4(bmat, obact->obmat);
+ sub_v3_v3v3(offset_global, gpcenter, ob->object_to_world[3]);
+ copy_m3_m4(bmat, obact->object_to_world);
invert_m3_m3(imat, bmat);
mul_m3_v3(imat, offset_global);
mul_v3_m3v3(offset_local, imat, offset_global);
@@ -1699,7 +1699,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
ob_other->flag |= OB_DONE;
DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
+ mul_v3_mat3_m4v3(centn, ob_other->object_to_world, cent); /* omit translation part */
add_v3_v3(ob_other->loc, centn);
Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
@@ -1873,9 +1873,9 @@ static void object_transform_axis_target_calc_depth_init(XFormAxisData *xfd, con
int center_tot = 0;
for (XFormAxisItem &item : xfd->object_data) {
const Object *ob = item.ob;
- const float *ob_co_a = ob->obmat[3];
+ const float *ob_co_a = ob->object_to_world[3];
float ob_co_b[3];
- add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
+ add_v3_v3v3(ob_co_b, ob->object_to_world[3], ob->object_to_world[2]);
float view_isect[3], ob_isect[3];
if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
add_v3_v3(center, view_isect);
@@ -1946,7 +1946,7 @@ static void object_apply_location(Object *ob, const float loc[3])
/* quick but weak */
Object ob_prev = blender::dna::shallow_copy(*ob);
float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
copy_v3_v3(mat[3], loc);
BKE_object_apply_mat4(ob, mat, true, true);
copy_v3_v3(mat[3], ob->loc);
@@ -1961,7 +1961,7 @@ static bool object_orient_to_location(Object *ob,
const bool z_flip)
{
float delta[3];
- sub_v3_v3v3(delta, ob->obmat[3], location);
+ sub_v3_v3v3(delta, ob->object_to_world[3], location);
if (normalize_v3(delta) != 0.0f) {
if (z_flip) {
negate_v3(delta);
@@ -2139,7 +2139,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
float xform_rot_offset_inv_first[3][3];
for (const int i : xfd->object_data.index_range()) {
XFormAxisItem &item = xfd->object_data[i];
- copy_m3_m4(item.xform_rot_offset, item.ob->obmat);
+ copy_m3_m4(item.xform_rot_offset, item.ob->object_to_world);
normalize_m3(item.xform_rot_offset);
if (i == 0) {
@@ -2158,8 +2158,8 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
XFormAxisItem &item = xfd->object_data[i];
if (is_translate_init) {
float ob_axis[3];
- item.xform_dist = len_v3v3(item.ob->obmat[3], location_world);
- normalize_v3_v3(ob_axis, item.ob->obmat[2]);
+ item.xform_dist = len_v3v3(item.ob->object_to_world[3], location_world);
+ normalize_v3_v3(ob_axis, item.ob->object_to_world[2]);
/* Scale to avoid adding distance when moving between surfaces. */
if (normal_found) {
float scale = fabsf(dot_v3v3(ob_axis, normal));
@@ -2173,7 +2173,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
copy_v3_v3(target_normal, normal);
}
else {
- normalize_v3_v3(target_normal, item.ob->obmat[2]);
+ normalize_v3_v3(target_normal, item.ob->object_to_world[2]);
}
#ifdef USE_RELATIVE_ROTATION
@@ -2190,7 +2190,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
madd_v3_v3fl(loc, target_normal, item.xform_dist);
object_apply_location(item.ob, loc);
/* so orient behaves as expected */
- copy_v3_v3(item.ob->obmat[3], loc);
+ copy_v3_v3(item.ob->object_to_world[3], loc);
}
object_orient_to_location(
diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c
index 50ba5b8af5f..1387282357f 100644
--- a/source/blender/editors/object/object_utils.c
+++ b/source/blender/editors/object/object_utils.c
@@ -114,20 +114,20 @@ bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_ce
{
if (ob->mode & OB_MODE_EDIT) {
if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
+ mul_m4_v3(ob->object_to_world, r_center);
return true;
}
return false;
}
if (ob->mode & OB_MODE_POSE) {
if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
+ mul_m4_v3(ob->object_to_world, r_center);
return true;
}
return false;
}
if (!select_only || (ob->base_flag & BASE_SELECTED)) {
- copy_v3_v3(r_center, ob->obmat[3]);
+ copy_v3_v3(r_center, ob->object_to_world[3]);
return true;
}
return false;
@@ -245,11 +245,11 @@ void ED_object_xform_skip_child_container_item_ensure(struct XFormObjectSkipChil
if (!BLI_ghash_ensure_p(xcs->obchild_in_obmode_map, ob, &xf_p)) {
struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__);
copy_m4_m4(xf->parentinv_orig, ob->parentinv);
- copy_m4_m4(xf->obmat_orig, ob->obmat);
- copy_m4_m4(xf->parent_obmat_orig, ob->parent->obmat);
- invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->obmat);
+ copy_m4_m4(xf->obmat_orig, ob->object_to_world);
+ copy_m4_m4(xf->parent_obmat_orig, ob->parent->object_to_world);
+ invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->object_to_world);
if (ob_parent_recurse) {
- copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->obmat);
+ copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->object_to_world);
}
xf->mode = mode;
xf->ob_parent_recurse = ob_parent_recurse;
@@ -274,14 +274,14 @@ void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild
if (xf->mode == XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM) {
/* Parent is transformed, this isn't so compensate. */
Object *ob_parent_eval = DEG_get_evaluated_object(depsgraph, ob->parent);
- mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat);
+ mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->object_to_world);
invert_m4(dmat);
}
else if (xf->mode == XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT) {
/* Calculate parent matrix (from the root transform). */
Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse);
float parent_recurse_obmat_inv[4][4];
- invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
+ invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->object_to_world);
mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
invert_m4(dmat);
float parent_obmat_calc[4][4];
@@ -296,7 +296,7 @@ void ED_object_xform_skip_child_container_update_all(struct XFormObjectSkipChild
/* Transform this - without transform data. */
Object *ob_parent_recurse_eval = DEG_get_evaluated_object(depsgraph, xf->ob_parent_recurse);
float parent_recurse_obmat_inv[4][4];
- invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
+ invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->object_to_world);
mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
invert_m4(dmat);
float obmat_calc[4][4];
@@ -350,7 +350,7 @@ void ED_object_data_xform_container_item_ensure(struct XFormObjectData_Container
void **xf_p;
if (!BLI_ghash_ensure_p(xds->obdata_in_obmode_map, ob->data, &xf_p)) {
struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
- copy_m4_m4(xf->obmat_orig, ob->obmat);
+ copy_m4_m4(xf->obmat_orig, ob->object_to_world);
xf->ob = ob;
/* Result may be NULL, that's OK. */
xf->xod = ED_object_data_xform_create(ob->data);
@@ -378,7 +378,7 @@ void ED_object_data_xform_container_update_all(struct XFormObjectData_Container
Object *ob_eval = DEG_get_evaluated_object(depsgraph, xf->ob);
float imat[4][4], dmat[4][4];
invert_m4_m4(imat, xf->obmat_orig);
- mul_m4_m4m4(dmat, imat, ob_eval->obmat);
+ mul_m4_m4m4(dmat, imat, ob_eval->object_to_world);
invert_m4(dmat);
ED_object_data_xform_by_mat4(xf->xod, dmat);
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index a1d53cadd06..d1e6e7000d9 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -38,7 +38,7 @@ static void object_warp_calc_view_matrix(float r_mat_view[4][4],
mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
/* apply the view and the object matrix */
- mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat);
+ mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->object_to_world);
/* get the view-space cursor */
mul_v3_m4v3(r_center_view, viewmat_roll, center);
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index e6d0aca7902..6dc3860fdf2 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3930,7 +3930,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance)
copy_v3_v3(co_root, co);
copy_v3_v3(no_root, &edit->emitter_cosnos[point_index * 6 + 3]);
- mul_mat3_m4_v3(data->ob->obmat, no_root); /* normal into global-space */
+ mul_mat3_m4_v3(data->ob->object_to_world, no_root); /* normal into global-space */
normalize_v3(no_root);
if (puff_volume) {
@@ -4016,8 +4016,8 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance)
point_index = BLI_kdtree_3d_find_nearest(edit->emitter_field, kco, NULL);
if (point_index != -1) {
copy_v3_v3(onor, &edit->emitter_cosnos[point_index * 6 + 3]);
- mul_mat3_m4_v3(data->ob->obmat, onor); /* Normal into world-space. */
- mul_mat3_m4_v3(imat, onor); /* World-space into particle-space. */
+ mul_mat3_m4_v3(data->ob->object_to_world, onor); /* Normal into world-space. */
+ mul_mat3_m4_v3(imat, onor); /* World-space into particle-space. */
normalize_v3(onor);
}
else {
@@ -4412,7 +4412,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
short size = pset->brush[PE_BRUSH_ADD].size;
RNG *rng;
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
if (psys->flag & PSYS_GLOBAL_HAIR) {
return 0;
@@ -4797,7 +4797,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.combfac = 1.0f - data.combfac;
}
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
ED_view3d_win_to_delta(region, xy_delta, bedit->zfac, vec);
data.dvec = vec;
@@ -4865,7 +4865,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
}
data.invert = (brush->invert ^ flip);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
foreach_mouse_hit_point(&data, brush_puff, selected);
}
@@ -4895,7 +4895,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.smoothfac = brush->strength;
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
foreach_mouse_hit_key(&data, brush_smooth_get, selected);
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 210757173eb..852156f9403 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -726,8 +726,8 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
edit_point = target_edit ? target_edit->points : NULL;
- invert_m4_m4(from_ob_imat, ob->obmat);
- invert_m4_m4(to_ob_imat, target_ob->obmat);
+ invert_m4_m4(from_ob_imat, ob->object_to_world);
+ invert_m4_m4(to_ob_imat, target_ob->object_to_world);
invert_m4_m4(from_imat, from_mat);
invert_m4_m4(to_imat, to_mat);
@@ -843,7 +843,7 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
float offset[3];
if (to_global) {
- copy_m4_m4(imat, target_ob->obmat);
+ copy_m4_m4(imat, target_ob->object_to_world);
}
else {
/* NOTE: using target_dm here, which is in target_ob object space and has full modifiers.
@@ -923,8 +923,8 @@ static bool connect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, Particl
ob,
psys,
psys->edit,
- ob->obmat,
- ob->obmat,
+ ob->object_to_world,
+ ob->object_to_world,
psys->flag & PSYS_GLOBAL_HAIR,
false);
if (ok) {
@@ -1174,8 +1174,8 @@ static bool copy_particle_systems_to_object(const bContext *C,
to_mat = I;
break;
case PAR_COPY_SPACE_WORLD:
- from_mat = ob_from->obmat;
- to_mat = ob_to->obmat;
+ from_mat = ob_from->object_to_world;
+ to_mat = ob_to->object_to_world;
break;
default:
/* should not happen */
diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc
index 140199209da..5aae48b1138 100644
--- a/source/blender/editors/render/render_preview.cc
+++ b/source/blender/editors/render/render_preview.cc
@@ -785,7 +785,7 @@ static Object *object_preview_camera_create(Main *preview_main,
float rotmat[3][3];
float dummyscale[3];
- mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat);
+ mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->object_to_world);
/* Camera is Y up, so needs additional rotations to obliquely face the front. */
float drotmat[3][3];
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 39e3c7a2f0a..a62e027ba03 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -147,7 +147,7 @@ void ED_region_do_listen(wmRegionListenerParams *params)
}
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
- UI_block_views_listen(block, params);
+ UI_block_listen(block, params);
}
LISTBASE_FOREACH (uiList *, list, &region->ui_lists) {
@@ -187,7 +187,8 @@ static void area_draw_azone_fullscreen(
min_ff(alpha, 0.75f),
0.0f,
NULL,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/**
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
index e276bae6697..8172eb8a5d7 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
@@ -185,7 +185,7 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
/* Shorten ray when the surface object is hit. */
if (surface_object_eval != nullptr) {
- const float4x4 surface_to_world_mat = surface_object->obmat;
+ const float4x4 surface_to_world_mat = surface_object->object_to_world;
const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
Mesh *surface_eval = BKE_object_get_evaluated_mesh(surface_object_eval);
@@ -218,7 +218,7 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
}
}
- const float4x4 curves_to_world_mat = curves_object.obmat;
+ const float4x4 curves_to_world_mat = curves_object.object_to_world;
const float4x4 world_to_curves_mat = curves_to_world_mat.inverted();
const float3 center_ray_start_cu = world_to_curves_mat * center_ray_start_wo;
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
index 6366da310b6..df7dd871a94 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
@@ -220,8 +220,10 @@ static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEven
int return_value = op->type->modal(C, op, event);
if (return_value == OPERATOR_FINISHED) {
- paint_stroke_free(C, op, op_data->stroke);
- MEM_delete(op_data);
+ if (op->customdata != nullptr) {
+ paint_stroke_free(C, op, op_data->stroke);
+ MEM_delete(op_data);
+ }
return OPERATOR_FINISHED;
}
@@ -236,16 +238,19 @@ static int sculpt_curves_stroke_modal(bContext *C, wmOperator *op, const wmEvent
int return_value = paint_stroke_modal(C, op, event, &op_data->stroke);
if (ELEM(return_value, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
MEM_delete(op_data);
+ op->customdata = nullptr;
}
return return_value;
}
static void sculpt_curves_stroke_cancel(bContext *C, wmOperator *op)
{
- SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>(
- op->customdata);
- paint_stroke_cancel(C, op, op_data->stroke);
- MEM_delete(op_data);
+ if (op->customdata != nullptr) {
+ SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>(
+ op->customdata);
+ paint_stroke_cancel(C, op, op_data->stroke);
+ MEM_delete(op_data);
+ }
}
static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
@@ -786,7 +791,7 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
});
});
- float4x4 curves_to_world_mat = curves_ob.obmat;
+ float4x4 curves_to_world_mat = curves_ob.object_to_world;
float4x4 world_to_curves_mat = curves_to_world_mat.inverted();
float4x4 projection;
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 71ec444098e..b85b878af7d 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1071,7 +1071,7 @@ static void cursor_draw_tiling_preview(const uint gpuattr,
for (int dim = 0; dim < 3; dim++) {
location[dim] = cur[dim] * step[dim] + orgLoc[dim];
}
- cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3);
}
}
}
@@ -1092,7 +1092,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
/* Axis Symmetry. */
flip_v3_v3(location, true_location, (char)i);
- cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3);
/* Tiling. */
cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
@@ -1107,7 +1107,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
mul_m4_v3(symm_rot_mat, location);
cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
- cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3);
}
}
}
@@ -1334,7 +1334,7 @@ static void paint_cursor_update_pixel_radius(PaintCursorContext *pcontext)
}
copy_v3_v3(pcontext->scene_space_location, pcontext->location);
- mul_m4_v3(pcontext->vc.obact->obmat, pcontext->scene_space_location);
+ mul_m4_v3(pcontext->vc.obact->object_to_world, pcontext->scene_space_location);
}
else {
Sculpt *sd = CTX_data_tool_settings(pcontext->C)->sculpt;
@@ -1464,7 +1464,7 @@ static void paint_cursor_drawing_setup_cursor_space(PaintCursorContext *pcontext
float cursor_trans[4][4], cursor_rot[4][4];
const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
float quat[4];
- copy_m4_m4(cursor_trans, pcontext->vc.obact->obmat);
+ copy_m4_m4(cursor_trans, pcontext->vc.obact->object_to_world);
translate_m4(cursor_trans, pcontext->location[0], pcontext->location[1], pcontext->location[2]);
rotation_between_vecs_to_quat(quat, z_axis, pcontext->normal);
quat_to_mat4(cursor_rot, quat);
@@ -1508,7 +1508,7 @@ static void paint_cursor_pose_brush_origins_draw(PaintCursorContext *pcontext)
cursor_draw_point_screen_space(pcontext->pos,
pcontext->region,
ss->pose_ik_chain_preview->segments[i].initial_orig,
- pcontext->vc.obact->obmat,
+ pcontext->vc.obact->object_to_world,
3);
}
}
@@ -1526,7 +1526,7 @@ static void paint_cursor_preview_boundary_data_pivot_draw(PaintCursorContext *pc
pcontext->pos,
pcontext->region,
SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->boundary_preview->pivot_vertex),
- pcontext->vc.obact->obmat,
+ pcontext->vc.obact->object_to_world,
3);
}
@@ -1634,7 +1634,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
pcontext->pos,
pcontext->region,
SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->expand_cache->initial_active_vertex),
- pcontext->vc.obact->obmat,
+ pcontext->vc.obact->object_to_world,
2);
}
@@ -1656,7 +1656,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
NULL);
GPU_matrix_push();
- GPU_matrix_mul(pcontext->vc.obact->obmat);
+ GPU_matrix_mul(pcontext->vc.obact->object_to_world);
/* Drawing Cursor overlays in 3D object space. */
if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_GRAB &&
@@ -1747,7 +1747,7 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont
NULL,
NULL);
GPU_matrix_push();
- GPU_matrix_mul(pcontext->vc.obact->obmat);
+ GPU_matrix_mul(pcontext->vc.obact->object_to_world);
/* Draw the special active cursors different tools may have. */
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 22d6626ab16..26f76d46f85 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -44,7 +44,7 @@ bool paint_curve_poll(bContext *C)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
SpaceImage *sima;
- if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0))) {
+ if (rv3d && !(ob && ((ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_SCULPT_CURVES)) != 0))) {
return false;
}
@@ -676,6 +676,9 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
case PAINT_MODE_SCULPT:
name = "SCULPT_OT_brush_stroke";
break;
+ case PAINT_MODE_SCULPT_CURVES:
+ name = "SCULPT_CURVES_OT_brush_stroke";
+ break;
default:
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 79316361e53..b7ce4b2973c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -402,7 +402,8 @@ static ImBuf *brush_painter_imbuf_new(
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
+ const MTex *mtex = &brush->mtex;
+ BKE_brush_sample_tex_3d(scene, brush, mtex, texco, rgba, thread, pool);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
@@ -446,6 +447,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
+ const MTex *mtex = &brush->mtex;
BrushPainterCache *cache = &tile->cache;
const char *display_device = scene->display_settings.display_device;
@@ -485,7 +487,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
if (!use_texture_old) {
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
+ BKE_brush_sample_tex_3d(scene, brush, mtex, texco, rgba, thread, pool);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 41d5090b38c..ea33449f0dd 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3684,7 +3684,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet
ps->viewDir[1] = 0.0f;
ps->viewDir[2] = 1.0f;
- copy_m4_m4(ps->obmat, ps->ob->obmat);
+ copy_m4_m4(ps->obmat, ps->ob->object_to_world);
if (symmetry_flag) {
int i;
@@ -3742,7 +3742,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet
CameraParams params;
/* viewmat & viewinv */
- copy_m4_m4(viewinv, cam_ob_eval->obmat);
+ copy_m4_m4(viewinv, cam_ob_eval->object_to_world);
normalize_m4(viewinv);
invert_m4_m4(viewmat, viewinv);
@@ -4462,7 +4462,7 @@ static void project_paint_begin(const bContext *C,
if (ps->source == PROJ_SRC_VIEW) {
/* faster clipping lookups */
- ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat);
+ ED_view3d_clipping_local(ps->rv3d, ps->ob->object_to_world);
}
ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
@@ -5370,7 +5370,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
/* Color texture (alpha used as mask). */
if (ps->is_texbrush) {
- MTex *mtex = &brush->mtex;
+ const MTex *mtex = BKE_brush_color_texture_get(brush, OB_MODE_TEXTURE_PAINT);
float samplecos[3];
float texrgba[4];
@@ -5386,7 +5386,8 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
/* NOTE: for clone and smear,
* we only use the alpha, could be a special function */
- BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool);
+ BKE_brush_sample_tex_3d(
+ ps->scene, brush, mtex, samplecos, texrgba, thread_index, pool);
copy_v3_v3(texrgb, texrgba);
custom_mask *= texrgba[3];
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 571ebd79764..c3e3109ac87 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -1009,11 +1009,12 @@ static void sculpt_gesture_trim_shape_origin_normal_get(SculptGestureContext *sg
copy_v3_v3(r_normal, sgcontext->world_space_view_normal);
break;
case SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE:
- mul_v3_m4v3(r_origin, sgcontext->vc.obact->obmat, sgcontext->ss->gesture_initial_location);
+ mul_v3_m4v3(
+ r_origin, sgcontext->vc.obact->object_to_world, sgcontext->ss->gesture_initial_location);
/* Transforming the normal does not take non uniform scaling into account. Sculpt mode is not
* expected to work on object with non uniform scaling. */
copy_v3_v3(r_normal, sgcontext->ss->gesture_initial_normal);
- mul_mat3_m4_v3(sgcontext->vc.obact->obmat, r_normal);
+ mul_mat3_m4_v3(sgcontext->vc.obact->object_to_world, r_normal);
break;
}
}
@@ -1044,7 +1045,7 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext)
* mesh, coordinates are first calculated in world space, then converted to object space to
* store them. */
float world_space_vco[3];
- mul_v3_m4v3(world_space_vco, vc->obact->obmat, vco);
+ mul_v3_m4v3(world_space_vco, vc->obact->object_to_world, vco);
const float dist = dist_signed_to_plane_v3(world_space_vco, shape_plane);
trim_operation->depth_front = min_ff(dist, trim_operation->depth_front);
trim_operation->depth_back = max_ff(dist, trim_operation->depth_back);
@@ -1052,8 +1053,9 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext)
if (trim_operation->use_cursor_depth) {
float world_space_gesture_initial_location[3];
- mul_v3_m4v3(
- world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location);
+ mul_v3_m4v3(world_space_gesture_initial_location,
+ vc->obact->object_to_world,
+ ss->gesture_initial_location);
float mid_point_depth;
if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) {
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index bc4c6dc4148..a70924b0626 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -564,7 +564,7 @@ static void paint_brush_stroke_add_step(
if (SCULPT_stroke_get_location(
C, world_space_position, stroke->last_mouse_position, stroke->original)) {
copy_v3_v3(stroke->last_world_space_position, world_space_position);
- mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position);
}
else {
add_v3_v3(stroke->last_world_space_position, stroke->last_scene_spacing_delta);
@@ -825,7 +825,7 @@ static int paint_space_stroke(bContext *C,
if (use_scene_spacing) {
float world_space_position[3];
bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position);
if (hit && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position);
length = len_v3(d_world_space_position);
@@ -1216,8 +1216,8 @@ static void paint_line_strokes_spacing(bContext *C,
C, world_space_position_old, old_pos, stroke->original);
bool hit_new = SCULPT_stroke_get_location(
C, world_space_position_new, new_pos, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, world_space_position_old);
- mul_m4_v3(stroke->vc.obact->obmat, world_space_position_new);
+ mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position_old);
+ mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position_new);
if (hit_old && hit_new && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position_new, world_space_position_old);
length = len_v3(d_world_space_position);
@@ -1360,7 +1360,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
if (paint_stroke_use_scene_spacing(br, BKE_paintmode_get_active_from_context(C))) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, data + 2 * j, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position);
}
stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
@@ -1492,7 +1492,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
if (paint_stroke_use_scene_spacing(br, mode)) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, sample_average.mouse, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position);
}
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index ce4a5151a20..f87ca073c82 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -135,12 +135,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
float delta[3], scale, loc[3];
const float xy_delta[2] = {pixel_radius, 0.0f};
- mul_v3_m4v3(loc, ob->obmat, center);
+ mul_v3_m4v3(loc, ob->object_to_world, center);
const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc);
ED_view3d_win_to_delta(vc->region, xy_delta, zfac, delta);
- scale = fabsf(mat4_to_scale(ob->obmat));
+ scale = fabsf(mat4_to_scale(ob->object_to_world));
scale = (scale == 0.0f) ? 1.0f : scale;
return len_v3(delta) / scale;
@@ -297,7 +297,7 @@ static void imapaint_pick_uv(
GPU_matrix_model_view_get(matrix);
GPU_matrix_projection_get(proj);
view[0] = view[1] = 0;
- mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
+ mul_m4_m4m4(matrix, matrix, ob_eval->object_to_world);
mul_m4_m4m4(matrix, proj, matrix);
minabsw = 1e10;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc
index 6e3504332ed..ac5ad62c91f 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex.cc
@@ -433,9 +433,10 @@ static void paint_and_tex_color_alpha_intern(VPaint *vp,
float r_rgba[4])
{
const Brush *brush = BKE_paint_brush(&vp->paint);
- BLI_assert(brush->mtex.tex != nullptr);
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
- BKE_brush_sample_tex_3d(vc->scene, brush, co, r_rgba, 0, nullptr);
+ const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
+ BLI_assert(mtex->tex != nullptr);
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
+ BKE_brush_sample_tex_3d(vc->scene, brush, mtex, co, r_rgba, 0, nullptr);
}
else {
float co_ss[2]; /* screenspace */
@@ -445,7 +446,7 @@ static void paint_and_tex_color_alpha_intern(VPaint *vp,
co_ss,
(eV3DProjTest)(V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR)) == V3D_PROJ_RET_OK) {
const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */
- BKE_brush_sample_tex_3d(vc->scene, brush, co_ss_3d, r_rgba, 0, nullptr);
+ BKE_brush_sample_tex_3d(vc->scene, brush, mtex, co_ss_3d, r_rgba, 0, nullptr);
}
else {
zero_v4(r_rgba);
@@ -1646,7 +1647,7 @@ static void vwpaint_update_cache_invariants(
/* cache projection matrix */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
copy_m3_m4(mat, cache->vc->rv3d->viewinv);
mul_m3_v3(mat, view_dir);
copy_m3_m4(mat, ob->imat);
@@ -2517,7 +2518,7 @@ static void wpaint_stroke_update_step(bContext *C,
ED_view3d_init_mats_rv3d(ob, vc->rv3d);
/* load projection matrix */
- mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
+ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->object_to_world);
Mesh *mesh = static_cast<Mesh *>(ob->data);
@@ -2555,7 +2556,7 @@ static void wpaint_stroke_update_step(bContext *C,
/* Calculate pivot for rotation around selection if needed.
* also needed for "Frame Selected" on last stroke. */
float loc_world[3];
- mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
+ mul_v3_m4v3(loc_world, ob->object_to_world, ss->cache->true_location);
paint_last_stroke_update(scene, loc_world);
BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
@@ -3846,7 +3847,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P
ED_view3d_init_mats_rv3d(ob, vc->rv3d);
/* load projection matrix */
- mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
+ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->object_to_world);
swap_m4m4(vc->rv3d->persmat, mat);
@@ -3869,7 +3870,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P
/* Calculate pivot for rotation around selection if needed.
* also needed for "Frame Selected" on last stroke. */
float loc_world[3];
- mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
+ mul_v3_m4v3(loc_world, ob->object_to_world, ss->cache->true_location);
paint_last_stroke_update(scene, loc_world);
ED_region_tag_redraw(vc->region);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 0f71acd3698..24c6f1b0c3d 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1121,8 +1121,8 @@ void SCULPT_tag_update_overlays(bContext *C)
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
- View3D *v3d = CTX_wm_view3d(C);
- if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
}
@@ -2458,7 +2458,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
- const MTex *mtex = &br->mtex;
+ const MTex *mtex = BKE_brush_mask_texture_get(br, OB_MODE_SCULPT);
float avg = 1.0f;
float rgba[4];
float point[3];
@@ -2470,7 +2470,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
/* Get strength by feeding the vertex location directly into a texture. */
- avg = BKE_brush_sample_tex_3d(scene, br, point, rgba, 0, ss->tex_pool);
+ avg = BKE_brush_sample_tex_3d(scene, br, mtex, point, rgba, 0, ss->tex_pool);
}
else {
float symm_point[3], point_2d[2];
@@ -2499,19 +2499,19 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
x = symm_point[0];
y = symm_point[1];
- x *= br->mtex.size[0];
- y *= br->mtex.size[1];
+ x *= mtex->size[0];
+ y *= mtex->size[1];
- x += br->mtex.ofs[0];
- y += br->mtex.ofs[1];
+ x += mtex->ofs[0];
+ y += mtex->ofs[1];
- avg = paint_get_tex_pixel(&br->mtex, x, y, ss->tex_pool, thread_id);
+ avg = paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id);
avg += br->texture_sample_bias;
}
else {
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
- avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool);
+ avg = BKE_brush_sample_tex_3d(scene, br, mtex, point_3d, rgba, 0, ss->tex_pool);
}
}
@@ -2793,7 +2793,7 @@ static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat
float up[3];
/* Ensure `ob->imat` is up to date. */
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
/* Initialize last column of matrix. */
mat[0][3] = 0.0f;
@@ -2833,7 +2833,7 @@ void SCULPT_tilt_apply_to_normal(float r_normal[3], StrokeCache *cache, const fl
return;
}
const float rot_max = M_PI_2 * tilt_strength * SCULPT_TILT_SENSITIVITY;
- mul_v3_mat3_m4v3(r_normal, cache->vc->obact->obmat, r_normal);
+ mul_v3_mat3_m4v3(r_normal, cache->vc->obact->object_to_world, r_normal);
float normal_tilt_y[3];
rotate_v3_v3v3fl(normal_tilt_y, r_normal, cache->vc->rv3d->viewinv[0], cache->y_tilt * rot_max);
float normal_tilt_xy[3];
@@ -3284,7 +3284,7 @@ static void sculpt_topology_update(Sculpt *sd,
/* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
- mul_m4_v3(ob->obmat, location);
+ mul_m4_v3(ob->object_to_world, location);
}
static void do_brush_action_task_cb(void *__restrict userdata,
@@ -3615,7 +3615,7 @@ static void do_brush_action(Sculpt *sd,
/* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
- mul_m4_v3(ob->obmat, location);
+ mul_m4_v3(ob->object_to_world, location);
add_v3_v3(ups->average_stroke_accum, location);
ups->average_stroke_counter++;
@@ -4201,8 +4201,8 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
/* Store matrix for mirror object clipping. */
if (mmd->mirror_ob) {
float imtx_mirror_ob[4][4];
- invert_m4_m4(imtx_mirror_ob, mmd->mirror_ob->obmat);
- mul_m4_m4m4(ss->cache->clip_mirror_mtx, imtx_mirror_ob, ob->obmat);
+ invert_m4_m4(imtx_mirror_ob, mmd->mirror_ob->object_to_world);
+ mul_m4_m4m4(ss->cache->clip_mirror_mtx, imtx_mirror_ob, ob->object_to_world);
}
}
}
@@ -4354,7 +4354,7 @@ static void sculpt_update_cache_invariants(
/* Cache projection matrix. */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
copy_m3_m4(mat, cache->vc->rv3d->viewinv);
mul_m3_v3(mat, viewDir);
copy_m3_m4(mat, ob->imat);
@@ -4373,7 +4373,7 @@ static void sculpt_update_cache_invariants(
if (sd->gravity_object) {
Object *gravity_object = sd->gravity_object;
- copy_v3_v3(cache->true_gravity_direction, gravity_object->obmat[2]);
+ copy_v3_v3(cache->true_gravity_direction, gravity_object->object_to_world[2]);
}
else {
cache->true_gravity_direction[0] = cache->true_gravity_direction[1] = 0.0f;
@@ -4527,27 +4527,27 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
}
/* Compute 3d coordinate at same z from original location + mval. */
- mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location);
+ mul_v3_m4v3(loc, ob->object_to_world, cache->orig_grab_location);
ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mval, grab_location);
/* Compute delta to move verts by. */
if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (sculpt_needs_delta_from_anchored_origin(brush)) {
sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_mat3_m4_v3(imat, delta);
add_v3_v3(cache->grab_delta, delta);
}
else if (sculpt_needs_delta_for_tip_orientation(brush)) {
if (brush->flag & BRUSH_ANCHORED) {
float orig[3];
- mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
+ mul_v3_m4v3(orig, ob->object_to_world, cache->orig_grab_location);
sub_v3_v3v3(cache->grab_delta, grab_location, orig);
}
else {
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
}
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_mat3_m4_v3(imat, cache->grab_delta);
}
else {
@@ -4592,7 +4592,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
/* Handle 'rake' */
cache->is_rake_rotation_valid = false;
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_mat3_m4_v3(imat, grab_location);
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
@@ -4813,12 +4813,12 @@ static bool sculpt_needs_connectivity_info(const Sculpt *sd,
void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
{
SculptSession *ss = ob->sculpt;
- View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
bool need_pmap = sculpt_needs_connectivity_info(sd, brush, ss, 0);
if (ss->shapekey_active || ss->deform_modifiers_active ||
- (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
+ (!BKE_sculptsession_use_pbvh_draw(ob, rv3d) && need_pmap)) {
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
BKE_sculpt_update_object_for_edit(
depsgraph, ob, need_pmap, false, SCULPT_tool_is_paint(brush->sculpt_tool));
@@ -4913,7 +4913,7 @@ float SCULPT_raycast_init(ViewContext *vc,
ED_view3d_win_to_segment_clipped(
vc->depsgraph, vc->region, vc->v3d, mval, ray_start, ray_end, true);
- invert_m4_m4(obimat, ob->obmat);
+ invert_m4_m4(obimat, ob->object_to_world);
mul_m4_v3(obimat, ray_start);
mul_m4_v3(obimat, ray_end);
@@ -5021,7 +5021,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
float radius;
/* Update cursor data in SculptSession. */
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
copy_m3_m4(mat, vc.rv3d->viewinv);
mul_m3_v3(mat, viewDir);
copy_m3_m4(mat, ob->imat);
@@ -5249,7 +5249,6 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
SculptSession *ss = ob->sculpt;
ARegion *region = CTX_wm_region(C);
MultiresModifierData *mmd = ss->multires.modifier;
- View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d) {
@@ -5274,7 +5273,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
/* Only current viewport matters, slower update for all viewports will
* be done in sculpt_flush_update_done. */
- if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
/* Slow update with full dependency graph update and all that comes with it.
* Needed when there are modifiers or full shading in the 3D viewport. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -5316,16 +5315,15 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
/* After we are done drawing the stroke, check if we need to do a more
* expensive depsgraph tag to update geometry. */
wmWindowManager *wm = CTX_wm_manager(C);
- View3D *current_v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ RegionView3D *current_rv3d = CTX_wm_region_view3d(C);
SculptSession *ss = ob->sculpt;
Mesh *mesh = ob->data;
/* Always needed for linked duplicates. */
bool need_tag = (ID_REAL_USERS(&mesh->id) > 1);
- if (rv3d) {
- rv3d->rflag &= ~RV3D_PAINTING;
+ if (current_rv3d) {
+ current_rv3d->rflag &= ~RV3D_PAINTING;
}
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
@@ -5335,16 +5333,17 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
if (sl->spacetype != SPACE_VIEW3D) {
continue;
}
- View3D *v3d = (View3D *)sl;
- if (v3d != current_v3d) {
- need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d);
- }
/* Tag all 3D viewports for redraw now that we are done. Others
* viewports did not get a full redraw, and anti-aliasing for the
* current viewport was deactivated. */
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
+ if (rv3d != current_rv3d) {
+ need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, rv3d);
+ }
+
ED_region_tag_redraw(region);
}
}
@@ -5378,15 +5377,17 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
BKE_sculpt_attributes_destroy_temporary_stroke(ob);
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- BKE_pbvh_bmesh_after_stroke(ss->pbvh);
- }
+ if (update_flags & SCULPT_UPDATE_COORDS) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_bmesh_after_stroke(ss->pbvh);
+ }
- /* Optimization: if there is locked key and active modifiers present in */
- /* the stack, keyblock is updating at each step. otherwise we could update */
- /* keyblock only when stroke is finished. */
- if (ss->shapekey_active && !ss->deform_modifiers_active) {
- sculpt_update_keyblock(ob);
+ /* Optimization: if there is locked key and active modifiers present in */
+ /* the stack, keyblock is updating at each step. otherwise we could update */
+ /* keyblock only when stroke is finished. */
+ if (ss->shapekey_active && !ss->deform_modifiers_active) {
+ sculpt_update_keyblock(ob);
+ }
}
if (need_tag) {
@@ -5511,7 +5512,8 @@ static void sculpt_stroke_update_step(bContext *C,
sculpt_restore_mesh(sd, ob);
if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
- float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
+ float object_space_constant_detail = 1.0f / (sd->constant_detail *
+ mat4_to_scale(ob->object_to_world));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
}
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
@@ -5625,6 +5627,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
else {
BKE_sculpt_attributes_destroy_temporary_stroke(ob);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR);
}
}
else {
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index b6bb4c185f9..cf7e1d027f7 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -667,15 +667,15 @@ static void cloth_brush_solve_collision(Object *object,
BVHTreeRayHit hit;
float obmat_inv[4][4];
- invert_m4_m4(obmat_inv, object->obmat);
+ invert_m4_m4(obmat_inv, object->object_to_world);
for (collider_cache = cloth_sim->collider_list->first; collider_cache;
collider_cache = collider_cache->next) {
float ray_start[3], ray_normal[3];
float pos_world_space[3], prev_pos_world_space[3];
- mul_v3_m4v3(pos_world_space, object->obmat, cloth_sim->pos[i]);
- mul_v3_m4v3(prev_pos_world_space, object->obmat, cloth_sim->last_iteration_pos[i]);
+ mul_v3_m4v3(pos_world_space, object->object_to_world, cloth_sim->pos[i]);
+ mul_v3_m4v3(prev_pos_world_space, object->object_to_world, cloth_sim->last_iteration_pos[i]);
sub_v3_v3v3(ray_normal, pos_world_space, prev_pos_world_space);
copy_v3_v3(ray_start, prev_pos_world_space);
hit.index = -1;
@@ -1419,7 +1419,7 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
float sculpt_gravity[3] = {0.0f};
if (sd->gravity_object) {
- copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]);
+ copy_v3_v3(sculpt_gravity, sd->gravity_object->object_to_world[2]);
}
else {
sculpt_gravity[2] = -1.0f;
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
index 6dd718d6a0c..0e46fd50f3b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_detail.c
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -102,7 +102,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
size = max_fff(dim[0], dim[1], dim[2]);
/* Update topology size. */
- float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
+ float object_space_constant_detail = 1.0f /
+ (sd->constant_detail * mat4_to_scale(ob->object_to_world));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
SCULPT_undo_push_begin(ob, op);
@@ -223,7 +224,7 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, const int mval[2
if (srd.hit && srd.edge_length > 0.0f) {
/* Convert edge length to world space detail resolution. */
- sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
+ sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->object_to_world));
}
}
@@ -473,8 +474,8 @@ static void dyntopo_detail_size_parallel_lines_draw(uint pos3d,
bool flip,
const float angle)
{
- float object_space_constant_detail = 1.0f /
- (cd->detail_size * mat4_to_scale(cd->active_object->obmat));
+ float object_space_constant_detail = 1.0f / (cd->detail_size *
+ mat4_to_scale(cd->active_object->object_to_world));
/* The constant detail represents the maximum edge length allowed before subdividing it. If the
* triangle grid preview is created with this value it will represent an ideal mesh density where
@@ -592,7 +593,8 @@ static void dyntopo_detail_size_sample_from_surface(Object *ob,
if (num_neighbors > 0) {
const float avg_edge_len = len_accum / num_neighbors;
/* Use 0.7 as the average of min and max dyntopo edge length. */
- const float detail_size = 0.7f / (avg_edge_len * mat4_to_scale(cd->active_object->obmat));
+ const float detail_size = 0.7f /
+ (avg_edge_len * mat4_to_scale(cd->active_object->object_to_world));
cd->detail_size = clamp_f(detail_size, 1.0f, 500.0f);
}
}
@@ -716,7 +718,7 @@ static int dyntopo_detail_size_edit_invoke(bContext *C, wmOperator *op, const wm
float cursor_trans[4][4], cursor_rot[4][4];
const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
float quat[4];
- copy_m4_m4(cursor_trans, active_object->obmat);
+ copy_m4_m4(cursor_trans, active_object->object_to_world);
translate_m4(
cursor_trans, ss->cursor_location[0], ss->cursor_location[1], ss->cursor_location[2]);
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
index 655b03bbb36..3133bb2007e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -167,15 +167,16 @@ static float sculpt_expand_falloff_value_vertex_get(SculptSession *ss,
if (expand_cache->texture_distortion_strength == 0.0f) {
return expand_cache->vert_falloff[v_i];
}
-
- if (!expand_cache->brush->mtex.tex) {
+ const Brush *brush = expand_cache->brush;
+ const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
+ if (!mtex->tex) {
return expand_cache->vert_falloff[v_i];
}
float rgba[4];
const float *vertex_co = SCULPT_vertex_co_get(ss, v);
const float avg = BKE_brush_sample_tex_3d(
- expand_cache->scene, expand_cache->brush, vertex_co, rgba, 0, ss->tex_pool);
+ expand_cache->scene, brush, mtex, vertex_co, rgba, 0, ss->tex_pool);
const float distortion = (avg - 0.5f) * expand_cache->texture_distortion_strength *
expand_cache->max_vert_falloff;
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc
index ee1238e0f24..40835172be9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc
@@ -18,6 +18,7 @@
#include "BLI_math_vector.hh"
#include "BLI_span.hh"
#include "BLI_task.h"
+#include "BLI_task.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
@@ -313,6 +314,7 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = {
static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
{
+ using namespace blender;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
@@ -396,25 +398,16 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
if (mode == SCULPT_FACE_SET_SELECTION) {
- BMesh *bm;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- BMeshCreateParams create_params{};
- create_params.use_toolflags = true;
- bm = BM_mesh_create(&allocsize, &create_params);
-
- BMeshFromMeshParams convert_params{};
- convert_params.calc_vert_normal = true;
- convert_params.calc_face_normal = true;
- BM_mesh_bm_from_me(bm, mesh, &convert_params);
-
- BMIter iter;
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- ss->face_sets[BM_elem_index_get(f)] = next_face_set;
+ const bke::AttributeAccessor attributes = mesh->attributes();
+ const VArraySpan<bool> select_poly = attributes.lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+ threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) {
+ for (const int i : range) {
+ if (select_poly[i]) {
+ ss->face_sets[i] = next_face_set;
+ }
}
- }
- BM_mesh_free(bm);
+ });
}
for (int i = 0; i < totnode; i++) {
@@ -924,7 +917,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
float location[3];
copy_v3_v3(location, SCULPT_active_vertex_co_get(ss));
- mul_m4_v3(ob->obmat, location);
+ mul_m4_v3(ob->object_to_world, location);
copy_v3_v3(ups->average_stroke_accum, location);
ups->average_stroke_counter = 1;
ups->last_stroke_valid = true;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index 1fa53eaa006..078f0217416 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -146,8 +146,8 @@ void SCULPT_filter_cache_init(bContext *C,
0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
/* Setup orientation matrices. */
- copy_m4_m4(ss->filter_cache->obmat, ob->obmat);
- invert_m4_m4(ss->filter_cache->obmat_inv, ob->obmat);
+ copy_m4_m4(ss->filter_cache->obmat, ob->object_to_world);
+ invert_m4_m4(ss->filter_cache->obmat_inv, ob->object_to_world);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
@@ -203,7 +203,7 @@ void SCULPT_filter_cache_init(bContext *C,
/* Update last stroke location */
- mul_m4_v3(ob->obmat, co);
+ mul_m4_v3(ob->object_to_world, co);
add_v3_v3(ups->average_stroke_accum, co);
ups->average_stroke_counter++;
@@ -221,7 +221,7 @@ void SCULPT_filter_cache_init(bContext *C,
ED_view3d_ob_project_mat_get(vc.rv3d, ob, projection_mat);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
copy_m3_m4(mat, vc.rv3d->viewinv);
mul_m3_v3(mat, viewDir);
copy_m3_m4(mat, ob->imat);
diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c
index a740ec2773b..8affb0e9d53 100644
--- a/source/blender/editors/sculpt_paint/sculpt_ops.c
+++ b/source/blender/editors/sculpt_paint/sculpt_ops.c
@@ -323,7 +323,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
BKE_report(
reports, RPT_WARNING, "Object has non-uniform scale, sculpting may be unpredictable");
}
- else if (is_negative_m4(ob->obmat)) {
+ else if (is_negative_m4(ob->object_to_world)) {
BKE_report(reports, RPT_WARNING, "Object has negative scale, sculpting may be unpredictable");
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 13e3dd64521..eb92c865f18 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -857,7 +857,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
@@ -911,7 +911,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
- if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
@@ -1070,7 +1070,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
- tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d) ||
+ tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, rv3d) ||
ss->shapekey_active || ss->deform_modifiers_active;
if (tag_update) {
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index eb56c6c4b54..343975919e2 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -104,7 +104,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
UI_block_draw(C, block);
}
- /* free tempolary channels */
+ /* Free temporary channels. */
ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index a9ce9a3d723..9c8d46a41f9 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -41,7 +41,7 @@
/* -------------------------------------------------------------------- */
/** \name Start / Clear Search Filter Operators
*
- * \note Almost a duplicate of the file browser operator #FILE_OT_start_filter.
+ * \note Almost a duplicate of the file browser operator #FILE_OT_start_filter.
* \{ */
static int buttons_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
@@ -205,7 +205,7 @@ static int file_browse_exec(bContext *C, wmOperator *op)
if (BLI_is_dir(path)) {
/* Do this first so '//' isn't converted to '//\' on windows. */
- BLI_path_slash_ensure(path);
+ BLI_path_slash_ensure(path, sizeof(path));
if (is_relative) {
BLI_path_rel(path, BKE_main_blendfile_path(bmain));
str_len = strlen(path);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 5bdb4b185e7..c3249b26fdd 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -410,8 +410,15 @@ static void file_draw_preview(const SpaceFile *sfile,
}
icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f));
- UI_icon_draw_ex(
- icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ icon,
+ icon_aspect / U.dpi_fac,
+ icon_opacity,
+ 0.0f,
+ icon_color,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
if (is_link || is_offline) {
@@ -424,8 +431,24 @@ static void file_draw_preview(const SpaceFile *sfile,
/* At very bottom-left if preview style. */
const uchar dark[4] = {0, 0, 0, 255};
const uchar light[4] = {255, 255, 255, 255};
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1,
+ icon_y - 1,
+ arrow,
+ 1.0f / U.dpi_fac,
+ 0.2f,
+ 0.0f,
+ dark,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ arrow,
+ 1.0f / U.dpi_fac,
+ 0.6f,
+ 0.0f,
+ light,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
else {
/* Link to folder or non-previewed file. */
@@ -433,8 +456,15 @@ static void file_draw_preview(const SpaceFile *sfile,
UI_GetThemeColor4ubv(TH_BACK, icon_color);
icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
- UI_icon_draw_ex(
- icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ arrow,
+ icon_aspect / U.dpi_fac * 1.8,
+ 0.3f,
+ 0.0f,
+ icon_color,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
}
else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) {
@@ -444,8 +474,17 @@ static void file_draw_preview(const SpaceFile *sfile,
const uchar light[4] = {255, 255, 255, 255};
icon_x = xco + (2.0f * UI_DPI_FAC);
icon_y = yco + (2.0f * UI_DPI_FAC);
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1,
+ icon_y - 1,
+ icon,
+ 1.0f / U.dpi_fac,
+ 0.2f,
+ 0.0f,
+ dark,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
+ UI_icon_draw_ex(
+ icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false, UI_NO_ICON_OVERLAY_TEXT);
}
const bool is_current_main_data = filelist_file_get_id(file) != NULL;
@@ -456,7 +495,15 @@ static void file_draw_preview(const SpaceFile *sfile,
const uchar light[4] = {255, 255, 255, 255};
icon_x = xco + ex - UI_UNIT_X;
icon_y = yco + ey - UI_UNIT_Y;
- UI_icon_draw_ex(icon_x, icon_y, ICON_CURRENT_FILE, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ ICON_CURRENT_FILE,
+ 1.0f / U.dpi_fac,
+ 0.6f,
+ 0.0f,
+ light,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/* Contrasting outline around some preview types. */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index a4d4bf98474..f68d329329f 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -197,13 +197,12 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
}
else if (file->redirection_path) {
BLI_strncpy(params->dir, file->redirection_path, sizeof(params->dir));
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
- BLI_path_slash_ensure(params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir));
+ BLI_path_slash_ensure(params->dir, sizeof(params->dir));
}
else {
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
- strcat(params->dir, file->relpath);
- BLI_path_slash_ensure(params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir));
+ BLI_path_append_dir(params->dir, sizeof(params->dir), file->relpath);
}
ED_file_change_dir(C);
@@ -1095,7 +1094,7 @@ static int bookmark_select_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop, entry);
BLI_strncpy(params->dir, entry, sizeof(params->dir));
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir));
ED_file_change_dir(C);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1564,7 +1563,13 @@ void file_sfile_to_operator_ex(
PropertyRNA *prop;
/* XXX, not real length */
- BLI_path_join(filepath, FILE_MAX, params->dir, params->file);
+ if (params->file[0]) {
+ BLI_path_join(filepath, FILE_MAX, params->dir, params->file);
+ }
+ else {
+ BLI_strncpy(filepath, params->dir, FILE_MAX);
+ BLI_path_slash_ensure(filepath, FILE_MAX);
+ }
if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
if (RNA_property_boolean_get(op->ptr, prop)) {
@@ -1791,8 +1796,7 @@ static bool file_execute(bContext *C, SpaceFile *sfile)
}
else {
BLI_path_normalize(BKE_main_blendfile_path(bmain), params->dir);
- BLI_path_append(params->dir, sizeof(params->dir) - 1, file->relpath);
- BLI_path_slash_ensure(params->dir);
+ BLI_path_append_dir(params->dir, sizeof(params->dir), file->relpath);
}
ED_file_change_dir(C);
}
@@ -1955,7 +1959,7 @@ static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
if (params) {
if (BLI_path_parent_dir(params->dir)) {
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir));
ED_file_change_dir(C);
if (params->recursion_level > 1) {
/* Disable 'dirtree' recursion when going up in tree. */
@@ -2538,7 +2542,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
}
}
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir, sizeof(params->dir));
if (filelist_is_dir(sfile->files, params->dir)) {
if (!STREQ(params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */
@@ -2625,7 +2629,7 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
/* if directory, open it and empty filename field */
if (filelist_is_dir(sfile->files, filepath)) {
- BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath);
+ BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath, sizeof(filepath));
BLI_strncpy(params->dir, filepath, sizeof(params->dir));
params->file[0] = '\0';
ED_file_change_dir(C);
diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc
index 4aa85f3f169..d4a42c3f4f2 100644
--- a/source/blender/editors/space_file/filelist.cc
+++ b/source/blender/editors/space_file/filelist.cc
@@ -1220,7 +1220,7 @@ static int filelist_geticon_ex(const FileDirEntry *file,
}
else if (root) {
BLI_path_join(fullpath, sizeof(fullpath), root, file->relpath);
- BLI_path_slash_ensure(fullpath);
+ BLI_path_slash_ensure(fullpath, sizeof(fullpath));
}
for (; tfsm; tfsm = tfsm->next) {
if (STREQ(tfsm->path, target)) {
@@ -1964,7 +1964,7 @@ void filelist_setdir(struct FileList *filelist, char *r_dir)
const bool allow_invalid = filelist->asset_library_ref != nullptr;
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
- BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir);
+ BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir, FILE_MAX_LIBEXTRA);
const bool is_valid_path = filelist->check_dir_fn(filelist, r_dir, !allow_invalid);
BLI_assert(is_valid_path || allow_invalid);
UNUSED_VARS_NDEBUG(is_valid_path);
@@ -2932,7 +2932,7 @@ static int filelist_readjob_list_dir(const char *root,
if (BLI_file_alias_target(full_path, entry->redirection_path)) {
if (BLI_is_dir(entry->redirection_path)) {
entry->typeflag = FILE_TYPE_DIR;
- BLI_path_slash_ensure(entry->redirection_path);
+ BLI_path_slash_ensure(entry->redirection_path, FILE_MAXDIR);
}
else {
entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(entry->redirection_path);
@@ -3494,7 +3494,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
BLI_strncpy(dir, filelist->filelist.root, sizeof(dir));
BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob));
- BLI_path_normalize_dir(job_params->main_name, dir);
+ BLI_path_normalize_dir(job_params->main_name, dir, sizeof(dir));
td_dir->dir = BLI_strdup(dir);
/* Init the file indexer. */
@@ -3525,7 +3525,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
* Note that in the end, this means we 'cache' valid relative subdir once here,
* this is actually better. */
BLI_strncpy(rel_subdir, subdir, sizeof(rel_subdir));
- BLI_path_normalize_dir(root, rel_subdir);
+ BLI_path_normalize_dir(root, rel_subdir, sizeof(rel_subdir));
BLI_path_rel(rel_subdir, root);
bool is_lib = false;
@@ -3573,7 +3573,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
max_recursion, is_lib, recursion_level, entry)) {
/* We have a directory we want to list, add it to todo list! */
BLI_path_join(dir, sizeof(dir), root, entry->relpath);
- BLI_path_normalize_dir(job_params->main_name, dir);
+ BLI_path_normalize_dir(job_params->main_name, dir, sizeof(dir));
td_dir = static_cast<TodoDir *>(BLI_stack_push_r(todo_dirs));
td_dir->level = recursion_level + 1;
td_dir->dir = BLI_strdup(dir);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 8f419d256e5..6dd4e37fea8 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -199,7 +199,7 @@ static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile)
}
if (params->dir[0]) {
- BLI_path_normalize_dir(blendfile_path, params->dir);
+ BLI_path_normalize_dir(blendfile_path, params->dir, sizeof(params->dir));
BLI_path_abs(params->dir, blendfile_path);
}
@@ -1201,7 +1201,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
match = UI_autocomplete_end(autocpl, str);
if (match == AUTOCOMPLETE_FULL_MATCH) {
- BLI_path_slash_ensure(str);
+ BLI_path_slash_ensure(str, FILE_MAX);
}
}
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 41a8368152d..f8a0dff3a41 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -1446,7 +1446,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
GPU_blend(GPU_BLEND_NONE);
}
- /* free tempolary channels */
+ /* Free temporary channels. */
ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index aee72860a0a..12ee6f45991 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -235,7 +235,8 @@ static bool textview_draw_string(TextViewDrawState *tds,
1.0f,
0.0f,
icon_fg,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index f57c9fead56..45bbe50eedd 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -905,7 +905,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region)
}
}
- /* free tempolary channels */
+ /* Free temporary channels. */
ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index d7eccbf0b68..ff9e5352d0a 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
set(SRC
add_node_search.cc
+ add_menu_assets.cc
drawnode.cc
link_drag_search.cc
node_add.cc
diff --git a/source/blender/editors/space_node/add_menu_assets.cc b/source/blender/editors/space_node/add_menu_assets.cc
new file mode 100644
index 00000000000..1ba1d67d854
--- /dev/null
+++ b/source/blender/editors/space_node/add_menu_assets.cc
@@ -0,0 +1,314 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_multi_value_map.hh"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_asset.h"
+#include "BKE_asset_catalog.hh"
+#include "BKE_asset_library.hh"
+#include "BKE_idprop.h"
+#include "BKE_screen.h"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+#include "RNA_prototypes.h"
+
+#include "ED_asset.h"
+#include "ED_screen.h"
+
+#include "node_intern.hh"
+
+namespace blender::ed::space_node {
+
+static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/)
+{
+ return CTX_wm_space_node(C);
+}
+
+static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params)
+{
+ const wmNotifier *wmn = params->notifier;
+ ARegion *region = params->region;
+
+ switch (wmn->category) {
+ case NC_ASSET:
+ if (wmn->data == ND_ASSET_LIST_READING) {
+ ED_region_tag_refresh_ui(region);
+ }
+ break;
+ }
+}
+
+struct LibraryAsset {
+ AssetLibraryReference library_ref;
+ AssetHandle handle;
+};
+
+struct LibraryCatalog {
+ bke::AssetLibrary *library;
+ const bke::AssetCatalog *catalog;
+};
+
+struct AssetItemTree {
+ bke::AssetCatalogTree catalogs;
+ MultiValueMap<bke::AssetCatalogPath, LibraryAsset> assets_per_path;
+ Map<const bke::AssetCatalogTreeItem *, bke::AssetCatalogPath> full_catalog_per_tree_item;
+};
+
+static bool all_loading_finished()
+{
+ for (const AssetLibraryReference &library : bke::all_valid_asset_library_refs()) {
+ if (!ED_assetlist_is_loaded(&library)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node_tree)
+{
+ if (!node_tree) {
+ return {};
+ }
+ const Main &bmain = *CTX_data_main(&C);
+ const Vector<AssetLibraryReference> all_libraries = bke::all_valid_asset_library_refs();
+
+ /* Merge catalogs from all libraries to deduplicate menu items. Also store the catalog and
+ * library for each asset ID in order to use them later when retrieving assets and removing
+ * empty catalogs. */
+ Map<bke::CatalogID, LibraryCatalog> id_to_catalog_map;
+ bke::AssetCatalogTree catalogs_from_all_libraries;
+ for (const AssetLibraryReference &library_ref : all_libraries) {
+ if (bke::AssetLibrary *library = BKE_asset_library_load(&bmain, library_ref)) {
+ if (bke::AssetCatalogTree *tree = library->catalog_service->get_catalog_tree()) {
+ tree->foreach_item([&](bke::AssetCatalogTreeItem &item) {
+ const bke::CatalogID &id = item.get_catalog_id();
+ bke::AssetCatalog *catalog = library->catalog_service->find_catalog(id);
+ catalogs_from_all_libraries.insert_item(*catalog);
+ id_to_catalog_map.add(item.get_catalog_id(), LibraryCatalog{library, catalog});
+ });
+ }
+ }
+ }
+
+ /* Find all the matching node group assets for every catalog path. */
+ MultiValueMap<bke::AssetCatalogPath, LibraryAsset> assets_per_path;
+ for (const AssetLibraryReference &library_ref : all_libraries) {
+ AssetFilterSettings type_filter{};
+ type_filter.id_types = FILTER_ID_NT;
+
+ ED_assetlist_storage_fetch(&library_ref, &C);
+ ED_assetlist_ensure_previews_job(&library_ref, &C);
+ ED_assetlist_iterate(library_ref, [&](AssetHandle asset) {
+ if (!ED_asset_filter_matches_asset(&type_filter, &asset)) {
+ return true;
+ }
+ const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset);
+ const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
+ if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) {
+ return true;
+ }
+ if (BLI_uuid_is_nil(meta_data.catalog_id)) {
+ return true;
+ }
+ const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(meta_data.catalog_id);
+ assets_per_path.add(library_catalog.catalog->path, LibraryAsset{library_ref, asset});
+ return true;
+ });
+ }
+
+ /* Build the final tree without any of the catalogs that don't have proper node group assets. */
+ bke::AssetCatalogTree catalogs_with_node_assets;
+ catalogs_from_all_libraries.foreach_item([&](bke::AssetCatalogTreeItem &item) {
+ if (!assets_per_path.lookup(item.catalog_path()).is_empty()) {
+ const bke::CatalogID &id = item.get_catalog_id();
+ const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(id);
+ bke::AssetCatalog *catalog = library_catalog.library->catalog_service->find_catalog(id);
+ catalogs_with_node_assets.insert_item(*catalog);
+ }
+ });
+
+ /* Build another map storing full asset paths for each tree item, in order to have stable
+ * pointers to asset catalog paths to use for context pointers. This is necessary because
+ * #bke::AssetCatalogTreeItem doesn't store its full path directly. */
+ Map<const bke::AssetCatalogTreeItem *, bke::AssetCatalogPath> full_catalog_per_tree_item;
+ catalogs_with_node_assets.foreach_item([&](bke::AssetCatalogTreeItem &item) {
+ full_catalog_per_tree_item.add_new(&item, item.catalog_path());
+ });
+
+ return {std::move(catalogs_with_node_assets),
+ std::move(assets_per_path),
+ std::move(full_catalog_per_tree_item)};
+}
+
+static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
+{
+ bScreen &screen = *CTX_wm_screen(C);
+ const SpaceNode &snode = *CTX_wm_space_node(C);
+ if (!snode.runtime->assets_for_menu) {
+ BLI_assert_unreachable();
+ return;
+ }
+ AssetItemTree &tree = *snode.runtime->assets_for_menu;
+ const bNodeTree *edit_tree = snode.edittree;
+ if (!edit_tree) {
+ return;
+ }
+
+ const PointerRNA menu_path_ptr = CTX_data_pointer_get(C, "asset_catalog_path");
+ if (RNA_pointer_is_null(&menu_path_ptr)) {
+ return;
+ }
+ const bke::AssetCatalogPath &menu_path = *static_cast<const bke::AssetCatalogPath *>(
+ menu_path_ptr.data);
+
+ const Span<LibraryAsset> asset_items = tree.assets_per_path.lookup(menu_path);
+ bke::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(menu_path);
+ BLI_assert(catalog_item != nullptr);
+
+ if (asset_items.is_empty() && !catalog_item->has_children()) {
+ return;
+ }
+
+ uiLayout *layout = menu->layout;
+ uiItemS(layout);
+
+ for (const LibraryAsset &item : asset_items) {
+ uiLayout *col = uiLayoutColumn(layout, false);
+ PointerRNA file{
+ &screen.id, &RNA_FileSelectEntry, const_cast<FileDirEntry *>(item.handle.file_data)};
+ uiLayoutSetContextPointer(col, "active_file", &file);
+
+ PointerRNA library_ptr{&screen.id,
+ &RNA_AssetLibraryReference,
+ const_cast<AssetLibraryReference *>(&item.library_ref)};
+ uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr);
+
+ uiItemO(col, ED_asset_handle_get_name(&item.handle), ICON_NONE, "NODE_OT_add_group_asset");
+ }
+
+ catalog_item->foreach_child([&](bke::AssetCatalogTreeItem &child_item) {
+ const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(&child_item);
+ PointerRNA path_ptr{
+ &screen.id, &RNA_AssetCatalogPath, const_cast<bke::AssetCatalogPath *>(&path)};
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
+ uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE);
+ });
+}
+
+static void add_root_catalogs_draw(const bContext *C, Menu *menu)
+{
+ bScreen &screen = *CTX_wm_screen(C);
+ SpaceNode &snode = *CTX_wm_space_node(C);
+ const bNodeTree *edit_tree = snode.edittree;
+ uiLayout *layout = menu->layout;
+
+ snode.runtime->assets_for_menu = std::make_shared<AssetItemTree>(
+ build_catalog_tree(*C, edit_tree));
+
+ const bool loading_finished = all_loading_finished();
+
+ AssetItemTree &tree = *snode.runtime->assets_for_menu;
+ if (tree.catalogs.is_empty() && loading_finished) {
+ return;
+ }
+
+ uiItemS(layout);
+
+ if (!loading_finished) {
+ uiItemL(layout, IFACE_("Loading Asset Libraries"), ICON_INFO);
+ }
+
+ /* Avoid adding a separate root catalog when the assets have already been added to one of the
+ * builtin menus.
+ * TODO: The need to define the builtin menu labels here is completely non-ideal. We don't have
+ * any UI introspection that can do this though. This can be solved in the near future by
+ * removing the need to define the add menu completely, instead using a per-node-type path which
+ * can be merged with catalog tree.
+ */
+ static Set<std::string> all_builtin_menus = []() {
+ Set<std::string> menus;
+ menus.add_new("Attribute");
+ menus.add_new("Color");
+ menus.add_new("Curve");
+ menus.add_new("Curve Primitives");
+ menus.add_new("Curve Topology");
+ menus.add_new("Geometry");
+ menus.add_new("Input");
+ menus.add_new("Instances");
+ menus.add_new("Material");
+ menus.add_new("Mesh");
+ menus.add_new("Mesh Primitives");
+ menus.add_new("Mesh Topology");
+ menus.add_new("Output");
+ menus.add_new("Point");
+ menus.add_new("Text");
+ menus.add_new("Texture");
+ menus.add_new("Utilities");
+ menus.add_new("UV");
+ menus.add_new("Vector");
+ menus.add_new("Volume");
+ menus.add_new("Group");
+ menus.add_new("Layout");
+ return menus;
+ }();
+
+ tree.catalogs.foreach_root_item([&](bke::AssetCatalogTreeItem &item) {
+ if (all_builtin_menus.contains(item.get_name())) {
+ return;
+ }
+ const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(&item);
+ PointerRNA path_ptr{
+ &screen.id, &RNA_AssetCatalogPath, const_cast<bke::AssetCatalogPath *>(&path)};
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
+ uiItemM(col, "NODE_MT_node_add_catalog_assets", path.name().c_str(), ICON_NONE);
+ });
+}
+
+MenuType add_catalog_assets_menu_type()
+{
+ MenuType type{};
+ BLI_strncpy(type.idname, "NODE_MT_node_add_catalog_assets", sizeof(type.idname));
+ type.poll = node_add_menu_poll;
+ type.draw = node_add_catalog_assets_draw;
+ type.listener = node_add_menu_assets_listen_fn;
+ return type;
+}
+
+MenuType add_root_catalogs_menu_type()
+{
+ MenuType type{};
+ BLI_strncpy(type.idname, "NODE_MT_node_add_root_catalogs", sizeof(type.idname));
+ type.poll = node_add_menu_poll;
+ type.draw = add_root_catalogs_draw;
+ type.listener = node_add_menu_assets_listen_fn;
+ return type;
+}
+
+} // namespace blender::ed::space_node
+
+/* Note: This is only necessary because Python can't set an asset catalog path context item. */
+void uiTemplateNodeAssetMenuItems(uiLayout *layout, bContext *C, const char *catalog_path)
+{
+ using namespace blender;
+ using namespace blender::ed::space_node;
+ bScreen &screen = *CTX_wm_screen(C);
+ SpaceNode &snode = *CTX_wm_space_node(C);
+ AssetItemTree &tree = *snode.runtime->assets_for_menu;
+ const bke::AssetCatalogTreeItem *item = tree.catalogs.find_root_item(catalog_path);
+ if (!item) {
+ return;
+ }
+ const bke::AssetCatalogPath &path = tree.full_catalog_per_tree_item.lookup(item);
+ PointerRNA path_ptr{
+ &screen.id, &RNA_AssetCatalogPath, const_cast<bke::AssetCatalogPath *>(&path)};
+ uiItemS(layout);
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
+ uiItemMContents(col, "NODE_MT_node_add_catalog_assets");
+}
diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc
index 07eecff320a..41f70a6d8cf 100644
--- a/source/blender/editors/space_node/node_add.cc
+++ b/source/blender/editors/space_node/node_add.cc
@@ -30,6 +30,7 @@
#include "DEG_depsgraph_build.h"
+#include "ED_asset.h"
#include "ED_node.h" /* own include */
#include "ED_render.h"
#include "ED_screen.h"
@@ -244,38 +245,36 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
/** \name Add Node Group Operator
* \{ */
-static bNodeTree *node_add_group_get_and_poll_group_node_tree(Main *bmain,
- wmOperator *op,
- bNodeTree *ntree)
+static bool node_group_add_poll(const bNodeTree &node_tree,
+ const bNodeTree &node_group,
+ ReportList &reports)
{
- bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
- WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_NT));
- if (!node_group) {
- return nullptr;
+ if (node_group.type != node_tree.type) {
+ return false;
}
const char *disabled_hint = nullptr;
- if ((node_group->type != ntree->type) || !nodeGroupPoll(ntree, node_group, &disabled_hint)) {
+ if (!nodeGroupPoll(&node_tree, &node_group, &disabled_hint)) {
if (disabled_hint) {
- BKE_reportf(op->reports,
+ BKE_reportf(&reports,
RPT_ERROR,
"Can not add node group '%s' to '%s':\n %s",
- node_group->id.name + 2,
- ntree->id.name + 2,
+ node_group.id.name + 2,
+ node_tree.id.name + 2,
disabled_hint);
}
else {
- BKE_reportf(op->reports,
+ BKE_reportf(&reports,
RPT_ERROR,
"Can not add node group '%s' to '%s'",
- node_group->id.name + 2,
- ntree->id.name + 2);
+ node_group.id.name + 2,
+ node_tree.id.name + 2);
}
- return nullptr;
+ return false;
}
- return node_group;
+ return true;
}
static int node_add_group_exec(bContext *C, wmOperator *op)
@@ -284,10 +283,14 @@ static int node_add_group_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNodeTree *node_group = node_add_group_get_and_poll_group_node_tree(bmain, op, ntree);
+ bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
+ WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_NT));
if (!node_group) {
return OPERATOR_CANCELLED;
}
+ if (!node_group_add_poll(*ntree, *node_group, *op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
@@ -320,9 +323,8 @@ static bool node_add_group_poll(bContext *C)
}
const SpaceNode *snode = CTX_wm_space_node(C);
if (snode->edittree->type == NTREE_CUSTOM) {
- CTX_wm_operator_poll_msg_set(C,
- "This node editor displays a custom (Python defined) node tree. "
- "Dropping node groups isn't supported for this");
+ CTX_wm_operator_poll_msg_set(
+ C, "Adding node groups isn't supported for custom (Python defined) node trees");
return false;
}
return true;
@@ -367,6 +369,105 @@ void NODE_OT_add_group(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Add Node Group Asset Operator
+ * \{ */
+
+static bool add_node_group_asset(const bContext &C,
+ const AssetLibraryReference &library_ref,
+ const AssetHandle asset,
+ ReportList &reports)
+{
+ Main &bmain = *CTX_data_main(&C);
+ SpaceNode &snode = *CTX_wm_space_node(&C);
+ bNodeTree &edit_tree = *snode.edittree;
+
+ bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
+ asset::get_local_id_from_asset_or_append_and_reuse(bmain, library_ref, asset));
+ if (!node_group) {
+ return false;
+ }
+ if (!node_group_add_poll(edit_tree, *node_group, reports)) {
+ /* Remove the node group if it was newly appended but can't be added to the tree. */
+ id_us_plus(&node_group->id);
+ BKE_id_free_us(&bmain, node_group);
+ return false;
+ }
+
+ ED_preview_kill_jobs(CTX_wm_manager(&C), CTX_data_main(&C));
+
+ bNode *group_node = add_node(
+ C, ntreeTypeFind(node_group->idname)->group_idname, snode.runtime->cursor);
+ if (!group_node) {
+ BKE_report(&reports, RPT_WARNING, "Could not add node group");
+ return false;
+ }
+ /* By default, don't show the data-block selector since it's not usually necessary for assets. */
+ group_node->flag &= ~NODE_OPTIONS;
+
+ group_node->id = &node_group->id;
+ id_us_plus(group_node->id);
+ BKE_ntree_update_tag_node_property(&edit_tree, group_node);
+
+ nodeSetActive(&edit_tree, group_node);
+ ED_node_tree_propagate_change(&C, &bmain, nullptr);
+ DEG_relations_tag_update(&bmain);
+
+ return true;
+}
+
+static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion &region = *CTX_wm_region(C);
+ SpaceNode &snode = *CTX_wm_space_node(C);
+
+ const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C);
+ if (!library_ref) {
+ return OPERATOR_CANCELLED;
+ }
+ bool is_valid;
+ const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid);
+ if (!is_valid) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Convert mouse coordinates to v2d space. */
+ UI_view2d_region_to_view(&region.v2d,
+ event->mval[0],
+ event->mval[1],
+ &snode.runtime->cursor[0],
+ &snode.runtime->cursor[1]);
+
+ snode.runtime->cursor /= UI_DPI_FAC;
+
+ if (!add_node_group_asset(*C, *library_ref, handle, *op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ wmOperatorType *ot = WM_operatortype_find("NODE_OT_translate_attach_remove_on_cancel", true);
+ BLI_assert(ot);
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr);
+ WM_operator_properties_free(&ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_add_group_asset(wmOperatorType *ot)
+{
+ ot->name = "Add Node Group Asset";
+ ot->description = "Add a node group asset to the active node tree";
+ ot->idname = "NODE_OT_add_group_asset";
+
+ ot->invoke = node_add_group_asset_invoke;
+ ot->poll = node_add_group_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Add Node Object Operator
* \{ */
@@ -393,7 +494,7 @@ static int node_add_object_exec(bContext *C, wmOperator *op)
bNodeSocket *sock = nodeFindSocket(object_node, SOCK_IN, "Object");
if (!sock) {
- BKE_report(op->reports, RPT_WARNING, "Could not find node object socket");
+ BLI_assert_unreachable();
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index ee9ebd541a0..5ae6573df7c 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -2145,6 +2145,9 @@ static void node_draw_basis(const bContext &C,
0,
"");
UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit");
+ if (node.id) {
+ UI_but_icon_indicator_number_set(but, ID_REAL_USERS(node.id));
+ }
UI_block_emboss_set(&block, UI_EMBOSS);
}
if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) {
diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh
index 1c3026628a6..88be9a52c61 100644
--- a/source/blender/editors/space_node/node_intern.hh
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -38,6 +38,8 @@ extern const char *node_context_dir[];
namespace blender::ed::space_node {
+struct AssetItemTree;
+
/** Temporary data used in node link drag modal operator. */
struct bNodeLinkDrag {
/** Links dragged by the operator. */
@@ -96,6 +98,15 @@ struct SpaceNode_Runtime {
/* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */
/** Temporary data for node insert offset (in UI called Auto-offset). */
struct NodeInsertOfsData *iofsd;
+
+ /**
+ * Temporary data for node add menu in order to provide longer-term storage for context pointers.
+ * Recreated every time the root menu is opened. In the future this will be replaced with an "all
+ * libraries" cache in the asset system itself.
+ *
+ * Stored with a shared pointer so that it can be forward declared.
+ */
+ std::shared_ptr<AssetItemTree> assets_for_menu;
};
enum NodeResizeDirection {
@@ -253,6 +264,7 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location);
void NODE_OT_add_reroute(wmOperatorType *ot);
void NODE_OT_add_search(wmOperatorType *ot);
void NODE_OT_add_group(wmOperatorType *ot);
+void NODE_OT_add_group_asset(wmOperatorType *ot);
void NODE_OT_add_object(wmOperatorType *ot);
void NODE_OT_add_collection(wmOperatorType *ot);
void NODE_OT_add_file(wmOperatorType *ot);
@@ -383,4 +395,9 @@ void invoke_node_link_drag_add_menu(bContext &C,
void invoke_add_node_search_menu(bContext &C, const float2 &cursor, bool use_transform);
+/* add_menu_assets.cc */
+
+MenuType add_catalog_assets_menu_type();
+MenuType add_root_catalogs_menu_type();
+
} // namespace blender::ed::space_node
diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc
index d45c33a3c59..104d1acf3b4 100644
--- a/source/blender/editors/space_node/node_ops.cc
+++ b/source/blender/editors/space_node/node_ops.cc
@@ -78,6 +78,7 @@ void node_operatortypes()
WM_operatortype_append(NODE_OT_add_search);
WM_operatortype_append(NODE_OT_add_group);
+ WM_operatortype_append(NODE_OT_add_group_asset);
WM_operatortype_append(NODE_OT_add_object);
WM_operatortype_append(NODE_OT_add_collection);
WM_operatortype_append(NODE_OT_add_file);
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index b12afcb1faa..637c795d4d7 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -815,7 +815,8 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/,
nldrag->cursor[0];
const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC;
- UI_icon_draw_ex(x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false);
+ UI_icon_draw_ex(
+ x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
}
static void draw_draglink_tooltip_activate(const ARegion &region, bNodeLinkDrag &nldrag)
diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc
index ac49115959c..5754e77399f 100644
--- a/source/blender/editors/space_node/space_node.cc
+++ b/source/blender/editors/space_node/space_node.cc
@@ -1170,5 +1170,8 @@ void ED_spacetype_node()
art->draw = node_toolbar_region_draw;
BLI_addhead(&st->regiontypes, art);
+ WM_menutype_add(MEM_new<MenuType>(__func__, add_catalog_assets_menu_type()));
+ WM_menutype_add(MEM_new<MenuType>(__func__, add_root_catalogs_menu_type()));
+
BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index e366c58349f..699dd6d4844 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -2877,7 +2877,8 @@ static bool tselem_draw_icon(uiBlock *block,
TreeStoreElem *tselem,
TreeElement *te,
float alpha,
- const bool is_clickable)
+ const bool is_clickable,
+ const int num_elements)
{
TreeElementIcon data = tree_element_get_icon(tselem, te);
if (data.icon == 0) {
@@ -2885,6 +2886,8 @@ static bool tselem_draw_icon(uiBlock *block,
}
const bool is_collection = outliner_is_collection_tree_element(te);
+ IconTextOverlay text_overlay;
+ UI_icon_text_overlay_init_from_count(&text_overlay, num_elements);
/* Collection colors and icons covered by restrict buttons. */
if (!is_clickable || x >= xmax || is_collection) {
@@ -2904,7 +2907,8 @@ static bool tselem_draw_icon(uiBlock *block,
alpha,
0.0f,
btheme->collection_color[collection->color_tag].color,
- true);
+ true,
+ &text_overlay);
return true;
}
}
@@ -2915,10 +2919,10 @@ static bool tselem_draw_icon(uiBlock *block,
/* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */
uchar color[4];
if (UI_icon_get_theme_color(data.icon, color)) {
- UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true, &text_overlay);
}
else {
- UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false);
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, &text_overlay);
}
}
else {
@@ -2941,104 +2945,6 @@ static bool tselem_draw_icon(uiBlock *block,
return true;
}
-static bool outliner_is_main_row(const ARegion *region, const int ys)
-{
- int ystart;
-
- ystart = int(region->v2d.tot.ymax);
- ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- return ((ys - ystart) / UI_UNIT_Y) % 2;
-}
-
-/**
- * Get the expected row background color to use for the data-block counter
- *
- * This reproduces some of the logic of outliner_draw_highlights.
- * At the moment it doesn't implement the search match color since
- * we don't draw the data-block counter in those cases.
- */
-static void outliner_get_row_color(const ARegion *region,
- const TreeElement *te,
- int ys,
- float r_color[4])
-{
- const TreeStoreElem *tselem = TREESTORE(te);
-
- if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) {
- UI_GetThemeColor3fv(TH_ACTIVE, r_color);
- }
- else if (tselem->flag & TSE_SELECTED) {
- UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, r_color);
- }
- else if (outliner_is_main_row(region, ys)) {
- UI_GetThemeColor3fv(TH_BACK, r_color);
- }
- else {
- float color_alternating[4];
- UI_GetThemeColor4fv(TH_ROW_ALTERNATE, color_alternating);
- UI_GetThemeColorBlend3f(TH_BACK, TH_ROW_ALTERNATE, color_alternating[3], r_color);
- }
-
- if (tselem->flag & TSE_HIGHLIGHTED) {
- const float color_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
- interp_v3_v3v3(r_color, r_color, color_highlight, color_highlight[3]);
- }
- r_color[3] = 1.0f;
-}
-
-/**
- * For icon-only children of a collapsed tree,
- * Draw small number over the icon to show how many items of this type are displayed.
- */
-static void outliner_draw_iconrow_number(const ARegion *region,
- const uiFontStyle *fstyle,
- int offsx,
- int ys,
- const TreeElement *te_visible,
- const int num_elements)
-{
- float color[4];
- outliner_get_row_color(region, te_visible, ys, color);
-
- float ufac = 0.25f * UI_UNIT_X;
- float offset_x = float(offsx) + UI_UNIT_X * 0.35f;
- rctf rect{};
- BLI_rctf_init(&rect,
- offset_x + ufac,
- offset_x + UI_UNIT_X - ufac,
- float(ys) - UI_UNIT_Y * 0.2f + ufac,
- float(ys) - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv_ex(
- &rect, color, NULL, 1.0f, color, U.pixelsize, float(UI_UNIT_Y) / 2.0f - ufac);
-
- /* Now the numbers. */
- uchar text_col[4];
-
- UI_GetThemeColor3ubv(TH_TEXT, text_col);
- text_col[3] = 255;
-
- uiFontStyle fstyle_small = *fstyle;
- fstyle_small.points *= 0.8f;
-
- /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
- int num_digits = 4;
- char number_text[4] = "+99";
- if (num_elements < 100) {
- BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
- num_digits = num_elements < 10 ? 1 : 2;
- }
- UI_fontstyle_draw_simple(&fstyle_small,
- (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
- float(ys) - UI_UNIT_Y * 0.095f + ufac,
- number_text,
- text_col);
- UI_fontstyle_set(fstyle);
- GPU_blend(GPU_BLEND_ALPHA); /* Round-box and text drawing disables. */
-}
-
static void outliner_icon_background_colors(float icon_color[4], float icon_border[4])
{
float text[4];
@@ -3069,11 +2975,8 @@ static void outliner_draw_active_indicator(const float minx,
GPU_blend(GPU_BLEND_ALPHA); /* Round-box disables. */
}
-static void outliner_draw_iconrow_doit(const ARegion *region,
- uiBlock *block,
- TreeElement *te_visible,
+static void outliner_draw_iconrow_doit(uiBlock *block,
TreeElement *te,
- const uiFontStyle *fstyle,
int xmax,
int *offsx,
int ys,
@@ -3102,13 +3005,13 @@ static void outliner_draw_iconrow_doit(const ARegion *region,
if (tselem->flag & TSE_HIGHLIGHTED_ICON) {
alpha_fac += 0.5;
}
- tselem_draw_icon(block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false);
+ tselem_draw_icon(
+ block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false, num_elements);
te->xs = *offsx;
te->ys = ys;
te->xend = short(*offsx) + UI_UNIT_X;
if (num_elements > 1) {
- outliner_draw_iconrow_number(region, fstyle, *offsx, ys, te_visible, num_elements);
te->flag |= TE_ICONROW_MERGED;
}
else {
@@ -3145,16 +3048,15 @@ static void outliner_draw_iconrow(bContext *C,
const uiFontStyle *fstyle,
const TreeViewContext *tvc,
SpaceOutliner *space_outliner,
- TreeElement *te_visible,
ListBase *lb,
int level,
int xmax,
int *offsx,
int ys,
float alpha_fac,
+ bool in_bone_hierarchy,
MergedIconRow *merged)
{
- const ARegion *region = CTX_wm_region(C);
eOLDrawState active = OL_DRAWSEL_NONE;
LISTBASE_FOREACH (TreeElement *, te, lb) {
@@ -3162,8 +3064,12 @@ static void outliner_draw_iconrow(bContext *C,
te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED);
/* object hierarchy always, further constrained on level */
+ /* Bones are also hierarchies and get a merged count, but we only start recursing into them if
+ * an they are at the root level of a collapsed subtree (e.g. not "hidden" in a collapsed
+ * collection). */
+ const bool is_bone = ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL);
if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) ||
- ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL)) {
+ (in_bone_hierarchy && is_bone)) {
/* active blocks get white circle */
if (tselem->type == TSE_SOME_ID) {
if (te->idcode == ID_OB) {
@@ -3194,8 +3100,7 @@ static void outliner_draw_iconrow(bContext *C,
TSE_POSE_CHANNEL,
TSE_POSEGRP,
TSE_DEFGROUP)) {
- outliner_draw_iconrow_doit(
- region, block, te_visible, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
+ outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1);
}
else {
const int index = tree_element_id_type_to_index(te);
@@ -3207,20 +3112,25 @@ static void outliner_draw_iconrow(bContext *C,
}
}
- /* this tree element always has same amount of branches, so don't draw */
- if (tselem->type != TSE_R_LAYER) {
+ /* TSE_R_LAYER tree element always has same amount of branches, so don't draw. */
+ /* Also only recurse into bone hierarchies if a direct child of the collapsed element to merge
+ * into. */
+ const bool is_root_level_bone = is_bone && (level == 0);
+ in_bone_hierarchy |= is_root_level_bone;
+ if (!ELEM(tselem->type, TSE_R_LAYER, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL) ||
+ in_bone_hierarchy) {
outliner_draw_iconrow(C,
block,
fstyle,
tvc,
space_outliner,
- te,
&te->subtree,
level + 1,
xmax,
offsx,
ys,
alpha_fac,
+ in_bone_hierarchy,
merged);
}
}
@@ -3236,11 +3146,8 @@ static void outliner_draw_iconrow(bContext *C,
for (int j = 0; j < num_subtypes; j++) {
const int index = index_base + j;
if (merged->num_elements[index] != 0) {
- outliner_draw_iconrow_doit(region,
- block,
- te_visible,
+ outliner_draw_iconrow_doit(block,
merged->tree_element[index],
- fstyle,
xmax,
offsx,
ys,
@@ -3429,7 +3336,8 @@ static void outliner_draw_tree_element(bContext *C,
tselem,
te,
(tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac,
- true)) {
+ true,
+ 1)) {
offsx += UI_UNIT_X + 4 * ufac;
}
else {
@@ -3478,13 +3386,13 @@ static void outliner_draw_tree_element(bContext *C,
fstyle,
tvc,
space_outliner,
- te,
&te->subtree,
0,
xmax,
&tempx,
*starty,
alpha_fac,
+ false,
&merged);
GPU_blend(GPU_BLEND_NONE);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 8b6d37caa41..1d20926d16c 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -129,7 +129,6 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
region->regiontype = RGN_TYPE_TOOLS;
region->alignment = RGN_ALIGN_LEFT;
region->flag = RGN_FLAG_HIDDEN;
- region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
/* Channels. */
region = MEM_callocN(sizeof(ARegion), "channels for sequencer");
@@ -137,6 +136,7 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
BLI_addtail(&sseq->regionbase, region);
region->regiontype = RGN_TYPE_CHANNELS;
region->alignment = RGN_ALIGN_LEFT;
+ region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
/* Preview region. */
/* NOTE: if you change values here, also change them in sequencer_init_preview_region. */
diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc
index 635fbd75d74..05fb0c6a720 100644
--- a/source/blender/editors/space_view3d/space_view3d.cc
+++ b/source/blender/editors/space_view3d/space_view3d.cc
@@ -175,11 +175,11 @@ bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion
void ED_view3d_init_mats_rv3d(const struct Object *ob, struct RegionView3D *rv3d)
{
/* local viewmat and persmat, to calculate projections */
- mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
- mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
+ mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->object_to_world);
+ mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->object_to_world);
/* initializes object space clipping, speeds up clip tests */
- ED_view3d_clipping_local(rv3d, ob->obmat);
+ ED_view3d_clipping_local(rv3d, ob->object_to_world);
}
void ED_view3d_init_mats_rv3d_gl(const struct Object *ob, struct RegionView3D *rv3d)
@@ -189,7 +189,7 @@ void ED_view3d_init_mats_rv3d_gl(const struct Object *ob, struct RegionView3D *r
/* We have to multiply instead of loading `viewmatob` to make
* it work with duplis using display-lists, otherwise it will
* override the dupli-matrix. */
- GPU_matrix_mul(ob->obmat);
+ GPU_matrix_mul(ob->object_to_world);
}
#ifdef DEBUG
@@ -710,7 +710,7 @@ static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
copy_v3_v3(obmat_final[3], snap_data->loc);
float scale[3];
- mat4_to_size(scale, ob->obmat);
+ mat4_to_size(scale, ob->object_to_world);
rescale_m4(obmat_final, scale);
const BoundBox *bb = BKE_object_boundbox_get(ob);
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 4153f19f8be..83835535d49 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -474,7 +474,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
/* Location, X/Y/Z */
mul_v3_fl(median_basis.generic.location, 1.0f / (float)tot);
if (v3d->flag & V3D_GLOBAL_STATS) {
- mul_m4_v3(ob->obmat, median_basis.generic.location);
+ mul_m4_v3(ob->object_to_world, median_basis.generic.location);
}
if (has_meshdata) {
@@ -954,7 +954,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median));
if (v3d->flag & V3D_GLOBAL_STATS) {
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_v3(ob->imat, median_basis.generic.location);
mul_m4_v3(ob->imat, ve_median_basis.generic.location);
}
@@ -1215,7 +1215,7 @@ static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d
BKE_object_dimensions_get(ob, tfp->ob_dims);
copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims);
copy_v3_v3(tfp->ob_scale_orig, ob->scale);
- copy_m4_m4(tfp->ob_obmat_orig, ob->obmat);
+ copy_m4_m4(tfp->ob_obmat_orig, ob->object_to_world);
uiDefBut(block,
UI_BTYPE_LABEL,
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index b5962647278..299c8638b02 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -142,7 +142,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph
vctrl->obtfm = BKE_object_tfm_backup(ob_back);
BKE_object_where_is_calc(depsgraph, scene, v3d->camera);
- negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
+ negate_v3_v3(rv3d->ofs, v3d->camera->object_to_world[3]);
rv3d->dist = 0.0;
}
@@ -251,7 +251,7 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl,
invert_m4_m4(prev_view_imat, vctrl->view_mat_prev);
mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
- mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat);
+ mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->object_to_world);
if (object_apply_mat4_with_protect(vctrl->root_parent, parent_mat, false, rv3d, view_mat)) {
/* Calculate again since the view locking changes the matrix. */
diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc
index 8a86889f2d0..31b26ba4cda 100644
--- a/source/blender/editors/space_view3d/view3d_draw.cc
+++ b/source/blender/editors/space_view3d/view3d_draw.cc
@@ -2066,7 +2066,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
rv3d.persp = RV3D_CAMOB;
- copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
+ copy_m4_m4(rv3d.viewinv, v3d.camera->object_to_world);
normalize_m4(rv3d.viewinv);
invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index 4f73e2fada2..8a4301d1314 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -188,7 +188,7 @@ static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup
bspline_group->handles[i].index = i;
float mat[4][4];
- mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat);
+ mul_m4_m4m4(mat, ob->object_to_world, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat);
copy_m4_m4(gz->matrix_space, mat);
/* need to set property here for undo. TODO: would prefer to do this in _init. */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 952ef56710b..56a1f6212a0 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -85,7 +85,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup)
struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
gzgroup->customdata = cagzgroup;
- negate_v3_v3(dir, ob->obmat[2]);
+ negate_v3_v3(dir, ob->object_to_world[2]);
/* dof distance */
{
@@ -138,11 +138,11 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr);
- negate_v3_v3(dir, ob->obmat[2]);
+ negate_v3_v3(dir, ob->object_to_world[2]);
if ((ca->flag & CAM_SHOWLIMITS) && (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST)) {
- WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir);
+ WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->object_to_world[3]);
+ WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->object_to_world[1], dir);
WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize);
WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false);
@@ -183,17 +183,17 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f;
unit_m4(widget->matrix_basis);
- WM_gizmo_set_matrix_location(widget, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir);
+ WM_gizmo_set_matrix_location(widget, ob->object_to_world[3]);
+ WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->object_to_world[1], dir);
if (is_ortho) {
scale_matrix = ca->ortho_scale * 0.5f;
}
else {
const float ob_scale_inv[3] = {
- 1.0f / len_v3(ob->obmat[0]),
- 1.0f / len_v3(ob->obmat[1]),
- 1.0f / len_v3(ob->obmat[2]),
+ 1.0f / len_v3(ob->object_to_world[0]),
+ 1.0f / len_v3(ob->object_to_world[1]),
+ 1.0f / len_v3(ob->object_to_world[2]),
};
const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) /
3.0f;
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
index 41a763192ce..03fc7328e39 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c
@@ -139,7 +139,7 @@ static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzg
BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
- copy_m4_m4(gz->matrix_basis, ob->obmat);
+ copy_m4_m4(gz->matrix_basis, ob->object_to_world);
RNA_enum_set(gz->ptr,
"transform",
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
index 58b43301397..d194e2a6279 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c
@@ -87,8 +87,8 @@ static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *gzgr
PointerRNA field_ptr;
RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
- WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
- WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]);
+ WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]);
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->object_to_world[2]);
WM_gizmo_set_matrix_offset_location(gz, ofs);
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1);
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c
index 4401dbf7935..0b115bc0604 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_light.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c
@@ -85,10 +85,10 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr
Light *la = ob->data;
float dir[3];
- negate_v3_v3(dir, ob->obmat[2]);
+ negate_v3_v3(dir, ob->object_to_world[2]);
WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir);
- WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
+ WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]);
/* need to set property here for undo. TODO: would prefer to do this in _init. */
PointerRNA lamp_ptr;
@@ -199,7 +199,7 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr
Light *la = ob->data;
wmGizmo *gz = wwrapper->gizmo;
- copy_m4_m4(gz->matrix_basis, ob->obmat);
+ copy_m4_m4(gz->matrix_basis, ob->object_to_world);
int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE;
if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
@@ -296,7 +296,7 @@ static void WIDGETGROUP_light_target_draw_prepare(const bContext *C, wmGizmoGrou
Object *ob = BKE_view_layer_active_object_get(view_layer);
wmGizmo *gz = wwrapper->gizmo;
- normalize_m4_m4(gz->matrix_basis, ob->obmat);
+ normalize_m4_m4(gz->matrix_basis, ob->object_to_world);
unit_m4(gz->matrix_offset);
if (ob->type == OB_LAMP) {
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc
index 793ada4f577..86aecfb6c34 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc
@@ -97,7 +97,7 @@ static void gizmo_preselect_elem_draw(const bContext *C, wmGizmo *gz)
MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
if (gz_ele->base_index != -1) {
Object *ob = gz_ele->bases[gz_ele->base_index]->object;
- EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat);
+ EDBM_preselect_elem_draw(gz_ele->psel, ob->object_to_world);
}
}
@@ -185,7 +185,7 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
BMVert *vert = (BMVert *)eve_test;
float vert_p_co[2], vert_co[3];
const float mval_f[2] = {float(vc.mval[0]), float(vc.mval[1])};
- mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co);
+ mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->object_to_world, vert->co);
ED_view3d_project_v2(vc.region, vert_co, vert_p_co);
float len = len_v2v2(vert_p_co, mval_f);
if (len < 35) {
@@ -330,7 +330,7 @@ static void gizmo_preselect_edgering_draw(const bContext *C, wmGizmo *gz)
MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz;
if (gz_ring->base_index != -1) {
Object *ob = gz_ring->bases[gz_ring->base_index]->object;
- EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat);
+ EDBM_preselect_edgering_draw(gz_ring->psel, ob->object_to_world);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_iterators.cc b/source/blender/editors/space_view3d/view3d_iterators.cc
index 932563863fe..aaa817ec00c 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.cc
+++ b/source/blender/editors/space_view3d/view3d_iterators.cc
@@ -307,7 +307,7 @@ void meshobject_foreachScreenVert(
&me->vdata, CD_PROP_BOOL, ".hide_vert");
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat);
+ ED_view3d_clipping_local(vc->rv3d, vc->obact->object_to_world);
}
BKE_mesh_foreach_mapped_vert(me, meshobject_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP);
@@ -353,7 +353,8 @@ void mesh_foreachScreenVert(
data.clip_flag = clip_flag;
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ ED_view3d_clipping_local(vc->rv3d,
+ vc->obedit->object_to_world); /* for local clipping lookups */
}
BM_mesh_elem_table_ensure(vc->em->bm, BM_VERT);
@@ -422,7 +423,8 @@ void mesh_foreachScreenEdge(ViewContext *vc,
data.clip_flag = clip_flag;
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ ED_view3d_clipping_local(vc->rv3d,
+ vc->obedit->object_to_world); /* for local clipping lookups */
}
if (clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) {
@@ -520,7 +522,8 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc,
BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE);
if ((clip_flag & V3D_PROJ_TEST_CLIP_BB) && (vc->rv3d->clipbb != nullptr)) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups. */
+ ED_view3d_clipping_local(vc->rv3d,
+ vc->obedit->object_to_world); /* for local clipping lookups. */
BKE_mesh_foreach_mapped_edge(
me, vc->em->bm->totedge, mesh_foreachScreenEdge_clip_bb_segment__mapFunc, &data);
}
@@ -612,7 +615,8 @@ void nurbs_foreachScreenVert(ViewContext *vc,
ED_view3d_check_mats_rv3d(vc->rv3d);
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ ED_view3d_clipping_local(vc->rv3d,
+ vc->obedit->object_to_world); /* for local clipping lookups */
}
LISTBASE_FOREACH (Nurb *, nu, nurbs) {
@@ -732,7 +736,7 @@ void lattice_foreachScreenVert(ViewContext *vc,
ED_view3d_check_mats_rv3d(vc->rv3d);
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
+ ED_view3d_clipping_local(vc->rv3d, obedit->object_to_world); /* for local clipping lookups */
}
for (i = 0; i < N; i++, bp++, co += 3) {
diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c
index 25073d02a7f..7d2beecd9a3 100644
--- a/source/blender/editors/space_view3d/view3d_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_navigate.c
@@ -185,7 +185,7 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
copy_v3_v3(lastofs, stroke);
}
else {
- copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
+ copy_v3_v3(lastofs, ob_act_eval->object_to_world[3]);
}
is_set = true;
}
@@ -199,7 +199,7 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
}
mul_v2_fl(lastofs, 1.0f / 4.0f);
- mul_m4_v3(ob_act_eval->obmat, lastofs);
+ mul_m4_v3(ob_act_eval->object_to_world, lastofs);
is_set = true;
}
@@ -219,11 +219,11 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent);
- mul_m4_v3(ob_eval->obmat, cent);
+ mul_m4_v3(ob_eval->object_to_world, cent);
add_v3_v3(select_center, cent);
}
else {
- add_v3_v3(select_center, ob_eval->obmat[3]);
+ add_v3_v3(select_center, ob_eval->object_to_world[3]);
}
tot++;
}
@@ -626,7 +626,7 @@ static void view3d_object_calc_minmax(Depsgraph *depsgraph,
if (BKE_object_minmax_dupli(depsgraph, scene, ob_eval, min, max, false) == 0) {
/* Use if duplis aren't found. */
if (only_center) {
- minmax_v3v3_v3(min, max, ob_eval->obmat[3]);
+ minmax_v3v3_v3(min, max, ob_eval->object_to_world[3]);
}
else {
BKE_object_minmax(ob_eval, min, max, false);
@@ -934,8 +934,8 @@ static int viewselected_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
if ((ob_eval) && (ok)) {
- mul_m4_v3(ob_eval->obmat, min);
- mul_m4_v3(ob_eval->obmat, max);
+ mul_m4_v3(ob_eval->object_to_world, min);
+ mul_m4_v3(ob_eval->object_to_world, max);
}
}
else if (is_face_map) {
diff --git a/source/blender/editors/space_view3d/view3d_navigate_smoothview.c b/source/blender/editors/space_view3d/view3d_navigate_smoothview.c
index 6b150d1e771..a5eee436fdb 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_smoothview.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_smoothview.c
@@ -259,7 +259,7 @@ void ED_view3d_smooth_view_ex(
Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
if (sview->ofs != NULL) {
sms.dst.dist = ED_view3d_offset_distance(
- ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
+ ob_camera_eval->object_to_world, sview->ofs, VIEW3D_DIST_FALLBACK);
}
ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
sms.to_camera = true; /* restore view3d values in end */
@@ -282,7 +282,8 @@ void ED_view3d_smooth_view_ex(
if (sview->camera_old) {
Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
if (sview->ofs != NULL) {
- sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, sview->ofs, 0.0f);
+ sms.src.dist = ED_view3d_offset_distance(
+ ob_camera_old_eval->object_to_world, sview->ofs, 0.0f);
}
ED_view3d_from_object(
ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c
index 3e0ce892b5a..fcb4f549353 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_walk.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c
@@ -849,11 +849,15 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event)
if (ret) {
WalkTeleport *teleport = &walk->teleport;
+
+ /* Store the current navigation mode if we are not already teleporting. */
+ if (teleport->state == WALK_TELEPORT_STATE_OFF) {
+ teleport->navigation_mode = walk->navigation_mode;
+ }
teleport->state = WALK_TELEPORT_STATE_ON;
teleport->initial_time = PIL_check_seconds_timer();
teleport->duration = U.walk_navigation.teleport_time;
- teleport->navigation_mode = walk->navigation_mode;
walk_navigation_mode_set(walk, WALK_MODE_FREE);
copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
@@ -864,9 +868,7 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event)
sub_v3_v3v3(teleport->direction, loc, teleport->origin);
}
- else {
- walk->teleport.state = WALK_TELEPORT_STATE_OFF;
- }
+
break;
}
@@ -1229,11 +1231,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
/* keep moving if we were moving */
copy_v2_v2(dvec, walk->teleport.direction);
- z_cur = walk->rv3d->viewinv[3][2];
- z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;
+ z_cur = walk->rv3d->viewinv[3][2] / walk->grid;
+ z_new = (walk->teleport.origin[2] / walk->grid) - getFreeFallDistance(walk->gravity, t);
/* jump */
- z_new += t * walk->speed_jump * walk->grid;
+ z_new += t * walk->speed_jump;
/* duration is the jump duration */
if (t > walk->teleport.duration) {
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index c5f951bd64c..2718f14c855 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -80,7 +80,7 @@ eV3DProjStatus ED_view3d_project_base(const struct ARegion *region,
float r_co[2])
{
eV3DProjStatus ret = ED_view3d_project_float_global(
- region, base->object->obmat[3], r_co, V3D_PROJ_TEST_CLIP_DEFAULT);
+ region, base->object->object_to_world[3], r_co, V3D_PROJ_TEST_CLIP_DEFAULT);
/* Prevent uninitialized values when projection fails,
* although the callers should check the return value. */
@@ -687,7 +687,7 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob, fl
{
float vmat[4][4];
- mul_m4_m4m4(vmat, rv3d->viewmat, ob->obmat);
+ mul_m4_m4m4(vmat, rv3d->viewmat, ob->object_to_world);
mul_m4_m4m4(r_pmat, rv3d->winmat, vmat);
}
diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc
index cba85097071..9c450e85d23 100644
--- a/source/blender/editors/space_view3d/view3d_select.cc
+++ b/source/blender/editors/space_view3d/view3d_select.cc
@@ -2303,7 +2303,7 @@ static Base *mouse_select_object_center(ViewContext *vc, Base *startbase, const
if (BASE_SELECTABLE(v3d, base)) {
float screen_co[2];
if (ED_view3d_project_float_global(
- region, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) ==
+ region, base->object->object_to_world[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) ==
V3D_PROJ_RET_OK) {
float dist_test = len_manhattan_v2v2(mval_fl, screen_co);
if (base == oldbasact) {
@@ -2704,7 +2704,10 @@ static bool ed_object_select_pick(bContext *C,
/* When there is no `baseact` this will have operated on `oldbasact`,
* allowing #SelectPick_Params.deselect_all work in pose-mode.
* In this case no object operations are needed. */
- if (basact != nullptr) {
+ if (basact == nullptr) {
+ handled = true;
+ }
+ else {
/* By convention the armature-object is selected when in pose-mode.
* While leaving it unselected will work, leaving pose-mode would leave the object
* active + unselected which isn't ideal when performing other actions on the object. */
@@ -4725,9 +4728,10 @@ static bool object_circle_select(ViewContext *vc,
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) {
float screen_co[2];
- if (ED_view3d_project_float_global(
- vc->region, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) ==
- V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_global(vc->region,
+ base->object->object_to_world[3],
+ screen_co,
+ V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) {
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
changed = true;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index ee6b1886dc2..f2b952c4f46 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -86,18 +86,18 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
}
if (tvs.transverts_tot != 0) {
- copy_m3_m4(bmat, obedit->obmat);
+ copy_m3_m4(bmat, obedit->object_to_world);
invert_m3_m3(imat, bmat);
tv = tvs.transverts;
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
copy_v3_v3(vec, tv->loc);
mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
+ add_v3_v3(vec, obedit->object_to_world[3]);
vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
- sub_v3_v3(vec, obedit->obmat[3]);
+ sub_v3_v3(vec, obedit->object_to_world[3]);
mul_m3_v3(imat, vec);
copy_v3_v3(tv->loc, vec);
@@ -118,7 +118,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
bPoseChannel *pchan_eval;
bArmature *arm_eval = ob_eval->data;
- invert_m4_m4(ob_eval->imat, ob_eval->obmat);
+ invert_m4_m4(ob_eval->imat, ob_eval->object_to_world);
for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) {
if (pchan_eval->bone->flag & BONE_SELECTED) {
@@ -129,7 +129,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
/* get nearest grid point to snap to */
copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
/* We must operate in world space! */
- mul_m4_v3(ob_eval->obmat, nLoc);
+ mul_m4_v3(ob_eval->object_to_world, nLoc);
vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
@@ -214,9 +214,12 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
for (int ob_index = 0; ob_index < objects_eval_len; ob_index++) {
Object *ob_eval = objects_eval[ob_index];
Object *ob = DEG_get_original_object(ob_eval);
- vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
- vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
- vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
+ vec[0] = -ob_eval->object_to_world[3][0] +
+ gridf * floorf(0.5f + ob_eval->object_to_world[3][0] / gridf);
+ vec[1] = -ob_eval->object_to_world[3][1] +
+ gridf * floorf(0.5f + ob_eval->object_to_world[3][1] / gridf);
+ vec[2] = -ob_eval->object_to_world[3][2] +
+ gridf * floorf(0.5f + ob_eval->object_to_world[3][2] / gridf);
if (ob->parent) {
float originmat[3][3];
@@ -343,11 +346,11 @@ static bool snap_selected_to_location(bContext *C,
}
if (tvs.transverts_tot != 0) {
- copy_m3_m4(bmat, obedit->obmat);
+ copy_m3_m4(bmat, obedit->object_to_world);
invert_m3_m3(imat, bmat);
/* get the cursor in object space */
- sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
+ sub_v3_v3v3(snap_target_local, snap_target_global, obedit->object_to_world[3]);
mul_m3_v3(imat, snap_target_local);
if (use_offset) {
@@ -384,7 +387,7 @@ static bool snap_selected_to_location(bContext *C,
bArmature *arm = ob->data;
float snap_target_local[3];
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global);
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
@@ -409,7 +412,7 @@ static bool snap_selected_to_location(bContext *C,
float cursor_pose[3];
if (use_offset) {
- mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]);
+ mul_v3_m4v3(cursor_pose, ob->object_to_world, pchan->pose_mat[3]);
add_v3_v3(cursor_pose, offset_global);
mul_m4_v3(ob->imat, cursor_pose);
@@ -510,13 +513,13 @@ static bool snap_selected_to_location(bContext *C,
float cursor_parent[3]; /* parent-relative */
if (use_offset) {
- add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
+ add_v3_v3v3(cursor_parent, ob->object_to_world[3], offset_global);
}
else {
copy_v3_v3(cursor_parent, snap_target_global);
}
- sub_v3_v3(cursor_parent, ob->obmat[3]);
+ sub_v3_v3(cursor_parent, ob->object_to_world[3]);
if (ob->parent) {
float originmat[3][3], parentmat[4][4];
@@ -730,7 +733,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3])
tracking = &clip->tracking;
- copy_m4_m4(cammat, ob->obmat);
+ copy_m4_m4(cammat, ob->object_to_world);
BKE_tracking_get_camera_object_matrix(ob, mat);
@@ -809,13 +812,13 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs
count += tvs.transverts_tot;
if (tvs.transverts_tot != 0) {
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
- copy_m3_m4(bmat, obedit_eval->obmat);
+ copy_m3_m4(bmat, obedit_eval->object_to_world);
tv = tvs.transverts;
for (int i = 0; i < tvs.transverts_tot; i++, tv++) {
copy_v3_v3(vec, tv->loc);
mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit_eval->obmat[3]);
+ add_v3_v3(vec, obedit_eval->object_to_world[3]);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, max, vec);
}
@@ -835,7 +838,7 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs
if (arm->layer & pchan->bone->layer) {
if (pchan->bone->flag & BONE_SELECTED) {
copy_v3_v3(vec, pchan->pose_head);
- mul_m4_v3(obact_eval->obmat, vec);
+ mul_m4_v3(obact_eval->object_to_world, vec);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, max, vec);
count++;
@@ -845,7 +848,7 @@ static bool snap_curs_to_sel_ex(bContext *C, const int pivot_point, float r_curs
}
else {
FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
- copy_v3_v3(vec, ob_eval->obmat[3]);
+ copy_v3_v3(vec, ob_eval->object_to_world[3]);
/* special case for camera -- snap to bundles */
if (ob_eval->type == OB_CAMERA) {
@@ -1008,7 +1011,7 @@ bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
float ob_min[3], ob_max[3];
bool changed;
- changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
+ changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->object_to_world, SELECT);
if (changed) {
minmax_v3v3_v3(r_min, r_max, ob_min);
minmax_v3v3_v3(r_min, r_max, ob_max);
@@ -1024,13 +1027,13 @@ bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
return false;
}
- copy_m3_m4(bmat, obedit->obmat);
+ copy_m3_m4(bmat, obedit->object_to_world);
tv = tvs.transverts;
for (int a = 0; a < tvs.transverts_tot; a++, tv++) {
copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
+ add_v3_v3(vec, obedit->object_to_world[3]);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(r_min, r_max, vec);
}
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 1fc16939f3f..fc26e6b4a06 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -281,7 +281,7 @@ void ED_view3d_clipping_calc(
/* optionally transform to object space */
if (ob) {
float imat[4][4];
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
for (int val = 0; val < 8; val++) {
mul_m4_v3(imat, bb->vec[val]);
@@ -291,7 +291,7 @@ void ED_view3d_clipping_calc(
/* verify if we have negative scale. doing the transform before cross
* product flips the sign of the vector compared to doing cross product
* before transform then, so we correct for that. */
- int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
+ int flip_sign = (ob) ? is_negative_m4(ob->object_to_world) : false;
ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
}
@@ -466,7 +466,8 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph,
if (v3d->camera) {
Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
- rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ rv3d->dist = ED_view3d_offset_distance(
+ ob_camera_eval->object_to_world, rv3d->ofs, VIEW3D_DIST_FALLBACK);
ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
}
@@ -558,7 +559,7 @@ void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph,
if (calc_dist) {
/* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
rv3d->dist = ED_view3d_offset_distance(
- ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ ob_camera_eval->object_to_world, rv3d->ofs, VIEW3D_DIST_FALLBACK);
}
ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
}
@@ -592,12 +593,12 @@ bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionV
ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- normalize_m4_m4(tmat, ob_camera_eval->obmat);
+ normalize_m4_m4(tmat, ob_camera_eval->object_to_world);
invert_m4_m4(imat, tmat);
mul_m4_m4m4(diff_mat, view_mat, imat);
- mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat);
+ mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->object_to_world);
BKE_object_tfm_protected_backup(root_parent, &obtfm);
BKE_object_apply_mat4(root_parent, parent_mat, true, false);
@@ -1508,7 +1509,7 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c
void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
{
- ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
+ ED_view3d_from_m4(ob->object_to_world, ofs, quat, dist);
if (lens) {
CameraParams params;
@@ -1555,7 +1556,7 @@ static bool view3d_camera_to_view_selected_impl(struct Main *bmain,
is_ortho_camera = true;
}
- copy_m4_m4(obmat_new, camera_ob_eval->obmat);
+ copy_m4_m4(obmat_new, camera_ob_eval->object_to_world);
copy_v3_v3(obmat_new[3], co);
/* only touch location */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index d0db4de0c47..c630a1a5653 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -365,7 +365,7 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
rv3d->view = RV3D_VIEW_USER; /* don't show the grid */
- normalize_m4_m4(bmat, ob->obmat);
+ normalize_m4_m4(bmat, ob->object_to_world);
invert_m4_m4(rv3d->viewmat, bmat);
/* view quat calculation, needed for add object */
@@ -404,12 +404,12 @@ void view3d_viewmatrix_set(Depsgraph *depsgraph,
Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_center);
float vec[3];
- copy_v3_v3(vec, ob_eval->obmat[3]);
+ copy_v3_v3(vec, ob_eval->object_to_world[3]);
if (ob_eval->type == OB_ARMATURE && v3d->ob_center_bone[0]) {
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_center_bone);
if (pchan) {
copy_v3_v3(vec, pchan->pose_mat[3]);
- mul_m4_v3(ob_eval->obmat, vec);
+ mul_m4_v3(ob_eval->object_to_world, vec);
}
}
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 34e5b78c48f..ad6ab625438 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1594,9 +1594,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
RNA_enum_set(op->ptr, "snap_target", t->tsnap.source_select);
eSnapTargetSelect target = t->tsnap.target_select;
- RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) != 0);
- RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) != 0);
- RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) != 0);
+ RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) == 0);
+ RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) == 0);
+ RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) == 0);
RNA_boolean_set(
op->ptr, "use_snap_selectable", (target & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0);
}
@@ -1721,13 +1721,18 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
-static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2])
+static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precision)
{
+ /* Default values. */
+ r_snap[0] = r_snap[1] = 1.0f;
+ r_snap[2] = 0.0f;
+ *r_snap_precision = 0.1f;
+
if (t->spacetype == SPACE_VIEW3D) {
if (t->region->regiondata) {
View3D *v3d = t->area->spacedata.first;
- r_snap[0] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL) * 1.0f;
- r_snap[1] = r_snap[0] * 0.1f;
+ r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(
+ t->scene, v3d, t->region, NULL);
}
}
else if (t->spacetype == SPACE_IMAGE) {
@@ -1741,24 +1746,16 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2])
ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size);
/* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */
r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor);
- r_snap[1] = r_snap[0] / 2.0f;
- r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor);
- r_snap_y[1] = r_snap_y[0] / 2.0f;
+ r_snap[1] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor);
+ *r_snap_precision = 0.5f;
}
else if (t->spacetype == SPACE_CLIP) {
- r_snap[0] = 0.125f;
- r_snap[1] = 0.0625f;
+ r_snap[0] = r_snap[1] = 0.125f;
+ *r_snap_precision = 0.5f;
}
else if (t->spacetype == SPACE_NODE) {
r_snap[0] = r_snap[1] = ED_node_grid_size();
}
- else if (t->spacetype == SPACE_GRAPH) {
- r_snap[0] = 1.0;
- r_snap[1] = 0.1f;
- }
- else {
- r_snap[0] = r_snap[1] = 1.0f;
- }
}
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
@@ -1898,7 +1895,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initSnapping(t, op); /* Initialize snapping data AFTER mode flags */
- initSnapSpatial(t, t->snap_spatial_x, t->snap_spatial_y);
+ initSnapSpatial(t, t->snap_spatial, &t->snap_spatial_precision);
/* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
* will be removed (ton) */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 95686f12fe2..1e260ecd292 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -469,7 +469,8 @@ typedef struct TransDataContainer {
/**
* Store matrix, this avoids having to have duplicate check all over
- * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
+ * Typically: 'obedit->object_to_world' or 'poseobj->object_to_world', but may be used elsewhere
+ * too.
*/
bool use_local_mat;
@@ -555,9 +556,12 @@ typedef struct TransInfo {
/** Snapping Gears. */
float snap[2];
/** Spatial snapping gears(even when rotating, scaling... etc). */
- float snap_spatial_x[2];
- /** Spatial snapping in the Y coordinate, for non-uniform grid in UV Editor. */
- float snap_spatial_y[2];
+ float snap_spatial[3];
+ /**
+ * Precision factor that is multiplied to snap_spatial when precision
+ * modifier is enabled for snap to grid or incremental snap.
+ */
+ float snap_spatial_precision;
/** Mouse side of the current frame, 'L', 'R' or 'B' */
char frame_side;
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index fa56456d8e7..7abf0e5c00c 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -404,9 +404,11 @@ static void applyAxisConstraintVec(const TransInfo *t,
}
}
+ /* Fallback for when axes are aligned. */
+ mul_m3_v3(t->con.pmtx, out);
+
if (is_snap_to_point) {
- /* With snap points, a projection is alright, no adjustments needed. */
- mul_m3_v3(t->con.pmtx, out);
+ /* Pass. With snap points, a projection is alright, no adjustments needed. */
}
else {
const int dims = getConstraintSpaceDimension(t);
@@ -422,14 +424,9 @@ static void applyAxisConstraintVec(const TransInfo *t,
/* Disabled, as it has not proven to be really useful. (See T82386). */
// constraint_snap_plane_to_face(t, plane, out);
}
- else {
+ else if (!isPlaneProjectionViewAligned(t, plane)) {
/* View alignment correction. */
- if (!isPlaneProjectionViewAligned(t, plane)) {
- planeProjection(t, plane, in, out);
- }
- else {
- mul_m3_v3(t->con.pmtx, out);
- }
+ planeProjection(t, plane, in, out);
}
}
}
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 7a68ee1bfbf..a5b2442f11c 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -981,7 +981,7 @@ static void init_TransDataContainers(TransInfo *t,
if (tc->use_local_mat) {
BLI_assert((t->flag & T_2D_EDIT) == 0);
- copy_m4_m4(tc->mat, objects[i]->obmat);
+ copy_m4_m4(tc->mat, objects[i]->object_to_world);
copy_m3_m4(tc->mat3, tc->mat);
/* for non-invertible scale matrices, invert_m4_m4_fallback()
* can still provide a valid pivot */
@@ -1235,8 +1235,8 @@ void transform_convert_clip_mirror_modifier_apply(TransDataContainer *tc)
if (mmd->mirror_ob) {
float obinv[4][4];
- invert_m4_m4(obinv, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, obinv, ob->obmat);
+ invert_m4_m4(obinv, mmd->mirror_ob->object_to_world);
+ mul_m4_m4m4(mtx, obinv, ob->object_to_world);
invert_m4_m4(imtx, mtx);
}
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 8466fd88e1d..4798d666d70 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -226,8 +226,6 @@ void transform_convert_mesh_crazyspace_transdata_set(const float mtx[3][3],
struct TransData *r_td);
void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_crazyspace_data);
-void special_aftertrans_update__mesh(bContext *C, TransInfo *t);
-
/* transform_convert_mesh_edge.c */
extern TransConvertTypeInfo TransConvertType_MeshEdge;
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 4b79625fa66..2e37f6b7c34 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -306,8 +306,9 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
* just make things obey standard rotation locks too */
if (data->rootbone == 0) {
for (bPoseChannel *pchan_iter = pchan; pchan_iter; pchan_iter = pchan_iter->parent) {
- /* here, we set ik-settings for bone from pchan->protectflag */
- /* XXX: careful with quats/axis-angle rotations where we're locking 4d components. */
+ /* Here, we set IK-settings for bone from `pchan->protectflag`. */
+ /* XXX: careful with quaternion/axis-angle rotations
+ * where we're locking 4d components. */
if (pchan_iter->protectflag & OB_LOCK_ROTX) {
pchan_iter->ikflag |= BONE_IK_NO_XDOF_TEMP;
}
@@ -592,7 +593,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
td->ext->rotOrder = pchan->rotmode;
/* proper way to get parent transform + own transform + constraints transform */
- copy_m3_m4(omat, ob->obmat);
+ copy_m3_m4(omat, ob->object_to_world);
/* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
{
@@ -954,7 +955,7 @@ static void createTransArmatureVerts(bContext *UNUSED(C), TransInfo *t)
bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
BoneInitData *bid = tc->custom.type.data;
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone");
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
index 404b1293208..13ba28ec3d0 100644
--- a/source/blender/editors/transform/transform_convert_curve.c
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -174,7 +174,7 @@ static void createTransCurveVerts(bContext *UNUSED(C), TransInfo *t)
transform_mode_use_local_origins(t));
float mtx[3][3], smtx[3][3];
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
TransData *td = tc->data;
diff --git a/source/blender/editors/transform/transform_convert_lattice.c b/source/blender/editors/transform/transform_convert_lattice.c
index b77538dc249..e9b3401974b 100644
--- a/source/blender/editors/transform/transform_convert_lattice.c
+++ b/source/blender/editors/transform/transform_convert_lattice.c
@@ -66,7 +66,7 @@ static void createTransLatticeVerts(bContext *UNUSED(C), TransInfo *t)
}
tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)");
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
td = tc->data;
diff --git a/source/blender/editors/transform/transform_convert_mball.c b/source/blender/editors/transform/transform_convert_mball.c
index 7ae93524d0b..c90052e9e8c 100644
--- a/source/blender/editors/transform/transform_convert_mball.c
+++ b/source/blender/editors/transform/transform_convert_mball.c
@@ -61,7 +61,7 @@ static void createTransMBallVerts(bContext *UNUSED(C), TransInfo *t)
tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
"MetaElement_TransExtension");
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
for (ml = mb->editelems->first; ml; ml = ml->next) {
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index af7982f862a..3192b1b6786 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1527,7 +1527,7 @@ static void createTransEditVerts(bContext *UNUSED(C), TransInfo *t)
em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
}
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
/* we use a pseudo-inverse so that when one of the axes is scaled to 0,
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
@@ -2068,7 +2068,7 @@ static void recalcData_mesh(TransInfo *t)
/** \name Special After Transform Mesh
* \{ */
-void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
+static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
{
const bool is_canceling = (t->state == TRANS_CANCEL);
const bool use_automerge = !is_canceling && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c
index 7f26029850b..fd62b199345 100644
--- a/source/blender/editors/transform/transform_convert_mesh_edge.c
+++ b/source/blender/editors/transform/transform_convert_mesh_edge.c
@@ -62,7 +62,7 @@ static void createTransEdge(bContext *UNUSED(C), TransInfo *t)
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease");
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
/* create data we need */
@@ -125,5 +125,5 @@ TransConvertTypeInfo TransConvertType_MeshEdge = {
/* flags */ T_EDIT,
/* createTransData */ createTransEdge,
/* recalcData */ recalcData_mesh_edge,
- /* special_aftertrans_update */ special_aftertrans_update__mesh,
+ /* special_aftertrans_update */ NULL,
};
diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c
index 376e559181e..cb6108a4c45 100644
--- a/source/blender/editors/transform/transform_convert_mesh_skin.c
+++ b/source/blender/editors/transform/transform_convert_mesh_skin.c
@@ -130,7 +130,7 @@ static void createTransMeshSkin(bContext *UNUSED(C), TransInfo *t)
em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
}
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
/* we use a pseudo-inverse so that when one of the axes is scaled to 0,
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
diff --git a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c
index 59836180166..d253261f458 100644
--- a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c
+++ b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c
@@ -131,7 +131,7 @@ static void createTransMeshVertCData(bContext *UNUSED(C), TransInfo *t)
em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
}
- copy_m3_m4(mtx, tc->obedit->obmat);
+ copy_m3_m4(mtx, tc->obedit->object_to_world);
/* we use a pseudo-inverse so that when one of the axes is scaled to 0,
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c
index af5a51cbff6..830094ebe83 100644
--- a/source/blender/editors/transform/transform_convert_nla.c
+++ b/source/blender/editors/transform/transform_convert_nla.c
@@ -60,9 +60,9 @@ typedef struct TransDataNla {
* \{ */
/**
- * \brief Applies a translation to the given NlaStrip.
- * \param strip_rna_ptr The RNA pointer of the NLA strip to modify.
- * \param transdata The transformation info structure.
+ * \brief Applies a translation to the given #NlaStrip.
+ * \param strip_rna_ptr: The RNA pointer of the NLA strip to modify.
+ * \param transdata: The transformation info structure.
*/
static void applyTransformNLA_translation(PointerRNA *strip_rna_ptr, const TransDataNla *transdata)
{
diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc
index eb5eb822d69..6ab0e1fe701 100644
--- a/source/blender/editors/transform/transform_convert_node.cc
+++ b/source/blender/editors/transform/transform_convert_node.cc
@@ -155,9 +155,52 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Node Transform Creation
+/** \name Flush Transform Nodes
* \{ */
+static void node_snap_grid_apply(TransInfo *t)
+{
+ int i;
+
+ if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) {
+ return;
+ }
+
+ float grid_size[2];
+ copy_v2_v2(grid_size, t->snap_spatial);
+ if (t->modifiers & MOD_PRECISION) {
+ mul_v2_fl(grid_size, t->snap_spatial_precision);
+ }
+
+ /* Early exit on unusable grid size. */
+ if (is_zero_v2(grid_size)) {
+ return;
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td;
+
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ float iloc[2], loc[2], tvec[2];
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) {
+ continue;
+ }
+
+ copy_v2_v2(iloc, td->loc);
+
+ loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0];
+ loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1];
+
+ sub_v2_v2v2(tvec, loc, iloc);
+ add_v2_v2(td->loc, tvec);
+ }
+ }
+}
+
static void flushTransNodes(TransInfo *t)
{
using namespace blender::ed;
@@ -191,7 +234,7 @@ static void flushTransNodes(TransInfo *t)
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- applyGridAbsolute(t);
+ node_snap_grid_apply(t);
/* flush to 2d vector from internally used 3d vector */
for (int i = 0; i < tc->data_len; i++) {
diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c
index 0dcfd7206ad..55f7cd9b23d 100644
--- a/source/blender/editors/transform/transform_convert_object.c
+++ b/source/blender/editors/transform/transform_convert_object.c
@@ -158,14 +158,14 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
copy_qt_qt(td->ext->oquat, ob->quat);
}
/* update object's loc/rot to get current rigid body transform */
- mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
+ mat4_to_loc_rot_size(ob->loc, rot, scale, ob->object_to_world);
sub_v3_v3(ob->loc, ob->dloc);
BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
}
}
/* axismtx has the real orientation */
- transform_orientations_create_from_axis(td->axismtx, UNPACK3(ob->obmat));
+ transform_orientations_create_from_axis(td->axismtx, UNPACK3(ob->object_to_world));
if (t->orient_type_mask & (1 << V3D_ORIENT_GIMBAL)) {
if (!gimbal_axis_object(ob, td->ext->axismtx_gimbal)) {
copy_m3_m3(td->ext->axismtx_gimbal, td->axismtx);
@@ -192,7 +192,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
* More proper solution would be to make a shallow copy of the object and
* evaluate that, and access matrix of that evaluated copy of the object.
* Might be more tricky than it sounds, if some logic later on accesses the
- * object matrix via td->ob->obmat. */
+ * object matrix via td->ob->object_to_world. */
Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob);
if (skip_invert == false && constinv == false) {
object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */
@@ -208,7 +208,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
}
/* Copy newly evaluated fields to the original object, similar to how
* active dependency graph will do it. */
- copy_m4_m4(ob->obmat, object_eval->obmat);
+ copy_m4_m4(ob->object_to_world, object_eval->object_to_world);
/* Only copy negative scale flag, this is the only flag which is modified by
* the BKE_object_where_is_calc(). The rest of the flags we need to keep,
* otherwise we might lose dupli flags (see T61787). */
@@ -258,9 +258,9 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
copy_v3_v3(td->ext->isize, ob->scale);
copy_v3_v3(td->ext->dscale, ob->dscale);
- copy_v3_v3(td->center, ob->obmat[3]);
+ copy_v3_v3(td->center, ob->object_to_world[3]);
- copy_m4_m4(td->ext->obmat, ob->obmat);
+ copy_m4_m4(td->ext->obmat, ob->object_to_world);
/* is there a need to set the global<->data space conversion matrices? */
if (ob->parent || constinv) {
@@ -271,7 +271,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
* done, as it doesn't work well.
*/
BKE_object_to_mat3(ob, obmtx);
- copy_m3_m4(totmat, ob->obmat);
+ copy_m3_m4(totmat, ob->object_to_world);
/* If the object scale is zero on any axis, this might result in a zero matrix.
* In this case, the transformation would not do anything, see: T50103. */
diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c
index 839bf6b77b3..b4c1c134d49 100644
--- a/source/blender/editors/transform/transform_convert_object_texspace.c
+++ b/source/blender/editors/transform/transform_convert_object_texspace.c
@@ -67,8 +67,8 @@ static void createTransTexspace(bContext *UNUSED(C), TransInfo *t)
td->flag = TD_SELECTED;
td->ob = ob;
- copy_m3_m4(td->mtx, ob->obmat);
- copy_m3_m4(td->axismtx, ob->obmat);
+ copy_m3_m4(td->mtx, ob->object_to_world);
+ copy_m3_m4(td->axismtx, ob->object_to_world);
normalize_m3(td->axismtx);
pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c
index 3e056b6a048..f212f042773 100644
--- a/source/blender/editors/transform/transform_convert_particle.c
+++ b/source/blender/editors/transform/transform_convert_particle.c
@@ -95,7 +95,7 @@ static void createTransParticleVerts(bContext *UNUSED(C), TransInfo *t)
unit_m4(mat);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
TransData *head, *tail;
diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c
index f4f2e2a1c6e..cdbf497c584 100644
--- a/source/blender/editors/transform/transform_convert_sculpt.c
+++ b/source/blender/editors/transform/transform_convert_sculpt.c
@@ -49,7 +49,7 @@ static void createTransSculpt(bContext *C, TransInfo *t)
td->flag = TD_SELECTED;
copy_v3_v3(td->center, ss->pivot_pos);
- mul_m4_v3(ob->obmat, td->center);
+ mul_m4_v3(ob->object_to_world, td->center);
td->ob = ob;
td->loc = ss->pivot_pos;
@@ -60,16 +60,16 @@ static void createTransSculpt(bContext *C, TransInfo *t)
}
float obmat_inv[3][3];
- copy_m3_m4(obmat_inv, ob->obmat);
+ copy_m3_m4(obmat_inv, ob->object_to_world);
invert_m3(obmat_inv);
td->ext->rot = NULL;
td->ext->rotAxis = NULL;
td->ext->rotAngle = NULL;
td->ext->quat = ss->pivot_rot;
- copy_m4_m4(td->ext->obmat, ob->obmat);
+ copy_m4_m4(td->ext->obmat, ob->object_to_world);
copy_m3_m3(td->ext->l_smtx, obmat_inv);
- copy_m3_m4(td->ext->r_mtx, ob->obmat);
+ copy_m3_m4(td->ext->r_mtx, ob->object_to_world);
copy_m3_m3(td->ext->r_smtx, obmat_inv);
copy_qt_qt(td->ext->iquat, ss->pivot_rot);
@@ -83,8 +83,8 @@ static void createTransSculpt(bContext *C, TransInfo *t)
copy_v3_v3(td->ext->isize, ss->init_pivot_scale);
copy_m3_m3(td->smtx, obmat_inv);
- copy_m3_m4(td->mtx, ob->obmat);
- copy_m3_m4(td->axismtx, ob->obmat);
+ copy_m3_m4(td->mtx, ob->object_to_world);
+ copy_m3_m4(td->axismtx, ob->object_to_world);
BLI_assert(!(t->options & CTX_PAINT_CURVE));
ED_sculpt_init_transform(C, ob, t->mval, t->undo_name);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 301eac4536e..e1f93bf881b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1063,7 +1063,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
if (tc->obedit) {
if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
- mul_m4_v3(tc->obedit->obmat, r_center);
+ mul_m4_v3(tc->obedit->object_to_world, r_center);
return true;
}
}
@@ -1071,7 +1071,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
BKE_view_layer_synced_ensure(t->scene, t->view_layer);
Object *ob = BKE_view_layer_active_object_get(t->view_layer);
if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
+ mul_m4_v3(ob->object_to_world, r_center);
return true;
}
}
@@ -1088,7 +1088,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
BKE_view_layer_synced_ensure(t->scene, t->view_layer);
Base *base = BKE_view_layer_active_base_get(t->view_layer);
if (base && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
- copy_v3_v3(r_center, base->object->obmat[3]);
+ copy_v3_v3(r_center, base->object->object_to_world[3]);
return true;
}
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index f3d17559a63..2be210d24e7 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -581,12 +581,12 @@ bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3])
mul_m3_m3m3(mat, parent_mat, tmat);
/* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
+ copy_m3_m4(obmat, ob->object_to_world);
mul_m3_m3m3(gmat, obmat, mat);
}
else {
/* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
+ copy_m3_m4(obmat, ob->object_to_world);
mul_m3_m3m3(gmat, obmat, tmat);
}
@@ -608,7 +608,7 @@ bool gimbal_axis_object(Object *ob, float gmat[3][3])
if (ob->parent) {
float parent_mat[3][3];
- copy_m3_m4(parent_mat, ob->parent->obmat);
+ copy_m3_m4(parent_mat, ob->parent->object_to_world);
normalize_m3(parent_mat);
mul_m3_m3m3(gmat, parent_mat, gmat);
}
@@ -675,14 +675,14 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
copy_m3_m4(tbounds->axis, rv3d->twmat);
if (params->use_local_axis && (ob && ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) {
float diff_mat[3][3];
- copy_m3_m4(diff_mat, ob->obmat);
+ copy_m3_m4(diff_mat, ob->object_to_world);
normalize_m3(diff_mat);
invert_m3(diff_mat);
mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
normalize_m3(tbounds->axis);
tbounds->use_matrix_space = true;
- copy_m4_m4(tbounds->matrix_space, ob->obmat);
+ copy_m4_m4(tbounds->matrix_space, ob->object_to_world);
}
if (is_gp_edit) {
@@ -751,7 +751,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
#define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \
{ \
- invert_m4_m4(obedit->imat, obedit->obmat); \
+ invert_m4_m4(obedit->imat, obedit->object_to_world); \
uint objects_len = 0; \
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \
scene, view_layer, CTX_wm_view3d(C), &objects_len); \
@@ -780,7 +780,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
float mat_local[4][4];
if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world);
}
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
@@ -800,7 +800,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
float mat_local[4][4];
if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world);
}
LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
if (EBONE_VISIBLE(arm, ebo)) {
@@ -833,7 +833,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
float mat_local[4][4];
if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world);
}
nu = nurbs->first;
@@ -893,7 +893,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
float mat_local[4][4];
if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world);
}
LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
@@ -913,7 +913,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
float mat_local[4][4];
if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->object_to_world);
}
while (a--) {
@@ -933,13 +933,13 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
/* selection center */
if (totsel) {
mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
- mul_m4_v3(obedit->obmat, tbounds->center);
- mul_m4_v3(obedit->obmat, tbounds->min);
- mul_m4_v3(obedit->obmat, tbounds->max);
+ mul_m4_v3(obedit->object_to_world, tbounds->center);
+ mul_m4_v3(obedit->object_to_world, tbounds->min);
+ mul_m4_v3(obedit->object_to_world, tbounds->max);
}
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
uint objects_len = 0;
Object **objects = BKE_object_pose_array_get(scene, view_layer, v3d, &objects_len);
@@ -954,7 +954,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
float mat_local[4][4];
if (use_mat_local) {
- mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
+ mul_m4_m4m4(mat_local, ob->imat, ob_iter->object_to_world);
}
/* Use channels to get stats. */
@@ -971,18 +971,18 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
if (totsel) {
mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
- mul_m4_v3(ob->obmat, tbounds->center);
- mul_m4_v3(ob->obmat, tbounds->min);
- mul_m4_v3(ob->obmat, tbounds->max);
+ mul_m4_v3(ob->object_to_world, tbounds->center);
+ mul_m4_v3(ob->object_to_world, tbounds->min);
+ mul_m4_v3(ob->object_to_world, tbounds->max);
}
}
else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
if (ob->mode & OB_MODE_SCULPT) {
totsel = 1;
- calc_tw_center_with_matrix(tbounds, ob->sculpt->pivot_pos, false, ob->obmat);
- mul_m4_v3(ob->obmat, tbounds->center);
- mul_m4_v3(ob->obmat, tbounds->min);
- mul_m4_v3(ob->obmat, tbounds->max);
+ calc_tw_center_with_matrix(tbounds, ob->sculpt->pivot_pos, false, ob->object_to_world);
+ mul_m4_v3(ob->object_to_world, tbounds->center);
+ mul_m4_v3(ob->object_to_world, tbounds->min);
+ mul_m4_v3(ob->object_to_world, tbounds->max);
}
}
else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
@@ -1037,12 +1037,12 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
}
if (params->use_only_center || (bb == NULL)) {
- calc_tw_center(tbounds, base->object->obmat[3]);
+ calc_tw_center(tbounds, base->object->object_to_world[3]);
}
else {
for (uint j = 0; j < 8; j++) {
float co[3];
- mul_v3_m4v3(co, base->object->obmat, bb->vec[j]);
+ mul_v3_m4v3(co, base->object->object_to_world, bb->vec[j]);
calc_tw_center(tbounds, co);
}
}
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index 2eaeaf92c86..aeceedf0690 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -1041,7 +1041,7 @@ void ElementResize(const TransInfo *t,
if (t->options & CTX_POSE_BONE) {
/* Without this, the resulting location of scaled bones aren't correct,
* especially noticeable scaling root or disconnected bones around the cursor, see T92515. */
- mul_mat3_m4_v3(tc->poseobj->obmat, vec);
+ mul_mat3_m4_v3(tc->poseobj->object_to_world, vec);
}
mul_m3_v3(td->smtx, vec);
}
diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
index f7f9e14b8ac..0b87b45679a 100644
--- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_string.h"
#include "BKE_context.h"
@@ -62,7 +63,14 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
}
if (td->val) {
- *td->val = td->ival * ratio;
+ if (td->ival == 0.0f && ratio > 1.0f) {
+ /* Allow Shrink/Fatten for zero radius. */
+ *td->val = (ratio - 1.0f) * uint_as_float(POINTER_AS_UINT(t->custom.mode.data));
+ }
+ else {
+ *td->val = td->ival * ratio;
+ }
+
/* apply PET */
*td->val = interpf(*td->val, td->ival, td->factor);
CLAMP_MIN(*td->val, 0.0f);
@@ -92,6 +100,18 @@ void initCurveShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->flag |= T_NO_CONSTRAINT;
+
+ float scale_factor = 0.0f;
+ if (((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW) &&
+ (t->data_len_all == 1)) ||
+ (t->data_len_all == 3 && TRANS_DATA_CONTAINER_FIRST_OK(t)->data[0].val == NULL)) {
+ /* For cases where only one point on the curve is being transformed and the radius of that
+ * point is zero, use the factor to multiply the offset of the ratio and allow scaling.
+ * Note that for bezier curves, 3 TransData equals 1 point in most cases. */
+ RegionView3D *rv3d = t->region->regiondata;
+ scale_factor = rv3d->pixsize * t->mouse.factor * t->zfac;
+ }
+ t->custom.mode.data = POINTER_FROM_UINT(float_as_uint(scale_factor));
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c
index 5baf06006d9..5cdb4d3bf61 100644
--- a/source/blender/editors/transform/transform_mode_edge_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_slide.c
@@ -1149,7 +1149,7 @@ void drawEdgeSlide(TransInfo *t)
GPU_blend(GPU_BLEND_ALPHA);
GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 91388ecd661..59d34c3918b 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -170,7 +170,7 @@ static void transdata_elem_translate_fn(void *__restrict iter_data_v,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Transform (Translation)
+/** \name Transform (Translation) Header
* \{ */
static void translate_dist_to_str(char *r_str,
@@ -341,6 +341,96 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (Translation) Snapping
+ * \{ */
+
+static void translate_snap_target_grid_ensure(TransInfo *t)
+{
+ /* Only need to calculate once. */
+ if ((t->tsnap.status & TARGET_GRID_INIT) == 0) {
+ if (t->data_type == &TransConvertType_Cursor3D) {
+ /* Use a fallback when transforming the cursor.
+ * In this case the center is _not_ derived from the cursor which is being transformed. */
+ copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc);
+ }
+ else if (t->around == V3D_AROUND_CURSOR) {
+ /* Use a fallback for cursor selection,
+ * this isn't useful as a global center for absolute grid snapping
+ * since its not based on the position of the selection. */
+ tranform_snap_target_median_calc(t, t->tsnap.snapTargetGrid);
+ }
+ else {
+ copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global);
+ }
+ t->tsnap.status |= TARGET_GRID_INIT;
+ }
+}
+
+static void translate_snap_grid_apply(TransInfo *t,
+ const int max_index,
+ const float grid_dist[3],
+ const float loc[3],
+ float r_out[3])
+{
+ BLI_assert(max_index <= 2);
+ translate_snap_target_grid_ensure(t);
+ const float *center_global = t->tsnap.snapTargetGrid;
+ const float *asp = t->aspect;
+
+ float in[3];
+ if (t->con.mode & CON_APPLY) {
+ BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE);
+ t->con.applyVec(t, NULL, NULL, loc, in);
+ }
+ else {
+ copy_v3_v3(in, loc);
+ }
+
+ for (int i = 0; i <= max_index; i++) {
+ const float iter_fac = grid_dist[i] * asp[i];
+ r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i];
+ }
+}
+
+static bool translate_snap_grid(TransInfo *t, float *val)
+{
+ if (!activeSnap(t)) {
+ return false;
+ }
+
+ if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) {
+ /* Don't do grid snapping if there is a valid snap point. */
+ return false;
+ }
+
+ /* Don't do grid snapping if not in 3D viewport or UV editor */
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
+ return false;
+ }
+
+ if (t->mode != TFM_TRANSLATION) {
+ return false;
+ }
+
+ float grid_dist[3];
+ copy_v3_v3(grid_dist, t->snap_spatial);
+ if (t->modifiers & MOD_PRECISION) {
+ mul_v3_fl(grid_dist, t->snap_spatial_precision);
+ }
+
+ /* Early bailing out if no need to snap */
+ if (is_zero_v3(grid_dist)) {
+ return false;
+ }
+
+ translate_snap_grid_apply(t, t->idx_max, grid_dist, val, val);
+ t->tsnap.snapElem = SCE_SNAP_MODE_GRID;
+ return true;
+}
+
static void ApplySnapTranslation(TransInfo *t, float vec[3])
{
float point[3];
@@ -372,6 +462,12 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (Translation)
+ * \{ */
+
static void applyTranslationValue(TransInfo *t, const float vec[3])
{
struct TranslateCustomData *custom_data = t->custom.mode.data;
@@ -514,7 +610,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
t->tsnap.snapElem = SCE_SNAP_MODE_NONE;
applySnappingAsGroup(t, global_dir);
- transform_snap_grid(t, global_dir);
+ translate_snap_grid(t, global_dir);
if (t->con.mode & CON_APPLY) {
float in[3];
@@ -590,7 +686,8 @@ void initTranslation(TransInfo *t)
t->num.flag = 0;
t->num.idx_max = t->idx_max;
- copy_v2_v2(t->snap, t->snap_spatial_x);
+ t->snap[0] = t->snap_spatial[0];
+ t->snap[1] = t->snap_spatial[0] * t->snap_spatial_precision;
copy_v3_fl(t->num.val_inc, t->snap[0]);
t->num.unit_sys = t->scene->unit.system;
diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c
index d7c4d862b23..cc1ea188fbc 100644
--- a/source/blender/editors/transform/transform_mode_vert_slide.c
+++ b/source/blender/editors/transform/transform_mode_vert_slide.c
@@ -167,7 +167,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]
float dir_dot;
sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
- mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir);
+ mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world, tdir);
project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]);
normalize_v3(tdir);
@@ -382,7 +382,7 @@ void drawVertSlide(TransInfo *t)
GPU_blend(GPU_BLEND_ALPHA);
GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world);
GPU_line_width(line_size);
@@ -437,14 +437,15 @@ void drawVertSlide(TransInfo *t)
xy_delta[0] = t->mval[0] - t->mouse.imval[0];
xy_delta[1] = t->mval[1] - t->mouse.imval[1];
- mul_v3_m4v3(
- co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d);
+ mul_v3_m4v3(co_orig_3d,
+ TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world,
+ curr_sv->co_orig_3d);
zfac = ED_view3d_calc_zfac(t->region->regiondata, co_orig_3d);
ED_view3d_win_to_delta(t->region, xy_delta, zfac, co_dest_3d);
invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat,
- TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->object_to_world);
mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d);
add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 212df5978e4..66fee01f864 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -126,7 +126,7 @@ static TransformOrientation *createObjectSpace(bContext *C,
ob = base->object;
- copy_m3_m4(mat, ob->obmat);
+ copy_m3_m4(mat, ob->object_to_world);
normalize_m3(mat);
/* use object name if no name is given */
@@ -532,7 +532,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene,
ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat);
}
else {
- transform_orientations_create_from_axis(r_mat, UNPACK3(ob->obmat));
+ transform_orientations_create_from_axis(r_mat, UNPACK3(ob->object_to_world));
}
break;
}
@@ -764,7 +764,7 @@ int getTransformOrientation_ex(const Scene *scene,
float imat[3][3], mat[3][3];
/* we need the transpose of the inverse for a normal... */
- copy_m3_m4(imat, ob->obmat);
+ copy_m3_m4(imat, ob->object_to_world);
invert_m3_m3(mat, imat);
transpose_m3(mat);
@@ -1192,8 +1192,8 @@ int getTransformOrientation_ex(const Scene *scene,
if (result == ORIENTATION_EDGE) {
float tvec[3];
- mul_mat3_m4_v3(ob->obmat, normal);
- mul_mat3_m4_v3(ob->obmat, plane);
+ mul_mat3_m4_v3(ob->object_to_world, normal);
+ mul_mat3_m4_v3(ob->object_to_world, plane);
/* align normal to edge direction (so normal is perpendicular to the plane).
* 'ORIENTATION_EDGE' will do the other way around.
@@ -1235,7 +1235,7 @@ int getTransformOrientation_ex(const Scene *scene,
/* use for both active & all */
if (ok) {
/* we need the transpose of the inverse for a normal... */
- copy_m3_m4(imat, ob->obmat);
+ copy_m3_m4(imat, ob->object_to_world);
invert_m3_m3(mat, imat);
transpose_m3(mat);
@@ -1267,8 +1267,8 @@ int getTransformOrientation_ex(const Scene *scene,
}
if (ok) {
- copy_v3_v3(normal, ob->obmat[2]);
- copy_v3_v3(plane, ob->obmat[1]);
+ copy_v3_v3(normal, ob->object_to_world[2]);
+ copy_v3_v3(plane, ob->object_to_world[1]);
}
}
result = ORIENTATION_NORMAL;
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 553202b5798..11cb57dc911 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -372,7 +372,7 @@ static bool applyFaceProject(TransInfo *t, TransDataContainer *tc, TransData *td
}
else if (t->options & CTX_OBJECT) {
BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
+ copy_v3_v3(iloc, td->ob->object_to_world[3]);
}
if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) !=
@@ -444,7 +444,7 @@ static void applyFaceNearest(TransInfo *t, TransDataContainer *tc, TransData *td
}
else if (t->options & CTX_OBJECT) {
BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(init_loc, td->ob->obmat[3]);
+ copy_v3_v3(init_loc, td->ob->object_to_world[3]);
}
eSnapMode hit = ED_transform_snap_object_project_view3d(
@@ -511,56 +511,6 @@ void applySnappingIndividual(TransInfo *t)
}
}
-void applyGridAbsolute(TransInfo *t)
-{
- int i;
-
- if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) {
- return;
- }
-
- float grid_size_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0];
- float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0];
- float grid_size_z = grid_size_x;
-
- /* Early exit on unusable grid size. */
- if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) {
- return;
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td;
-
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- float iloc[3], loc[3], tvec[3];
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) {
- continue;
- }
-
- copy_v3_v3(iloc, td->loc);
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, iloc);
- }
- else if (t->options & CTX_OBJECT) {
- BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
- }
-
- loc[0] = roundf(iloc[0] / grid_size_x) * grid_size_x;
- loc[1] = roundf(iloc[1] / grid_size_y) * grid_size_y;
- loc[2] = roundf(iloc[2] / grid_size_z) * grid_size_z;
-
- sub_v3_v3v3(tvec, loc, iloc);
- mul_m3_v3(td->smtx, tvec);
- add_v3_v3(td->loc, tvec);
- }
- }
-}
-
void applySnappingAsGroup(TransInfo *t, float *vec)
{
if (!activeSnap_SnappingAsGroup(t)) {
@@ -1187,7 +1137,7 @@ static void snap_calc_sequencer_fn(TransInfo *t, float *UNUSED(vec))
/** \name Target
* \{ */
-static void snap_target_median_impl(TransInfo *t, float r_median[3])
+void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3])
{
int i_accum = 0;
@@ -1223,28 +1173,6 @@ static void snap_target_median_impl(TransInfo *t, float r_median[3])
// TargetSnapOffset(t, NULL);
}
-static void snap_target_grid_ensure(TransInfo *t)
-{
- /* Only need to calculate once. */
- if ((t->tsnap.status & TARGET_GRID_INIT) == 0) {
- if (t->data_type == &TransConvertType_Cursor3D) {
- /* Use a fallback when transforming the cursor.
- * In this case the center is _not_ derived from the cursor which is being transformed. */
- copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc);
- }
- else if (t->around == V3D_AROUND_CURSOR) {
- /* Use a fallback for cursor selection,
- * this isn't useful as a global center for absolute grid snapping
- * since its not based on the position of the selection. */
- snap_target_median_impl(t, t->tsnap.snapTargetGrid);
- }
- else {
- copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global);
- }
- t->tsnap.status |= TARGET_GRID_INIT;
- }
-}
-
static void TargetSnapOffset(TransInfo *t, TransData *td)
{
if (t->spacetype == SPACE_NODE && td != NULL) {
@@ -1316,7 +1244,7 @@ static void TargetSnapMedian(TransInfo *t)
{
/* Only need to calculate once. */
if ((t->tsnap.status & TARGET_INIT) == 0) {
- snap_target_median_impl(t, t->tsnap.snapTarget);
+ tranform_snap_target_median_calc(t, t->tsnap.snapTarget);
t->tsnap.status |= TARGET_INIT;
}
}
@@ -1654,66 +1582,6 @@ bool snapNodesTransform(
/** \name snap Grid
* \{ */
-static void snap_grid_apply(TransInfo *t,
- const int max_index,
- const float grid_dist_x,
- const float grid_dist_y,
- const float loc[3],
- float r_out[3])
-{
- BLI_assert(max_index <= 2);
- snap_target_grid_ensure(t);
- const float *center_global = t->tsnap.snapTargetGrid;
- const float *asp = t->aspect;
-
- float in[3];
- if (t->con.mode & CON_APPLY) {
- BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE);
- t->con.applyVec(t, NULL, NULL, loc, in);
- }
- else {
- copy_v3_v3(in, loc);
- }
-
- for (int i = 0; i <= max_index; i++) {
- const float iter_fac = ((i == 1) ? grid_dist_y : grid_dist_x) * asp[i];
- r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i];
- }
-}
-
-bool transform_snap_grid(TransInfo *t, float *val)
-{
- if (!activeSnap(t)) {
- return false;
- }
-
- if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) {
- /* Don't do grid snapping if there is a valid snap point. */
- return false;
- }
-
- /* Don't do grid snapping if not in 3D viewport or UV editor */
- if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
- return false;
- }
-
- if (t->mode != TFM_TRANSLATION) {
- return false;
- }
-
- float grid_dist_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0];
- float grid_dist_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0];
-
- /* Early bailing out if no need to snap */
- if (grid_dist_x == 0.0f || grid_dist_y == 0.0f) {
- return false;
- }
-
- snap_grid_apply(t, t->idx_max, grid_dist_x, grid_dist_y, val, val);
- t->tsnap.snapElem = SCE_SNAP_MODE_GRID;
- return true;
-}
-
static void snap_increment_apply_ex(const TransInfo *UNUSED(t),
const int max_index,
const float increment_val,
diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h
index 2b78c554ad8..16d9062e978 100644
--- a/source/blender/editors/transform/transform_snap.h
+++ b/source/blender/editors/transform/transform_snap.h
@@ -38,10 +38,10 @@ bool snapNodesTransform(struct TransInfo *t,
bool transformModeUseSnap(const TransInfo *t);
+void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]);
bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val);
bool transform_snap_increment(const TransInfo *t, float *val);
float transform_snap_increment_get(const TransInfo *t);
-bool transform_snap_grid(TransInfo *t, float *val);
bool activeSnap(const TransInfo *t);
bool activeSnap_SnappingIndividual(const TransInfo *t);
@@ -52,7 +52,6 @@ bool validSnap(const TransInfo *t);
void initSnapping(struct TransInfo *t, struct wmOperator *op);
void freeSnapping(struct TransInfo *t);
void applySnappingIndividual(TransInfo *t);
-void applyGridAbsolute(TransInfo *t);
void applySnappingAsGroup(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
eRedrawFlag handleSnapping(TransInfo *t, const struct wmEvent *event);
diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc
index 7971e1ca9af..24d76a50117 100644
--- a/source/blender/editors/transform/transform_snap_object.cc
+++ b/source/blender/editors/transform/transform_snap_object.cc
@@ -565,7 +565,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
free_object_duplilist(lb);
}
- sob_callback(sctx, params, obj_eval, obj_eval->obmat, is_object_active, data);
+ sob_callback(sctx, params, obj_eval, obj_eval->object_to_world, is_object_active, data);
}
}
@@ -1145,7 +1145,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
* \param r_index: Hit index or -1 when no valid index is found.
* (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE_RAYCAST`).
* \param r_ob: Hit object.
- * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
+ * \param r_obmat: Object matrix (may not be #Object.object_to_world with dupli-instances).
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
static bool raycastObjects(SnapObjectContext *sctx,
@@ -1483,7 +1483,7 @@ static void nearest_world_object_fn(SnapObjectContext *sctx,
* \param r_no: Normal of nearest point on target surface.
* \param r_index: Index of nearest polygon on target surface.
* \param r_ob: Nearest target object.
- * \param r_obmat: Nearest target matrix (may not be #Object.obmat with dupli-instances).
+ * \param r_obmat: Nearest target matrix (may not be #Object.object_to_world with dupli-instances).
*/
static bool nearestWorldObjects(SnapObjectContext *sctx,
const struct SnapObjectParams *params,
@@ -3177,7 +3177,7 @@ static void snap_obj_fn(SnapObjectContext *sctx,
* \param r_index: Hit index or -1 when no valid index is found.
* (currently only set to the polygon index when using `snap_to == SCE_SNAP_MODE_FACE_RAYCAST`).
* \param r_ob: Hit object.
- * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
+ * \param r_obmat: Object matrix (may not be #Object.object_to_world with dupli-instances).
*/
static eSnapMode snapObjectsRay(SnapObjectContext *sctx,
const SnapObjectParams *params,
diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc
index 5c03367cba8..4da1559b726 100644
--- a/source/blender/editors/util/ed_viewer_path.cc
+++ b/source/blender/editors/util/ed_viewer_path.cc
@@ -249,6 +249,9 @@ bool is_active_geometry_nodes_viewer(const bContext &C,
if (md->type != eModifierType_Nodes) {
return false;
}
+ if ((md->mode & eModifierMode_Realtime) == 0) {
+ return false;
+ }
modifier = reinterpret_cast<const NodesModifierData *>(md);
break;
}
diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc
index bdd05b06d94..92745667505 100644
--- a/source/blender/editors/uvedit/uvedit_islands.cc
+++ b/source/blender/editors/uvedit/uvedit_islands.cc
@@ -600,6 +600,22 @@ static BoxPack *pack_islands_params(const blender::Vector<FaceIsland *> &island_
return box_array;
}
+static bool island_has_pins(FaceIsland *island)
+{
+ BMLoop *l;
+ BMIter iter;
+ const int cd_loop_uv_offset = island->cd_loop_uv_offset;
+ for (int i = 0; i < island->faces_len; i++) {
+ BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset));
+ if (luv->flag & MLOOPUV_PINNED) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/* -------------------------------------------------------------------- */
/** \name Public UV Island Packing
*
@@ -651,8 +667,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
aspect_y,
cd_loop_uv_offset);
- int index;
- LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) {
+ /* Remove from linked list and append to blender::Vector. */
+ LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) {
+ BLI_remlink(&island_list, island);
+ if (params->ignore_pinned && island_has_pins(island)) {
+ MEM_freeN(island->faces);
+ MEM_freeN(island);
+ continue;
+ }
island_vector.append(island);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 5e2d9097abd..b65f4889347 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -37,6 +37,7 @@
#include "BKE_node.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -113,7 +114,8 @@ bool ED_object_get_active_image(Object *ob,
bNode **r_node,
bNodeTree **r_ntree)
{
- Material *ma = BKE_object_material_get(ob, mat_nr);
+ Material *ma = DEG_is_evaluated_object(ob) ? BKE_object_material_get_eval(ob, mat_nr) :
+ BKE_object_material_get(ob, mat_nr);
bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index 7dd223a9252..777cc1d97e4 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -4705,7 +4705,7 @@ static int uv_select_similar_vert_exec(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
BMFace *face;
BMIter iter;
@@ -4742,7 +4742,7 @@ static int uv_select_similar_vert_exec(bContext *C, wmOperator *op)
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
BMFace *face;
BMIter iter;
@@ -4818,7 +4818,7 @@ static int uv_select_similar_edge_exec(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
BMFace *face;
BMIter iter;
@@ -4859,7 +4859,7 @@ static int uv_select_similar_edge_exec(bContext *C, wmOperator *op)
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
BMFace *face;
BMIter iter;
@@ -4927,7 +4927,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
@@ -4963,7 +4963,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
float ob_m3[3][3];
- copy_m3_m4(ob_m3, ob->obmat);
+ copy_m3_m4(ob_m3, ob->object_to_world);
BMFace *face;
BMIter iter;
@@ -5053,7 +5053,7 @@ static int uv_select_similar_island_exec(bContext *C, wmOperator *op)
}
float ob_m3[3][3];
- copy_m3_m4(ob_m3, obedit->obmat);
+ copy_m3_m4(ob_m3, obedit->object_to_world);
int index;
LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list_ptr[ob_index], index) {
@@ -5082,7 +5082,7 @@ static int uv_select_similar_island_exec(bContext *C, wmOperator *op)
continue;
}
float ob_m3[3][3];
- copy_m3_m4(ob_m3, obedit->obmat);
+ copy_m3_m4(ob_m3, obedit->object_to_world);
bool changed = false;
int index;
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 2c977552e72..de1c88fe896 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1050,31 +1050,6 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
/** \name Pack UV Islands Operator
* \{ */
-/**
- * \warning Since this uses #ParamHandle it doesn't work with non-manifold meshes (see T82637).
- * Use #ED_uvedit_pack_islands_multi for a more general solution.
- *
- * TODO: remove this function, in favor of #ED_uvedit_pack_islands_multi.
- */
-static void uvedit_pack_islands_multi(const Scene *scene,
- Object **objects,
- const uint objects_len,
- const UnwrapOptions *options,
- bool rotate,
- bool ignore_pinned)
-{
- ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, options);
- GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
- GEO_uv_parametrizer_flush(handle);
- GEO_uv_parametrizer_delete(handle);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
- }
-}
-
/* Packing targets. */
enum {
PACK_UDIM_SRC_CLOSEST = 0,
@@ -1119,16 +1094,22 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
const bool use_udim_params = ED_uvedit_udim_params_from_image_space(
sima, use_active, &udim_params);
- struct UVPackIsland_Params params = {
+ const struct UVPackIsland_Params pack_island_params = {
.rotate = RNA_boolean_get(op->ptr, "rotate"),
- .only_selected_uvs = true,
- .only_selected_faces = true,
- .correct_aspect = true,
+ .only_selected_uvs = options.only_selected_uvs,
+ .only_selected_faces = options.only_selected_faces,
+ .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams,
+ .correct_aspect = options.correct_aspect,
+ .ignore_pinned = false,
.margin_method = RNA_enum_get(op->ptr, "margin_method"),
.margin = RNA_float_get(op->ptr, "margin"),
};
- ED_uvedit_pack_islands_multi(
- scene, objects, objects_len, NULL, use_udim_params ? &udim_params : NULL, &params);
+ ED_uvedit_pack_islands_multi(scene,
+ objects,
+ objects_len,
+ NULL,
+ use_udim_params ? &udim_params : NULL,
+ &pack_island_params);
MEM_freeN(objects);
return OPERATOR_FINISHED;
@@ -1407,7 +1388,7 @@ static void uv_map_transform_center(const Scene *scene,
}
case V3D_AROUND_CURSOR: /* cursor center */
{
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_v3_m4v3(r_center, ob->imat, scene->cursor.location);
break;
}
@@ -1458,7 +1439,7 @@ static void uv_map_rotation_matrix_ex(float result[4][4],
zero_v3(viewmatrix[3]);
/* get rotation of the current object matrix */
- copy_m4_m4(rotobj, ob->obmat);
+ copy_m4_m4(rotobj, ob->object_to_world);
zero_v3(rotobj[3]);
/* but shifting */
@@ -1793,8 +1774,8 @@ static void uv_map_clip_correct(const Scene *scene,
dy = 1.0f / dy;
}
- if (dx == 1.0f && dy == 1.0f) {
- /* Scaling by 1.0 has no effect. */
+ if (dx == 1.0f && dy == 1.0f && min[0] == 0.0f && min[1] == 0.0f) {
+ /* Scaling by 1.0, without translating, has no effect. */
return;
}
@@ -1889,12 +1870,19 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
.fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
.correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
};
-
- bool rotate = true;
- bool ignore_pinned = true;
-
uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+
+ const struct UVPackIsland_Params pack_island_params = {
+ .rotate = true,
+ .only_selected_uvs = options.only_selected_uvs,
+ .only_selected_faces = options.only_selected_faces,
+ .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams,
+ .correct_aspect = options.correct_aspect,
+ .ignore_pinned = true,
+ .margin_method = ED_UVPACK_MARGIN_SCALED,
+ .margin = scene->toolsettings->uvcalc_margin,
+ };
+ ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params);
}
}
@@ -1926,8 +1914,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
.correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"),
};
- bool rotate = true;
- bool ignore_pinned = true;
if (CTX_wm_space_image(C)) {
/* Inside the UV Editor, only unwrap selected UVs. */
options.only_selected_uvs = true;
@@ -1962,7 +1948,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
continue;
}
- mat4_to_size(obsize, obedit->obmat);
+ mat4_to_size(obsize, obedit->object_to_world);
if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f)) {
if ((reported_errors & UNWRAP_ERROR_NONUNIFORM) == 0) {
BKE_report(op->reports,
@@ -1972,7 +1958,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
reported_errors |= UNWRAP_ERROR_NONUNIFORM;
}
}
- else if (is_negative_m4(obedit->obmat)) {
+ else if (is_negative_m4(obedit->object_to_world)) {
if ((reported_errors & UNWRAP_ERROR_NEGATIVE) == 0) {
BKE_report(
op->reports,
@@ -2032,7 +2018,18 @@ static int unwrap_exec(bContext *C, wmOperator *op)
.count_failed = 0,
};
uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+
+ const struct UVPackIsland_Params pack_island_params = {
+ .rotate = true,
+ .only_selected_uvs = options.only_selected_uvs,
+ .only_selected_faces = options.only_selected_faces,
+ .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams,
+ .correct_aspect = options.correct_aspect,
+ .ignore_pinned = true,
+ .margin_method = RNA_enum_get(op->ptr, "margin_method"),
+ .margin = RNA_float_get(op->ptr, "margin"),
+ };
+ ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params);
MEM_freeN(objects);
@@ -2541,7 +2538,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
float objects_pos_avg[4] = {0};
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- add_v4_v4(objects_pos_avg, objects[ob_index]->obmat[3]);
+ add_v4_v4(objects_pos_avg, objects[ob_index]->object_to_world[3]);
}
mul_v4_fl(objects_pos_avg, 1.0f / objects_len);
@@ -2579,7 +2576,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
const bool camera_bounds = RNA_boolean_get(op->ptr, "camera_bounds");
struct ProjCameraInfo *uci = BLI_uvproject_camera_info(
v3d->camera,
- obedit->obmat,
+ obedit->object_to_world,
camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f,
camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f);
@@ -2600,7 +2597,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
}
}
else {
- copy_m4_m4(rotmat, obedit->obmat);
+ copy_m4_m4(rotmat, obedit->object_to_world);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index 0d41b5a773d..53c2b1d235b 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -431,7 +431,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
// Compute matrix including camera transform
float obmat[4][4], nmat[4][4];
- mul_m4_m4m4(obmat, viewmat, ob->obmat);
+ mul_m4_m4m4(obmat, viewmat, ob->object_to_world);
invert_m4_m4(nmat, obmat);
transpose_m4(nmat);
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp
index ad9b7dfa5ed..0d47665c6d3 100644
--- a/source/blender/freestyle/intern/geometry/FitCurve.cpp
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -12,6 +12,8 @@
#include "FitCurve.h"
+#include "BLI_sys_types.h"
+
using namespace std;
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
index c17fb92a58c..db6816bf045 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -25,6 +25,8 @@
#include "BKE_global.h"
+#include "BLI_sys_types.h"
+
using namespace std;
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
index f1e4297ab5e..b8beeed5880 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -7,6 +7,8 @@
#include "GeomUtils.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle::GeomUtils {
// This internal procedure is defined below.
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp
index 51c87757645..46ce9184951 100644
--- a/source/blender/freestyle/intern/geometry/HashGrid.cpp
+++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp
@@ -7,6 +7,8 @@
#include "HashGrid.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
void HashGrid::clear()
diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
index 306913e6297..04e271f7a5b 100644
--- a/source/blender/freestyle/intern/geometry/Noise.cpp
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -12,6 +12,7 @@
#include "BLI_compiler_attrs.h"
#include "BLI_rand.h"
+#include "BLI_sys_types.h"
#include "Noise.h"
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp
index 95afa4dda48..bc68d17a1f9 100644
--- a/source/blender/freestyle/intern/image/ImagePyramid.cpp
+++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp
@@ -11,6 +11,8 @@
#include "Image.h"
#include "ImagePyramid.h"
+#include "BLI_sys_types.h"
+
using namespace std;
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
index 114fafea55b..d79c2f4d9b0 100644
--- a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
@@ -9,6 +9,8 @@
#include "../stroke/ContextFunctions.h"
+#include "BLI_sys_types.h"
+
using namespace Freestyle;
#ifdef __cplusplus
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
index 097fdb6a16b..684edb26a97 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
@@ -9,6 +9,8 @@
#include "../system/RandGen.h"
+#include "BLI_sys_types.h"
+
#include <sstream>
#ifdef __cplusplus
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
index d88d3edecc0..711cf9c6bab 100644
--- a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
@@ -12,6 +12,8 @@
#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
index 1c5e90474ab..860573016f2 100644
--- a/source/blender/freestyle/intern/python/BPy_Operators.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -16,6 +16,8 @@
#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+#include "BLI_sys_types.h"
+
#include <sstream>
#ifdef __cplusplus
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
index 7fb647119e6..92867e36479 100644
--- a/source/blender/freestyle/intern/python/BPy_SShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -12,6 +12,8 @@
#include "Interface0D/BPy_SVertex.h"
#include "Interface1D/BPy_FEdge.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
index 77c3c708103..130526ac309 100644
--- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -11,6 +11,8 @@
#include "Interface0D/BPy_ViewVertex.h"
#include "Interface1D/BPy_ViewEdge.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp
index ad54787ad05..40df2033221 100644
--- a/source/blender/freestyle/intern/python/Director.cpp
+++ b/source/blender/freestyle/intern/python/Director.cpp
@@ -42,6 +42,8 @@
#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+#include "BLI_sys_types.h"
+
using namespace Freestyle;
// BinaryPredicate0D: __call__
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
index cb84b7e82ba..55faebc509c 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -10,6 +10,8 @@
#include "../BPy_Id.h"
#include "../Interface1D/BPy_FEdge.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index e9dcedef34e..6f90406d74d 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -13,6 +13,8 @@
#include "../Interface0D/CurvePoint/BPy_StrokeVertex.h"
#include "../Iterator/BPy_StrokeVertexIterator.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
index 0a4d1a5d32c..aae8d5514c9 100644
--- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
@@ -9,6 +9,8 @@
#include "../../BPy_Convert.h"
#include "../../Interface0D/BPy_SVertex.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
index 51ae9334f37..6516ad8af9c 100644
--- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
@@ -9,6 +9,8 @@
#include "../../BPy_Convert.h"
#include "../../Interface0D/BPy_SVertex.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
index 29e1a1d3525..8faefd085d6 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
@@ -11,6 +11,8 @@
#include "UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
index e0aa5af2adb..7f5b98da223 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
@@ -11,6 +11,8 @@
#include "UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
index 3a2c9868014..82362704119 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
@@ -8,6 +8,8 @@
#include "../../../stroke/AdvancedFunctions0D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
index 41bc3199271..800a5da1978 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
@@ -12,6 +12,8 @@
#include "UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
index 242f4a141bc..fa15983f0d3 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -14,6 +14,8 @@
#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h"
#include "UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
index b513686524e..d1479f27935 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
@@ -10,6 +10,8 @@
#include "../../BPy_Convert.h"
#include "../../BPy_IntegrationType.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
index ecf95e189d8..99c688985f5 100644
--- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
@@ -6,6 +6,8 @@
#include "BPy_EqualToChainingTimeStampUP1D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
index b75e45cb132..48365507d1a 100644
--- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
@@ -6,6 +6,8 @@
#include "BPy_EqualToTimeStampUP1D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
index ad8aba9eb29..b410ee14831 100644
--- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
@@ -6,6 +6,8 @@
#include "BPy_ShapeUP1D.h"
+#include "BLI_sys_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
index 3962ac0aa35..39dbf4b87a9 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -7,6 +7,8 @@
#include "IndexedFaceSet.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
IndexedFaceSet::IndexedFaceSet()
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
index 97fa07df4c9..0089f68ce2d 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
@@ -9,6 +9,7 @@
#include "NodeTransform.h"
#include "BLI_math.h"
+#include "BLI_sys_types.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
index a4ef70722d0..0ab83003514 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
@@ -6,6 +6,8 @@
#include "SceneHash.h"
+#include "BLI_sys_types.h"
+
#include <sstream>
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
index cc5d8ef6ed4..4a2b6979985 100644
--- a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
@@ -10,6 +10,8 @@
#include "IndexedFaceSet.h"
#include "ScenePrettyPrinter.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
#define VISIT(CLASS) \
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
index 79825b626d5..a221e0e8bbd 100644
--- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
@@ -10,6 +10,8 @@
#include "../view_map/SteerableViewMap.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle::Functions1D {
int GetSteerableViewMapDensityF1D::operator()(Interface1D &inter)
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
index c19ac31ae4a..e5009f2b4f8 100644
--- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
@@ -33,7 +33,7 @@ class DensityF1D : public UnaryFunction1D<double> {
public:
/** Builds the functor.
* \param sigma:
- * Thesigma used in DensityF0D and determining the window size used in each density query.
+ * The sigma used in DensityF0D and determining the window size used in each density query.
* \param iType:
* The integration method used to compute a single value from a set of values.
* \param sampling:
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
index 4ff00dd0a08..6508c95f2b4 100644
--- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
@@ -11,6 +11,8 @@
#include "../system/PseudoNoise.h"
#include "../system/RandGen.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
/////////////////////////////////////////
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
index 4df0bd7b089..e77ba63f3d6 100644
--- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
@@ -23,6 +23,8 @@
#include "BKE_global.h"
+#include "BLI_sys_types.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp
index af79a8eb4eb..741fad592cf 100644
--- a/source/blender/freestyle/intern/stroke/Canvas.cpp
+++ b/source/blender/freestyle/intern/stroke/Canvas.cpp
@@ -22,6 +22,8 @@
#include "../view_map/SteerableViewMap.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
// soc #include <qimage.h>
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
index 879ea49b43a..cd37a5f893d 100644
--- a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
@@ -12,6 +12,8 @@
#include "../system/TimeStamp.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle::ContextFunctions {
uint GetTimeStampCF()
diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp
index b45e3218a13..93524e6ebe5 100644
--- a/source/blender/freestyle/intern/stroke/Operators.cpp
+++ b/source/blender/freestyle/intern/stroke/Operators.cpp
@@ -14,6 +14,8 @@
#include "Stroke.h"
#include "StrokeIterators.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
index 30dacb7f7df..095cb74d607 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
@@ -9,6 +9,8 @@
#include "../geometry/GeomUtils.h"
+#include "BLI_sys_types.h"
+
using namespace std;
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp
index 79b2cea0446..fbd85815da1 100644
--- a/source/blender/freestyle/intern/system/StringUtils.cpp
+++ b/source/blender/freestyle/intern/system/StringUtils.cpp
@@ -10,6 +10,8 @@
#include "StringUtils.h"
#include "FreestyleConfig.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle::StringUtils {
void getPathName(const string &path, const string &base, vector<string> &pathnames)
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
index 7fa4f52506d..f4619e6e85f 100644
--- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
@@ -7,6 +7,8 @@
#include "ArbitraryGridDensityProvider.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
index 11ba5933ce0..b984d5dba29 100644
--- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
@@ -7,6 +7,8 @@
#include "AverageAreaGridDensityProvider.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
index 36afb0119a2..4464aab6419 100644
--- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
@@ -10,6 +10,8 @@
#include "BoxGrid.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
using namespace std;
diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
index e2886370800..c1afb6de881 100644
--- a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
+++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
@@ -9,6 +9,8 @@
#include "../geometry/GridHelpers.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
index e455011f187..b7e805f8767 100644
--- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -12,6 +12,8 @@
#include "../geometry/GeomUtils.h"
#include "../geometry/normal_cycle.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp
index 2157c533986..aaafc5c884a 100644
--- a/source/blender/freestyle/intern/view_map/Functions0D.cpp
+++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp
@@ -8,6 +8,8 @@
#include "Functions0D.h"
#include "ViewMap.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
using namespace std;
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
index 7e4f673e2fb..40fa8387637 100644
--- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
@@ -7,6 +7,8 @@
#include "HeuristicGridDensityProviderFactory.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor,
diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.cpp b/source/blender/freestyle/intern/view_map/OccluderSource.cpp
index 54c30661de9..7ac5de9abbc 100644
--- a/source/blender/freestyle/intern/view_map/OccluderSource.cpp
+++ b/source/blender/freestyle/intern/view_map/OccluderSource.cpp
@@ -9,6 +9,8 @@
#include "OccluderSource.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
index 43809f83dc4..af6924eea6e 100644
--- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
@@ -7,6 +7,8 @@
#include "Pow23GridDensityProvider.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
index 7d9d871f586..ce4c8fcd453 100644
--- a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
@@ -14,6 +14,8 @@
#include "../geometry/GeomUtils.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
using namespace std;
diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
index 6d800d13b3b..bb4dbd17f70 100644
--- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
+++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
@@ -10,6 +10,8 @@
#include "SphericalGrid.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
using namespace std;
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
index ba37dc434f4..20472599835 100644
--- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
@@ -16,8 +16,10 @@
#include "../image/Image.h"
#include "../image/ImagePyramid.h"
-#include "BKE_global.h"
#include "BLI_math.h"
+#include "BLI_sys_types.h"
+
+#include "BKE_global.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
index 277334d13fd..fcb157a4e60 100644
--- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
@@ -13,6 +13,8 @@
#include "../winged_edge/WXEdge.h"
+#include "BLI_sys_types.h"
+
using namespace std;
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp
index 0ba4850eed5..09432aa4ac7 100644
--- a/source/blender/freestyle/intern/view_map/ViewMap.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp
@@ -13,6 +13,8 @@
#include "../geometry/GeomUtils.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
/**********************************/
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
index 4ef06c0ac96..9c2919b0ca8 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -24,6 +24,8 @@
#include "../winged_edge/WFillGrid.h"
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
index 2da95d47912..c666e548884 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
@@ -89,7 +89,7 @@ class ViewMapTesselator {
#endif
};
-/** Class to tesselate the 2D projected silhouette */
+/** Class to tessellate the 2D projected silhouette */
class ViewMapTesselator2D : public ViewMapTesselator {
public:
inline ViewMapTesselator2D() : ViewMapTesselator()
@@ -110,7 +110,7 @@ class ViewMapTesselator2D : public ViewMapTesselator {
#endif
};
-/** Class to tesselate the 3D silhouette */
+/** Class to tessellate the 3D silhouette */
class ViewMapTesselator3D : public ViewMapTesselator {
public:
inline ViewMapTesselator3D() : ViewMapTesselator()
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
index 33f72cc0c9f..3082988bd36 100644
--- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
@@ -9,6 +9,8 @@
#include "WEdge.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
/** Temporary structures */
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
index 2c107a01d13..6838060b44e 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -6,6 +6,9 @@
*/
#include "WXEdge.h"
+
+#include "BLI_sys_types.h"
+
#include "BKE_global.h"
namespace Freestyle {
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
index 929e9b7e4dd..e22de505472 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
@@ -9,6 +9,8 @@
#include "WXEdgeBuilder.h"
#include "WXEdge.h"
+#include "BLI_sys_types.h"
+
namespace Freestyle {
void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet &ifs)
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
index e8095d89ee1..ce6054830f3 100644
--- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
@@ -14,6 +14,8 @@
#include "../scene_graph/NodeShape.h"
+#include "BLI_sys_types.h"
+
using namespace std;
namespace Freestyle {
diff --git a/source/blender/geometry/intern/fillet_curves.cc b/source/blender/geometry/intern/fillet_curves.cc
index 1bbbee6edef..2479458f88d 100644
--- a/source/blender/geometry/intern/fillet_curves.cc
+++ b/source/blender/geometry/intern/fillet_curves.cc
@@ -148,12 +148,14 @@ static float limit_radius(const float3 &position_prev,
const float displacement_prev = radius_prev * std::tan(angle_prev / 2.0f);
const float segment_length_prev = math::distance(position, position_prev);
const float total_displacement_prev = displacement_prev + displacement;
- const float factor_prev = std::clamp(segment_length_prev / total_displacement_prev, 0.0f, 1.0f);
+ const float factor_prev = std::clamp(
+ safe_divide(segment_length_prev, total_displacement_prev), 0.0f, 1.0f);
const float displacement_next = radius_next * std::tan(angle_next / 2.0f);
const float segment_length_next = math::distance(position, position_next);
const float total_displacement_next = displacement_next + displacement;
- const float factor_next = std::clamp(segment_length_next / total_displacement_next, 0.0f, 1.0f);
+ const float factor_next = std::clamp(
+ safe_divide(segment_length_next, total_displacement_next), 0.0f, 1.0f);
return radius * std::min(factor_prev, factor_next);
}
diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc
index c649bde06ca..2d9c23df348 100644
--- a/source/blender/geometry/intern/realize_instances.cc
+++ b/source/blender/geometry/intern/realize_instances.cc
@@ -433,7 +433,7 @@ static void foreach_geometry_in_reference(
int index = 0;
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) {
const GeometrySet object_geometry_set = object_get_evaluated_geometry_set(*object);
- const float4x4 matrix = base_transform * offset_matrix * object->obmat;
+ const float4x4 matrix = base_transform * offset_matrix * object->object_to_world;
const int sub_id = noise::hash(id, index);
fn(object_geometry_set, matrix, sub_id);
index++;
diff --git a/source/blender/geometry/intern/resample_curves.cc b/source/blender/geometry/intern/resample_curves.cc
index a7f6ac16f8d..3be850ec097 100644
--- a/source/blender/geometry/intern/resample_curves.cc
+++ b/source/blender/geometry/intern/resample_curves.cc
@@ -139,6 +139,9 @@ static void gather_point_attributes_to_interpolate(
if (meta_data.domain != ATTR_DOMAIN_POINT) {
return true;
}
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
if (!interpolate_attribute_to_curves(id, dst_curves.curve_type_counts())) {
return true;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index 8bb61136cc2..e51fe8832f0 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -104,9 +104,9 @@ static void BKE_gpencil_instance_modifier_instance_tfm(Object *ob,
if (mmd->flag & GP_ARRAY_USE_OFFSET) {
add_v3_v3(mat_offset[3], mmd->offset);
}
- invert_m4_m4(obinv, ob->obmat);
+ invert_m4_m4(obinv, ob->object_to_world);
- mul_m4_series(r_offset, mat_offset, obinv, mmd->object->obmat);
+ mul_m4_series(r_offset, mat_offset, obinv, mmd->object->object_to_world);
copy_m4_m4(mat_offset, r_offset);
/* clear r_mat locations to avoid double transform */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index 3c971ec6af0..49ac3275c82 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -303,8 +303,8 @@ static void build_sequential(Object *ob,
/* Compute distance to control object if set, and build according to that order. */
if (mmd->object) {
float sv1[3], sv2[3];
- mul_v3_m4v3(sv1, ob->obmat, &gps->points[0].x);
- mul_v3_m4v3(sv2, ob->obmat, &gps->points[gps->totpoints - 1].x);
+ mul_v3_m4v3(sv1, ob->object_to_world, &gps->points[0].x);
+ mul_v3_m4v3(sv2, ob->object_to_world, &gps->points[gps->totpoints - 1].x);
float dist_l = len_v3v3(sv1, mmd->object->loc);
float dist_r = len_v3v3(sv2, mmd->object->loc);
if (dist_r < dist_l) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index 1a2bfebdc55..6e31fffd11d 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -234,13 +234,13 @@ static void deformStroke(GpencilModifierData *md,
/* get world-space matrix of target, corrected for the space the verts are in */
if (mmd->subtarget[0] && pchan) {
/* bone target if there's a matching pose-channel */
- mul_m4_m4m4(dmat, mmd->object->obmat, pchan->pose_mat);
+ mul_m4_m4m4(dmat, mmd->object->object_to_world, pchan->pose_mat);
}
else {
/* just object target */
- copy_m4_m4(dmat, mmd->object->obmat);
+ copy_m4_m4(dmat, mmd->object->object_to_world);
}
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_series(tData.mat, ob->imat, dmat, mmd->parentinv);
/* loop points and apply deform */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index 326e86091c5..bc91094e80e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -81,8 +81,8 @@ static void update_mirror_object(Object *ob,
float tmp[4][4];
float itmp[4][4];
- invert_m4_m4(tmp, mmd->object->obmat);
- mul_m4_m4m4(tmp, tmp, ob->obmat);
+ invert_m4_m4(tmp, mmd->object->object_to_world);
+ mul_m4_m4m4(tmp, tmp, ob->object_to_world);
invert_m4_m4(itmp, tmp);
mul_m4_series(mtx, itmp, mtx, tmp);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
index 1cf11a694ac..cb4a7893080 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
@@ -109,7 +109,7 @@ static void duplicateStroke(Object *ob,
float opacity_factor;
/* Apply object scale to offset distance. */
- offset *= mat4_to_scale(ob->obmat);
+ offset *= mat4_to_scale(ob->object_to_world);
BKE_gpencil_stroke_normal(gps, stroke_normal);
if (len_v3(stroke_normal) < FLT_EPSILON) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c
index 387e3c2d5ce..455d8b0b528 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c
@@ -116,7 +116,7 @@ static void convert_stroke(GpencilModifierData *md,
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
- gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
/* Stroke. */
@@ -197,7 +197,7 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec
}
Object *cam_ob = scene->camera;
float viewmat[4][4];
- invert_m4_m4(viewmat, cam_ob->obmat);
+ invert_m4_m4(viewmat, cam_ob->object_to_world);
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
@@ -240,7 +240,7 @@ static void bakeModifier(Main *UNUSED(bmain),
BKE_scene_graph_update_for_newframe(depsgraph);
/* Ensure the camera is the right one. */
BKE_scene_camera_switch_update(scene);
- invert_m4_m4(viewmat, cam_ob->obmat);
+ invert_m4_m4(viewmat, cam_ob->object_to_world);
/* Prepare transform matrix. */
float diff_mat[4][4];
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index 94d8cb98290..7add5c7b84e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -144,7 +144,7 @@ static void deformStroke(GpencilModifierData *md,
float coba_res[4];
float matrix[4][4];
if (is_gradient) {
- mul_m4_m4m4(matrix, mmd->object->imat, ob->obmat);
+ mul_m4_m4m4(matrix, mmd->object->imat, ob->object_to_world);
}
/* loop points and apply color. */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c
index 3ecff4bf447..e9761732614 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_angle.c
@@ -97,7 +97,7 @@ static void deformStroke(GpencilModifierData *md,
/* Apply the rotation of the object. */
if (mmd->space == GP_SPACE_LOCAL) {
- mul_mat3_m4_v3(ob->obmat, vec_ref);
+ mul_mat3_m4_v3(ob->object_to_world, vec_ref);
}
/* Ensure there is a vertex group. */
@@ -122,8 +122,8 @@ static void deformStroke(GpencilModifierData *md,
bGPDspoint *pt1 = (i > 0) ? &gps->points[i] : &gps->points[i + 1];
bGPDspoint *pt2 = (i > 0) ? &gps->points[i - 1] : &gps->points[i];
float fpt1[3], fpt2[3];
- mul_v3_m4v3(fpt1, ob->obmat, &pt1->x);
- mul_v3_m4v3(fpt2, ob->obmat, &pt2->x);
+ mul_v3_m4v3(fpt1, ob->object_to_world, &pt1->x);
+ mul_v3_m4v3(fpt2, ob->object_to_world, &pt2->x);
float vec[3];
sub_v3_v3v3(vec, fpt1, fpt2);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c
index f64c83443d8..ddf852bcd11 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight_proximity.c
@@ -64,8 +64,8 @@ static float calc_point_weight_by_distance(Object *ob,
{
float weight;
float gvert[3];
- mul_v3_m4v3(gvert, ob->obmat, &pt->x);
- float dist = len_v3v3(mmd->object->obmat[3], gvert);
+ mul_v3_m4v3(gvert, ob->object_to_world, &pt->x);
+ float dist = len_v3v3(mmd->object->object_to_world[3], gvert);
if (dist > dist_max) {
weight = 1.0f;
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc
index 5e741ccbd55..85f158d42e6 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc
@@ -9,17 +9,15 @@
#include "MOD_lineart.h"
#include "lineart_intern.h"
-static bool cmp_adjacent_items(const LineartAdjacentEdge &p1, const LineartAdjacentEdge &p2)
-{
- int a = p1.v1 - p2.v1;
- int b = p1.v2 - p2.v2;
- /* parallel_sort() requires cmp() to return true when the first element needs to appear before
- * the second element in the sorted array, false otherwise (strict weak ordering), see
- * https://en.cppreference.com/w/cpp/named_req/Compare. */
- return a < 0 ? true : (a == 0 ? b < 0 : false);
-}
-
void lineart_sort_adjacent_items(LineartAdjacentEdge *ai, int length)
{
- blender::parallel_sort(ai, ai + length, cmp_adjacent_items);
+ blender::parallel_sort(
+ ai, ai + length, [](const LineartAdjacentEdge &p1, const LineartAdjacentEdge &p2) {
+ int a = p1.v1 - p2.v1;
+ int b = p1.v2 - p2.v2;
+ /* parallel_sort() requires cmp() to return true when the first element needs to appear
+ * before the second element in the sorted array, false otherwise (strict weak ordering),
+ * see https://en.cppreference.com/w/cpp/named_req/Compare. */
+ return a < 0 ? true : (a == 0 ? b < 0 : false);
+ });
}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index c1e71bde254..4b5c40c0e38 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -2633,7 +2633,7 @@ void lineart_main_load_geometries(Depsgraph *depsgraph,
scene,
eval_ob,
eval_ob,
- eval_ob->obmat,
+ eval_ob->object_to_world,
is_render,
olti,
thread_count,
@@ -3589,11 +3589,11 @@ static LineartData *lineart_create_render_buffer(Scene *scene,
clipping_offset = 0.0001;
}
- copy_v3db_v3fl(ld->conf.camera_pos, camera->obmat[3]);
+ copy_v3db_v3fl(ld->conf.camera_pos, camera->object_to_world[3]);
if (active_camera) {
- copy_v3db_v3fl(ld->conf.active_camera_pos, active_camera->obmat[3]);
+ copy_v3db_v3fl(ld->conf.active_camera_pos, active_camera->object_to_world[3]);
}
- copy_m4_m4(ld->conf.cam_obmat, camera->obmat);
+ copy_m4_m4(ld->conf.cam_obmat, camera->object_to_world);
ld->conf.cam_is_persp = (c->type == CAM_PERSP);
ld->conf.near_clip = c->clip_start + clipping_offset;
@@ -3620,8 +3620,8 @@ static LineartData *lineart_create_render_buffer(Scene *scene,
if (lmd->light_contour_object) {
Object *light_obj = lmd->light_contour_object;
- copy_v3db_v3fl(ld->conf.camera_pos_secondary, light_obj->obmat[3]);
- copy_m4_m4(ld->conf.cam_obmat_secondary, light_obj->obmat);
+ copy_v3db_v3fl(ld->conf.camera_pos_secondary, light_obj->object_to_world[3]);
+ copy_m4_m4(ld->conf.cam_obmat_secondary, light_obj->object_to_world);
ld->conf.light_reference_available = true;
if (light_obj->type == OB_LAMP) {
ld->conf.cam_is_persp_secondary = ((Light *)light_obj->data)->type != LA_SUN;
@@ -5418,7 +5418,7 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
}
float gp_obmat_inverse[4][4];
- invert_m4_m4(gp_obmat_inverse, ob->obmat);
+ invert_m4_m4(gp_obmat_inverse, ob->object_to_world);
lineart_gpencil_generate(cache,
depsgraph,
ob,
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c
index e34e6fc43ea..edea052e728 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_shadow.c
@@ -1167,7 +1167,7 @@ bool lineart_main_try_generate_shadow(Depsgraph *depsgraph,
copy_v3_v3_db(ld->conf.camera_pos_secondary, ld->conf.camera_pos);
copy_m4_m4(ld->conf.cam_obmat_secondary, ld->conf.cam_obmat);
- copy_m4_m4(ld->conf.cam_obmat, lmd->light_contour_object->obmat);
+ copy_m4_m4(ld->conf.cam_obmat, lmd->light_contour_object->object_to_world);
copy_v3db_v3fl(ld->conf.camera_pos, ld->conf.cam_obmat[3]);
ld->conf.cam_is_persp_secondary = ld->conf.cam_is_persp;
ld->conf.cam_is_persp = is_persp;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 5a1e0cde1d8..bfbbf1be225 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -12,6 +12,7 @@ endif()
set(INC
.
intern
+ vulkan
metal
opengl
../blenkernel
@@ -184,6 +185,34 @@ set(OPENGL_SRC
opengl/gl_vertex_buffer.hh
)
+set(VULKAN_SRC
+ vulkan/vk_backend.cc
+ vulkan/vk_batch.cc
+ vulkan/vk_context.cc
+ vulkan/vk_drawlist.cc
+ vulkan/vk_framebuffer.cc
+ vulkan/vk_index_buffer.cc
+ vulkan/vk_query.cc
+ vulkan/vk_shader.cc
+ vulkan/vk_storage_buffer.cc
+ vulkan/vk_texture.cc
+ vulkan/vk_uniform_buffer.cc
+ vulkan/vk_vertex_buffer.cc
+
+ vulkan/vk_backend.hh
+ vulkan/vk_batch.hh
+ vulkan/vk_context.hh
+ vulkan/vk_drawlist.hh
+ vulkan/vk_framebuffer.hh
+ vulkan/vk_index_buffer.hh
+ vulkan/vk_query.hh
+ vulkan/vk_shader.hh
+ vulkan/vk_storage_buffer.hh
+ vulkan/vk_texture.hh
+ vulkan/vk_uniform_buffer.hh
+ vulkan/vk_vertex_buffer.hh
+)
+
set(METAL_SRC
metal/mtl_backend.mm
metal/mtl_batch.mm
@@ -235,6 +264,10 @@ if(WITH_OPENGL)
list(APPEND SRC ${OPENGL_SRC})
endif()
+if(WITH_VULKAN_BACKEND)
+ list(APPEND SRC ${VULKAN_SRC})
+endif()
+
if(WITH_METAL_BACKEND)
list(APPEND SRC ${METAL_SRC})
endif()
@@ -282,6 +315,8 @@ set(GLSL_SRC
shaders/gpu_shader_2D_image_vert.glsl
shaders/gpu_shader_2D_image_rect_vert.glsl
shaders/gpu_shader_2D_image_multi_rect_vert.glsl
+ shaders/gpu_shader_icon_frag.glsl
+ shaders/gpu_shader_icon_vert.glsl
shaders/gpu_shader_image_frag.glsl
shaders/gpu_shader_image_desaturate_frag.glsl
shaders/gpu_shader_image_overlays_merge_frag.glsl
@@ -349,6 +384,7 @@ set(GLSL_SRC
shaders/compositor/compositor_morphological_distance_feather.glsl
shaders/compositor/compositor_morphological_distance_threshold.glsl
shaders/compositor/compositor_morphological_step.glsl
+ shaders/compositor/compositor_normalize.glsl
shaders/compositor/compositor_parallel_reduction.glsl
shaders/compositor/compositor_projector_lens_distortion.glsl
shaders/compositor/compositor_realize_on_domain.glsl
@@ -357,6 +393,8 @@ set(GLSL_SRC
shaders/compositor/compositor_split_viewer.glsl
shaders/compositor/compositor_symmetric_blur.glsl
shaders/compositor/compositor_symmetric_separable_blur.glsl
+ shaders/compositor/compositor_tone_map_photoreceptor.glsl
+ shaders/compositor/compositor_tone_map_simple.glsl
shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl
shaders/compositor/library/gpu_shader_compositor_blur_common.glsl
@@ -606,6 +644,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/gpu_shader_3D_smooth_color_info.hh
shaders/infos/gpu_shader_3D_uniform_color_info.hh
shaders/infos/gpu_shader_gpencil_stroke_info.hh
+ shaders/infos/gpu_shader_icon_info.hh
shaders/infos/gpu_shader_instance_varying_color_varying_size_info.hh
shaders/infos/gpu_shader_keyframe_shape_info.hh
shaders/infos/gpu_shader_line_dashed_uniform_color_info.hh
@@ -631,6 +670,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/compositor/infos/compositor_morphological_distance_info.hh
shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh
shaders/compositor/infos/compositor_morphological_step_info.hh
+ shaders/compositor/infos/compositor_normalize_info.hh
shaders/compositor/infos/compositor_parallel_reduction_info.hh
shaders/compositor/infos/compositor_projector_lens_distortion_info.hh
shaders/compositor/infos/compositor_realize_on_domain_info.hh
@@ -639,6 +679,8 @@ set(SRC_SHADER_CREATE_INFOS
shaders/compositor/infos/compositor_split_viewer_info.hh
shaders/compositor/infos/compositor_symmetric_blur_info.hh
shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh
+ shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh
+ shaders/compositor/infos/compositor_tone_map_simple_info.hh
)
set(SRC_SHADER_CREATE_INFOS_MTL
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index b59ea9e55d2..ac82774039a 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -21,6 +21,8 @@ extern "C" {
* automatically initializes the back-end, and #GPU_context_discard frees it when there
* are no more contexts. */
bool GPU_backend_supported(void);
+void GPU_backend_type_selection_set(const eGPUBackendType backend);
+eGPUBackendType GPU_backend_type_selection_get(void);
eGPUBackendType GPU_backend_get_type(void);
/** Opaque type hiding blender::gpu::Context. */
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index bdb384c16f1..917407eece3 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -47,6 +47,9 @@ typedef struct GPUOffScreen GPUOffScreen;
GPUFrameBuffer *GPU_framebuffer_create(const char *name);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
void GPU_framebuffer_bind(GPUFrameBuffer *fb);
+
+const char *GPU_framebuffer_get_name(GPUFrameBuffer *fb);
+
/**
* Workaround for binding a SRGB frame-buffer without doing the SRGB transform.
*/
diff --git a/source/blender/gpu/GPU_platform.h b/source/blender/gpu/GPU_platform.h
index b63fe4c0580..657b45df1a5 100644
--- a/source/blender/gpu/GPU_platform.h
+++ b/source/blender/gpu/GPU_platform.h
@@ -16,6 +16,7 @@ typedef enum eGPUBackendType {
GPU_BACKEND_NONE = 0,
GPU_BACKEND_OPENGL = 1 << 0,
GPU_BACKEND_METAL = 1 << 1,
+ GPU_BACKEND_VULKAN = 1 << 3,
GPU_BACKEND_ANY = 0xFFFFFFFFu
} eGPUBackendType;
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 3f35db42eb9..1148207fc57 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -209,6 +209,10 @@ typedef enum eGPUBuiltinShader {
GPU_SHADER_KEYFRAME_SHAPE,
GPU_SHADER_SIMPLE_LIGHTING,
/**
+ * Draw an icon, leaving a semi-transparent rectangle on top of the icon.
+ */
+ GPU_SHADER_ICON,
+ /**
* Take a 2D position and color for each vertex with linear interpolation in window space.
*
* \param color: in vec4
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 48d7b2019c5..7e94538892a 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -33,6 +33,9 @@
# include "gl_backend.hh"
# include "gl_context.hh"
#endif
+#ifdef WITH_VULKAN_BACKEND
+# include "vk_backend.hh"
+#endif
#ifdef WITH_METAL_BACKEND
# include "mtl_backend.hh"
#endif
@@ -223,9 +226,19 @@ void GPU_render_step()
/* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`.
* Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL:
* `m_useMetalForRendering = true`. */
-static const eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL;
+static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL;
static GPUBackend *g_backend = nullptr;
+void GPU_backend_type_selection_set(const eGPUBackendType backend)
+{
+ g_backend_type = backend;
+}
+
+eGPUBackendType GPU_backend_type_selection_get()
+{
+ return g_backend_type;
+}
+
bool GPU_backend_supported(void)
{
switch (g_backend_type) {
@@ -235,6 +248,12 @@ bool GPU_backend_supported(void)
#else
return false;
#endif
+ case GPU_BACKEND_VULKAN:
+#ifdef WITH_VULKAN_BACKEND
+ return true;
+#else
+ return false;
+#endif
case GPU_BACKEND_METAL:
#ifdef WITH_METAL_BACKEND
return MTLBackend::metal_is_supported();
@@ -258,6 +277,11 @@ static void gpu_backend_create()
g_backend = new GLBackend;
break;
#endif
+#ifdef WITH_VULKAN_BACKEND
+ case GPU_BACKEND_VULKAN:
+ g_backend = new VKBackend;
+ break;
+#endif
#ifdef WITH_METAL_BACKEND
case GPU_BACKEND_METAL:
g_backend = new MTLBackend;
diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc
index 6528f39d4ec..5b50fd66196 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.cc
+++ b/source/blender/gpu/intern/gpu_framebuffer.cc
@@ -238,6 +238,11 @@ void GPU_framebuffer_free(GPUFrameBuffer *gpu_fb)
delete unwrap(gpu_fb);
}
+const char *GPU_framebuffer_get_name(GPUFrameBuffer *gpu_fb)
+{
+ return unwrap(gpu_fb)->name_get();
+}
+
/* ---------- Binding ----------- */
void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb)
diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh
index 76e816e7f65..cb7fd62445c 100644
--- a/source/blender/gpu/intern/gpu_framebuffer_private.hh
+++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh
@@ -95,11 +95,6 @@ class FrameBuffer {
#endif
public:
- /* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer.
- * Points to #BPyGPUFrameBuffer::fb */
- void **ref = nullptr;
-
- public:
FrameBuffer(const char *name);
virtual ~FrameBuffer();
@@ -209,6 +204,11 @@ class FrameBuffer {
{
return attachments_[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
};
+
+ inline const char *const name_get() const
+ {
+ return name_;
+ };
};
/* Syntactic sugar. */
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index 3b4accf9cc5..81c0a65bb7c 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -45,7 +45,7 @@ void immBindShader(GPUShader *shader)
BLI_assert(imm->shader == nullptr);
imm->shader = shader;
- imm->builtin_shader_bound = GPU_SHADER_TEXT; /* Default value. */
+ imm->builtin_shader_bound = std::nullopt;
if (!imm->vertex_format.packed) {
VertexFormat_pack(&imm->vertex_format);
@@ -125,9 +125,12 @@ static void wide_line_workaround_start(GPUPrimType prim_type)
/* No need to change the shader. */
return;
}
+ if (!imm->builtin_shader_bound) {
+ return;
+ }
eGPUBuiltinShader polyline_sh;
- switch (imm->builtin_shader_bound) {
+ switch (*imm->builtin_shader_bound) {
case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR:
polyline_sh = GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR;
break;
@@ -180,8 +183,8 @@ static void wide_line_workaround_end()
}
immUnbindProgram();
- immBindBuiltinProgram(imm->prev_builtin_shader);
- imm->prev_builtin_shader = GPU_SHADER_TEXT;
+ immBindBuiltinProgram(*imm->prev_builtin_shader);
+ imm->prev_builtin_shader = std::nullopt;
}
}
diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh
index 74ebbdc7ae3..c4e11e7082b 100644
--- a/source/blender/gpu/intern/gpu_immediate_private.hh
+++ b/source/blender/gpu/intern/gpu_immediate_private.hh
@@ -9,6 +9,8 @@
#pragma once
+#include <optional>
+
#include "GPU_batch.h"
#include "GPU_primitive.h"
#include "GPU_shader.h"
@@ -42,9 +44,9 @@ class Immediate {
/** Wide Line workaround. */
/** Previously bound shader to restore after drawing. */
- eGPUBuiltinShader prev_builtin_shader = GPU_SHADER_TEXT;
- /** Builtin shader index. Used to test if the workaround can be done. */
- eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT;
+ std::optional<eGPUBuiltinShader> prev_builtin_shader;
+ /** Builtin shader index. Used to test if the line width workaround can be done. */
+ std::optional<eGPUBuiltinShader> builtin_shader_bound;
/** Uniform color: Kept here to update the wide-line shader just before #immBegin. */
float uniform_color[4];
diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc
index 3aa2963ecd0..abb45ca074a 100644
--- a/source/blender/gpu/intern/gpu_shader_builder.cc
+++ b/source/blender/gpu/intern/gpu_shader_builder.cc
@@ -15,6 +15,8 @@
#include "GPU_init_exit.h"
#include "gpu_shader_create_info_private.hh"
+#include "BLI_vector.hh"
+
#include "CLG_log.h"
namespace blender::gpu::shader_builder {
@@ -41,6 +43,22 @@ void ShaderBuilder::init()
CLG_init();
GHOST_GLSettings glSettings = {0};
+ switch (GPU_backend_type_selection_get()) {
+ case GPU_BACKEND_OPENGL:
+ glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
+ break;
+
+#ifdef WITH_METAL_BACKEND
+ case GPU_BACKEND_METAL:
+ glSettings.context_type = GHOST_kDrawingContextTypeMetal;
+ break;
+#endif
+
+ default:
+ BLI_assert_unreachable();
+ break;
+ }
+
ghost_system_ = GHOST_CreateSystem();
ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings);
GHOST_ActivateOpenGLContext(ghost_context_);
@@ -73,13 +91,32 @@ int main(int argc, const char *argv[])
int exit_code = 0;
- blender::gpu::shader_builder::ShaderBuilder builder;
- builder.init();
- if (!builder.bake_create_infos()) {
- exit_code = 1;
+ struct NamedBackend {
+ std::string name;
+ eGPUBackendType backend;
+ };
+
+ blender::Vector<NamedBackend> backends_to_validate;
+ backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL});
+#ifdef WITH_METAL_BACKEND
+ backends_to_validate.append({"Metal", GPU_BACKEND_METAL});
+#endif
+ for (NamedBackend &backend : backends_to_validate) {
+ GPU_backend_type_selection_set(backend.backend);
+ if (!GPU_backend_supported()) {
+ printf("%s isn't supported on this platform. Shader compilation is skipped\n",
+ backend.name.c_str());
+ continue;
+ }
+ blender::gpu::shader_builder::ShaderBuilder builder;
+ builder.init();
+ if (!builder.bake_create_infos()) {
+ printf("Shader compilation failed for %s backend\n", backend.name.c_str());
+ exit_code = 1;
+ }
+ builder.exit();
}
- builder.exit();
- exit(exit_code);
+ exit(exit_code);
return exit_code;
}
diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
index 7a06ede5c6d..65bda7ba858 100644
--- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
+++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
@@ -46,6 +46,15 @@ void IMB_freeImBuf(ImBuf * /*ibuf*/)
BLI_assert_unreachable();
}
+struct ImBuf *IMB_allocImBuf(unsigned int /*x*/,
+ unsigned int /*y*/,
+ unsigned char /*planes*/,
+ unsigned int /*flags*/)
+{
+ BLI_assert_unreachable();
+ return nullptr;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index 8a6586e06f6..470643ba863 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -153,6 +153,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.create_info = "gpu_shader_2D_diag_stripes",
},
+ [GPU_SHADER_ICON] =
+ {
+ .name = "GPU_SHADER_ICON",
+ .create_info = "gpu_shader_icon",
+ },
[GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] =
{
.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE",
diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh
index 2ad31183206..124b1751b96 100644
--- a/source/blender/gpu/intern/gpu_texture_private.hh
+++ b/source/blender/gpu/intern/gpu_texture_private.hh
@@ -588,7 +588,7 @@ inline eGPUFrameBufferBits to_framebuffer_bits(eGPUTextureFormat tex_format)
static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format)
{
- if (format->attr_len > 1 || format->attr_len == 0) {
+ if (format->attr_len == 0) {
BLI_assert_msg(0, "Incorrect vertex format for buffer texture");
return GPU_DEPTH_COMPONENT24;
}
diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc
index b30e3c358c8..76d95ac1b55 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.cc
+++ b/source/blender/gpu/intern/gpu_vertex_format.cc
@@ -361,8 +361,12 @@ void VertexFormat_texture_buffer_pack(GPUVertFormat *format)
* minimum per-vertex stride, which mandates 4-byte alignment in Metal.
* This additional alignment padding caused smaller data types, e.g. U16,
* to mis-align. */
- BLI_assert_msg(format->attr_len == 1,
- "Texture buffer mode should only use a single vertex attribute.");
+ for (int i = 0; i < format->attr_len; i++) {
+ /* The buffer texture setup uses the first attribute for type and size.
+ * Make sure all attributes use the same size. */
+ BLI_assert_msg(format->attrs[i].size == format->attrs[0].size,
+ "Texture buffer mode should only use a attributes with the same size.");
+ }
/* Pack vertex format without minimum stride, as this is not required by texture buffers. */
VertexFormat_pack_impl(format, 1);
diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm
index e9804d4be77..988fb9b793b 100644
--- a/source/blender/gpu/metal/mtl_batch.mm
+++ b/source/blender/gpu/metal/mtl_batch.mm
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
@@ -68,7 +69,7 @@ void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_ensure()
}
}
- /* Initialise cache if not ready. */
+ /* Initialize cache if not ready. */
if (cache_context_ == nullptr) {
this->vertex_descriptor_cache_init(MTLContext::get());
}
@@ -188,7 +189,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
buffer_stride);
}
else {
- /* Ensure stride is correct for de-interlevaed attributes. */
+ /* Ensure stride is correct for de-interleaved attributes. */
desc.vertex_descriptor.buffer_layouts[buffer_index].stride = buffer_stride;
}
@@ -278,7 +279,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
* elements).
*
* Certain conversion cannot be performed however, and in these cases, we need to
- * instruct the shader to generate a specialised version with a conversion routine upon
+ * instruct the shader to generate a specialized version with a conversion routine upon
* attribute read.
* - This handles cases such as conversion between types e.g. Integer to float without
* normalization.
@@ -310,7 +311,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
* This then controls how a given attribute is interpreted. The data will be read
* as specified and then converted appropriately to the correct form.
*
- * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialised read-routine
+ * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialized read-routine
* in the shader will read the data as an int, and cast this to floating point
* representation. (Rather than reading the source data as float).
*
@@ -403,7 +404,7 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
active_shader_ = (shader) ? static_cast<MTLShader *>(unwrap(shader)) : nullptr;
if (active_shader_ == nullptr || !active_shader_->is_valid()) {
- /* Skip drawing if there is no vaid Metal shader.
+ /* Skip drawing if there is no valid Metal shader.
* This will occur if the path through which the shader is prepared
* is invalid (e.g. Python without create-info), or, the source shader uses a geometry pass. */
BLI_assert_msg(false, "No valid Metal shader!");
@@ -455,7 +456,7 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
/* Fetch RenderPassState to enable resource binding for active pass. */
MTLRenderPassState &rps = ctx->main_command_buffer.get_render_pass_state();
- /* Debug Check: Ensure Framebuffer instance is not dirty. */
+ /* Debug Check: Ensure Frame-buffer instance is not dirty. */
BLI_assert(!ctx->main_command_buffer.get_active_framebuffer()->get_dirty());
/* Bind Shader. */
@@ -495,8 +496,8 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
if (mtl_elem != nullptr) {
- /* Fetch index buffer. This function can situationally return an optimised
- * index buffer of a different primtiive type. If this is the case, `final_prim_type`
+ /* Fetch index buffer. This function can situationally return an optimized
+ * index buffer of a different primitive type. If this is the case, `final_prim_type`
* and `v_count` will be updated with the new format.
* NOTE: For indexed rendering, v_count represents the number of indices. */
idx_buffer = mtl_elem->get_index_buffer(final_prim_type, v_count);
@@ -594,8 +595,10 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(
desc.reset_vertex_descriptor();
/* Fetch Vertex and Instance Buffers. */
- Span<MTLVertBuf *> mtl_verts(reinterpret_cast<MTLVertBuf **>(this->verts), GPU_BATCH_VBO_MAX_LEN);
- Span<MTLVertBuf *> mtl_inst(reinterpret_cast<MTLVertBuf **>(this->inst), GPU_BATCH_INST_VBO_MAX_LEN);
+ Span<MTLVertBuf *> mtl_verts(reinterpret_cast<MTLVertBuf **>(this->verts),
+ GPU_BATCH_VBO_MAX_LEN);
+ Span<MTLVertBuf *> mtl_inst(reinterpret_cast<MTLVertBuf **>(this->inst),
+ GPU_BATCH_INST_VBO_MAX_LEN);
/* SSBO Vertex fetch also passes vertex descriptor information into the shader. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
@@ -671,7 +674,7 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(
}
}
- /* Extract Vertex attribues (First-bound vertex buffer takes priority). */
+ /* Extract Vertex attributes (First-bound vertex buffer takes priority). */
for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
if (mtl_verts[v] != NULL) {
MTL_LOG_INFO(" -- [Batch] Checking bindings for bound vertex buffer %p\n", mtl_verts[v]);
@@ -829,7 +832,7 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count)
"Index offset is not 2/4-byte aligned as per METAL spec");
/* Fetch index buffer. May return an index buffer of a differing format,
- * if index buffer optimisation is used. In these cases, final_prim_type and
+ * if index buffer optimization is used. In these cases, final_prim_type and
* index_count get updated with the new properties. */
GPUPrimType final_prim_type = this->prim_type;
uint index_count = v_count;
diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm
index 76e2abb4ea6..99194d2b72c 100644
--- a/source/blender/gpu/metal/mtl_drawlist.mm
+++ b/source/blender/gpu/metal/mtl_drawlist.mm
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
/** \file
* \ingroup gpu
*
@@ -151,7 +153,7 @@ void MTLDrawList::submit()
{
/* Metal does not support MDI from the host side, but we still benefit from only executing the
* batch bind a single time, rather than per-draw.
- * NOTE(Metal): Consider using MTLIndirectCommandBuffer to achieve similar behaviour. */
+ * NOTE(Metal): Consider using #MTLIndirectCommandBuffer to achieve similar behavior. */
if (command_len_ == 0) {
return;
}
@@ -192,12 +194,12 @@ void MTLDrawList::submit()
/* Common properties. */
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(batch_->prim_type);
- /* Execute multidraw indirect. */
+ /* Execute multi-draw indirect. */
if (can_use_MDI && false) {
/* Metal Doesn't support MDI -- Singular Indirect draw calls are supported,
- * but Multidraw is not.
- * TODO(Metal): Consider using IndirectCommandBuffers to provide similar
- * behaviour. */
+ * but Multi-draw is not.
+ * TODO(Metal): Consider using #IndirectCommandBuffers to provide similar
+ * behavior. */
}
else {
@@ -214,7 +216,7 @@ void MTLDrawList::submit()
uint32_t index_count = cmd->indexCount;
/* Fetch index buffer. May return an index buffer of a differing format,
- * if index buffer optimisation is used. In these cases, mtl_prim_type and
+ * if index buffer optimization is used. In these cases, mtl_prim_type and
* index_count get updated with the new properties. */
GPUPrimType final_prim_type = batch_->prim_type;
id<MTLBuffer> index_buffer = mtl_elem->get_index_buffer(final_prim_type, index_count);
diff --git a/source/blender/gpu/metal/mtl_shader_generator.hh b/source/blender/gpu/metal/mtl_shader_generator.hh
index 43890ca0170..63e2e6d5924 100644
--- a/source/blender/gpu/metal/mtl_shader_generator.hh
+++ b/source/blender/gpu/metal/mtl_shader_generator.hh
@@ -497,7 +497,7 @@ inline std::string get_stage_class_name(ShaderStage stage)
inline bool is_builtin_type(std::string type)
{
/* Add Types as needed. */
- /* TODO(Metal): Consider replacing this with a switch and constexpr hash and switch.
+ /* TODO(Metal): Consider replacing this with a switch and `constexpr` hash and switch.
* Though most efficient and maintainable approach to be determined. */
static std::map<std::string, eMTLDataType> glsl_builtin_types = {
{"float", MTL_DATATYPE_FLOAT},
diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm
index 4931f8a4f52..29dcc8d32ee 100644
--- a/source/blender/gpu/metal/mtl_texture.mm
+++ b/source/blender/gpu/metal/mtl_texture.mm
@@ -1510,7 +1510,7 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
texture_descriptor_.mipmapLevelCount = mtl_max_mips_;
texture_descriptor_.usage =
MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
- MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimise usage flags. */
+ MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimize usage flags. */
texture_descriptor_.storageMode = [source_buffer storageMode];
texture_descriptor_.sampleCount = 1;
texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode];
diff --git a/source/blender/gpu/metal/mtl_texture_util.mm b/source/blender/gpu/metal/mtl_texture_util.mm
index 5ed7659f260..33a62e2e3ef 100644
--- a/source/blender/gpu/metal/mtl_texture_util.mm
+++ b/source/blender/gpu/metal/mtl_texture_util.mm
@@ -34,7 +34,7 @@ MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format)
{
switch (tex_format) {
- /* Formats texture & renderbuffer. */
+ /* Formats texture & render-buffer. */
case GPU_RGBA8UI:
return MTLPixelFormatRGBA8Uint;
case GPU_RGBA8I:
diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc
index ff8867fe3e6..28105e326ee 100644
--- a/source/blender/gpu/opengl/gl_batch.cc
+++ b/source/blender/gpu/opengl/gl_batch.cc
@@ -272,8 +272,8 @@ void GLBatch::bind(int i_first)
#if GPU_TRACK_INDEX_RANGE
/* Can be removed if GL 4.3 is required. */
- if (!GLContext::fixed_restart_index_support && (elem != nullptr)) {
- glPrimitiveRestartIndex(this->elem_()->restart_index());
+ if (!GLContext::fixed_restart_index_support) {
+ glPrimitiveRestartIndex((elem != nullptr) ? this->elem_()->restart_index() : 0xFFFFFFFFu);
}
#endif
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc
index c9432fca561..ef97d74bf81 100644
--- a/source/blender/gpu/opengl/gl_shader_interface.cc
+++ b/source/blender/gpu/opengl/gl_shader_interface.cc
@@ -200,6 +200,9 @@ static Type gpu_type_from_gl_type(int gl_type)
GLShaderInterface::GLShaderInterface(GLuint program)
{
+ GLuint last_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program);
+
/* Necessary to make #glUniform works. */
glUseProgram(program);
@@ -385,6 +388,8 @@ GLShaderInterface::GLShaderInterface(GLuint program)
// this->debug_print();
this->sort_inputs();
+
+ glUseProgram(last_program);
}
GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateInfo &info)
@@ -442,6 +447,9 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
uint32_t name_buffer_offset = 0;
/* Necessary to make #glUniform works. TODO(fclem) Remove. */
+ GLuint last_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program);
+
glUseProgram(program);
/* Attributes */
@@ -552,6 +560,8 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
this->sort_inputs();
// this->debug_print();
+
+ glUseProgram(last_program);
}
GLShaderInterface::~GLShaderInterface()
diff --git a/source/blender/gpu/shaders/compositor/compositor_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_blur.glsl
index 4f981c84f59..c7ac620f99b 100644
--- a/source/blender/gpu/shaders/compositor/compositor_blur.glsl
+++ b/source/blender/gpu/shaders/compositor/compositor_blur.glsl
@@ -18,13 +18,24 @@ vec4 load_input(ivec2 texel)
}
/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from
- * the weights texture, where the texel (0, 0) is considered the center of weights texture. */
+ * the weights texture, where the given texel (0, 0) corresponds the center of weights texture.
+ * Note that we load the weights texture inverted along both directions to maintain the shape of
+ * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D
+ * weights texture whose right half is all ones and whose left half is all zeros. Further, consider
+ * that we are blurring a single white pixel on a black background. When computing the value of a
+ * pixel that is to the right of the white pixel, the white pixel will be in the left region of the
+ * search window, and consequently, without inversion, a zero will be sampled from the left side of
+ * the weights texture and result will be zero. However, what we expect is that pixels to the right
+ * of the white pixel will be white, that is, they should sample a weight of 1 from the right side
+ * of the weights texture, hence the need for inversion. */
vec4 load_weight(ivec2 texel)
{
- /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper
- * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the
- * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */
- return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1));
+ /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5
+ * to sample at the center of the pixels, then divide by the upper bound plus one to transform
+ * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally,
+ * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as
+ * mentioned in the function description. */
+ return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1)));
}
void main()
diff --git a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl
index e7e5aac12a5..9383bbf9825 100644
--- a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl
+++ b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl
@@ -2,7 +2,16 @@
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from
- * the weights texture, where the texel (0, 0) is considered the center of weights texture. */
+ * the weights texture, where the given texel (0, 0) corresponds the center of weights texture.
+ * Note that we load the weights texture inverted along both directions to maintain the shape of
+ * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D
+ * weights texture whose right half is all ones and whose left half is all zeros. Further, consider
+ * that we are blurring a single white pixel on a black background. When computing the value of a
+ * pixel that is to the right of the white pixel, the white pixel will be in the left region of the
+ * search window, and consequently, without inversion, a zero will be sampled from the left side of
+ * the weights texture and result will be zero. However, what we expect is that pixels to the right
+ * of the white pixel will be white, that is, they should sample a weight of 1 from the right side
+ * of the weights texture, hence the need for inversion. */
vec4 load_weight(ivec2 texel, float radius)
{
/* The center zero texel is always assigned a unit weight regardless of the corresponding weight
@@ -12,10 +21,12 @@ vec4 load_weight(ivec2 texel, float radius)
return vec4(1.0);
}
- /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper
- * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the
- * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */
- return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1));
+ /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5
+ * to sample at the center of the pixels, then divide by the upper bound plus one to transform
+ * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally,
+ * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as
+ * mentioned in the function description. */
+ return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1)));
}
void main()
diff --git a/source/blender/gpu/shaders/compositor/compositor_normalize.glsl b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl
new file mode 100644
index 00000000000..53dfeb01730
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl
@@ -0,0 +1,10 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+ float value = texture_load(input_tx, texel).x;
+ float normalized_value = (value - minimum) * scale;
+ float clamped_value = clamp(normalized_value, 0.0, 1.0);
+ imageStore(output_img, texel, vec4(clamped_value));
+}
diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl
new file mode 100644
index 00000000000..167006585ca
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl
@@ -0,0 +1,22 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+
+/* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and (7)
+ * from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor
+ * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+
+ vec4 input_color = texture_load(input_tx, texel);
+ float input_luminance = dot(input_color.rgb, luminance_coefficients);
+
+ /* Trilinear interpolation between equations (6) and (7) from Reinhard's 2005 paper. */
+ vec4 local_adaptation_level = mix(vec4(input_luminance), input_color, chromatic_adaptation);
+ vec4 adaptation_level = mix(global_adaptation_level, local_adaptation_level, light_adaptation);
+
+ /* Equation (1) from Reinhard's 2005 paper, assuming Vmax is 1. */
+ vec4 semi_saturation = pow(intensity * adaptation_level, vec4(contrast));
+ vec4 tone_mapped_color = input_color / (input_color + semi_saturation);
+
+ imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a));
+}
diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl
new file mode 100644
index 00000000000..ce42d021dd1
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl
@@ -0,0 +1,26 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl)
+
+/* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction
+ * for digital images." Proceedings of the 29th annual conference on Computer graphics and
+ * interactive techniques. 2002. */
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+
+ vec4 input_color = texture_load(input_tx, texel);
+
+ /* Equation (2) from Reinhard's 2002 paper. */
+ vec4 scaled_color = input_color * luminance_scale;
+
+ /* Equation (3) from Reinhard's 2002 paper, but with the 1 replaced with the blend factor for
+ * more flexibility. See ToneMapOperation::compute_luminance_scale_blend_factor. */
+ vec4 denominator = luminance_scale_blend_factor + scaled_color;
+ vec4 tone_mapped_color = safe_divide(scaled_color, denominator);
+
+ if (inverse_gamma != 0.0) {
+ tone_mapped_color = pow(max(tone_mapped_color, vec4(0.0)), vec4(inverse_gamma));
+ }
+
+ imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a));
+}
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh
new file mode 100644
index 00000000000..02fdc424014
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_normalize)
+ .local_group_size(16, 16)
+ .push_constant(Type::FLOAT, "minimum")
+ .push_constant(Type::FLOAT, "scale")
+ .sampler(0, ImageType::FLOAT_2D, "input_tx")
+ .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .compute_source("compositor_normalize.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
index 2e661f280af..e2252b14758 100644
--- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
@@ -12,14 +12,17 @@ GPU_SHADER_CREATE_INFO(compositor_parallel_reduction_shared)
* Sum Reductions.
*/
-GPU_SHADER_CREATE_INFO(compositor_sum_float_shared)
+GPU_SHADER_CREATE_INFO(compositor_sum_shared)
.additional_info("compositor_parallel_reduction_shared")
- .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
- .define("TYPE", "float")
.define("IDENTITY", "vec4(0.0)")
- .define("LOAD(value)", "value.x")
.define("REDUCE(lhs, rhs)", "lhs + rhs");
+GPU_SHADER_CREATE_INFO(compositor_sum_float_shared)
+ .additional_info("compositor_sum_shared")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .define("TYPE", "float")
+ .define("LOAD(value)", "value.x");
+
GPU_SHADER_CREATE_INFO(compositor_sum_red)
.additional_info("compositor_sum_float_shared")
.define("INITIALIZE(value)", "value.r")
@@ -41,6 +44,20 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance)
.define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)")
.do_static_compilation(true);
+GPU_SHADER_CREATE_INFO(compositor_sum_log_luminance)
+ .additional_info("compositor_sum_float_shared")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .define("INITIALIZE(value)", "log(max(dot(value.rgb, luminance_coefficients), 1e-5))")
+ .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_sum_color)
+ .additional_info("compositor_sum_shared")
+ .image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .define("TYPE", "vec4")
+ .define("INITIALIZE(value)", "value")
+ .define("LOAD(value)", "value")
+ .do_static_compilation(true);
+
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
@@ -74,3 +91,59 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance_squared_difference)
.push_constant(Type::VEC3, "luminance_coefficients")
.define("INITIALIZE(value)", "pow(dot(value.rgb, luminance_coefficients) - subtrahend, 2.0)")
.do_static_compilation(true);
+
+/* --------------------------------------------------------------------
+ * Maximum Reductions.
+ */
+
+GPU_SHADER_CREATE_INFO(compositor_maximum_luminance)
+ .additional_info("compositor_parallel_reduction_shared")
+ .typedef_source("common_math_lib.glsl")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(FLT_MIN)")
+ .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "max(lhs, rhs)")
+ .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_maximum_float_in_range)
+ .additional_info("compositor_parallel_reduction_shared")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::FLOAT, "lower_bound")
+ .push_constant(Type::FLOAT, "upper_bound")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(lower_bound)")
+ .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : lower_bound")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "((rhs > lhs) && (rhs <= upper_bound)) ? rhs : lhs")
+ .do_static_compilation(true);
+
+/* --------------------------------------------------------------------
+ * Minimum Reductions.
+ */
+
+GPU_SHADER_CREATE_INFO(compositor_minimum_luminance)
+ .additional_info("compositor_parallel_reduction_shared")
+ .typedef_source("common_math_lib.glsl")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(FLT_MAX)")
+ .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "min(lhs, rhs)")
+ .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_minimum_float_in_range)
+ .additional_info("compositor_parallel_reduction_shared")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::FLOAT, "lower_bound")
+ .push_constant(Type::FLOAT, "upper_bound")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(upper_bound)")
+ .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : upper_bound")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "((rhs < lhs) && (rhs >= lower_bound)) ? rhs : lhs")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh
new file mode 100644
index 00000000000..a460c9d58a6
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_tone_map_photoreceptor)
+ .local_group_size(16, 16)
+ .push_constant(Type::VEC4, "global_adaptation_level")
+ .push_constant(Type::FLOAT, "contrast")
+ .push_constant(Type::FLOAT, "intensity")
+ .push_constant(Type::FLOAT, "chromatic_adaptation")
+ .push_constant(Type::FLOAT, "light_adaptation")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .sampler(0, ImageType::FLOAT_2D, "input_tx")
+ .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .compute_source("compositor_tone_map_photoreceptor.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh
new file mode 100644
index 00000000000..2b220af9460
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_tone_map_simple)
+ .local_group_size(16, 16)
+ .push_constant(Type::FLOAT, "luminance_scale")
+ .push_constant(Type::FLOAT, "luminance_scale_blend_factor")
+ .push_constant(Type::FLOAT, "inverse_gamma")
+ .sampler(0, ImageType::FLOAT_2D, "input_tx")
+ .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .compute_source("compositor_tone_map_simple.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl
new file mode 100644
index 00000000000..4452349f23c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl
@@ -0,0 +1,42 @@
+/**
+ * Draw the icons, leaving a semi-transparent rectangle on top of the icon.
+ *
+ * The top-left corner of the rectangle is rounded and drawned with anti-alias.
+ * The anti-alias is done by transitioning from the outer to the inner radius of
+ * the rounded corner, and the rectangle sides.
+ */
+
+void main()
+{
+ /* Top-left rounded corner parameters. */
+ const float circle_radius_outer = 0.1;
+ const float circle_radius_inner = 0.075;
+
+ /**
+ * Add a bit transparency to see a bit of the icon, without
+ * getting on the way of readability. */
+ const float mask_transparency = 0.25;
+
+ vec2 circle_center = vec2(circle_radius_outer - text_width, 0.5);
+ fragColor = texture(image, texCoord_interp) * color;
+
+ /* radius in icon space (1 is the icon width). */
+ float radius = length(mask_coord_interp - circle_center);
+ float mask = smoothstep(circle_radius_inner, circle_radius_outer, radius);
+
+ bool lower_half = mask_coord_interp.y < circle_center.y;
+ bool right_half = mask_coord_interp.x > circle_center.x;
+
+ if (right_half && mask_coord_interp.y < circle_center.y + circle_radius_outer) {
+ mask = smoothstep(circle_center.y + circle_radius_inner,
+ circle_center.y + circle_radius_outer,
+ mask_coord_interp.y);
+ }
+ if (lower_half && mask_coord_interp.x > circle_center.x - circle_radius_outer) {
+ mask = smoothstep(circle_center.x - circle_radius_inner,
+ circle_center.x - circle_radius_outer,
+ mask_coord_interp.x);
+ }
+
+ fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl
new file mode 100644
index 00000000000..25f64bfe0b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl
@@ -0,0 +1,37 @@
+/**
+ * Simple shader that just draw one icon at the specified location
+ * does not need any vertex input (producing less call to immBegin/End)
+ */
+
+void main()
+{
+ vec2 uv;
+ vec2 co;
+
+ if (gl_VertexID == 0) {
+ co = rect_geom.xw;
+ uv = rect_icon.xw;
+ mask_coord_interp = vec2(0, 1);
+ }
+ else if (gl_VertexID == 1) {
+ co = rect_geom.xy;
+ uv = rect_icon.xy;
+ mask_coord_interp = vec2(0, 0);
+ }
+ else if (gl_VertexID == 2) {
+ co = rect_geom.zw;
+ uv = rect_icon.zw;
+ mask_coord_interp = vec2(1, 1);
+ }
+ else {
+ co = rect_geom.zy;
+ uv = rect_icon.zy;
+ mask_coord_interp = vec2(1, 0);
+ }
+
+ /* Put origin in lower right corner. */
+ mask_coord_interp.x -= 1;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
+ texCoord_interp = uv;
+}
diff --git a/source/blender/gpu/shaders/infos/gpu_interface_info.hh b/source/blender/gpu/shaders/infos/gpu_interface_info.hh
index d77c65e48a7..060def16f81 100644
--- a/source/blender/gpu/shaders/infos/gpu_interface_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_interface_info.hh
@@ -18,3 +18,6 @@ GPU_SHADER_INTERFACE_INFO(smooth_radii_outline_iface, "").smooth(Type::VEC4, "ra
GPU_SHADER_INTERFACE_INFO(flat_color_smooth_tex_coord_interp_iface, "")
.flat(Type::VEC4, "finalColor")
.smooth(Type::VEC2, "texCoord_interp");
+GPU_SHADER_INTERFACE_INFO(smooth_icon_interp_iface, "")
+ .smooth(Type::VEC2, "texCoord_interp")
+ .smooth(Type::VEC2, "mask_coord_interp");
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh
new file mode 100644
index 00000000000..3d4077bdb09
--- /dev/null
+++ b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "gpu_interface_info.hh"
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(gpu_shader_icon)
+ .vertex_out(smooth_icon_interp_iface)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .push_constant(Type::MAT4, "ModelViewProjectionMatrix")
+ .push_constant(Type::VEC4, "color")
+ .push_constant(Type::VEC4, "rect_icon")
+ .push_constant(Type::VEC4, "rect_geom")
+ .push_constant(Type::FLOAT, "text_width")
+ .sampler(0, ImageType::FLOAT_2D, "image")
+ .vertex_source("gpu_shader_icon_vert.glsl")
+ .fragment_source("gpu_shader_icon_frag.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc
new file mode 100644
index 00000000000..00bc43333d6
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_backend.cc
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_backend.hh"
+
+#include "vk_batch.hh"
+#include "vk_context.hh"
+#include "vk_drawlist.hh"
+#include "vk_framebuffer.hh"
+#include "vk_index_buffer.hh"
+#include "vk_query.hh"
+#include "vk_shader.hh"
+#include "vk_storage_buffer.hh"
+#include "vk_texture.hh"
+#include "vk_uniform_buffer.hh"
+#include "vk_vertex_buffer.hh"
+
+namespace blender::gpu {
+
+void VKBackend::delete_resources()
+{
+}
+
+void VKBackend::samplers_update()
+{
+}
+
+void VKBackend::compute_dispatch(int /*groups_x_len*/, int /*groups_y_len*/, int /*groups_z_len*/)
+{
+}
+
+void VKBackend::compute_dispatch_indirect(StorageBuf * /*indirect_buf*/)
+{
+}
+
+Context *VKBackend::context_alloc(void * /*ghost_window*/, void * /*ghost_context*/)
+{
+ return new VKContext();
+}
+
+Batch *VKBackend::batch_alloc()
+{
+ return new VKBatch();
+}
+
+DrawList *VKBackend::drawlist_alloc(int /*list_length*/)
+{
+ return new VKDrawList();
+}
+
+FrameBuffer *VKBackend::framebuffer_alloc(const char *name)
+{
+ return new VKFrameBuffer(name);
+}
+
+IndexBuf *VKBackend::indexbuf_alloc()
+{
+ return new VKIndexBuffer();
+}
+
+QueryPool *VKBackend::querypool_alloc()
+{
+ return new VKQueryPool();
+}
+
+Shader *VKBackend::shader_alloc(const char *name)
+{
+ return new VKShader(name);
+}
+
+Texture *VKBackend::texture_alloc(const char *name)
+{
+ return new VKTexture(name);
+}
+
+UniformBuf *VKBackend::uniformbuf_alloc(int size, const char *name)
+{
+ return new VKUniformBuffer(size, name);
+}
+
+StorageBuf *VKBackend::storagebuf_alloc(int size, GPUUsageType /*usage*/, const char *name)
+{
+ return new VKStorageBuffer(size, name);
+}
+
+VertBuf *VKBackend::vertbuf_alloc()
+{
+ return new VKVertexBuffer();
+}
+
+void VKBackend::render_begin()
+{
+}
+
+void VKBackend::render_end()
+{
+}
+
+void VKBackend::render_step()
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_backend.hh b/source/blender/gpu/vulkan/vk_backend.hh
new file mode 100644
index 00000000000..549478586e8
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_backend.hh
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_backend.hh"
+
+namespace blender::gpu {
+
+class VKBackend : public GPUBackend {
+ public:
+ void delete_resources() override;
+
+ void samplers_update() override;
+ void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) override;
+ void compute_dispatch_indirect(StorageBuf *indirect_buf) override;
+
+ Context *context_alloc(void *ghost_window, void *ghost_context) override;
+
+ Batch *batch_alloc() override;
+ DrawList *drawlist_alloc(int list_length) override;
+ FrameBuffer *framebuffer_alloc(const char *name) override;
+ IndexBuf *indexbuf_alloc() override;
+ QueryPool *querypool_alloc() override;
+ Shader *shader_alloc(const char *name) override;
+ Texture *texture_alloc(const char *name) override;
+ UniformBuf *uniformbuf_alloc(int size, const char *name) override;
+ StorageBuf *storagebuf_alloc(int size, GPUUsageType usage, const char *name) override;
+ VertBuf *vertbuf_alloc() override;
+
+ /* Render Frame Coordination --
+ * Used for performing per-frame actions globally */
+ void render_begin() override;
+ void render_end() override;
+ void render_step() override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_batch.cc b/source/blender/gpu/vulkan/vk_batch.cc
new file mode 100644
index 00000000000..a25f98a2e24
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_batch.cc
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_batch.hh"
+
+namespace blender::gpu {
+
+void VKBatch::draw(int /*v_first*/, int /*v_count*/, int /*i_first*/, int /*i_count*/)
+{
+}
+
+void VKBatch::draw_indirect(GPUStorageBuf * /*indirect_buf*/, intptr_t /*offset*/)
+{
+}
+
+void VKBatch::multi_draw_indirect(GPUStorageBuf * /*indirect_buf*/,
+ int /*count*/,
+ intptr_t /*offset*/,
+ intptr_t /*stride*/)
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_batch.hh b/source/blender/gpu/vulkan/vk_batch.hh
new file mode 100644
index 00000000000..0f6df41606d
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_batch.hh
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_batch_private.hh"
+
+namespace blender::gpu {
+
+class VKBatch : public Batch {
+ public:
+ void draw(int v_first, int v_count, int i_first, int i_count) override;
+ void draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset) override;
+ void multi_draw_indirect(GPUStorageBuf *indirect_buf,
+ int count,
+ intptr_t offset,
+ intptr_t stride) override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_context.cc b/source/blender/gpu/vulkan/vk_context.cc
new file mode 100644
index 00000000000..55b29ea4e2f
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_context.cc
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_context.hh"
+
+namespace blender::gpu {
+
+void VKContext::activate()
+{
+}
+
+void VKContext::deactivate()
+{
+}
+
+void VKContext::begin_frame()
+{
+}
+
+void VKContext::end_frame()
+{
+}
+
+void VKContext::flush()
+{
+}
+
+void VKContext::finish()
+{
+}
+
+void VKContext::memory_statistics_get(int * /*total_mem*/, int * /*free_mem*/)
+{
+}
+
+void VKContext::debug_group_begin(const char *, int)
+{
+}
+
+void VKContext::debug_group_end()
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_context.hh b/source/blender/gpu/vulkan/vk_context.hh
new file mode 100644
index 00000000000..17292b891b6
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_context.hh
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_context_private.hh"
+
+namespace blender::gpu {
+
+class VKContext : public Context {
+ public:
+ VKContext()
+ {
+ }
+
+ void activate() override;
+ void deactivate() override;
+ void begin_frame() override;
+ void end_frame() override;
+
+ void flush() override;
+ void finish() override;
+
+ void memory_statistics_get(int *total_mem, int *free_mem) override;
+
+ void debug_group_begin(const char *, int) override;
+ void debug_group_end() override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_drawlist.cc b/source/blender/gpu/vulkan/vk_drawlist.cc
new file mode 100644
index 00000000000..c8f3c736bb8
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_drawlist.cc
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_drawlist.hh"
+
+namespace blender::gpu {
+
+void VKDrawList::append(GPUBatch * /*batch*/, int /*i_first*/, int /*i_count*/)
+{
+}
+
+void VKDrawList::submit()
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_drawlist.hh b/source/blender/gpu/vulkan/vk_drawlist.hh
new file mode 100644
index 00000000000..4707bf4bb26
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_drawlist.hh
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_drawlist_private.hh"
+
+namespace blender::gpu {
+
+class VKDrawList : public DrawList {
+ public:
+ void append(GPUBatch *batch, int i_first, int i_count) override;
+ void submit() override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_framebuffer.cc b/source/blender/gpu/vulkan/vk_framebuffer.cc
new file mode 100644
index 00000000000..48b0685bf38
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_framebuffer.cc
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_framebuffer.hh"
+
+namespace blender::gpu {
+
+void VKFrameBuffer::bind(bool /*enabled_srgb*/)
+{
+}
+
+bool VKFrameBuffer::check(char /*err_out*/[256])
+{
+ return false;
+}
+
+void VKFrameBuffer::clear(eGPUFrameBufferBits /*buffers*/,
+ const float /*clear_col*/[4],
+ float /*clear_depth*/,
+ uint /*clear_stencil*/)
+{
+}
+
+void VKFrameBuffer::clear_multi(const float (*/*clear_col*/)[4])
+{
+}
+
+void VKFrameBuffer::clear_attachment(GPUAttachmentType /*type*/,
+ eGPUDataFormat /*data_format*/,
+ const void * /*clear_value*/)
+{
+}
+
+void VKFrameBuffer::attachment_set_loadstore_op(GPUAttachmentType /*type*/,
+ eGPULoadOp /*load_action*/,
+ eGPUStoreOp /*store_action*/)
+{
+}
+
+void VKFrameBuffer::read(eGPUFrameBufferBits /*planes*/,
+ eGPUDataFormat /*format*/,
+ const int /*area*/[4],
+ int /*channel_len*/,
+ int /*slot*/,
+ void * /*r_data*/)
+{
+}
+
+void VKFrameBuffer::blit_to(eGPUFrameBufferBits /*planes*/,
+ int /*src_slot*/,
+ FrameBuffer * /*dst*/,
+ int /*dst_slot*/,
+ int /*dst_offset_x*/,
+ int /*dst_offset_y*/)
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_framebuffer.hh b/source/blender/gpu/vulkan/vk_framebuffer.hh
new file mode 100644
index 00000000000..632d45ce709
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_framebuffer.hh
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_framebuffer_private.hh"
+
+namespace blender::gpu {
+
+class VKFrameBuffer : public FrameBuffer {
+ public:
+ VKFrameBuffer(const char *name) : FrameBuffer(name)
+ {
+ }
+
+ void bind(bool enabled_srgb) override;
+ bool check(char err_out[256]) override;
+ void clear(eGPUFrameBufferBits buffers,
+ const float clear_col[4],
+ float clear_depth,
+ uint clear_stencil) override;
+ void clear_multi(const float (*clear_col)[4]) override;
+ void clear_attachment(GPUAttachmentType type,
+ eGPUDataFormat data_format,
+ const void *clear_value) override;
+
+ void attachment_set_loadstore_op(GPUAttachmentType type,
+ eGPULoadOp load_action,
+ eGPUStoreOp store_action) override;
+
+ void read(eGPUFrameBufferBits planes,
+ eGPUDataFormat format,
+ const int area[4],
+ int channel_len,
+ int slot,
+ void *r_data) override;
+
+ void blit_to(eGPUFrameBufferBits planes,
+ int src_slot,
+ FrameBuffer *dst,
+ int dst_slot,
+ int dst_offset_x,
+ int dst_offset_y) override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_index_buffer.cc b/source/blender/gpu/vulkan/vk_index_buffer.cc
new file mode 100644
index 00000000000..119a617a159
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_index_buffer.cc
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_index_buffer.hh"
+
+namespace blender::gpu {
+
+void VKIndexBuffer::upload_data()
+{
+}
+
+void VKIndexBuffer::bind_as_ssbo(uint /*binding*/)
+{
+}
+
+const uint32_t *VKIndexBuffer::read() const
+{
+ return 0;
+}
+
+void VKIndexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/)
+{
+}
+
+void VKIndexBuffer::strip_restart_indices()
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_index_buffer.hh b/source/blender/gpu/vulkan/vk_index_buffer.hh
new file mode 100644
index 00000000000..f002d5581c7
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_index_buffer.hh
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_index_buffer_private.hh"
+
+namespace blender::gpu {
+
+class VKIndexBuffer : public IndexBuf {
+ public:
+ void upload_data() override;
+
+ void bind_as_ssbo(uint binding) override;
+
+ const uint32_t *read() const override;
+
+ void update_sub(uint start, uint len, const void *data) override;
+
+ private:
+ void strip_restart_indices() override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_query.cc b/source/blender/gpu/vulkan/vk_query.cc
new file mode 100644
index 00000000000..e24fe54e5d0
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_query.cc
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_query.hh"
+
+namespace blender::gpu {
+
+void VKQueryPool::init(GPUQueryType /*type*/)
+{
+}
+
+void VKQueryPool::begin_query()
+{
+}
+
+void VKQueryPool::end_query()
+{
+}
+
+void VKQueryPool::get_occlusion_result(MutableSpan<uint32_t> /*r_values*/)
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_query.hh b/source/blender/gpu/vulkan/vk_query.hh
new file mode 100644
index 00000000000..36558ef9549
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_query.hh
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_query.hh"
+
+namespace blender::gpu {
+
+class VKQueryPool : public QueryPool {
+ public:
+ void init(GPUQueryType type) override;
+ void begin_query() override;
+ void end_query() override;
+ void get_occlusion_result(MutableSpan<uint32_t> r_values) override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc
new file mode 100644
index 00000000000..d628f3eb851
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_shader.cc
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_shader.hh"
+
+namespace blender::gpu {
+void VKShader::vertex_shader_from_glsl(MutableSpan<const char *> /*sources*/)
+{
+}
+
+void VKShader::geometry_shader_from_glsl(MutableSpan<const char *> /*sources*/)
+{
+}
+
+void VKShader::fragment_shader_from_glsl(MutableSpan<const char *> /*sources*/)
+{
+}
+
+void VKShader::compute_shader_from_glsl(MutableSpan<const char *> /*sources*/)
+{
+}
+
+bool VKShader::finalize(const shader::ShaderCreateInfo * /*info*/)
+{
+ return false;
+}
+
+void VKShader::transform_feedback_names_set(Span<const char *> /*name_list*/,
+ eGPUShaderTFBType /*geom_type*/)
+{
+}
+
+bool VKShader::transform_feedback_enable(GPUVertBuf *)
+{
+ return false;
+}
+
+void VKShader::transform_feedback_disable()
+{
+}
+
+void VKShader::bind()
+{
+}
+
+void VKShader::unbind()
+{
+}
+
+void VKShader::uniform_float(int /*location*/,
+ int /*comp_len*/,
+ int /*array_size*/,
+ const float * /*data*/)
+{
+}
+void VKShader::uniform_int(int /*location*/,
+ int /*comp_len*/,
+ int /*array_size*/,
+ const int * /*data*/)
+{
+}
+
+std::string VKShader::resources_declare(const shader::ShaderCreateInfo & /*info*/) const
+{
+ return std::string();
+}
+
+std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo & /*info*/) const
+{
+ return std::string();
+}
+
+std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo & /*info*/) const
+{
+ return std::string();
+}
+
+std::string VKShader::geometry_interface_declare(const shader::ShaderCreateInfo & /*info*/) const
+{
+ return std::string();
+}
+
+std::string VKShader::geometry_layout_declare(const shader::ShaderCreateInfo & /*info*/) const
+{
+ return std::string();
+}
+
+std::string VKShader::compute_layout_declare(const shader::ShaderCreateInfo & /*info*/) const
+{
+ return std::string();
+}
+
+int VKShader::program_handle_get() const
+{
+ return -1;
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_shader.hh b/source/blender/gpu/vulkan/vk_shader.hh
new file mode 100644
index 00000000000..9ab0aca67eb
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_shader.hh
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_shader_private.hh"
+
+namespace blender::gpu {
+
+class VKShader : public Shader {
+ public:
+ VKShader(const char *name) : Shader(name)
+ {
+ }
+
+ void vertex_shader_from_glsl(MutableSpan<const char *> sources) override;
+ void geometry_shader_from_glsl(MutableSpan<const char *> sources) override;
+ void fragment_shader_from_glsl(MutableSpan<const char *> sources) override;
+ void compute_shader_from_glsl(MutableSpan<const char *> sources) override;
+ bool finalize(const shader::ShaderCreateInfo *info = nullptr) override;
+
+ void transform_feedback_names_set(Span<const char *> name_list,
+ eGPUShaderTFBType geom_type) override;
+ bool transform_feedback_enable(GPUVertBuf *) override;
+ void transform_feedback_disable() override;
+
+ void bind() override;
+ void unbind() override;
+
+ void uniform_float(int location, int comp_len, int array_size, const float *data) override;
+ void uniform_int(int location, int comp_len, int array_size, const int *data) override;
+
+ std::string resources_declare(const shader::ShaderCreateInfo &info) const override;
+ std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override;
+ std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override;
+ std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override;
+ std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override;
+ std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override;
+
+ /* DEPRECATED: Kept only because of BGL API. */
+ int program_handle_get() const override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_storage_buffer.cc b/source/blender/gpu/vulkan/vk_storage_buffer.cc
new file mode 100644
index 00000000000..2b6fda0547d
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_storage_buffer.cc
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_vertex_buffer.hh"
+
+#include "vk_storage_buffer.hh"
+
+namespace blender::gpu {
+
+void VKStorageBuffer::update(const void * /*data*/)
+{
+}
+
+void VKStorageBuffer::bind(int /*slot*/)
+{
+}
+
+void VKStorageBuffer::unbind()
+{
+}
+
+void VKStorageBuffer::clear(eGPUTextureFormat /* internal_format*/,
+ eGPUDataFormat /*data_format*/,
+ void * /*data*/)
+{
+}
+void VKStorageBuffer::copy_sub(VertBuf * /*src*/,
+ uint /*dst_offset*/,
+ uint /*src_offset*/,
+ uint /*copy_size*/)
+{
+}
+
+void VKStorageBuffer::read(void * /*data*/)
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_storage_buffer.hh b/source/blender/gpu/vulkan/vk_storage_buffer.hh
new file mode 100644
index 00000000000..a51f89f627a
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_storage_buffer.hh
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "GPU_texture.h"
+
+#include "gpu_storage_buffer_private.hh"
+
+namespace blender::gpu {
+
+class VKStorageBuffer : public StorageBuf {
+ public:
+ VKStorageBuffer(int size, const char *name) : StorageBuf(size, name)
+ {
+ }
+
+ void update(const void *data) override;
+ void bind(int slot) override;
+ void unbind() override;
+ void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
+ void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
+ void read(void *data) override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_texture.cc b/source/blender/gpu/vulkan/vk_texture.cc
new file mode 100644
index 00000000000..ea5379e6572
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_texture.cc
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_texture.hh"
+
+namespace blender::gpu {
+
+void VKTexture::generate_mipmap()
+{
+}
+
+void VKTexture::copy_to(Texture * /*tex*/)
+{
+}
+
+void VKTexture::clear(eGPUDataFormat /*format*/, const void * /*data*/)
+{
+}
+
+void VKTexture::swizzle_set(const char /*swizzle_mask*/[4])
+{
+}
+
+void VKTexture::stencil_texture_mode_set(bool /*use_stencil*/)
+{
+}
+
+void VKTexture::mip_range_set(int /*min*/, int /*max*/)
+{
+}
+
+void *VKTexture::read(int /*mip*/, eGPUDataFormat /*format*/)
+{
+ return nullptr;
+}
+
+void VKTexture::update_sub(int /*mip*/,
+ int /*offset*/[3],
+ int /*extent*/[3],
+ eGPUDataFormat /*format*/,
+ const void * /*data*/)
+{
+}
+
+/* TODO(fclem): Legacy. Should be removed at some point. */
+uint VKTexture::gl_bindcode_get() const
+{
+ return 0;
+}
+
+bool VKTexture::init_internal()
+{
+ return false;
+}
+
+bool VKTexture::init_internal(GPUVertBuf * /*vbo*/)
+{
+ return false;
+}
+
+bool VKTexture::init_internal(const GPUTexture * /*src*/, int /*mip_offset*/, int /*layer_offset*/)
+{
+ return false;
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_texture.hh b/source/blender/gpu/vulkan/vk_texture.hh
new file mode 100644
index 00000000000..93094b7e540
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_texture.hh
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_texture_private.hh"
+
+namespace blender::gpu {
+
+class VKTexture : public Texture {
+ public:
+ VKTexture(const char *name) : Texture(name)
+ {
+ }
+
+ void generate_mipmap() override;
+ void copy_to(Texture *tex) override;
+ void clear(eGPUDataFormat format, const void *data) override;
+ void swizzle_set(const char swizzle_mask[4]) override;
+ void stencil_texture_mode_set(bool use_stencil) override;
+ void mip_range_set(int min, int max) override;
+ void *read(int mip, eGPUDataFormat format) override;
+ void update_sub(
+ int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data) override;
+
+ /* TODO(fclem): Legacy. Should be removed at some point. */
+ uint gl_bindcode_get() const override;
+
+ protected:
+ bool init_internal() override;
+ bool init_internal(GPUVertBuf *vbo) override;
+ bool init_internal(const GPUTexture *src, int mip_offset, int layer_offset) override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_uniform_buffer.cc b/source/blender/gpu/vulkan/vk_uniform_buffer.cc
new file mode 100644
index 00000000000..8ef5b19273a
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_uniform_buffer.cc
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_uniform_buffer.hh"
+
+namespace blender::gpu {
+
+void VKUniformBuffer::update(const void * /*data*/)
+{
+}
+
+void VKUniformBuffer::bind(int /*slot*/)
+{
+}
+
+void VKUniformBuffer::unbind()
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_uniform_buffer.hh b/source/blender/gpu/vulkan/vk_uniform_buffer.hh
new file mode 100644
index 00000000000..f086a7aa391
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_uniform_buffer.hh
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_uniform_buffer_private.hh"
+
+namespace blender::gpu {
+
+class VKUniformBuffer : public UniformBuf {
+ public:
+ VKUniformBuffer(int size, const char *name) : UniformBuf(size, name)
+ {
+ }
+
+ void update(const void *data) override;
+ void bind(int slot) override;
+ void unbind() override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.cc b/source/blender/gpu/vulkan/vk_vertex_buffer.cc
new file mode 100644
index 00000000000..5791e20fb30
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_vertex_buffer.cc
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_vertex_buffer.hh"
+
+namespace blender::gpu {
+
+void VKVertexBuffer::bind_as_ssbo(uint /*binding*/)
+{
+}
+
+void VKVertexBuffer::bind_as_texture(uint /*binding*/)
+{
+}
+
+void VKVertexBuffer::wrap_handle(uint64_t /*handle*/)
+{
+}
+
+void VKVertexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/)
+{
+}
+
+const void *VKVertexBuffer::read() const
+{
+ return nullptr;
+}
+
+void *VKVertexBuffer::unmap(const void * /*mapped_data*/) const
+{
+ return nullptr;
+}
+
+void VKVertexBuffer::acquire_data()
+{
+}
+
+void VKVertexBuffer::resize_data()
+{
+}
+
+void VKVertexBuffer::release_data()
+{
+}
+
+void VKVertexBuffer::upload_data()
+{
+}
+
+void VKVertexBuffer::duplicate_data(VertBuf * /*dst*/)
+{
+}
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.hh b/source/blender/gpu/vulkan/vk_vertex_buffer.hh
new file mode 100644
index 00000000000..84ccc65bcdf
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_vertex_buffer.hh
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_vertex_buffer_private.hh"
+
+namespace blender::gpu {
+
+class VKVertexBuffer : public VertBuf {
+ public:
+ void bind_as_ssbo(uint binding) override;
+ void bind_as_texture(uint binding) override;
+ void wrap_handle(uint64_t handle) override;
+
+ void update_sub(uint start, uint len, const void *data) override;
+ const void *read() const override;
+ void *unmap(const void *mapped_data) const override;
+
+ protected:
+ void acquire_data() override;
+ void resize_data() override;
+ void release_data() override;
+ void upload_data() override;
+ void duplicate_data(VertBuf *dst) override;
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 6d99fde9df6..c467e48d21e 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -406,7 +406,7 @@ static void execute_posetree(struct Depsgraph *depsgraph,
}
copy_v3_v3(rootmat[3], pchan->pose_head);
- mul_m4_m4m4(imat, ob->obmat, rootmat);
+ mul_m4_m4m4(imat, ob->object_to_world, rootmat);
invert_m4_m4(goalinv, imat);
for (target = tree->targets.first; target; target = target->next) {
@@ -465,7 +465,7 @@ static void execute_posetree(struct Depsgraph *depsgraph,
/* end effector in world space */
copy_m4_m4(end_pose, pchan->pose_mat);
copy_v3_v3(end_pose[3], pchan->pose_tail);
- mul_m4_series(world_pose, goalinv, ob->obmat, end_pose);
+ mul_m4_series(world_pose, goalinv, ob->object_to_world, end_pose);
/* blend position */
goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0];
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index 9317f14b7f1..2878bbb6da7 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -586,10 +586,10 @@ static bool target_callback(const iTaSC::Timestamp &timestamp,
float chanmat[4][4];
copy_m4_m4(chanmat, pchan->pose_mat);
copy_v3_v3(chanmat[3], pchan->pose_tail);
- mul_m4_series(restmat, target->owner->obmat, chanmat, target->eeRest);
+ mul_m4_series(restmat, target->owner->object_to_world, chanmat, target->eeRest);
}
else {
- mul_m4_m4m4(restmat, target->owner->obmat, target->eeRest);
+ mul_m4_m4m4(restmat, target->owner->object_to_world, target->eeRest);
}
/* blend the target */
blend_m4_m4m4(tarmat, restmat, tarmat, constraint->enforce);
@@ -620,10 +620,10 @@ static bool base_callback(const iTaSC::Timestamp &timestamp,
ikscene->baseFrame.setValue(&chanmat[0][0]);
/* iTaSC armature is scaled to object scale, scale the base frame too */
ikscene->baseFrame.p *= ikscene->blScale;
- mul_m4_m4m4(rootmat, ikscene->blArmature->obmat, chanmat);
+ mul_m4_m4m4(rootmat, ikscene->blArmature->object_to_world, chanmat);
}
else {
- copy_m4_m4(rootmat, ikscene->blArmature->obmat);
+ copy_m4_m4(rootmat, ikscene->blArmature->object_to_world);
ikscene->baseFrame = iTaSC::F_identity;
}
next.setValue(&rootmat[0][0]);
@@ -1065,7 +1065,7 @@ static void convert_pose(IK_Scene *ikscene)
int a, joint;
/* assume uniform scaling and take Y scale as general scale for the armature */
- scale = len_v3(ikscene->blArmature->obmat[1]);
+ scale = len_v3(ikscene->blArmature->object_to_world[1]);
rot = ikscene->jointArray(0);
for (joint = a = 0, ikchan = ikscene->channels;
a < ikscene->numchan && joint < ikscene->numjoint;
@@ -1105,7 +1105,7 @@ static void BKE_pose_rest(IK_Scene *ikscene)
int a, joint;
/* assume uniform scaling and take Y scale as general scale for the armature */
- scale = len_v3(ikscene->blArmature->obmat[1]);
+ scale = len_v3(ikscene->blArmature->object_to_world[1]);
/* rest pose is 0 */
SetToZero(ikscene->jointArray);
/* except for transY joints */
@@ -1183,7 +1183,7 @@ static IK_Scene *convert_tree(
}
ikscene->blArmature = ob;
/* assume uniform scaling and take Y scale as general scale for the armature */
- ikscene->blScale = len_v3(ob->obmat[1]);
+ ikscene->blScale = len_v3(ob->object_to_world[1]);
ikscene->blInvScale = (ikscene->blScale < KDL::epsilon) ? 0.0f : 1.0f / ikscene->blScale;
std::string joint;
@@ -1667,7 +1667,7 @@ static void create_scene(struct Depsgraph *depsgraph, Scene *scene, Object *ob,
static int init_scene(Object *ob)
{
/* check also if scaling has changed */
- float scale = len_v3(ob->obmat[1]);
+ float scale = len_v3(ob->object_to_world[1]);
IK_Scene *scene;
if (ob->pose->ikdata) {
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 71e0d0fe11e..94c0555dcf0 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -1100,7 +1100,12 @@ static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
* experimentally. Note: Too big offset can impact performance. Current 3 frame offset has no
* measurable impact.
*/
- return pts_to_search - (ffmpeg_steps_per_frame_get(anim) * 3);
+ int64_t seek_pts = pts_to_search - (ffmpeg_steps_per_frame_get(anim) * 3);
+
+ if (seek_pts < 0) {
+ seek_pts = 0;
+ }
+ return seek_pts;
}
/* This gives us an estimate of which pts our requested frame will have.
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 8965700c08a..63836690ee4 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -377,9 +377,9 @@ static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_l
{
if (!anim->index_dir[0]) {
char filename[FILE_MAXFILE];
- BLI_split_dirfile(anim->name, index_dir, filename, index_dir_len, sizeof(filename));
- BLI_path_append(index_dir, index_dir_len, "BL_proxy");
- BLI_path_append(index_dir, index_dir_len, filename);
+ char dirname[FILE_MAXDIR];
+ BLI_split_dirfile(anim->name, dirname, filename, index_dir_len, sizeof(filename));
+ BLI_path_join(index_dir, index_dir_len, dirname, "BL_proxy", filename);
}
else {
BLI_strncpy(index_dir, anim->index_dir, index_dir_len);
@@ -498,7 +498,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->anim = anim;
get_proxy_filepath(rv->anim, rv->proxy_size, filepath, true);
- BLI_make_existing_file(filepath);
+ if (!BLI_make_existing_file(filepath)) {
+ return NULL;
+ }
rv->of = avformat_alloc_context();
rv->of->oformat = av_guess_format("avi", NULL, NULL);
@@ -905,6 +907,14 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
}
}
+ if (context->proxy_ctx[0] == NULL && context->proxy_ctx[1] == NULL &&
+ context->proxy_ctx[2] == NULL && context->proxy_ctx[3] == NULL) {
+ avformat_close_input(&context->iFormatCtx);
+ avcodec_free_context(&context->iCodecCtx);
+ MEM_freeN(context);
+ return NULL; /* Nothing to transcode. */
+ }
+
for (i = 0; i < num_indexers; i++) {
if (tcs_in_use & tc_types[i]) {
char filepath[FILE_MAX];
diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c
index dd509677d8d..35cdefbaaeb 100644
--- a/source/blender/imbuf/intern/util_gpu.c
+++ b/source/blender/imbuf/intern/util_gpu.c
@@ -174,6 +174,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
/* Other colorspace, store as float texture to avoid precision loss. */
data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__);
*r_freedata = freedata = true;
+ is_float_rect = true;
if (data_rect == NULL) {
return NULL;
@@ -300,6 +301,16 @@ GPUTexture *IMB_create_gpu_texture(const char *name,
int size[2] = {GPU_texture_size_with_limit(ibuf->x), GPU_texture_size_with_limit(ibuf->y)};
bool do_rescale = (ibuf->x != size[0]) || (ibuf->y != size[1]);
+ /* Correct the smaller size to maintain the original aspect ratio of the image. */
+ if (do_rescale && ibuf->x != ibuf->y) {
+ if (size[0] > size[1]) {
+ size[1] = (int)(ibuf->y * ((float)size[0] / ibuf->x));
+ }
+ else {
+ size[0] = (int)(ibuf->x * ((float)size[1] / ibuf->y));
+ }
+ }
+
#ifdef WITH_DDS
if (ibuf->ftype == IMB_FTYPE_DDS) {
eGPUTextureFormat compressed_format;
diff --git a/source/blender/imbuf/intern/webp.c b/source/blender/imbuf/intern/webp.c
index 27c26fb19c1..3031b8c3e33 100644
--- a/source/blender/imbuf/intern/webp.c
+++ b/source/blender/imbuf/intern/webp.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
- * \ingroup imbuf
+ * \ingroup imbuf
*/
#ifdef _WIN32
diff --git a/source/blender/io/alembic/exporter/abc_writer_hair.cc b/source/blender/io/alembic/exporter/abc_writer_hair.cc
index f872943ad5c..13136372c56 100644
--- a/source/blender/io/alembic/exporter/abc_writer_hair.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_hair.cc
@@ -118,7 +118,7 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
{
/* Get untransformed vertices, there's a xform under the hair. */
float inv_mat[4][4];
- invert_m4_m4_safe(inv_mat, context.object->obmat);
+ invert_m4_m4_safe(inv_mat, context.object->object_to_world);
MTFace *mtface = (MTFace *)CustomData_get_layer(&mesh->fdata, CD_MTFACE);
MFace *mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE);
@@ -241,7 +241,7 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context,
{
/* Get untransformed vertices, there's a xform under the hair. */
float inv_mat[4][4];
- invert_m4_m4_safe(inv_mat, context.object->obmat);
+ invert_m4_m4_safe(inv_mat, context.object->object_to_world);
MFace *mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE);
MTFace *mtface = (MTFace *)CustomData_get_layer(&mesh->fdata, CD_MTFACE);
diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.cc b/source/blender/io/alembic/intern/abc_axis_conversion.cc
index 00e5890e9d3..35a19d0fbc0 100644
--- a/source/blender/io/alembic/intern/abc_axis_conversion.cc
+++ b/source/blender/io/alembic/intern/abc_axis_conversion.cc
@@ -134,15 +134,15 @@ void create_transform_matrix(Object *obj,
if (mode == ABC_MATRIX_LOCAL && obj->parent) {
/* Note that this produces another matrix than the local matrix, due to
* constraints and modifiers as well as the obj->parentinv matrix. */
- invert_m4_m4(obj->parent->imat, obj->parent->obmat);
- mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
+ invert_m4_m4(obj->parent->imat, obj->parent->object_to_world);
+ mul_m4_m4m4(zup_mat, obj->parent->imat, obj->object_to_world);
}
else {
- copy_m4_m4(zup_mat, obj->obmat);
+ copy_m4_m4(zup_mat, obj->object_to_world);
}
if (proxy_from) {
- mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat);
+ mul_m4_m4m4(zup_mat, proxy_from->object_to_world, zup_mat);
}
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc
index f08514dc45c..2531bd62609 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.cc
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc
@@ -763,7 +763,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
std::map<std::string, int> mat_map;
bke::MutableAttributeAccessor attributes = new_mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map);
material_indices.finish();
}
@@ -823,8 +823,8 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSel
{
std::map<std::string, int> mat_map;
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
- bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map);
material_indices.finish();
utils::assign_materials(bmain, m_object, mat_map);
diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc
index af26565f8d6..f3a07eaad3f 100644
--- a/source/blender/io/alembic/intern/abc_reader_object.cc
+++ b/source/blender/io/alembic/intern/abc_reader_object.cc
@@ -165,7 +165,7 @@ void AbcObjectReader::setupObjectTransform(const chrono_t time)
/* Apply the matrix to the object. */
BKE_object_apply_mat4(m_object, transform_from_alembic, true, false);
- BKE_object_to_mat4(m_object, m_object->obmat);
+ BKE_object_to_mat4(m_object, m_object->object_to_world);
if (!is_constant || m_settings->always_add_cache_reader) {
bConstraint *con = BKE_constraint_add_for_object(
diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp
index 2d872377bbf..826d7864067 100644
--- a/source/blender/io/collada/AnimationImporter.cpp
+++ b/source/blender/io/collada/AnimationImporter.cpp
@@ -332,8 +332,8 @@ void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob)
float mat[4][4];
TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
if (ob) {
- copy_m4_m4(ob->obmat, mat);
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ copy_m4_m4(ob->object_to_world, mat);
+ BKE_object_apply_mat4(ob, ob->object_to_world, false, false);
}
}
@@ -2097,7 +2097,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root,
if (par_job) {
float temp[4][4], ipar[4][4];
- invert_m4_m4(ipar, par_job->obmat);
+ invert_m4_m4(ipar, par_job->object_to_world);
copy_m4_m4(temp, mat);
mul_m4_m4m4(mat, ipar, temp);
}
diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp
index 1310337f501..7de08f89b7d 100644
--- a/source/blender/io/collada/ArmatureImporter.cpp
+++ b/source/blender/io/collada/ArmatureImporter.cpp
@@ -114,7 +114,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin,
Object *ob_arm = skin->BKE_armature_from_object();
if (ob_arm) {
float invmat[4][4];
- invert_m4_m4(invmat, ob_arm->obmat);
+ invert_m4_m4(invmat, ob_arm->object_to_world);
mul_m4_m4m4(mat, invmat, mat);
}
@@ -708,7 +708,7 @@ void ArmatureImporter::set_pose(Object *ob_arm,
copy_m4_m4(mat, obmat);
float invObmat[4][4];
- invert_m4_m4(invObmat, ob_arm->obmat);
+ invert_m4_m4(invObmat, ob_arm->object_to_world);
mul_m4_m4m4(pchan->pose_mat, invObmat, mat);
}
diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp
index 6bf8d904a41..62bcdc5bf4c 100644
--- a/source/blender/io/collada/ControllerExporter.cpp
+++ b/source/blender/io/collada/ControllerExporter.cpp
@@ -406,7 +406,7 @@ void ControllerExporter::add_bind_shape_mat(Object *ob)
bc_add_global_transform(f_obmat, export_settings.get_global_transform());
}
- // UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat);
+ // UnitConverter::mat4_to_dae_double(bind_mat, ob->object_to_world);
UnitConverter::mat4_to_dae_double(bind_mat, f_obmat);
if (this->export_settings.get_limit_precision()) {
BCMatrix::sanitize(bind_mat, LIMITTED_PRECISION);
@@ -523,7 +523,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
}
/* make world-space matrix (bind_mat is armature-space) */
- mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
+ mul_m4_m4m4(world, ob_arm->object_to_world, bind_mat);
if (!has_bindmat) {
if (export_settings.get_apply_global_orientation()) {
diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp
index 5e432682564..dae1c4ba894 100644
--- a/source/blender/io/collada/DocumentImporter.cpp
+++ b/source/blender/io/collada/DocumentImporter.cpp
@@ -412,8 +412,8 @@ Object *DocumentImporter::create_instance_node(Object *source_ob,
}
}
/* calc new matrix and apply */
- mul_m4_m4m4(obn->obmat, obn->obmat, mat);
- BKE_object_apply_mat4(obn, obn->obmat, false, false);
+ mul_m4_m4m4(obn->object_to_world, obn->object_to_world, mat);
+ BKE_object_apply_mat4(obn, obn->object_to_world, false, false);
}
}
else {
diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp
index 0654bae3730..b4615635318 100644
--- a/source/blender/io/collada/SkinInfo.cpp
+++ b/source/blender/io/collada/SkinInfo.cpp
@@ -214,12 +214,12 @@ void SkinInfo::link_armature(bContext *C,
ob->partype = PAROBJECT;
BKE_object_workob_calc_parent(scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.object_to_world);
DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
#endif
- copy_m4_m4(ob->obmat, bind_shape_matrix);
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ copy_m4_m4(ob->object_to_world, bind_shape_matrix);
+ BKE_object_apply_mat4(ob, ob->object_to_world, false, false);
amd->deformflag = ARM_DEF_VGROUP;
diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp
index 22a73cd7db2..96ff78a715a 100644
--- a/source/blender/io/collada/collada_utils.cpp
+++ b/source/blender/io/collada/collada_utils.cpp
@@ -129,7 +129,7 @@ bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
const bool keep_transform = false;
if (par && is_parent_space) {
- mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat);
+ mul_m4_m4m4(ob->object_to_world, par->object_to_world, ob->object_to_world);
}
bool ok = ED_object_parent_set(
@@ -348,10 +348,10 @@ std::string bc_replace_string(std::string data,
void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
{
if (scale_to_scene) {
- mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
+ mul_m4_m4m4(ob->object_to_world, bc_unit.get_scale(), ob->object_to_world);
}
- mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ mul_m4_m4m4(ob->object_to_world, bc_unit.get_rotation(), ob->object_to_world);
+ BKE_object_apply_mat4(ob, ob->object_to_world, false, false);
}
void bc_match_scale(std::vector<Object *> *objects_done,
diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc
index 03c1ba94d94..d559b0efe82 100644
--- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc
+++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc
@@ -416,7 +416,7 @@ void AbstractHierarchyIterator::visit_object(Object *object,
context->original_export_path = "";
context->higher_up_export_path = "";
- copy_m4_m4(context->matrix_world, object->obmat);
+ copy_m4_m4(context->matrix_world, object->object_to_world);
ExportGraph::key_type graph_index = determine_graph_index_object(context);
context_update_for_graph_index(context, graph_index);
diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc
index b9d7b6719b1..6cc977bfced 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_base.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc
@@ -79,7 +79,7 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara
BKE_camera_params_compute_matrix(&params);
float viewmat[4][4];
- invert_m4_m4(viewmat, cam_ob->obmat);
+ invert_m4_m4(viewmat, cam_ob->object_to_world);
mul_m4_m4m4(persmat_, params.winmat, viewmat);
}
@@ -152,7 +152,7 @@ void GpencilIO::create_object_list()
/* Save z-depth from view to sort from back to front. */
if (is_camera_) {
- float camera_z = dot_v3v3(camera_z_axis, object->obmat[3]);
+ float camera_z = dot_v3v3(camera_z_axis, object->object_to_world[3]);
ObjectZ obz = {camera_z, object};
ob_list_.append(obz);
}
@@ -160,10 +160,10 @@ void GpencilIO::create_object_list()
float zdepth = 0;
if (rv3d_) {
if (rv3d_->is_persp) {
- zdepth = ED_view3d_calc_zfac(rv3d_, object->obmat[3]);
+ zdepth = ED_view3d_calc_zfac(rv3d_, object->object_to_world[3]);
}
else {
- zdepth = -dot_v3v3(rv3d_->viewinv[2], object->obmat[3]);
+ zdepth = -dot_v3v3(rv3d_->viewinv[2], object->object_to_world[3]);
}
ObjectZ obz = {zdepth * -1.0f, object};
ob_list_.append(obz);
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
index ddd72f816b0..c042ca597c8 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
@@ -177,7 +177,7 @@ void GpencilExporterPDF::export_gpencil_layers()
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
- gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
/* Fill. */
if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
index 58f12e9b8b1..8acb87f8e58 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
@@ -197,7 +197,7 @@ void GpencilExporterSVG::export_gpencil_layers()
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
- gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0) ||
diff --git a/source/blender/io/stl/CMakeLists.txt b/source/blender/io/stl/CMakeLists.txt
index 3a21da5c579..f7eb933d198 100644
--- a/source/blender/io/stl/CMakeLists.txt
+++ b/source/blender/io/stl/CMakeLists.txt
@@ -2,7 +2,7 @@
set(INC
.
- ./importer
+ importer
../common
../../blenkernel
../../blenlib
diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc
index 77c79852141..8138f38fcad 100644
--- a/source/blender/io/usd/intern/usd_reader_mesh.cc
+++ b/source/blender/io/usd/intern/usd_reader_mesh.cc
@@ -33,6 +33,7 @@
#include <pxr/base/vt/value.h>
#include <pxr/usd/sdf/types.h>
#include <pxr/usd/usdGeom/mesh.h>
+#include <pxr/usd/usdGeom/primvarsAPI.h>
#include <pxr/usd/usdGeom/subset.h>
#include <pxr/usd/usdShade/materialBindingAPI.h>
@@ -287,11 +288,13 @@ bool USDMeshReader::topology_changed(const Mesh *existing_mesh, const double mot
mesh_prim_.GetFaceVertexCountsAttr().Get(&face_counts_, motionSampleTime);
mesh_prim_.GetPointsAttr().Get(&positions_, motionSampleTime);
+ pxr::UsdGeomPrimvarsAPI primvarsAPI(mesh_prim_);
+
/* TODO(makowalski): Reading normals probably doesn't belong in this function,
* as this is not required to determine if the topology has changed. */
/* If 'normals' and 'primvars:normals' are both specified, the latter has precedence. */
- pxr::UsdGeomPrimvar primvar = mesh_prim_.GetPrimvar(usdtokens::normalsPrimvar);
+ pxr::UsdGeomPrimvar primvar = primvarsAPI.GetPrimvar(usdtokens::normalsPrimvar);
if (primvar.HasValue()) {
primvar.ComputeFlattened(&normals_, motionSampleTime);
normal_interpolation_ = primvar.GetInterpolation();
@@ -355,6 +358,8 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo
std::vector<UVSample> uv_primvars(ldata->totlayer);
+ pxr::UsdGeomPrimvarsAPI primvarsAPI(mesh_prim_);
+
if (has_uvs_) {
for (int layer_idx = 0; layer_idx < ldata->totlayer; layer_idx++) {
const CustomDataLayer *layer = &ldata->layers[layer_idx];
@@ -385,11 +390,11 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo
}
/* Early out if mesh doesn't have primvar. */
- if (!mesh_prim_.HasPrimvar(uv_token)) {
+ if (!primvarsAPI.HasPrimvar(uv_token)) {
continue;
}
- if (pxr::UsdGeomPrimvar uv_primvar = mesh_prim_.GetPrimvar(uv_token)) {
+ if (pxr::UsdGeomPrimvar uv_primvar = primvarsAPI.GetPrimvar(uv_token)) {
uv_primvar.ComputeFlattened(&uv_primvars[layer_idx].uvs, motionSampleTime);
uv_primvars[layer_idx].interpolation = uv_primvar.GetInterpolation();
}
@@ -804,8 +809,8 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
std::map<pxr::SdfPath, int> mat_map;
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
- bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
this->assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
material_indices.finish();
/* Build material name map if it's not built yet. */
@@ -835,12 +840,14 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
is_left_handed_ = true;
}
+ pxr::UsdGeomPrimvarsAPI primvarsAPI(mesh_prim_);
+
std::vector<pxr::TfToken> uv_tokens;
/* Currently we only handle UV primvars. */
if (read_flag & MOD_MESHSEQ_READ_UV) {
- std::vector<pxr::UsdGeomPrimvar> primvars = mesh_prim_.GetPrimvars();
+ std::vector<pxr::UsdGeomPrimvar> primvars = primvarsAPI.GetPrimvars();
for (pxr::UsdGeomPrimvar p : primvars) {
@@ -914,7 +921,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
std::map<pxr::SdfPath, int> mat_map;
bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
material_indices.finish();
}
diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc
index e949bafe517..e7d79e888e4 100644
--- a/source/blender/io/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/io/usd/intern/usd_writer_mesh.cc
@@ -4,6 +4,7 @@
#include "usd_hierarchy_iterator.h"
#include <pxr/usd/usdGeom/mesh.h>
+#include <pxr/usd/usdGeom/primvarsAPI.h>
#include <pxr/usd/usdShade/material.h>
#include <pxr/usd/usdShade/materialBindingAPI.h>
@@ -107,6 +108,8 @@ void USDGenericMeshWriter::write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_
{
pxr::UsdTimeCode timecode = get_export_time_code();
+ pxr::UsdGeomPrimvarsAPI primvarsAPI(usd_mesh.GetPrim());
+
const CustomData *ldata = &mesh->ldata;
for (int layer_idx = 0; layer_idx < ldata->totlayer; layer_idx++) {
const CustomDataLayer *layer = &ldata->layers[layer_idx];
@@ -119,7 +122,7 @@ void USDGenericMeshWriter::write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_
* for texture coordinates by naming the UV Map as such, without having to guess which UV Map
* is the "standard" one. */
pxr::TfToken primvar_name(pxr::TfMakeValidIdentifier(layer->name));
- pxr::UsdGeomPrimvar uv_coords_primvar = usd_mesh.CreatePrimvar(
+ pxr::UsdGeomPrimvar uv_coords_primvar = primvarsAPI.CreatePrimvar(
primvar_name, pxr::SdfValueTypeNames->TexCoord2fArray, pxr::UsdGeomTokens->faceVarying);
MLoopUV *mloopuv = static_cast<MLoopUV *>(layer->data);
diff --git a/source/blender/io/usd/tests/usd_imaging_test.cc b/source/blender/io/usd/tests/usd_imaging_test.cc
index 5cd3c042e59..80c232ad099 100644
--- a/source/blender/io/usd/tests/usd_imaging_test.cc
+++ b/source/blender/io/usd/tests/usd_imaging_test.cc
@@ -42,8 +42,8 @@ TEST_F(USDImagingTest, CapsuleAdapterTest)
}
pxr::UsdImagingCapsuleAdapter capsule_adapter;
- pxr::VtValue points_value = pxr::UsdImagingCapsuleAdapter::GetMeshPoints(
- capsule.GetPrim(), pxr::UsdTimeCode::Default());
+ pxr::VtValue points_value = capsule_adapter.GetPoints(capsule.GetPrim(),
+ pxr::UsdTimeCode::Default());
if (!points_value.IsHolding<pxr::VtArray<pxr::GfVec3f>>()) {
FAIL() << "Mesh points value holding unexpected type.";
return;
@@ -52,7 +52,8 @@ TEST_F(USDImagingTest, CapsuleAdapterTest)
pxr::VtArray<pxr::GfVec3f> points = points_value.Get<pxr::VtArray<pxr::GfVec3f>>();
EXPECT_FALSE(points.empty());
- pxr::VtValue topology_value = pxr::UsdImagingCapsuleAdapter::GetMeshTopology();
+ pxr::VtValue topology_value = capsule_adapter.GetTopology(
+ capsule.GetPrim(), pxr::SdfPath(), pxr::UsdTimeCode::Default());
if (!topology_value.IsHolding<pxr::HdMeshTopology>()) {
FAIL() << "Mesh topology value holding unexpected type.";
diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt
index f7958ef4ec6..bfbc715a45f 100644
--- a/source/blender/io/wavefront_obj/CMakeLists.txt
+++ b/source/blender/io/wavefront_obj/CMakeLists.txt
@@ -2,8 +2,8 @@
set(INC
.
- ./exporter
- ./importer
+ exporter
+ importer
../common
../../blenkernel
../../blenlib
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
index d00c09b9013..f5a94b1fc8a 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
@@ -124,10 +124,11 @@ void OBJMesh::set_world_axes_transform(const eIOAxis forward, const eIOAxis up)
unit_m3(axes_transform);
/* +Y-forward and +Z-up are the default Blender axis settings. */
mat3_from_axis_conversion(forward, up, IO_AXIS_Y, IO_AXIS_Z, axes_transform);
- mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.obmat);
+ mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.object_to_world);
/* mul_m4_m3m4 does not transform last row of obmat, i.e. location data. */
- mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_.obmat[3]);
- world_and_axes_transform_[3][3] = export_object_eval_.obmat[3][3];
+ mul_v3_m3v3(
+ world_and_axes_transform_[3], axes_transform, export_object_eval_.object_to_world[3]);
+ world_and_axes_transform_[3][3] = export_object_eval_.object_to_world[3][3];
/* Normals need inverse transpose of the regular matrix to handle non-uniform scale. */
float normal_matrix[3][3];
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc b/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc
index 812c3e7b5d4..1b1ee5f8386 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_nurbs.cc
@@ -31,10 +31,10 @@ void OBJCurve::set_world_axes_transform(const eIOAxis forward, const eIOAxis up)
unit_m3(axes_transform);
/* +Y-forward and +Z-up are the Blender's default axis settings. */
mat3_from_axis_conversion(forward, up, IO_AXIS_Y, IO_AXIS_Z, axes_transform);
- mul_m4_m3m4(world_axes_transform_, axes_transform, export_object_eval_->obmat);
- /* #mul_m4_m3m4 does not transform last row of #Object.obmat, i.e. location data. */
- mul_v3_m3v3(world_axes_transform_[3], axes_transform, export_object_eval_->obmat[3]);
- world_axes_transform_[3][3] = export_object_eval_->obmat[3][3];
+ mul_m4_m3m4(world_axes_transform_, axes_transform, export_object_eval_->object_to_world);
+ /* #mul_m4_m3m4 does not transform last row of #Object.object_to_world, i.e. location data. */
+ mul_v3_m3v3(world_axes_transform_[3], axes_transform, export_object_eval_->object_to_world[3]);
+ world_axes_transform_[3][3] = export_object_eval_->object_to_world[3][3];
}
const char *OBJCurve::get_curve_name() const
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 287a9e2f3b9..0355ed3febe 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -116,7 +116,7 @@ typedef enum eCustomDataType {
CD_PROP_BYTE_COLOR = 17,
CD_TANGENT = 18,
CD_MDISPS = 19,
- CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
+ CD_PREVIEW_MCOL = 20, /* For displaying weight-paint colors. */
/* CD_ID_MCOL = 21, */
/* CD_TEXTURE_MLOOPCOL = 22, */ /* UNUSED */
CD_CLOTH_ORCO = 23,
@@ -209,7 +209,7 @@ typedef enum eCustomDataType {
#define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH)
-/** Multires loop data. */
+/** Multi-resolution loop data. */
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)
/* All data layers. */
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 26dbb544f52..8b3f4956cfe 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -243,12 +243,15 @@ typedef struct bGPDstroke_Runtime {
/** Runtime falloff factor (only for transform). */
float multi_frame_falloff;
- /** Vertex offset in the VBO where this stroke starts. */
+ /** Triangle offset in the IBO where this stroke starts. */
int stroke_start;
/** Triangle offset in the IBO where this fill starts. */
int fill_start;
+ /** Vertex offset in the VBO where this stroke starts. */
+ int vertex_start;
/** Curve Handles offset in the IBO where this handle starts. */
int curve_start;
+ int _pad0;
/** Original stroke (used to dereference evaluated data) */
struct bGPDstroke *gps_orig;
@@ -613,8 +616,9 @@ typedef struct bGPdata_Runtime {
/** Stroke buffer. */
void *sbuffer;
/** Temp batches cleared after drawing. */
- struct GPUBatch *sbuffer_stroke_batch;
- struct GPUBatch *sbuffer_fill_batch;
+ struct GPUVertBuf *sbuffer_position_buf;
+ struct GPUVertBuf *sbuffer_color_buf;
+ struct GPUBatch *sbuffer_batch;
/** Temp stroke used for drawing. */
struct bGPDstroke *sbuffer_gps;
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 827e07725a1..6ea35dfb770 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -134,13 +134,13 @@ typedef struct ViewLayerAOV {
typedef struct ViewLayerLightgroup {
struct ViewLayerLightgroup *next, *prev;
- /* Name of the Lightgroup */
+ /* Name of the Light-group. */
char name[64];
} ViewLayerLightgroup;
-/* Lightgroup membership information. */
+/* Light-group membership information. */
typedef struct LightgroupMembership {
- /* Name of the Lightgroup */
+ /* Name of the Light-group. */
char name[64];
} LightgroupMembership;
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
index d0c09a0d6ab..b4a66a46efe 100644
--- a/source/blender/makesdna/DNA_meta_types.h
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -42,7 +42,7 @@ typedef struct MetaElem {
float rad2;
/** Stiffness, how much of the element to fill. */
float s;
- /** Old, only used for backwards compat. use dimensions now. */
+ /** Old, only used for backwards compatibility. use dimensions now. */
float len;
/** Matrix and inverted matrix. */
@@ -63,7 +63,7 @@ typedef struct MetaBall {
/* material of the mother ball will define the material used of all others */
struct Material **mat;
- /** Flag is enum for updates, flag2 is bitflags for settings. */
+ /** Flag is enum for updates, flag2 is bit-flags for settings. */
char flag, flag2;
short totcol;
/** Used to store MB_AUTOSPACE. */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 7625f04fefa..c4180071352 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -195,7 +195,7 @@ typedef struct LatticeModifierData {
ModifierData modifier;
struct Object *object;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char name[64];
float strength;
short flag;
@@ -212,7 +212,7 @@ typedef struct CurveModifierData {
ModifierData modifier;
struct Object *object;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char name[64];
/** Axis along which curve deforms. */
short defaxis;
@@ -262,7 +262,7 @@ typedef struct MaskModifierData {
/** Armature to use to in place of hardcoded vgroup. */
struct Object *ob_arm;
- /** Name of vertex group to use to mask, MAX_VGROUP_NAME. */
+ /** Name of vertex group to use to mask, #MAX_VGROUP_NAME. */
char vgroup[64];
/** Using armature or hardcoded vgroup. */
@@ -447,7 +447,7 @@ typedef struct BevelModifierData {
float bevel_angle;
float spread;
/** if the MOD_BEVEL_VWEIGHT option is set,
- * this will be the name of the vert group, MAX_VGROUP_NAME */
+ * this will be the name of the vert group, #MAX_VGROUP_NAME */
char defgrp_name[64];
char _pad1[4];
@@ -565,7 +565,7 @@ typedef struct DisplaceModifierData {
float strength;
int direction;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
float midlevel;
int space;
@@ -635,7 +635,7 @@ typedef struct DecimateModifierData {
/** (mode == MOD_DECIM_MODE_DISSOLVE). */
float angle;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
float defgrp_factor;
short flag, mode;
@@ -663,7 +663,7 @@ enum {
typedef struct SmoothModifierData {
ModifierData modifier;
float fac;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
short flag, repeat;
@@ -684,7 +684,7 @@ typedef struct CastModifierData {
float fac;
float radius;
float size;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
short flag;
/** Cast modifier projection type. */
@@ -725,7 +725,7 @@ typedef struct WaveModifierData {
/* End MappingInfoModifierData. */
struct Object *objectcenter;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
short flag;
@@ -760,7 +760,7 @@ typedef struct ArmatureModifierData {
struct Object *object;
/** Stored input of previous modifier, for vertex-group blending. */
float (*vert_coords_prev)[3];
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
} ArmatureModifierData;
@@ -803,11 +803,11 @@ typedef struct HookModifierData {
struct CurveMapping *curfalloff;
- /** If NULL, it's using vertexgroup. */
+ /** If NULL, it's using vertex-group. */
int *indexar;
int indexar_num;
float force;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char name[64];
void *_pad1;
} HookModifierData;
@@ -946,7 +946,7 @@ typedef struct MeshDeformModifierData {
/** Mesh object. */
struct Object *object;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char defgrp_name[64];
short gridsize, flag;
@@ -1124,7 +1124,7 @@ typedef struct ShrinkwrapModifierData {
struct Object *target;
/** Additional shrink target. */
struct Object *auxTarget;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgroup_name[64];
/** Distance offset to keep from mesh/projection point. */
float keepDist;
@@ -1171,9 +1171,9 @@ enum {
/** #ShrinkwrapModifierData.shrinkOpts */
enum {
- /** allow shrinkwrap to move the vertex in the positive direction of axis */
+ /** Allow shrink-wrap to move the vertex in the positive direction of axis. */
MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR = (1 << 0),
- /** allow shrinkwrap to move the vertex in the negative direction of axis */
+ /** Allow shrink-wrap to move the vertex in the negative direction of axis. */
MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR = (1 << 1),
/** ignore vertex moves if a vertex ends projected on a front face of the target */
@@ -1207,7 +1207,7 @@ typedef struct SimpleDeformModifierData {
/** Object to control the origin of modifier space coordinates. */
struct Object *origin;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgroup_name[64];
/** Factors to control simple deforms. */
float factor;
@@ -1250,7 +1250,7 @@ typedef struct ShapeKeyModifierData {
typedef struct SolidifyModifierData {
ModifierData modifier;
- /** Name of vertex group to use, MAX_VGROUP_NAME. */
+ /** Name of vertex group to use, #MAX_VGROUP_NAME. */
char defgrp_name[64];
char shell_defgrp_name[64];
char rim_defgrp_name[64];
@@ -1451,7 +1451,7 @@ typedef struct WarpModifierData {
char bone_to[64];
struct CurveMapping *curfalloff;
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char defgrp_name[64];
float strength;
float falloff_radius;
@@ -1484,7 +1484,7 @@ typedef enum {
typedef struct WeightVGEditModifierData {
ModifierData modifier;
- /** Name of vertex group to edit. MAX_VGROUP_NAME. */
+ /** Name of vertex group to edit. #MAX_VGROUP_NAME. */
char defgrp_name[64];
/** Using MOD_WVG_EDIT_* flags. */
@@ -1504,7 +1504,7 @@ typedef struct WeightVGEditModifierData {
/* Masking options. */
/** The global "influence", if no vgroup nor tex is used as mask. */
float mask_constant;
- /** Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME. */
+ /** Name of mask vertex group from which to get weight factors. #MAX_VGROUP_NAME. */
char mask_defgrp_name[64];
/* Texture masking. */
@@ -1540,9 +1540,9 @@ enum {
typedef struct WeightVGMixModifierData {
ModifierData modifier;
- /** Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
+ /** Name of vertex group to modify/weight. #MAX_VGROUP_NAME. */
char defgrp_name_a[64];
- /** Name of other vertex group to mix in. MAX_VGROUP_NAME. */
+ /** Name of other vertex group to mix in. #MAX_VGROUP_NAME. */
char defgrp_name_b[64];
/** Default weight value for first vgroup. */
float default_weight_a;
@@ -1558,7 +1558,7 @@ typedef struct WeightVGMixModifierData {
/* Masking options. */
/** The global "influence", if no vgroup nor tex is used as mask. */
float mask_constant;
- /** Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME. */
+ /** Name of mask vertex group from which to get weight factors. #MAX_VGROUP_NAME. */
char mask_defgrp_name[64];
/* Texture masking. */
@@ -1628,7 +1628,7 @@ enum {
typedef struct WeightVGProximityModifierData {
ModifierData modifier;
- /** Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
+ /** Name of vertex group to modify/weight. #MAX_VGROUP_NAME. */
char defgrp_name[64];
/* Mapping stuff. */
@@ -1646,7 +1646,7 @@ typedef struct WeightVGProximityModifierData {
/* Masking options. */
/** The global "influence", if no vgroup nor tex is used as mask. */
float mask_constant;
- /** Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME. */
+ /** Name of mask vertex group from which to get weight factors. #MAX_VGROUP_NAME. */
char mask_defgrp_name[64];
/* Texture masking. */
@@ -1840,7 +1840,7 @@ typedef struct LaplacianSmoothModifierData {
float lambda, lambda_border;
char _pad1[4];
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
short flag, repeat;
} LaplacianSmoothModifierData;
@@ -1887,7 +1887,7 @@ typedef struct CorrectiveSmoothModifierData {
char smooth_type, rest_source;
char _pad[6];
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
/* runtime-only cache */
@@ -1932,7 +1932,7 @@ typedef struct UVWarpModifierData {
/** Optional name of bone target, MAX_ID_NAME-2. */
char bone_dst[64];
- /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ /** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgroup_name[64];
/** MAX_CUSTOMDATA_LAYER_NAME. */
char uvlayer_name[64];
@@ -2013,7 +2013,7 @@ enum {
typedef struct LaplacianDeformModifierData {
ModifierData modifier;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char anchor_grp_name[64];
int verts_num, repeat;
float *vertexco;
@@ -2035,7 +2035,7 @@ enum {
*/
typedef struct WireframeModifierData {
ModifierData modifier;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
float offset;
float offset_fac;
@@ -2059,7 +2059,7 @@ typedef struct WeldModifierData {
/* The limit below which to merge vertices. */
float merge_dist;
- /* Name of vertex group to use to mask, MAX_VGROUP_NAME. */
+ /** Name of vertex group to use to mask, #MAX_VGROUP_NAME. */
char defgrp_name[64];
char mode;
@@ -2107,7 +2107,7 @@ typedef struct DataTransferModifierData {
/** See CDT_MIX_ enum in BKE_customdata.h. */
int mix_mode;
float mix_factor;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
int flags;
@@ -2130,7 +2130,7 @@ enum {
/** Set Split Normals modifier. */
typedef struct NormalEditModifierData {
ModifierData modifier;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
/** Source of normals, or center of ellipsoid. */
struct Object *target;
@@ -2253,7 +2253,7 @@ enum {
typedef struct WeightedNormalModifierData {
ModifierData modifier;
- /** MAX_VGROUP_NAME. */
+ /** #MAX_VGROUP_NAME. */
char defgrp_name[64];
char mode, flag;
short weight;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 315bcbd971c..74714cf7e41 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -931,7 +931,7 @@ typedef struct NodeImageMultiFileSocket {
char path[1024];
ImageFormatData format;
- /* multilayer output */
+ /* Multi-layer output. */
/** EXR_TOT_MAXNAME-2 ('.' and channel char are appended). */
char layer[30];
char _pad2[2];
@@ -1273,7 +1273,7 @@ typedef struct CryptomatteLayer {
typedef struct NodeCryptomatte_Runtime {
/* Contains `CryptomatteLayer`. */
ListBase layers;
- /* Temp storage for the cryptomatte picker. */
+ /* Temp storage for the crypto-matte picker. */
float add[3];
float remove[3];
} NodeCryptomatte_Runtime;
@@ -2083,6 +2083,12 @@ typedef enum CMPNodeLevelsChannel {
CMP_NODE_LEVLES_LUMINANCE_BT709 = 5,
} CMPNodeLevelsChannel;
+/* Tone Map Node. Stored in NodeTonemap.type. */
+typedef enum CMPNodeToneMapType {
+ CMP_NODE_TONE_MAP_SIMPLE = 0,
+ CMP_NODE_TONE_MAP_PHOTORECEPTOR = 1,
+} CMPNodeToneMapType;
+
/* Plane track deform node. */
enum {
diff --git a/source/blender/makesdna/DNA_object_defaults.h b/source/blender/makesdna/DNA_object_defaults.h
index 14683869bc4..2a5796d2aea 100644
--- a/source/blender/makesdna/DNA_object_defaults.h
+++ b/source/blender/makesdna/DNA_object_defaults.h
@@ -23,7 +23,7 @@
\
.constinv = _DNA_DEFAULT_UNIT_M4, \
.parentinv = _DNA_DEFAULT_UNIT_M4, \
- .obmat = _DNA_DEFAULT_UNIT_M4, \
+ .object_to_world = _DNA_DEFAULT_UNIT_M4, \
\
.scale = {1, 1, 1}, \
.dscale = {1, 1, 1}, \
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 8296855ec29..3ef32d28e85 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -323,7 +323,7 @@ typedef struct Object {
/** Axis angle rotation - angle part. */
float rotAngle, drotAngle;
/** Final world-space matrix with constraints & animsys applied. */
- float obmat[4][4];
+ float object_to_world[4][4];
/** Inverse result of parent, so that object doesn't 'stick' to parent. */
float parentinv[4][4];
/** Inverse result of constraints.
@@ -333,7 +333,7 @@ typedef struct Object {
* Inverse matrix of 'obmat' for any other use than rendering!
*
* \note this isn't assured to be valid as with 'obmat',
- * before using this value you should do: `invert_m4_m4(ob->imat, ob->obmat)`
+ * before using this value you should do: `invert_m4_m4(ob->imat, ob->object_to_world)`
*/
float imat[4][4];
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 44f1d3479b1..c4f11905e10 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -465,7 +465,7 @@ enum {
#define PART_REACT_MULTIPLE 2
//#define PART_LOOP 4 /* not used anymore */
-/* for dopesheet */
+/* For dope-sheet. */
#define PART_DS_EXPAND 8
#define PART_HAIR_REGROW 16 /* regrow hair for each frame */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 5fa5d4c7787..28359038be5 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -472,6 +472,7 @@ typedef struct ImageFormatData {
#define R_IMF_IMTYPE_THEORA 33
#define R_IMF_IMTYPE_PSD 34
#define R_IMF_IMTYPE_WEBP 35
+#define R_IMF_IMTYPE_AV1 36
#define R_IMF_IMTYPE_INVALID 255
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 55563ca6823..d05ba0f7e2e 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -667,7 +667,7 @@ typedef struct SpaceSeq {
struct SequencerPreviewOverlay preview_overlay;
struct SequencerTimelineOverlay timeline_overlay;
- /** Multiview current eye - for internal use. */
+ /** Multi-view current eye - for internal use. */
char multiview_eye;
char _pad2[7];
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 9b235fac049..7231a995f10 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -89,13 +89,13 @@ typedef struct Report {
} Report;
/**
- * \note Saved in the wm, don't remove.
+ * \note Saved in the #wmWindowManager, don't remove.
*/
typedef struct ReportList {
ListBase list;
- /** eReportType. */
+ /** #eReportType. */
int printlevel;
- /** eReportType. */
+ /** #eReportType. */
int storelevel;
int flag;
char _pad[4];
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index e99f317f057..0cd1144b30d 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -199,8 +199,10 @@ typedef struct WorkSpaceInstanceHook {
WorkSpace *active;
struct WorkSpaceLayout *act_layout;
- /** Needed because we can't change workspaces/layouts in running handler loop,
- * it would break context. */
+ /**
+ * Needed because we can't change work-spaces/layouts in running handler loop,
+ * it would break context.
+ */
WorkSpace *temp_workspace_store;
struct WorkSpaceLayout *temp_layout_store;
} WorkSpaceInstanceHook;
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 0d04d7df067..50fd51e88a1 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -116,8 +116,8 @@ blender_add_lib(bf_dna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# -----------------------------------------------------------------------------
# Build bf_dna_blenlib library
set(INC
+ ..
../../blenlib
- ../../makesdna
../../../../intern/atomic
../../../../intern/guardedalloc
)
diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h
index f968b7409f7..864fbc45b13 100644
--- a/source/blender/makesdna/intern/dna_rename_defs.h
+++ b/source/blender/makesdna/intern/dna_rename_defs.h
@@ -97,6 +97,7 @@ DNA_STRUCT_RENAME_ELEM(Object, dup_group, instance_collection)
DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale)
DNA_STRUCT_RENAME_ELEM(Object, restrictflag, visibility_flag)
DNA_STRUCT_RENAME_ELEM(Object, size, scale)
+DNA_STRUCT_RENAME_ELEM(Object, obmat, object_to_world)
DNA_STRUCT_RENAME_ELEM(Object_Runtime, crazyspace_num_verts, crazyspace_verts_num)
DNA_STRUCT_RENAME_ELEM(MEdge, bweight, bweight_legacy)
DNA_STRUCT_RENAME_ELEM(MEdge, crease, crease_legacy)
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 0a17ae637bc..4fbb246e056 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -201,7 +201,7 @@ set(INC
../../imbuf
../../makesdna
../../modifiers
- ../../nodes/
+ ../../nodes
../../sequencer
../../simulation
../../windowmanager
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index e6b1ea1321c..a2386205013 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -1129,7 +1129,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
RNA_define_lib_overridable(false);
}
-/* err... bones should not be directly edited (only editbones should be...) */
+/* Err... bones should not be directly edited (only edit-bones should be...). */
static void rna_def_bone(BlenderRNA *brna)
{
StructRNA *srna;
diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c
index a04fdbae465..7fbb6926cf1 100644
--- a/source/blender/makesrna/intern/rna_asset.c
+++ b/source/blender/makesrna/intern/rna_asset.c
@@ -505,6 +505,12 @@ static void rna_def_asset_handle(BlenderRNA *brna)
rna_def_asset_handle_api(srna);
}
+static void rna_def_asset_catalog_path(BlenderRNA *brna)
+{
+ StructRNA *srna = RNA_def_struct(brna, "AssetCatalogPath", NULL);
+ RNA_def_struct_ui_text(srna, "Catalog Path", "");
+}
+
static void rna_def_asset_library_reference(BlenderRNA *brna)
{
StructRNA *srna = RNA_def_struct(brna, "AssetLibraryReference", NULL);
@@ -556,6 +562,7 @@ void RNA_def_asset(BlenderRNA *brna)
rna_def_asset_library_reference(brna);
rna_def_asset_library_reference_custom(brna);
rna_def_asset_handle(brna);
+ rna_def_asset_catalog_path(brna);
RNA_define_animate_sdna(true);
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 35e01be366b..5ba31070e1d 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -3616,6 +3616,10 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Vertex", "Use this brush in grease pencil vertex color mode");
+ prop = RNA_def_property(srna, "use_paint_sculpt_curves", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "ob_mode", OB_MODE_SCULPT_CURVES);
+ RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in sculpt curves mode");
+
/* texture */
prop = RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BrushTextureSlot");
@@ -3659,13 +3663,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mask Texture Overlay Alpha", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "cursor_color_add", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "cursor_color_add", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "add_col");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Add Color", "Color of cursor when adding");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "cursor_color_subtract", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "cursor_color_subtract", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "sub_col");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Subtract Color", "Color of cursor when subtracting");
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index db5b3c33c59..9af76de2a2b 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -168,7 +168,7 @@ static void rna_DepsgraphObjectInstance_matrix_world_get(PointerRNA *ptr, float
/* We can return actual object's matrix here, no reason to return identity matrix
* when this is not actually an instance... */
Object *ob = (Object *)di->iter.current;
- copy_m4_m4((float(*)[4])mat, ob->obmat);
+ copy_m4_m4((float(*)[4])mat, ob->object_to_world);
}
}
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 727d329781d..9fe7dda0e20 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -2416,7 +2416,7 @@ static void rna_def_fcurve(BlenderRNA *brna)
prop, "Color Mode", "Method used to determine color of F-Curve in Graph Editor");
RNA_def_property_update(prop, NC_ANIMATION, NULL);
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Color", "Color of the F-Curve in the Graph Editor");
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index cf0ff546d41..a55a1b0ffcd 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -334,13 +334,13 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr, const char **
static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char *substr)
{
if (type == PAROBJECT) {
- invert_m4_m4(gpl->inverse, par->obmat);
+ invert_m4_m4(gpl->inverse, par->object_to_world);
gpl->parent = par;
gpl->partype |= PAROBJECT;
gpl->parsubstr[0] = 0;
}
else if (type == PARSKEL) {
- invert_m4_m4(gpl->inverse, par->obmat);
+ invert_m4_m4(gpl->inverse, par->object_to_world);
gpl->parent = par;
gpl->partype |= PARSKEL;
gpl->parsubstr[0] = 0;
@@ -349,7 +349,7 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char *
bPoseChannel *pchan = BKE_pose_channel_find_name(par->pose, substr);
if (pchan) {
float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, par->obmat, pchan->pose_mat);
+ mul_m4_m4m4(tmp_mat, par->object_to_world, pchan->pose_mat);
invert_m4_m4(gpl->inverse, tmp_mat);
gpl->parent = par;
@@ -357,7 +357,7 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char *
BLI_strncpy(gpl->parsubstr, substr, sizeof(gpl->parsubstr));
}
else {
- invert_m4_m4(gpl->inverse, par->obmat);
+ invert_m4_m4(gpl->inverse, par->object_to_world);
gpl->parent = par;
gpl->partype |= PAROBJECT;
gpl->parsubstr[0] = 0;
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 4a36443ca42..320ef169ae5 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -9,11 +9,8 @@
#include <stdlib.h>
#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_cachefile_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
@@ -21,20 +18,13 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
+#include "BLI_math_base.h"
+#include "BLI_math_rotation.h"
#include "BLI_string_utils.h"
#include "BLT_translation.h"
#include "BKE_animsys.h"
-#include "BKE_data_transfer.h"
-#include "BKE_dynamicpaint.h"
-#include "BKE_effect.h"
-#include "BKE_fluid.h" /* For BKE_fluid_modifier_free & BKE_fluid_modifier_create_type_data */
-#include "BKE_mesh_mapping.h"
-#include "BKE_mesh_remap.h"
-#include "BKE_multires.h"
#include "RNA_access.h"
#include "RNA_define.h"
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index fdd702ac377..9b7534d081d 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -323,7 +323,9 @@ void rna_object_vcollayer_name_set(struct PointerRNA *ptr,
PointerRNA rna_object_shapekey_index_get(struct ID *id, int value);
int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current);
-void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag);
+void rna_def_object_type_visibility_flags_common(StructRNA *srna,
+ int noteflag,
+ const char *update_func);
int rna_object_type_visibility_icon_get_common(int object_type_exclude_viewport,
const int *object_type_exclude_select);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 0b0970a835e..865399df9ef 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -12230,7 +12230,7 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Custom Color", "Use custom color for the node");
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Color", "Custom color of the node body");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 46a89d3a6e0..1d6b3d5d69e 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -356,7 +356,8 @@ static void rna_Object_internal_update_draw(Main *UNUSED(bmain),
static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
/* don't use compat so we get predictable rotation */
- BKE_object_apply_mat4((Object *)ptr->owner_id, ((Object *)ptr->owner_id)->obmat, false, true);
+ BKE_object_apply_mat4(
+ (Object *)ptr->owner_id, ((Object *)ptr->owner_id)->object_to_world, false, true);
rna_Object_internal_update(bmain, scene, ptr);
}
@@ -407,7 +408,7 @@ static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16])
Object *ob = (Object *)ptr->owner_id;
float local_mat[4][4];
- /* Localspace matrix is truly relative to the parent,
+ /* Local-space matrix is truly relative to the parent,
* but parameters stored in object are relative to parentinv matrix.
* Undo the parent inverse part before applying it as local matrix. */
if (ob->parent) {
@@ -3390,7 +3391,7 @@ static void rna_def_object(BlenderRNA *brna)
/* matrix */
prop = RNA_def_property(srna, "matrix_world", PROP_FLOAT, PROP_MATRIX);
- RNA_def_property_float_sdna(prop, NULL, "obmat");
+ RNA_def_property_float_sdna(prop, NULL, "object_to_world");
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 07702f3b4b6..02105c7b425 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -471,7 +471,7 @@ static void rna_ParticleSystem_co_hair(
if (step >= 0 && step <= max_k) {
copy_v3_v3(n_co, (cache + step)->co);
mul_m4_v3(particlesystem->imat, n_co);
- mul_m4_v3(object->obmat, n_co);
+ mul_m4_v3(object->object_to_world, n_co);
}
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 8fc504f192e..fde8fcf651c 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5945,7 +5945,8 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{AV_CODEC_ID_PNG, "PNG", 0, "PNG", ""},
{AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""},
{AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
- {AV_CODEC_ID_VP9, "WEBM", 0, "WEBM / VP9", ""},
+ {AV_CODEC_ID_VP9, "WEBM", 0, "WebM / VP9", ""},
+ {AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index b5469a30568..2ac30c44ea8 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1002,6 +1002,13 @@ static PointerRNA rna_SpaceView3D_region_3d_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_RegionView3D, regiondata);
}
+static void rna_SpaceView3D_object_type_visibility_update(Main *UNUSED(bmain),
+ Scene *scene,
+ PointerRNA *UNUSED(ptr))
+{
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+}
+
static void rna_SpaceView3D_region_quadviews_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
@@ -5098,7 +5105,8 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_mirror_xr_session_update");
rna_def_object_type_visibility_flags_common(srna,
- NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING);
+ NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING,
+ "rna_SpaceView3D_object_type_visibility_update");
/* Helper for drawing the icon. */
prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index b3896919275..9790a85e1c8 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -119,7 +119,9 @@ void RNA_api_space_text(StructRNA *srna)
RNA_def_function_output(func, parm);
}
-void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag)
+void rna_def_object_type_visibility_flags_common(StructRNA *srna,
+ int noteflag,
+ const char *update_func)
{
PropertyRNA *prop;
@@ -173,7 +175,7 @@ void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag)
RNA_def_property_boolean_negative_sdna(
prop, NULL, view_mask_member[mask_index], info[type_index].type_mask);
RNA_def_property_ui_text(prop, info[type_index].name, "");
- RNA_def_property_update(prop, noteflag, NULL);
+ RNA_def_property_update(prop, noteflag, update_func);
}
}
}
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index c4a11d4e9e0..44df0db9ade 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -1640,7 +1640,7 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
/* color */
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index fc68e8421d7..eac29ac5e61 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -1785,6 +1785,10 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ func = RNA_def_function(srna, "template_node_asset_menu_items", "uiTemplateNodeAssetMenuItems");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm = RNA_def_string(func, "catalog_path", NULL, 0, "", "");
+
func = RNA_def_function(srna, "template_texture_user", "uiTemplateTextureUser");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 2fed4e3f4a3..72722053a64 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -561,7 +561,7 @@ static void rna_Userdef_disk_cache_dir_update(Main *UNUSED(bmain),
{
if (U.sequencer_disk_cache_dir[0] != '\0') {
BLI_path_abs(U.sequencer_disk_cache_dir, BKE_main_blendfile_path_from_global());
- BLI_path_slash_ensure(U.sequencer_disk_cache_dir);
+ BLI_path_slash_ensure(U.sequencer_disk_cache_dir, sizeof(U.sequencer_disk_cache_dir));
BLI_path_make_safe(U.sequencer_disk_cache_dir);
}
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 5b5544120a1..eebe595820e 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -99,13 +99,6 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""},
{NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""},
{NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""},
-# if 0 /* Never used (converted to keyboard events by GHOST). */
- /* keyboard emulation */
- {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"},
- {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"},
- {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"},
- {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"},
-# endif
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""},
@@ -120,6 +113,21 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "Button A", ""},
{NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "Button B", ""},
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""},
+ /* View buttons. */
+ {NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "View 1", ""},
+ {NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "View 2", ""},
+ {NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "View 3", ""},
+# if 0 /* Never used (converted to keyboard events by GHOST). */
+ /* keyboard emulation */
+ {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"},
+ {NDOF_BUTTON_ENTER, "NDOF_BUTTON_ENTER", 0, "Enter"},
+ {NDOF_BUTTON_DELETE, "NDOF_BUTTON_DELETE", 0, "Delete"},
+ {NDOF_BUTTON_TAB, "NDOF_BUTTON_TAB", 0, "Tab"},
+ {NDOF_BUTTON_SPACE, "NDOF_BUTTON_SPACE", 0, "Space"},
+ {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"},
+ {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"},
+ {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"},
+# endif
{0, NULL, 0, NULL, NULL},
};
#endif /* RNA_RUNTIME */
diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c
index dcfa1bbca51..c803e5dc9a8 100644
--- a/source/blender/makesrna/intern/rna_xr.c
+++ b/source/blender/makesrna/intern/rna_xr.c
@@ -2052,7 +2052,7 @@ static void rna_def_xr_session_settings(BlenderRNA *brna)
"Allow the VR tracking origin to be defined independently of the headset location");
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
- rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED);
+ rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED, NULL);
/* Helper for drawing the icon. */
prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE);
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index bf534b0d586..2d725af7fe4 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -456,13 +456,13 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
float result_mat[4][4];
if (ctx->object) {
- invert_m4_m4(obinv, ctx->object->obmat);
+ invert_m4_m4(obinv, ctx->object->object_to_world);
}
else {
unit_m4(obinv);
}
- mul_m4_series(result_mat, offset, obinv, amd->offset_ob->obmat);
+ mul_m4_series(result_mat, offset, obinv, amd->offset_ob->object_to_world);
copy_m4_m4(offset, result_mat);
}
@@ -474,7 +474,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
Object *curve_ob = amd->curve_ob;
CurveCache *curve_cache = curve_ob->runtime.curve_cache;
if (curve_cache != NULL && curve_cache->anim_path_accum_length != NULL) {
- float scale_fac = mat4_to_scale(curve_ob->obmat);
+ float scale_fac = mat4_to_scale(curve_ob->object_to_world);
length = scale_fac * BKE_anim_path_get_length(curve_cache);
}
}
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc
index 7ad49f43e1b..21f05158e8b 100644
--- a/source/blender/modifiers/intern/MOD_boolean.cc
+++ b/source/blender/modifiers/intern/MOD_boolean.cc
@@ -139,8 +139,8 @@ static Mesh *get_quick_mesh(
float imat[4][4];
float omat[4][4];
- invert_m4_m4(imat, ob_self->obmat);
- mul_m4_m4m4(omat, imat, ob_operand_ob->obmat);
+ invert_m4_m4(imat, ob_self->object_to_world);
+ mul_m4_m4m4(omat, imat, ob_operand_ob->object_to_world);
MutableSpan<MVert> verts = result->verts_for_write();
for (const int i : verts.index_range()) {
@@ -227,7 +227,8 @@ static BMesh *BMD_mesh_bm_create(
SCOPED_TIMER(__func__);
#endif
- *r_is_flip = (is_negative_m4(object->obmat) != is_negative_m4(operand_ob->obmat));
+ *r_is_flip = (is_negative_m4(object->object_to_world) !=
+ is_negative_m4(operand_ob->object_to_world));
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_operand_ob);
@@ -294,8 +295,8 @@ static void BMD_mesh_intersection(BMesh *bm,
float imat[4][4];
float omat[4][4];
- invert_m4_m4(imat, object->obmat);
- mul_m4_m4m4(omat, imat, operand_ob->obmat);
+ invert_m4_m4(imat, object->object_to_world);
+ mul_m4_m4m4(omat, imat, operand_ob->object_to_world);
BMVert *eve;
i = 0;
@@ -414,7 +415,7 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
}
meshes.append(mesh);
- obmats.append((float4x4 *)&ctx->object->obmat);
+ obmats.append((float4x4 *)&ctx->object->object_to_world);
material_remaps.append({});
if (mesh->totcol == 0) {
/* Necessary for faces using the default material when there are no material slots. */
@@ -431,7 +432,7 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
}
BKE_mesh_wrapper_ensure_mdata(mesh_operand);
meshes.append(mesh_operand);
- obmats.append((float4x4 *)&bmd->object->obmat);
+ obmats.append((float4x4 *)&bmd->object->object_to_world);
material_remaps.append(get_material_remap(*bmd->object, *mesh_operand, materials));
}
else if (bmd->flag & eBooleanModifierFlag_Collection) {
@@ -446,7 +447,7 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
}
BKE_mesh_wrapper_ensure_mdata(collection_mesh);
meshes.append(collection_mesh);
- obmats.append((float4x4 *)&ob->obmat);
+ obmats.append((float4x4 *)&ob->object_to_world);
material_remaps.append(get_material_remap(*ob, *collection_mesh, materials));
}
}
@@ -456,14 +457,15 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
const bool use_self = (bmd->flag & eBooleanModifierFlag_Self) != 0;
const bool hole_tolerant = (bmd->flag & eBooleanModifierFlag_HoleTolerant) != 0;
- Mesh *result = blender::meshintersect::direct_mesh_boolean(meshes,
- obmats,
- *(float4x4 *)&ctx->object->obmat,
- material_remaps,
- use_self,
- hole_tolerant,
- bmd->operation,
- nullptr);
+ Mesh *result = blender::meshintersect::direct_mesh_boolean(
+ meshes,
+ obmats,
+ *(float4x4 *)&ctx->object->object_to_world,
+ material_remaps,
+ use_self,
+ hole_tolerant,
+ bmd->operation,
+ nullptr);
MEM_SAFE_FREE(result->mat);
result->mat = (Material **)MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__);
result->totcol = materials.size();
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 30be1d33653..7581b2aa8e5 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -126,13 +126,13 @@ static void sphere_do(CastModifierData *cmd,
* we use its location, transformed to ob's local space */
if (ctrl_ob) {
if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- invert_m4_m4(imat, ctrl_ob->obmat);
- mul_m4_m4m4(mat, imat, ob->obmat);
+ invert_m4_m4(imat, ctrl_ob->object_to_world);
+ mul_m4_m4m4(mat, imat, ob->object_to_world);
invert_m4_m4(imat, mat);
}
- invert_m4_m4(ob->imat, ob->obmat);
- mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
+ invert_m4_m4(ob->imat, ob->object_to_world);
+ mul_v3_m4v3(center, ob->imat, ctrl_ob->object_to_world[3]);
}
/* now we check which options the user wants */
@@ -275,13 +275,13 @@ static void cuboid_do(CastModifierData *cmd,
if (ctrl_ob) {
if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- invert_m4_m4(imat, ctrl_ob->obmat);
- mul_m4_m4m4(mat, imat, ob->obmat);
+ invert_m4_m4(imat, ctrl_ob->object_to_world);
+ mul_m4_m4m4(mat, imat, ob->object_to_world);
invert_m4_m4(imat, mat);
}
- invert_m4_m4(ob->imat, ob->obmat);
- mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
+ invert_m4_m4(ob->imat, ob->object_to_world);
+ mul_v3_m4v3(center, ob->imat, ctrl_ob->object_to_world[3]);
}
if ((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index e38bf96500e..82faf08b349 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -149,7 +149,7 @@ static void deformVerts(ModifierData *md,
for (uint i = 0; i < mvert_num; i++) {
/* we save global positions */
- mul_m4_v3(ob->obmat, collmd->x[i].co);
+ mul_m4_v3(ob->object_to_world, collmd->x[i].co);
}
collmd->xnew = MEM_dupallocN(collmd->x); /* Frame end position. */
@@ -188,7 +188,7 @@ static void deformVerts(ModifierData *md,
for (uint i = 0; i < mvert_num; i++) {
/* we save global positions */
- mul_m4_v3(ob->obmat, collmd->xnew[i].co);
+ mul_m4_v3(ob->object_to_world, collmd->xnew[i].co);
/* detect motion */
is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co);
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index ad5be57ad68..fc12a9c2aad 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -322,7 +322,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
}
else if (ELEM(direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
use_global_direction) {
- copy_m4_m4(local_mat, ob->obmat);
+ copy_m4_m4(local_mat, ob->object_to_world);
}
DisplaceUserdata data = {NULL};
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index af167bf9b32..96bf836fa4a 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -985,7 +985,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
MTFace *mtface = CustomData_get_layer_named(&explode->fdata, CD_MTFACE, emd->uvname);
/* getting back to object space */
- invert_m4_m4(imat, ctx->object->obmat);
+ invert_m4_m4(imat, ctx->object->object_to_world);
psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
@@ -1020,7 +1020,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
psys_get_particle_state(&sim, ed_v2, &state, 1);
vertco = explode_verts[v].co;
- mul_m4_v3(ctx->object->obmat, vertco);
+ mul_m4_v3(ctx->object->object_to_world, vertco);
sub_v3_v3(vertco, birth.co);
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 11bc9ee9574..6cf2e1538e9 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -338,13 +338,13 @@ static void deformVerts_do(HookModifierData *hmd,
/* get world-space matrix of target, corrected for the space the verts are in */
if (hmd->subtarget[0] && pchan) {
/* bone target if there's a matching pose-channel */
- mul_m4_m4m4(dmat, ob_target->obmat, pchan->pose_mat);
+ mul_m4_m4m4(dmat, ob_target->object_to_world, pchan->pose_mat);
}
else {
/* just object target */
- copy_m4_m4(dmat, ob_target->obmat);
+ copy_m4_m4(dmat, ob_target->object_to_world);
}
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
mul_m4_series(hd.mat, ob->imat, dmat, hmd->parentinv);
/* --- done with 'hd' init --- */
diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
index cad9fdfe30d..778f12d6745 100644
--- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
+++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
@@ -135,7 +135,7 @@ static Volume *mesh_to_volume(ModifierData *md,
BKE_mesh_wrapper_ensure_mdata(mesh);
const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->imat) *
- float4x4(object_to_convert->obmat);
+ float4x4(object_to_convert->object_to_world);
geometry::MeshToVolumeResolution resolution;
resolution.mode = (MeshToVolumeModifierResolutionMode)mvmd->resolution_mode;
if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) {
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index d7ed346a61f..2aaaee2ccc7 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -358,8 +358,8 @@ static void meshdeformModifier_do(ModifierData *md,
}
/* compute matrices to go in and out of cage object space */
- invert_m4_m4(imat, ob_target->obmat);
- mul_m4_m4m4(cagemat, imat, ob->obmat);
+ invert_m4_m4(imat, ob_target->object_to_world);
+ mul_m4_m4m4(cagemat, imat, ob->object_to_world);
mul_m4_m4m4(cmat, mmd->bindmat, cagemat);
invert_m4_m4(iobmat, cmat);
copy_m3_m4(icagemat, iobmat);
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc
index 43ded18fcc4..7d422826cf8 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.cc
+++ b/source/blender/modifiers/intern/MOD_normal_edit.cc
@@ -94,8 +94,8 @@ static void generate_vert_coordinates(Mesh *mesh,
/* Translate our coordinates so that center of ob_center is at (0, 0, 0). */
/* Get ob_center (world) coordinates in ob local coordinates.
* No need to take into account ob_center's space here, see T44027. */
- invert_m4_m4(inv_obmat, ob->obmat);
- mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]);
+ invert_m4_m4(inv_obmat, ob->object_to_world);
+ mul_v3_m4v3(diff, inv_obmat, ob_center->object_to_world[3]);
negate_v3(diff);
do_diff = true;
@@ -383,8 +383,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
/* Get target's center coordinates in ob local coordinates. */
float mat[4][4];
- invert_m4_m4(mat, ob->obmat);
- mul_m4_m4m4(mat, mat, ob_target->obmat);
+ invert_m4_m4(mat, ob->object_to_world);
+ mul_m4_m4m4(mat, mat, ob_target->object_to_world);
copy_v3_v3(target_co, mat[3]);
if (use_parallel_normals) {
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index aab48101351..f65f8bc4fb3 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -273,7 +273,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
break;
case eParticleInstanceSpace_Local:
/* get particle states in the particle object's local space */
- invert_m4_m4(spacemat, pimd->ob->obmat);
+ invert_m4_m4(spacemat, pimd->ob->object_to_world);
break;
default:
/* should not happen */
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 91f8947bbc3..afd7f5a2e48 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -274,8 +274,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
if (ob_axis != NULL) {
/* Calculate the matrix relative to the axis object. */
- invert_m4_m4(mtx_tmp_a, ctx->object->obmat);
- copy_m4_m4(mtx_tx_inv, ob_axis->obmat);
+ invert_m4_m4(mtx_tmp_a, ctx->object->object_to_world);
+ copy_m4_m4(mtx_tx_inv, ob_axis->object_to_world);
mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);
/* Calculate the axis vector. */
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index c5e117635b5..a34d66f394b 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -154,7 +154,7 @@ static void deformVerts(ModifierData *md,
MVert *verts = BKE_mesh_verts_for_write(surmd->mesh);
for (i = 0, x = surmd->x, v = surmd->v; i < mesh_verts_num; i++, x++, v++) {
float *vec = verts[i].co;
- mul_m4_v3(ctx->object->obmat, vec);
+ mul_m4_v3(ctx->object->object_to_world, vec);
if (init) {
v->co[0] = v->co[1] = v->co[2] = 0.0f;
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 53bfdc35b31..6a9321a78a2 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -1466,8 +1466,8 @@ static void surfacedeformModifier_do(ModifierData *md,
ob, md);
float tmp_mat[4][4];
- invert_m4_m4(tmp_mat, ob->obmat);
- mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->obmat);
+ invert_m4_m4(tmp_mat, ob->object_to_world);
+ mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->object_to_world);
/* Avoid converting edit-mesh data, binding is an exception. */
BKE_mesh_wrapper_ensure_mdata(target);
diff --git a/source/blender/modifiers/intern/MOD_util.cc b/source/blender/modifiers/intern/MOD_util.cc
index 589a3d28ad9..a94fc6732a0 100644
--- a/source/blender/modifiers/intern/MOD_util.cc
+++ b/source/blender/modifiers/intern/MOD_util.cc
@@ -75,15 +75,15 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
bPoseChannel *pchan = BKE_pose_channel_find_name(map_object->pose, dmd->map_bone);
if (pchan) {
float mat_bone_world[4][4];
- mul_m4_m4m4(mat_bone_world, map_object->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat_bone_world, map_object->object_to_world, pchan->pose_mat);
invert_m4_m4(mapref_imat, mat_bone_world);
}
else {
- invert_m4_m4(mapref_imat, map_object->obmat);
+ invert_m4_m4(mapref_imat, map_object->object_to_world);
}
}
else {
- invert_m4_m4(mapref_imat, map_object->obmat);
+ invert_m4_m4(mapref_imat, map_object->object_to_world);
}
}
else { /* if there is no map object, default to local */
@@ -138,10 +138,10 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
copy_v3_v3(*r_texco, cos != nullptr ? *cos : mv->co);
break;
case MOD_DISP_MAP_GLOBAL:
- mul_v3_m4v3(*r_texco, ob->obmat, cos != nullptr ? *cos : mv->co);
+ mul_v3_m4v3(*r_texco, ob->object_to_world, cos != nullptr ? *cos : mv->co);
break;
case MOD_DISP_MAP_OBJECT:
- mul_v3_m4v3(*r_texco, ob->obmat, cos != nullptr ? *cos : mv->co);
+ mul_v3_m4v3(*r_texco, ob->object_to_world, cos != nullptr ? *cos : mv->co);
mul_m4_v3(mapref_imat, *r_texco);
break;
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.cc b/source/blender/modifiers/intern/MOD_uvproject.cc
index c07b2059b5b..895572d9477 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.cc
+++ b/source/blender/modifiers/intern/MOD_uvproject.cc
@@ -132,7 +132,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
float offsetmat[4][4];
Camera *cam = nullptr;
/* calculate projection matrix */
- invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat);
+ invert_m4_m4(projectors[i].projmat, projectors[i].ob->object_to_world);
projectors[i].uci = nullptr;
@@ -178,7 +178,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
projectors[i].normal[0] = 0;
projectors[i].normal[1] = 0;
projectors[i].normal[2] = 1;
- mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
+ mul_mat3_m4_v3(projectors[i].ob->object_to_world, projectors[i].normal);
}
polys_num = mesh->totpoly;
@@ -192,7 +192,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
/* Convert coords to world-space. */
for (i = 0, co = coords; i < verts_num; i++, co++) {
- mul_m4_v3(ob->obmat, *co);
+ mul_m4_v3(ob->object_to_world, *co);
}
/* if only one projector, project coords to UVs */
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.cc b/source/blender/modifiers/intern/MOD_uvwarp.cc
index 4ec273bcbc6..a96b28b4e2e 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.cc
+++ b/source/blender/modifiers/intern/MOD_uvwarp.cc
@@ -72,10 +72,10 @@ static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonen
{
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
if (pchan) {
- mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat);
}
else {
- copy_m4_m4(mat, ob->obmat);
+ copy_m4_m4(mat, ob->object_to_world);
}
}
diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc
index e66793d7cce..fbd5f27f69a 100644
--- a/source/blender/modifiers/intern/MOD_volume_displace.cc
+++ b/source/blender/modifiers/intern/MOD_volume_displace.cc
@@ -254,14 +254,14 @@ struct DisplaceGridOp {
return index_to_object;
}
case MOD_VOLUME_DISPLACE_MAP_GLOBAL: {
- const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->obmat);
+ const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->object_to_world);
return index_to_object * object_to_world;
}
case MOD_VOLUME_DISPLACE_MAP_OBJECT: {
if (vdmd.texture_map_object == nullptr) {
return index_to_object;
}
- const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->obmat);
+ const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->object_to_world);
const openvdb::Mat4s world_to_texture = matrix_to_openvdb(vdmd.texture_map_object->imat);
return index_to_object * object_to_world * world_to_texture;
}
diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc
index 35fd5a4af42..b4ac23b5c61 100644
--- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc
+++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc
@@ -157,7 +157,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
volume_grid);
openvdb::math::Transform::Ptr transform = local_grid->transform().copy();
- transform->postMult(openvdb::Mat4d((float *)vmmd->object->obmat));
+ transform->postMult(openvdb::Mat4d((float *)vmmd->object->object_to_world));
openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->imat);
/* `imat` had floating point issues and wasn't affine. */
imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1));
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 3fafbd97fee..791eed28a71 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -93,11 +93,11 @@ static void matrix_from_obj_pchan(float mat[4][4],
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
if (pchan) {
float mat_bone_world[4][4];
- mul_m4_m4m4(mat_bone_world, ob->obmat, pchan->pose_mat);
+ mul_m4_m4m4(mat_bone_world, ob->object_to_world, pchan->pose_mat);
mul_m4_m4m4(mat, obinv, mat_bone_world);
}
else {
- mul_m4_m4m4(mat, obinv, ob->obmat);
+ mul_m4_m4m4(mat, obinv, ob->object_to_world);
}
}
@@ -215,7 +215,7 @@ static void warpModifier_do(WarpModifierData *wmd,
BKE_curvemapping_init(wmd->curfalloff);
}
- invert_m4_m4(obinv, ob->obmat);
+ invert_m4_m4(obinv, ob->object_to_world);
/* Checks that the objects/bones are available. */
matrix_from_obj_pchan(mat_from, obinv, wmd->object_from, wmd->bone_from);
diff --git a/source/blender/modifiers/intern/MOD_wave.cc b/source/blender/modifiers/intern/MOD_wave.cc
index 647e0324707..1489927ba34 100644
--- a/source/blender/modifiers/intern/MOD_wave.cc
+++ b/source/blender/modifiers/intern/MOD_wave.cc
@@ -152,8 +152,8 @@ static void waveModifier_do(WaveModifierData *md,
if (wmd->objectcenter != nullptr) {
float mat[4][4];
/* get the control object's location in local coordinates */
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
+ mul_m4_m4m4(mat, ob->imat, wmd->objectcenter->object_to_world);
wmd->startx = mat[3][0];
wmd->starty = mat[3][1];
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.cc b/source/blender/modifiers/intern/MOD_weightvgproximity.cc
index 93052f4215d..e4e03a2cbc9 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.cc
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.cc
@@ -223,9 +223,9 @@ static void get_vert2ob_distance(
while (i-- > 0) {
/* Get world-coordinates of the vertex (constraints and anim included). */
- mul_v3_m4v3(v_wco, ob->obmat, v_cos[i]);
+ mul_v3_m4v3(v_wco, ob->object_to_world, v_cos[i]);
/* Return distance between both coordinates. */
- dist[i] = len_v3v3(v_wco, obr->obmat[3]);
+ dist[i] = len_v3v3(v_wco, obr->object_to_world[3]);
}
}
@@ -235,7 +235,7 @@ static void get_vert2ob_distance(
*/
static float get_ob2ob_distance(const Object *ob, const Object *obr)
{
- return len_v3v3(ob->obmat[3], obr->obmat[3]);
+ return len_v3v3(ob->object_to_world[3], obr->object_to_world[3]);
}
/**
diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.cc b/source/blender/nodes/composite/nodes/node_composite_normalize.cc
index 21765825468..34fd63e5805 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normalize.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_normalize.cc
@@ -5,7 +5,9 @@
* \ingroup cmpnodes
*/
+#include "COM_algorithm_parallel_reduction.hh"
#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
#include "node_composite_util.hh"
@@ -15,19 +17,60 @@ namespace blender::nodes::node_composite_normalize_cc {
static void cmp_node_normalize_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Float>(N_("Value")).default_value(1.0f).min(0.0f).max(1.0f);
+ b.add_input<decl::Float>(N_("Value"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .compositor_domain_priority(0);
b.add_output<decl::Float>(N_("Value"));
}
using namespace blender::realtime_compositor;
class NormalizeOperation : public NodeOperation {
+ private:
+ /* The normalize operation is specifically designed to normalize Z Depth information. But since Z
+ * Depth can contain near infinite values, normalization is limited to [-range_, range], meaning
+ * that values outside of that range will be ignored when computing the maximum and minimum for
+ * normalization and will eventually be 0 or 1 if they are less than or larger than the range
+ * respectively. */
+ constexpr static float range_ = 10000.0f;
+
public:
using NodeOperation::NodeOperation;
void execute() override
{
- get_input("Value").pass_through(get_result("Value"));
+ Result &input_image = get_input("Value");
+ Result &output_image = get_result("Value");
+ if (input_image.is_single_value()) {
+ input_image.pass_through(output_image);
+ return;
+ }
+
+ const float maximum = maximum_float_in_range(
+ context(), input_image.texture(), -range_, range_);
+ const float minimum = minimum_float_in_range(
+ context(), input_image.texture(), -range_, range_);
+ const float scale = (maximum != minimum) ? (1.0f / (maximum - minimum)) : 0.0f;
+
+ GPUShader *shader = shader_manager().get("compositor_normalize");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "minimum", minimum);
+ GPU_shader_uniform_1f(shader, "scale", scale);
+
+ input_image.bind_as_texture(shader, "input_tx");
+
+ const Domain domain = compute_domain();
+ output_image.allocate_texture(domain);
+ output_image.bind_as_image(shader, "output_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ GPU_shader_unbind();
+ output_image.unbind_as_image();
+ input_image.unbind_as_texture();
}
};
diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc
index 2e06ad99df1..d26a01bb3c9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc
@@ -5,20 +5,35 @@
* \ingroup cmpnodes
*/
+#include <cmath>
+
+#include "BLI_assert.h"
+#include "BLI_math_base.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
+
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_resources.h"
+#include "IMB_colormanagement.h"
+
+#include "COM_algorithm_parallel_reduction.hh"
#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
#include "node_composite_util.hh"
namespace blender::nodes::node_composite_tonemap_cc {
+NODE_STORAGE_FUNCS(NodeTonemap)
+
static void cmp_node_tonemap_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
}
@@ -68,7 +83,236 @@ class ToneMapOperation : public NodeOperation {
void execute() override
{
- get_input("Image").pass_through(get_result("Image"));
+ Result &input_image = get_input("Image");
+ Result &output_image = get_result("Image");
+ if (input_image.is_single_value()) {
+ input_image.pass_through(output_image);
+ return;
+ }
+
+ switch (get_type()) {
+ case CMP_NODE_TONE_MAP_SIMPLE:
+ execute_simple();
+ return;
+ case CMP_NODE_TONE_MAP_PHOTORECEPTOR:
+ execute_photoreceptor();
+ return;
+ default:
+ BLI_assert_unreachable();
+ return;
+ }
+ }
+
+ /* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction
+ * for digital images." Proceedings of the 29th annual conference on Computer graphics and
+ * interactive techniques. 2002. */
+ void execute_simple()
+ {
+ const float luminance_scale = compute_luminance_scale();
+ const float luminance_scale_blend_factor = compute_luminance_scale_blend_factor();
+ const float gamma = node_storage(bnode()).gamma;
+ const float inverse_gamma = gamma != 0.0f ? 1.0f / gamma : 0.0f;
+
+ GPUShader *shader = shader_manager().get("compositor_tone_map_simple");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "luminance_scale", luminance_scale);
+ GPU_shader_uniform_1f(shader, "luminance_scale_blend_factor", luminance_scale_blend_factor);
+ GPU_shader_uniform_1f(shader, "inverse_gamma", inverse_gamma);
+
+ const Result &input_image = get_input("Image");
+ input_image.bind_as_texture(shader, "input_tx");
+
+ const Domain domain = compute_domain();
+ Result &output_image = get_result("Image");
+ output_image.allocate_texture(domain);
+ output_image.bind_as_image(shader, "output_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ GPU_shader_unbind();
+ output_image.unbind_as_image();
+ input_image.unbind_as_texture();
+ }
+
+ /* Computes the scaling factor in equation (2) from Reinhard's 2002 paper. */
+ float compute_luminance_scale()
+ {
+ const float geometric_mean = compute_geometric_mean_of_luminance();
+ return geometric_mean != 0.0 ? node_storage(bnode()).key / geometric_mean : 0.0f;
+ }
+
+ /* Computes equation (1) from Reinhard's 2002 paper. However, note that the equation in the paper
+ * is most likely wrong, and the intention is actually to compute the geometric mean through a
+ * logscale arithmetic mean, that is, the division should happen inside the exponential function,
+ * not outside of it. That's because the sum of the log luminance will be a very large negative
+ * number, whose exponential will almost always be zero, which is unexpected and useless. */
+ float compute_geometric_mean_of_luminance()
+ {
+ return std::exp(compute_average_log_luminance());
+ }
+
+ /* Equation (3) from Reinhard's 2002 paper blends between high luminance scaling for high
+ * luminance values and low luminance scaling for low luminance values. This is done by adding 1
+ * to the denominator, since for low luminance values, the denominator will be close to 1 and for
+ * high luminance values, the 1 in the denominator will be relatively insignificant. But the
+ * response of such function is not always ideal, so in this implementation, the 1 was exposed as
+ * a parameter to the user for more flexibility. */
+ float compute_luminance_scale_blend_factor()
+ {
+ return node_storage(bnode()).offset;
+ }
+
+ /* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and
+ * (7) from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor
+ * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */
+ void execute_photoreceptor()
+ {
+ const float4 global_adaptation_level = compute_global_adaptation_level();
+ const float contrast = compute_contrast();
+ const float intensity = compute_intensity();
+ const float chromatic_adaptation = get_chromatic_adaptation();
+ const float light_adaptation = get_light_adaptation();
+
+ GPUShader *shader = shader_manager().get("compositor_tone_map_photoreceptor");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_4fv(shader, "global_adaptation_level", global_adaptation_level);
+ GPU_shader_uniform_1f(shader, "contrast", contrast);
+ GPU_shader_uniform_1f(shader, "intensity", intensity);
+ GPU_shader_uniform_1f(shader, "chromatic_adaptation", chromatic_adaptation);
+ GPU_shader_uniform_1f(shader, "light_adaptation", light_adaptation);
+
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ const Result &input_image = get_input("Image");
+ input_image.bind_as_texture(shader, "input_tx");
+
+ const Domain domain = compute_domain();
+ Result &output_image = get_result("Image");
+ output_image.allocate_texture(domain);
+ output_image.bind_as_image(shader, "output_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ GPU_shader_unbind();
+ output_image.unbind_as_image();
+ input_image.unbind_as_texture();
+ }
+
+ /* Computes the global adaptation level from the trilinear interpolation equations constructed
+ * from equations (6) and (7) in Reinhard's 2005 paper. */
+ float4 compute_global_adaptation_level()
+ {
+ const float4 average_color = compute_average_color();
+ const float average_luminance = compute_average_luminance();
+ const float chromatic_adaptation = get_chromatic_adaptation();
+ return math::interpolate(float4(average_luminance), average_color, chromatic_adaptation);
+ }
+
+ float4 compute_average_color()
+ {
+ /* The average color will reduce to zero if chromatic adaptation is zero, so just return zero
+ * in this case to avoid needlessly computing the average. See the trilinear interpolation
+ * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */
+ if (get_chromatic_adaptation() == 0.0f) {
+ return float4(0.0f);
+ }
+
+ const Result &input = get_input("Image");
+ return sum_color(context(), input.texture()) / (input.domain().size.x * input.domain().size.y);
+ }
+
+ float compute_average_luminance()
+ {
+ /* The average luminance will reduce to zero if chromatic adaptation is one, so just return
+ * zero in this case to avoid needlessly computing the average. See the trilinear interpolation
+ * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */
+ if (get_chromatic_adaptation() == 1.0f) {
+ return 0.0f;
+ }
+
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const Result &input = get_input("Image");
+ float sum = sum_luminance(context(), input.texture(), luminance_coefficients);
+ return sum / (input.domain().size.x * input.domain().size.y);
+ }
+
+ /* Computes equation (5) from Reinhard's 2005 paper. */
+ float compute_intensity()
+ {
+ return std::exp(-node_storage(bnode()).f);
+ }
+
+ /* If the contrast is not zero, return it, otherwise, a zero contrast denote automatic derivation
+ * of the contrast value based on equations (2) and (4) from Reinhard's 2005 paper. */
+ float compute_contrast()
+ {
+ if (node_storage(bnode()).m != 0.0f) {
+ return node_storage(bnode()).m;
+ }
+
+ const float log_maximum_luminance = compute_log_maximum_luminance();
+ const float log_minimum_luminance = compute_log_minimum_luminance();
+
+ /* This is merely to guard against zero division later. */
+ if (log_maximum_luminance == log_minimum_luminance) {
+ return 1.0f;
+ }
+
+ const float average_log_luminance = compute_average_log_luminance();
+ const float dynamic_range = log_maximum_luminance - log_minimum_luminance;
+ const float luminance_key = (log_maximum_luminance - average_log_luminance) / (dynamic_range);
+
+ return 0.3f + 0.7f * std::pow(luminance_key, 1.4f);
+ }
+
+ float compute_average_log_luminance()
+ {
+ const Result &input_image = get_input("Image");
+
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const float sum_of_log_luminance = sum_log_luminance(
+ context(), input_image.texture(), luminance_coefficients);
+
+ return sum_of_log_luminance / (input_image.domain().size.x * input_image.domain().size.y);
+ }
+
+ float compute_log_maximum_luminance()
+ {
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const float maximum = maximum_luminance(
+ context(), get_input("Image").texture(), luminance_coefficients);
+ return std::log(math::max(maximum, 1e-5f));
+ }
+
+ float compute_log_minimum_luminance()
+ {
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const float minimum = minimum_luminance(
+ context(), get_input("Image").texture(), luminance_coefficients);
+ return std::log(math::max(minimum, 1e-5f));
+ }
+
+ float get_chromatic_adaptation()
+ {
+ return node_storage(bnode()).c;
+ }
+
+ float get_light_adaptation()
+ {
+ return node_storage(bnode()).a;
+ }
+
+ CMPNodeToneMapType get_type()
+ {
+ return static_cast<CMPNodeToneMapType>(node_storage(bnode()).type);
}
};
diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
index df677e1c399..51393ed8709 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc
@@ -112,7 +112,7 @@ static void node_geo_exec(GeoNodeExecParams params)
else {
sub_v3_v3(transform.values[3], collection->instance_offset);
}
- mul_m4_m4_post(transform.values, child_object->obmat);
+ mul_m4_m4_post(transform.values, child_object->object_to_world);
}
entries.append({handle, &(child_object->id.name[2]), transform});
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc
index 0932624bdc3..dabd2a1a9f2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc
@@ -310,7 +310,8 @@ static void node_geo_exec(GeoNodeExecParams params)
ATTR_DOMAIN_CORNER);
const VArraySpan<float3> rest_positions = mesh_attributes_eval.lookup<float3>(rest_position_name,
ATTR_DOMAIN_POINT);
- const Span<float2> surface_uv_coords = curves.surface_uv_coords();
+ const VArraySpan<float2> surface_uv_coords = curves.attributes().lookup_or_default(
+ "surface_uv_coordinate", ATTR_DOMAIN_CURVE, float2(0));
const Span<MLoopTri> looptris_orig = surface_mesh_orig->looptris();
const Span<MLoopTri> looptris_eval = surface_mesh_eval->looptris();
@@ -379,7 +380,8 @@ static void node_geo_exec(GeoNodeExecParams params)
invalid_uv_count);
/* Then also deform edit curve information for use in sculpt mode. */
const CurvesGeometry &curves_orig = CurvesGeometry::wrap(edit_hints->curves_id_orig.geometry);
- const Span<float2> surface_uv_coords_orig = curves_orig.surface_uv_coords();
+ const VArraySpan<float2> surface_uv_coords_orig = curves_orig.attributes().lookup_or_default(
+ "surface_uv_coordinate", ATTR_DOMAIN_CURVE, float2(0));
if (!surface_uv_coords_orig.is_empty()) {
deform_curves(curves_orig,
*surface_mesh_orig,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index a433a0df9b0..3e48a9fd923 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -4,6 +4,7 @@
#include "UI_resources.h"
#include "BLI_array.hh"
+#include "BLI_array_utils.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -23,15 +24,9 @@ namespace blender::nodes::node_geo_delete_geometry_cc {
using blender::bke::CustomDataAttributes;
template<typename T>
-static void copy_data_based_on_mask(Span<T> data, MutableSpan<T> r_data, IndexMask mask)
-{
- for (const int i_out : mask.index_range()) {
- r_data[i_out] = data[mask[i_out]];
- }
-}
-
-template<typename T>
-static void copy_data_based_on_map(Span<T> src, MutableSpan<T> dst, Span<int> index_map)
+static void copy_data_based_on_map(const Span<T> src,
+ const Span<int> index_map,
+ MutableSpan<T> dst)
{
for (const int i_src : index_map.index_range()) {
const int i_dst = index_map[i_src];
@@ -55,26 +50,17 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
if (!attribute) {
continue;
}
-
/* Only copy if it is on a domain we want. */
if (!domains.contains(attribute.domain)) {
continue;
}
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
-
GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, attribute.domain, data_type);
-
if (!result_attribute) {
continue;
}
-
- attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
- using T = decltype(dummy);
- VArraySpan<T> span{attribute.varray.typed<T>()};
- MutableSpan<T> out_span = result_attribute.span.typed<T>();
- out_span.copy_from(span);
- });
+ attribute.varray.materialize(result_attribute.span.data());
result_attribute.finish();
}
}
@@ -95,26 +81,19 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
if (!attribute) {
continue;
}
-
/* Only copy if it is on a domain we want. */
if (domain != attribute.domain) {
continue;
}
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
-
GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, attribute.domain, data_type);
-
if (!result_attribute) {
continue;
}
- attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
- using T = decltype(dummy);
- VArraySpan<T> span{attribute.varray.typed<T>()};
- MutableSpan<T> out_span = result_attribute.span.typed<T>();
- copy_data_based_on_mask(span, out_span, mask);
- });
+ array_utils::gather(attribute.varray, mask, result_attribute.span);
+
result_attribute.finish();
}
}
@@ -131,16 +110,13 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind
if (!attribute) {
continue;
}
-
/* Only copy if it is on a domain we want. */
if (domain != attribute.domain) {
continue;
}
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
-
GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, attribute.domain, data_type);
-
if (!result_attribute) {
continue;
}
@@ -149,7 +125,7 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind
using T = decltype(dummy);
VArraySpan<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.span.typed<T>();
- copy_data_based_on_map(span, out_span, index_map);
+ copy_data_based_on_map(span, index_map, out_span);
});
result_attribute.finish();
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc
index 091337c28cf..95173bd23a5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc
@@ -15,6 +15,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "DEG_depsgraph_query.h"
+
#include "node_geometry_util.hh"
namespace blender::nodes {
@@ -208,6 +210,7 @@ static void geo_node_distribute_points_in_volume_exec(GeoNodeExecParams params)
}
const VolumeComponent *component = geometry_set.get_component_for_read<VolumeComponent>();
const Volume *volume = component->get_for_read();
+ BKE_volume_load(volume, DEG_get_bmain(params.depsgraph()));
Vector<float3> positions;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
index 84e63845b84..9b1c13bf563 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_task.hh"
#include "DNA_mesh_types.h"
@@ -105,18 +106,6 @@ static void copy_data_based_on_pairs(Span<T> data,
}
}
-/* Copy using the map. */
-template<typename T>
-static void copy_data_based_on_new_to_old_map(Span<T> data,
- MutableSpan<T> r_data,
- const Span<int> new_to_old_map)
-{
- for (const int i : r_data.index_range()) {
- const int old_i = new_to_old_map[i];
- r_data[i] = data[old_i];
- }
-}
-
/**
* Transfers the attributes from the original mesh to the new mesh using the following logic:
* - If the attribute was on the face domain it is now on the point domain, and this is true
@@ -168,7 +157,6 @@ static void transfer_attributes(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
-
if (!dst_attribute) {
continue;
}
@@ -177,20 +165,24 @@ static void transfer_attributes(
using T = decltype(dummy);
VArraySpan<T> span{src_attribute.varray.typed<T>()};
MutableSpan<T> dst_span = dst_attribute.span.typed<T>();
- if (src_attribute.domain == ATTR_DOMAIN_FACE) {
- dst_span.take_front(span.size()).copy_from(span);
- if (keep_boundaries) {
- copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map);
- }
- }
- else if (src_attribute.domain == ATTR_DOMAIN_POINT) {
- copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries);
- }
- else if (src_attribute.domain == ATTR_DOMAIN_EDGE) {
- copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_edges_map);
- }
- else {
- copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_face_corners_map);
+ switch (src_attribute.domain) {
+ case ATTR_DOMAIN_POINT:
+ copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries);
+ break;
+ case ATTR_DOMAIN_EDGE:
+ array_utils::gather(span, new_to_old_edges_map, dst_span);
+ break;
+ case ATTR_DOMAIN_FACE:
+ dst_span.take_front(span.size()).copy_from(span);
+ if (keep_boundaries) {
+ copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map);
+ }
+ break;
+ case ATTR_DOMAIN_CORNER:
+ array_utils::gather(span, new_to_old_face_corners_map, dst_span);
+ break;
+ default:
+ BLI_assert_unreachable();
}
});
dst_attribute.finish();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
index 70583625a7a..486f900aca5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_map.hh"
#include "BLI_noise.hh"
#include "BLI_span.hh"
@@ -105,16 +106,6 @@ static void threaded_slice_fill(Span<int> offsets,
});
}
-template<typename T>
-static void threaded_mapped_copy(const Span<int> mapping, const Span<T> src, MutableSpan<T> dst)
-{
- threading::parallel_for(mapping.index_range(), 512, [&](IndexRange range) {
- for (const int i : range) {
- dst[i] = src[mapping[i]];
- }
- });
-}
-
static void copy_hashed_ids(const Span<int> src, const int hash, MutableSpan<int> dst)
{
for (const int i : src.index_range()) {
@@ -440,17 +431,17 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set,
MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (out_domain) {
- case ATTR_DOMAIN_FACE:
- threaded_slice_fill<T>(offsets, selection, src, dst);
+ case ATTR_DOMAIN_POINT:
+ array_utils::gather(src, vert_mapping, dst);
break;
case ATTR_DOMAIN_EDGE:
- threaded_mapped_copy<T>(edge_mapping, src, dst);
+ array_utils::gather(src, edge_mapping, dst);
break;
- case ATTR_DOMAIN_POINT:
- threaded_mapped_copy<T>(vert_mapping, src, dst);
+ case ATTR_DOMAIN_FACE:
+ threaded_slice_fill<T>(offsets, selection, src, dst);
break;
case ATTR_DOMAIN_CORNER:
- threaded_mapped_copy<T>(loop_mapping, src, dst);
+ array_utils::gather(src, loop_mapping, dst);
break;
default:
break;
@@ -653,7 +644,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set,
threaded_slice_fill<T>(offsets, selection, src, dst);
break;
case ATTR_DOMAIN_POINT:
- threaded_mapped_copy<T>(point_mapping, src, dst);
+ array_utils::gather(src, point_mapping, dst);
break;
default:
break;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index 1d8c9d6312c..151ba3e59cc 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_disjoint_set.hh"
#include "BLI_task.hh"
#include "BLI_vector_set.hh"
@@ -175,24 +176,6 @@ static MPoly new_poly(const int loopstart, const int totloop)
return poly;
}
-template<typename T> void copy_with_indices(MutableSpan<T> dst, Span<T> src, Span<int> indices)
-{
- BLI_assert(dst.size() == indices.size());
- for (const int i : dst.index_range()) {
- dst[i] = src[indices[i]];
- }
-}
-
-template<typename T> void copy_with_mask(MutableSpan<T> dst, Span<T> src, IndexMask mask)
-{
- BLI_assert(dst.size() == mask.size());
- threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) {
- for (const int i : range) {
- dst[i] = src[mask[i]];
- }
- });
-}
-
/**
* \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every
* result point.
@@ -260,28 +243,29 @@ static void extrude_mesh_vertices(Mesh &mesh,
if (!ELEM(meta_data.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE)) {
return true;
}
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
id, meta_data.domain, meta_data.data_type);
- attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- MutableSpan<T> data = attribute.span.typed<T>();
- switch (attribute.domain) {
- case ATTR_DOMAIN_POINT: {
- /* New vertices copy the attribute values from their source vertex. */
- copy_with_mask(data.slice(new_vert_range), data.as_span(), selection);
- break;
- }
- case ATTR_DOMAIN_EDGE: {
+ switch (attribute.domain) {
+ case ATTR_DOMAIN_POINT:
+ /* New vertices copy the attribute values from their source vertex. */
+ array_utils::gather(attribute.span, selection, attribute.span.slice(new_vert_range));
+ break;
+ case ATTR_DOMAIN_EDGE:
+ attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
+ using T = decltype(dummy);
+ MutableSpan<T> data = attribute.span.typed<T>();
/* New edge values are mixed from of all the edges connected to the source vertex. */
copy_with_mixing(data.slice(new_edge_range), data.as_span(), [&](const int i) {
return vert_to_edge_map[selection[i]].as_span();
});
- break;
- }
- default:
- BLI_assert_unreachable();
- }
- });
+ });
+ break;
+ default:
+ BLI_assert_unreachable();
+ }
attribute.finish();
return true;
@@ -506,6 +490,9 @@ static void extrude_mesh_edges(Mesh &mesh,
MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
id, meta_data.domain, meta_data.data_type);
if (!attribute) {
@@ -518,13 +505,14 @@ static void extrude_mesh_edges(Mesh &mesh,
switch (attribute.domain) {
case ATTR_DOMAIN_POINT: {
/* New vertices copy the attribute values from their source vertex. */
- copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices);
+ array_utils::gather(
+ data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range));
break;
}
case ATTR_DOMAIN_EDGE: {
/* Edges parallel to original edges copy the edge attributes from the original edges. */
MutableSpan<T> duplicate_data = data.slice(duplicate_edge_range);
- copy_with_mask(duplicate_data, data.as_span(), edge_selection);
+ array_utils::gather(data.as_span(), edge_selection, duplicate_data);
/* Edges connected to original vertices mix values of selected connected edges. */
MutableSpan<T> connect_data = data.slice(connect_edge_range);
@@ -889,6 +877,9 @@ static void extrude_mesh_face_regions(Mesh &mesh,
MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
id, meta_data.domain, meta_data.data_type);
if (!attribute) {
@@ -901,17 +892,18 @@ static void extrude_mesh_face_regions(Mesh &mesh,
switch (attribute.domain) {
case ATTR_DOMAIN_POINT: {
/* New vertices copy the attributes from their original vertices. */
- copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices);
+ array_utils::gather(
+ data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range));
break;
}
case ATTR_DOMAIN_EDGE: {
/* Edges parallel to original edges copy the edge attributes from the original edges. */
MutableSpan<T> boundary_data = data.slice(boundary_edge_range);
- copy_with_indices(boundary_data, data.as_span(), boundary_edge_indices);
+ array_utils::gather(data.as_span(), boundary_edge_indices.as_span(), boundary_data);
/* Edges inside of face regions also just duplicate their source data. */
MutableSpan<T> new_inner_data = data.slice(new_inner_edge_range);
- copy_with_indices(new_inner_data, data.as_span(), new_inner_edge_indices);
+ array_utils::gather(data.as_span(), new_inner_edge_indices.as_span(), new_inner_data);
/* Edges connected to original vertices mix values of selected connected edges. */
MutableSpan<T> connect_data = data.slice(connect_edge_range);
@@ -923,8 +915,8 @@ static void extrude_mesh_face_regions(Mesh &mesh,
case ATTR_DOMAIN_FACE: {
/* New faces on the side of extrusions get the values from the corresponding selected
* face. */
- copy_with_indices(
- data.slice(side_poly_range), data.as_span(), edge_extruded_face_indices);
+ array_utils::gather(
+ data.as_span(), edge_extruded_face_indices.as_span(), data.slice(side_poly_range));
break;
}
case ATTR_DOMAIN_CORNER: {
@@ -1143,6 +1135,9 @@ static void extrude_individual_mesh_faces(Mesh &mesh,
MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
id, meta_data.domain, meta_data.data_type);
if (!attribute) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc
index 613425716d4..95a0013a9e1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc
@@ -47,6 +47,9 @@ static void mesh_flip_faces(Mesh &mesh, const Field<bool> &selection_field)
MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all(
[&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
if (meta_data.domain == ATTR_DOMAIN_CORNER) {
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
attribute_id, ATTR_DOMAIN_CORNER, meta_data.data_type);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
index affeb43e33b..64546684186 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
@@ -2,6 +2,7 @@
#include "DNA_collection_types.h"
+#include "BLI_array_utils.hh"
#include "BLI_hash.h"
#include "BLI_task.hh"
@@ -172,18 +173,7 @@ static void add_instances_from_component(
dst_attribute_opt = instance_attributes.get_for_write(attribute_id);
}
BLI_assert(dst_attribute_opt);
- const GMutableSpan dst_attribute = dst_attribute_opt->slice(start_len, select_len);
- threading::parallel_for(selection.index_range(), 1024, [&](IndexRange selection_range) {
- attribute_math::convert_to_static_type(attribute_kind.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- VArray<T> src = src_attribute.typed<T>();
- MutableSpan<T> dst = dst_attribute.typed<T>();
- for (const int range_i : selection_range) {
- const int i = selection[range_i];
- dst[range_i] = src[i];
- }
- });
- });
+ array_utils::gather(src_attribute, selection, dst_attribute_opt->slice(start_len, select_len));
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
index ec9b9faf4ec..ea2646a9786 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -31,6 +31,9 @@ static Map<AttributeIDRef, AttributeMetaData> get_final_attribute_info(
if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) {
return true;
}
+ if (meta_data.data_type == CD_PROP_STRING) {
+ return true;
+ }
info.add_or_modify(
attribute_id,
[&](AttributeMetaData *meta_data_final) { *meta_data_final = meta_data; },
diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
index bf064c6fcbe..dc35607fe45 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
@@ -45,7 +45,7 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
- const float4x4 &object_matrix = object->obmat;
+ const float4x4 &object_matrix = object->object_to_world;
const float4x4 transform = float4x4(self_object->imat) * object_matrix;
if (transform_space_relative) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc
index 44851a0ade5..95bf7199d63 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc
@@ -240,7 +240,11 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_default_remaining_outputs();
return;
}
- if (mesh->totpoly == 0 && mesh->totvert != 0) {
+ if (mesh->totvert == 0) {
+ params.set_default_remaining_outputs();
+ return;
+ }
+ if (mesh->totpoly == 0) {
params.error_message_add(NodeWarningType::Error, TIP_("The source mesh must have faces"));
params.set_default_remaining_outputs();
return;
diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
index 5bf245f1832..197f0997160 100644
--- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
+++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
@@ -604,6 +604,7 @@ class LazyFunctionForGroupNode : public LazyFunction {
private:
const bNode &group_node_;
bool has_many_nodes_ = false;
+ bool use_fallback_outputs_ = false;
std::optional<GeometryNodesLazyFunctionLogger> lf_logger_;
std::optional<GeometryNodesLazyFunctionSideEffectProvider> lf_side_effect_provider_;
std::optional<lf::GraphExecutor> graph_executor_;
@@ -640,6 +641,9 @@ class LazyFunctionForGroupNode : public LazyFunction {
}
}
}
+ else {
+ use_fallback_outputs_ = true;
+ }
lf_logger_.emplace(lf_graph_info);
lf_side_effect_provider_.emplace();
@@ -660,6 +664,11 @@ class LazyFunctionForGroupNode : public LazyFunction {
* if every individual node is very small. */
lazy_threading::send_hint();
}
+ if (use_fallback_outputs_) {
+ /* The node group itself does not have an output node, so use default values as outputs.
+ * The group should still be executed in case it has side effects. */
+ params.set_default_remaining_outputs();
+ }
/* The compute context changes when entering a node group. */
bke::NodeGroupComputeContext compute_context{user_data->compute_context, group_node_.name};
diff --git a/source/blender/nodes/intern/node_exec.cc b/source/blender/nodes/intern/node_exec.cc
index 724d6f1a1e1..af783ca391f 100644
--- a/source/blender/nodes/intern/node_exec.cc
+++ b/source/blender/nodes/intern/node_exec.cc
@@ -162,7 +162,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
/* XXX could let callbacks do this for specialized data */
exec = MEM_cnew<bNodeTreeExec>("node tree execution data");
- /* backpointer to node tree */
+ /* Back-pointer to node tree. */
exec->nodetree = ntree;
/* set stack indices */
diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h
index dc07f52e23f..55bf409444e 100644
--- a/source/blender/nodes/intern/node_exec.h
+++ b/source/blender/nodes/intern/node_exec.h
@@ -27,7 +27,7 @@ struct bNodeTree;
/* Node execution data */
typedef struct bNodeExec {
- /** Backpointer to node. */
+ /** Back-pointer to node. */
struct bNode *node;
bNodeExecData data;
@@ -37,7 +37,7 @@ typedef struct bNodeExec {
/* Execution Data for each instance of node tree execution */
typedef struct bNodeTreeExec {
- struct bNodeTree *nodetree; /* backpointer to node tree */
+ struct bNodeTree *nodetree; /* Back-pointer to node tree. */
int totnodes; /* total node count */
struct bNodeExec *nodeexec; /* per-node execution data */
diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc
index 52edf68b3ff..f177fc95ef8 100644
--- a/source/blender/nodes/shader/node_shader_tree.cc
+++ b/source/blender/nodes/shader/node_shader_tree.cc
@@ -1126,7 +1126,8 @@ void ntreeShaderEndExecTree(bNodeTreeExec *exec)
bNodeTree *ntree = exec->nodetree;
ntreeShaderEndExecTree_internal(exec);
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+ /* XXX: clear node-tree back-pointer to exec data,
+ * same problem as noted in #ntreeBeginExecTree. */
ntree->execdata = nullptr;
}
}
diff --git a/source/blender/nodes/texture/CMakeLists.txt b/source/blender/nodes/texture/CMakeLists.txt
index 77db71d4b1a..2d704ac2228 100644
--- a/source/blender/nodes/texture/CMakeLists.txt
+++ b/source/blender/nodes/texture/CMakeLists.txt
@@ -2,7 +2,7 @@
set(INC
.
- ../
+ ..
../intern
../../editors/include
../../blenkernel
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 81d0b0fbc84..99146f1a25c 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -308,7 +308,8 @@ void ntreeTexEndExecTree(bNodeTreeExec *exec)
bNodeTree *ntree = exec->nodetree;
ntreeTexEndExecTree_internal(exec);
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+ /* XXX: clear node-tree back-pointer to exec data,
+ * same problem as noted in #ntreeBeginExecTree. */
ntree->execdata = NULL;
}
}
diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c
index b877e3ceb98..c6e964405fa 100644
--- a/source/blender/python/gpu/gpu_py_platform.c
+++ b/source/blender/python/gpu/gpu_py_platform.c
@@ -11,6 +11,7 @@
#include "BLI_utildefines.h"
+#include "GPU_context.h"
#include "GPU_platform.h"
#include "gpu_py_platform.h" /* Own include. */
@@ -83,6 +84,30 @@ static PyObject *pygpu_platform_device_type_get(PyObject *UNUSED(self))
return PyUnicode_FromString("UNKNOWN");
}
+PyDoc_STRVAR(pygpu_platform_backend_type_get_doc,
+ ".. function:: backend_type_get()\n"
+ "\n"
+ " Get actuve GPU backend.\n"
+ "\n"
+ " :return: Backend type ('OPENGL', 'VULKAN', 'METAL', 'NONE', 'UNKNOWN').\n"
+ " :rtype: str\n");
+static PyObject *pygpu_platform_backend_type_get(PyObject *UNUSED(self))
+{
+ switch (GPU_backend_get_type()) {
+ case GPU_BACKEND_VULKAN:
+ return PyUnicode_FromString("VULKAN");
+ case GPU_BACKEND_METAL:
+ return PyUnicode_FromString("METAL");
+ case GPU_BACKEND_NONE:
+ return PyUnicode_FromString("NONE");
+ case GPU_BACKEND_OPENGL:
+ return PyUnicode_FromString("OPENGL");
+ case GPU_BACKEND_ANY:
+ break;
+ }
+ return PyUnicode_FromString("UNKNOWN");
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -106,6 +131,10 @@ static struct PyMethodDef pygpu_platform__tp_methods[] = {
(PyCFunction)pygpu_platform_device_type_get,
METH_NOARGS,
pygpu_platform_device_type_get_doc},
+ {"backend_type_get",
+ (PyCFunction)pygpu_platform_backend_type_get,
+ METH_NOARGS,
+ pygpu_platform_backend_type_get_doc},
{NULL, NULL, 0, NULL},
};
diff --git a/source/blender/python/intern/bpy_gizmo_wrap.h b/source/blender/python/intern/bpy_gizmo_wrap.h
index 6a876747e22..7d5edebed0f 100644
--- a/source/blender/python/intern/bpy_gizmo_wrap.h
+++ b/source/blender/python/intern/bpy_gizmo_wrap.h
@@ -13,7 +13,7 @@ struct wmGizmoType;
extern "C" {
#endif
-/* exposed to rna/wm api */
+/* Exposed to RNA/WM API. */
void BPY_RNA_gizmo_wrapper(struct wmGizmoType *gzt, void *userdata);
void BPY_RNA_gizmogroup_wrapper(struct wmGizmoGroupType *gzgt, void *userdata);
diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h
index de3779332da..4b8ceba5f0c 100644
--- a/source/blender/python/intern/bpy_operator_wrap.h
+++ b/source/blender/python/intern/bpy_operator_wrap.h
@@ -12,10 +12,11 @@ struct wmOperatorType;
extern "C" {
#endif
-/* these are used for operator methods, used by bpy_operator.c */
+/** These are used for operator methods, used by `bpy_operator.c`. */
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args);
-/* exposed to rna/wm api */
+/* Exposed to RNA/WM API. */
+
/**
* Generic function used by all Python defined operators
* it's passed as an argument to #WM_operatortype_append_ptr in for operator registration.
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 0eaa5d6b6c7..02f7e16e805 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -380,10 +380,10 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr,
const short order_fallback,
PropertyRNA **r_prop_eul_order);
-/* bpyrna vector/euler/quat callbacks. */
+/* `bpyrna` vector/euler/quaternion callbacks. */
static uchar mathutils_rna_array_cb_index = -1; /* Index for our callbacks. */
-/* Subtype not used much yet. */
+/* Sub-type not used much yet. */
# define MATHUTILS_CB_SUBTYPE_EUL 0
# define MATHUTILS_CB_SUBTYPE_VEC 1
# define MATHUTILS_CB_SUBTYPE_QUAT 2
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 3a3297f27f7..3c564142160 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -40,7 +40,7 @@
*
* Any feedback is very welcome.
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
- * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space). */
+ * email: `m-mat @ math.sci.hiroshima-u.ac.jp` (remove space). */
/* Period parameters */
#define N 624
@@ -120,7 +120,7 @@ static void setRndSeed(int seed)
}
}
-/* float number in range [0, 1) using the mersenne twister rng */
+/* Float number in range [0, 1) using the mersenne twister random number generator. */
static float frand(void)
{
ulong y;
diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c
index 8fd62f7ec34..9b56e18bb26 100644
--- a/source/blender/render/intern/bake.c
+++ b/source/blender/render/intern/bake.c
@@ -967,7 +967,7 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
size_t i;
float iobmat[4][4];
- invert_m4_m4(iobmat, ob->obmat);
+ invert_m4_m4(iobmat, ob->object_to_world);
for (i = 0; i < pixels_num; i++) {
size_t offset;
diff --git a/source/blender/render/intern/engine.cc b/source/blender/render/intern/engine.cc
index 5eb4db6faa4..b8757d33580 100644
--- a/source/blender/render/intern/engine.cc
+++ b/source/blender/render/intern/engine.cc
@@ -969,6 +969,40 @@ static void engine_render_view_layer(Render *re,
engine_depsgraph_exit(engine);
}
+/* Callback function for engine_render_create_result to add all render passes to the result. */
+static void engine_render_add_result_pass_cb(void *user_data,
+ struct Scene *UNUSED(scene),
+ struct ViewLayer *view_layer,
+ const char *name,
+ int channels,
+ const char *chanid,
+ eNodeSocketDatatype UNUSED(type))
+{
+ RenderResult *rr = (RenderResult *)user_data;
+ RE_create_render_pass(rr, name, channels, chanid, view_layer->name, RR_ALL_VIEWS, false);
+}
+
+static RenderResult *engine_render_create_result(Render *re)
+{
+ RenderResult *rr = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ if (rr == nullptr) {
+ return nullptr;
+ }
+
+ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
+ RE_engine_update_render_passes(
+ re->engine, re->scene, view_layer, engine_render_add_result_pass_cb, rr);
+ }
+ FOREACH_VIEW_LAYER_TO_RENDER_END;
+
+ /* Preview does not support deferred render result allocation. */
+ if (re->r.scemode & R_BUTS_PREVIEW) {
+ render_result_passes_allocated_ensure(rr);
+ }
+
+ return rr;
+}
+
bool RE_engine_render(Render *re, bool do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
@@ -1008,6 +1042,14 @@ bool RE_engine_render(Render *re, bool do_all)
render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
}
+ /* Create engine. */
+ RenderEngine *engine = re->engine;
+
+ if (!engine) {
+ engine = RE_engine_create(type);
+ re->engine = engine;
+ }
+
/* create render result */
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
if (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW)) {
@@ -1015,7 +1057,7 @@ bool RE_engine_render(Render *re, bool do_all)
render_result_free(re->result);
}
- re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ re->result = engine_render_create_result(re);
}
BLI_rw_mutex_unlock(&re->resultmutex);
@@ -1024,6 +1066,9 @@ bool RE_engine_render(Render *re, bool do_all)
if (re->draw_lock) {
re->draw_lock(re->dlh, false);
}
+ /* Free engine. */
+ RE_engine_free(engine);
+ re->engine = nullptr;
/* Too small image is handled earlier, here it could only happen if
* there was no sufficient memory to allocate all passes.
*/
@@ -1036,14 +1081,6 @@ bool RE_engine_render(Render *re, bool do_all)
re->i.cfra = re->scene->r.cfra;
BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
- /* render */
- RenderEngine *engine = re->engine;
-
- if (!engine) {
- engine = RE_engine_create(type);
- re->engine = engine;
- }
-
engine->flag |= RE_ENGINE_RENDERING;
/* TODO: actually link to a parent which shouldn't happen */
diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc
index bd5c6a0f5c4..94f6e2f1509 100644
--- a/source/blender/render/intern/render_result.cc
+++ b/source/blender/render/intern/render_result.cc
@@ -262,7 +262,7 @@ RenderResult *render_result_new(Render *re,
render_result_views_new(rr, &re->r);
- /* check renderdata for amount of layers */
+ /* Check render-data for amount of layers. */
FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
if (layername && layername[0]) {
if (!STREQ(view_layer->name, layername)) {
@@ -290,90 +290,8 @@ RenderResult *render_result_new(Render *re,
}
}
-#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \
- do { \
- if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id, false) == nullptr) { \
- render_result_free(rr); \
- return nullptr; \
- } \
- } while (false)
-
/* A render-layer should always have a "Combined" pass. */
render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA", false);
-
- if (view_layer->passflag & SCE_PASS_Z) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
- }
- if (view_layer->passflag & SCE_PASS_VECTOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
- }
- if (view_layer->passflag & SCE_PASS_NORMAL) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
- }
- if (view_layer->passflag & SCE_PASS_POSITION) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_POSITION, view, "XYZ");
- }
- if (view_layer->passflag & SCE_PASS_UV) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
- }
- if (view_layer->passflag & SCE_PASS_EMIT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_AO) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_ENVIRONMENT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SHADOW) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_INDEXOB) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
- }
- if (view_layer->passflag & SCE_PASS_INDEXMA) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
- }
- if (view_layer->passflag & SCE_PASS_MIST) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
- }
- if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_TRANSM_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
- }
-#undef RENDER_LAYER_ADD_PASS_SAFE
}
}
FOREACH_VIEW_LAYER_TO_RENDER_END;
@@ -411,11 +329,6 @@ RenderResult *render_result_new(Render *re,
rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
- /* Preview does not support deferred render result allocation. */
- if (re->r.scemode & R_BUTS_PREVIEW) {
- render_result_passes_allocated_ensure(rr);
- }
-
return rr;
}
diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c
index 2a2b62be1f0..b285bbd1459 100644
--- a/source/blender/render/intern/texture_pointdensity.c
+++ b/source/blender/render/intern/texture_pointdensity.c
@@ -175,7 +175,7 @@ static void pointdensity_cache_psys(
sim.psmd = psys_get_modifier(ob, psys);
/* in case ob->imat isn't up-to-date */
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->imat, ob->object_to_world);
total_particles = psys->totpart + psys->totchild;
psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
@@ -399,12 +399,12 @@ static void pointdensity_cache_object(PointDensity *pd, Object *ob)
case TEX_PD_OBJECTSPACE:
break;
case TEX_PD_OBJECTLOC:
- mul_m4_v3(ob->obmat, co);
+ mul_m4_v3(ob->object_to_world, co);
sub_v3_v3(co, ob->loc);
break;
case TEX_PD_WORLDSPACE:
default:
- mul_m4_v3(ob->obmat, co);
+ mul_m4_v3(ob->object_to_world, co);
break;
}
@@ -778,7 +778,7 @@ static void particle_system_minmax(Depsgraph *depsgraph,
sim.psys = psys;
sim.psmd = psys_get_modifier(object, psys);
- invert_m4_m4(imat, object->obmat);
+ invert_m4_m4(imat, object->object_to_world);
total_particles = psys->totpart + psys->totchild;
psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
diff --git a/source/blender/sequencer/intern/disk_cache.c b/source/blender/sequencer/intern/disk_cache.c
index 1f52d2ea41b..596a28201cc 100644
--- a/source/blender/sequencer/intern/disk_cache.c
+++ b/source/blender/sequencer/intern/disk_cache.c
@@ -182,7 +182,7 @@ static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
if (is_dir && !FILENAME_IS_CURRPAR(file)) {
char subpath[FILE_MAX];
BLI_strncpy(subpath, fl->path, sizeof(subpath));
- BLI_path_slash_ensure(subpath);
+ BLI_path_slash_ensure(subpath, sizeof(sizeof(subpath)));
seq_disk_cache_get_files(disk_cache, subpath);
}
@@ -291,8 +291,8 @@ static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path,
/* Use suffix, so that the cache directory name does not conflict with the bmain's blend file. */
const char *suffix = "_seq_cache";
strncat(cache_dir, suffix, sizeof(cache_dir) - strlen(cache_dir) - 1);
- BLI_strncpy(path, seq_disk_cache_base_dir(), path_len);
- BLI_path_append(path, path_len, cache_dir);
+
+ BLI_path_join(path, path_len, seq_disk_cache_base_dir(), cache_dir);
}
static void seq_disk_cache_get_dir(
@@ -307,9 +307,8 @@ static void seq_disk_cache_get_dir(
BLI_strncpy(seq_name, seq->name, sizeof(seq_name));
BLI_filename_make_safe(scene_name);
BLI_filename_make_safe(seq_name);
- BLI_strncpy(path, project_dir, path_len);
- BLI_path_append(path, path_len, scene_name);
- BLI_path_append(path, path_len, seq_name);
+
+ BLI_path_join(path, path_len, project_dir, scene_name, seq_name);
}
static void seq_disk_cache_get_file_path(SeqDiskCache *disk_cache,
@@ -350,8 +349,7 @@ static void seq_disk_cache_handle_versioning(SeqDiskCache *disk_cache)
int version = 0;
seq_disk_cache_get_project_dir(disk_cache, filepath, sizeof(filepath));
- BLI_strncpy(path_version_file, filepath, sizeof(path_version_file));
- BLI_path_append(path_version_file, sizeof(path_version_file), "cache_version");
+ BLI_path_join(path_version_file, sizeof(path_version_file), filepath, "cache_version");
if (BLI_exists(filepath) && BLI_is_dir(filepath)) {
FILE *file = BLI_fopen(path_version_file, "r");
@@ -384,7 +382,7 @@ static void seq_disk_cache_delete_invalid_files(SeqDiskCache *disk_cache,
DiskCacheFile *next_file, *cache_file = disk_cache->files.first;
char cache_dir[FILE_MAX];
seq_disk_cache_get_dir(disk_cache, scene, seq, cache_dir, sizeof(cache_dir));
- BLI_path_slash_ensure(cache_dir);
+ BLI_path_slash_ensure(cache_dir, sizeof(cache_dir));
while (cache_file) {
next_file = cache_file->next;
diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c
index 9f08db2aa45..fc1df4dc3ac 100644
--- a/source/blender/sequencer/intern/proxy.c
+++ b/source/blender/sequencer/intern/proxy.c
@@ -585,8 +585,7 @@ void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir)
char fname[FILE_MAXFILE];
IMB_anim_get_fname(anim, fname, FILE_MAXFILE);
- BLI_strncpy(dir, base_dir, sizeof(dir));
- BLI_path_append(dir, sizeof(dir), fname);
+ BLI_path_join(dir, sizeof(dir), base_dir, fname);
IMB_anim_set_index_dir(anim, dir);
}
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index dbbece73695..e3fd9216842 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -1026,6 +1026,15 @@ static ImBuf *seq_render_movie_strip_custom_file_proxy(const SeqRenderData *cont
return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
}
+static IMB_Timecode_Type seq_render_movie_strip_timecode_get(Sequence *seq)
+{
+ bool use_timecodes = (seq->flag & SEQ_USE_PROXY) != 0;
+ if (!use_timecodes) {
+ return IMB_TC_NONE;
+ }
+ return seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_NONE;
+}
+
/**
* Render individual view for multi-view or single (default view) for mono-view.
*/
@@ -1049,7 +1058,7 @@ static ImBuf *seq_render_movie_strip_view(const SeqRenderData *context,
else {
ibuf = IMB_anim_absolute(sanim->anim,
frame_index + seq->anim_startofs,
- seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ seq_render_movie_strip_timecode_get(seq),
psize);
}
@@ -1062,7 +1071,7 @@ static ImBuf *seq_render_movie_strip_view(const SeqRenderData *context,
if (ibuf == NULL) {
ibuf = IMB_anim_absolute(sanim->anim,
frame_index + seq->anim_startofs,
- seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ seq_render_movie_strip_timecode_get(seq),
IMB_PROXY_NONE);
}
if (ibuf == NULL) {
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 9a664456b9c..038438ff151 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -361,7 +361,7 @@ typedef struct wmNotifier {
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000
-/* NC_WM windowmanager */
+/* NC_WM (window-manager). */
#define ND_FILEREAD (1 << 16)
#define ND_FILESAVE (2 << 16)
#define ND_DATACHANGED (3 << 16)
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc
index 0896daec561..fb63abed9e9 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.cc
+++ b/source/blender/windowmanager/intern/wm_dragdrop.cc
@@ -853,7 +853,8 @@ static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag
y = xy[1] - 2 * UI_DPI_FAC;
const uchar text_col[] = {255, 255, 255, 255};
- UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false);
+ UI_icon_draw_ex(
+ x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc
index affe0bcf45a..181ec89cabd 100644
--- a/source/blender/windowmanager/intern/wm_event_system.cc
+++ b/source/blender/windowmanager/intern/wm_event_system.cc
@@ -5620,7 +5620,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
case GHOST_kEventNDOFButton: {
GHOST_TEventNDOFButtonData *e = static_cast<GHOST_TEventNDOFButtonData *>(customdata);
- event.type = NDOF_BUTTON_NONE + e->button;
+ event.type = NDOF_BUTTON_INDEX_AS_EVENT(e->button);
switch (e->action) {
case GHOST_kPress:
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index bf793ee41a0..3e5399a6f56 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -59,6 +59,8 @@
#include "DEG_depsgraph.h"
+#include "wm_window_private.h"
+
#include "WM_api.h" /* only for WM_main_playanim */
#ifdef WITH_AUDASPACE
@@ -1340,6 +1342,8 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
{
GHOST_GLSettings glsettings = {0};
+ const eGPUBackendType gpu_backend = GPU_backend_type_selection_get();
+ glsettings.context_type = wm_ghost_drawing_context_type(gpu_backend);
uint32_t scr_w, scr_h;
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
@@ -1356,7 +1360,6 @@ static void playanim_window_open(const char *title, int posx, int posy, int size
/* Could optionally start full-screen. */
GHOST_kWindowStateNormal,
false,
- GHOST_kDrawingContextTypeOpenGL,
glsettings);
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 30fbb855871..292d58b80d1 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -574,6 +574,9 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
glSettings.flags |= GHOST_glDebugContext;
}
+ eGPUBackendType gpu_backend = GPU_backend_type_selection_get();
+ glSettings.context_type = wm_ghost_drawing_context_type(gpu_backend);
+
int scr_w, scr_h;
wm_get_desktopsize(&scr_w, &scr_h);
int posy = (scr_h - win->posy - win->sizey);
@@ -591,7 +594,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
win->sizey,
(GHOST_TWindowState)win->windowstate,
is_dialog,
- GHOST_kDrawingContextTypeOpenGL,
glSettings);
if (ghostwin) {
@@ -1662,6 +1664,32 @@ const char *WM_ghost_backend(void)
#endif
}
+GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend)
+{
+ switch (gpu_backend) {
+ case GPU_BACKEND_NONE:
+ return GHOST_kDrawingContextTypeNone;
+ case GPU_BACKEND_ANY:
+ case GPU_BACKEND_OPENGL:
+ return GHOST_kDrawingContextTypeOpenGL;
+ case GPU_BACKEND_VULKAN:
+ BLI_assert_unreachable();
+ return GHOST_kDrawingContextTypeNone;
+ case GPU_BACKEND_METAL:
+#ifdef WITH_METAL_BACKEND
+ return GHOST_kDrawingContextTypeMetal;
+#else
+ BLI_assert_unreachable();
+ return GHOST_kDrawingContextTypeNone;
+#endif
+ }
+
+ /* Avoid control reaches end of non-void function compilation warning, which could be promoted
+ * to error. */
+ BLI_assert_unreachable();
+ return GHOST_kDrawingContextTypeNone;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/windowmanager/intern/wm_window_private.h b/source/blender/windowmanager/intern/wm_window_private.h
index f68d4e3e693..dad3e749817 100644
--- a/source/blender/windowmanager/intern/wm_window_private.h
+++ b/source/blender/windowmanager/intern/wm_window_private.h
@@ -7,8 +7,11 @@
#pragma once
#include "BLI_sys_types.h"
+
#include "GHOST_Types.h"
+#include "GPU_context.h"
+
/* *************** Message box *************** */
/* `WM_ghost_show_message_box` is implemented in `wm_windows.c` it is
* defined here as it was implemented to be used for showing
@@ -21,3 +24,5 @@ void WM_ghost_show_message_box(const char *title,
const char *continue_label,
const char *link,
GHOST_DialogOptions dialog_options);
+
+GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend);
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index 0b54560c56a..0a27b9c1cfd 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -45,12 +45,12 @@ extern void wm_close_and_free_all(bContext *C, ListBase *);
extern void wm_add_default(struct Main *bmain, bContext *C);
extern void wm_clear_default_size(bContext *C);
-/* register to windowmanager for redo or macro */
+/* Register to window-manager for redo or macro. */
/**
* Called on event handling by `event_system.c`.
*
- * All operations get registered in the windowmanager here.
+ * All operations get registered in the window-manager here.
*/
void wm_operator_register(bContext *C, wmOperator *op);
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 405b7225bd5..c36c57a12ae 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -252,8 +252,6 @@ enum {
#define _NDOF_MIN NDOF_MOTION
#define _NDOF_BUTTON_MIN NDOF_BUTTON_MENU
- /* used internally, never sent */
- NDOF_BUTTON_NONE = NDOF_MOTION,
/* these two are available from any 3Dconnexion device */
NDOF_BUTTON_MENU = 0x0191, /* 401 */
@@ -281,35 +279,42 @@ enum {
NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */
NDOF_BUTTON_PLUS = 0x01a4, /* 420 */
NDOF_BUTTON_MINUS = 0x01a5, /* 421 */
+ /* General-purpose buttons. */
+ NDOF_BUTTON_1 = 0x01a6, /* 422 */
+ NDOF_BUTTON_2 = 0x01a7, /* 423 */
+ NDOF_BUTTON_3 = 0x01a8, /* 424 */
+ NDOF_BUTTON_4 = 0x01a9, /* 425 */
+ NDOF_BUTTON_5 = 0x01aa, /* 426 */
+ NDOF_BUTTON_6 = 0x01ab, /* 427 */
+ NDOF_BUTTON_7 = 0x01ac, /* 428 */
+ NDOF_BUTTON_8 = 0x01ad, /* 429 */
+ NDOF_BUTTON_9 = 0x01ae, /* 430 */
+ NDOF_BUTTON_10 = 0x01af, /* 431 */
+ /* more general-purpose buttons */
+ NDOF_BUTTON_A = 0x01b0, /* 432 */
+ NDOF_BUTTON_B = 0x01b1, /* 433 */
+ NDOF_BUTTON_C = 0x01b2, /* 434 */
+ /* Store/restore views. */
+ NDOF_BUTTON_V1 = 0x01b3, /* 435 */
+ NDOF_BUTTON_V2 = 0x01b4, /* 436 */
+ NDOF_BUTTON_V3 = 0x01b5, /* 437 */
/* Disabled as GHOST converts these to keyboard events
* which use regular keyboard event handling logic. */
#if 0
/* keyboard emulation */
- NDOF_BUTTON_ESC = 0x01a6, /* 422 */
- NDOF_BUTTON_ALT = 0x01a7, /* 423 */
- NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */
- NDOF_BUTTON_CTRL = 0x01a9, /* 425 */
+ NDOF_BUTTON_ESC = 0x01b6, /* 438 */
+ NDOF_BUTTON_ENTER = 0x01b7, /* 439 */
+ NDOF_BUTTON_DELETE = 0x01b8, /* 440 */
+ NDOF_BUTTON_TAB = 0x01b9, /* 441 */
+ NDOF_BUTTON_SPACE = 0x01ba, /* 442 */
+ NDOF_BUTTON_ALT = 0x01bb, /* 443 */
+ NDOF_BUTTON_SHIFT = 0x01bc, /* 444 */
+ NDOF_BUTTON_CTRL = 0x01bd, /* 445 */
#endif
- /* general-purpose buttons */
- NDOF_BUTTON_1 = 0x01aa, /* 426 */
- NDOF_BUTTON_2 = 0x01ab, /* 427 */
- NDOF_BUTTON_3 = 0x01ac, /* 428 */
- NDOF_BUTTON_4 = 0x01ad, /* 429 */
- NDOF_BUTTON_5 = 0x01ae, /* 430 */
- NDOF_BUTTON_6 = 0x01af, /* 431 */
- NDOF_BUTTON_7 = 0x01b0, /* 432 */
- NDOF_BUTTON_8 = 0x01b1, /* 433 */
- NDOF_BUTTON_9 = 0x01b2, /* 434 */
- NDOF_BUTTON_10 = 0x01b3, /* 435 */
- /* more general-purpose buttons */
- NDOF_BUTTON_A = 0x01b4, /* 436 */
- NDOF_BUTTON_B = 0x01b5, /* 437 */
- NDOF_BUTTON_C = 0x01b6, /* 438 */
-
-#define _NDOF_MAX NDOF_BUTTON_C
-#define _NDOF_BUTTON_MAX NDOF_BUTTON_C
+#define _NDOF_MAX NDOF_BUTTON_V3
+#define _NDOF_BUTTON_MAX NDOF_BUTTON_V3
/* ********** End of Input devices. ********** */
@@ -449,6 +454,8 @@ enum eEventType_Mask {
(EVT_TYPE_MASK_KEYBOARD | EVT_TYPE_MASK_MOUSE | EVT_TYPE_MASK_NDOF)
#define EVT_TYPE_MASK_HOTKEY_EXCLUDE EVT_TYPE_MASK_KEYBOARD_MODIFIER
+#define NDOF_BUTTON_INDEX_AS_EVENT(i) (_NDOF_BUTTON_MIN + (i))
+
bool WM_event_type_mask_test(int event_type, enum eEventType_Mask mask);
/** \} */
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index abc41833de6..aefc3afff66 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -178,7 +178,7 @@ static void wm_xr_session_base_pose_calc(const Scene *scene,
float tmp_quat[4];
float tmp_eul[3];
- mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->obmat);
+ mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->object_to_world);
/* Only use rotation around Z-axis to align view with floor. */
quat_to_eul(tmp_eul, tmp_quat);
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index caaffa283ba..bb9e73c0895 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -1077,6 +1077,13 @@ elseif(WIN32)
)
endif()
+ if(WITH_PYTHON_MODULE AND TARGETDIR_BPY)
+ install(
+ TARGETS blender
+ LIBRARY DESTINATION ${TARGETDIR_BPY}
+ )
+ endif()
+
if(PLATFORM_BUNDLED_LIBRARIES)
install(
FILES ${PLATFORM_BUNDLED_LIBRARIES}
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 06b898587bf..2ebdcdb35ba 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -42,6 +42,8 @@
# include "BKE_scene.h"
# include "BKE_sound.h"
+# include "GPU_context.h"
+
# ifdef WITH_FFMPEG
# include "IMB_imbuf.h"
# endif
@@ -1111,6 +1113,52 @@ static int arg_handle_debug_gpu_set(int UNUSED(argc),
return 0;
}
+static const char arg_handle_gpu_backend_set_doc[] =
+ "\n"
+ "\tForce to use a specific GPU backend. Valid options: "
+# ifdef WITH_VULKAN_BACKEND
+ "'vulkan', "
+# endif
+# ifdef WITH_METAL_BACKEND
+ "'metal', "
+# endif
+ "'opengl'.";
+static int arg_handle_gpu_backend_set(int argc, const char **argv, void *UNUSED(data))
+{
+ if (argc == 0) {
+ printf("\nError: GPU backend must follow '--gpu-backend'.\n");
+ return 0;
+ }
+
+ eGPUBackendType gpu_backend = GPU_BACKEND_NONE;
+
+ if (STREQ(argv[1], "opengl")) {
+ gpu_backend = GPU_BACKEND_OPENGL;
+ }
+# ifdef WITH_VULKAN_BACKEND
+ else if (STREQ(argv[1], "vulkan")) {
+ gpu_backend = GPU_BACKEND_VULKAN;
+ }
+# endif
+# ifdef WITH_METAL_BACKEND
+ else if (STREQ(argv[1], "metal")) {
+ gpu_backend = GPU_BACKEND_METAL;
+ }
+# endif
+ else {
+ printf("\nError: Unrecognized GPU backend for '--gpu-backend'.\n");
+ return 0;
+ }
+
+ GPU_backend_type_selection_set(gpu_backend);
+ if (!GPU_backend_supported()) {
+ printf("\nError: GPU backend not supported.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
static const char arg_handle_debug_fpe_set_doc[] =
"\n\t"
"Enable floating-point exceptions.";
@@ -2074,6 +2122,10 @@ void main_args_setup(bContext *C, bArgs *ba)
BLI_args_add(ba, NULL, "--log-show-timestamp", CB(arg_handle_log_show_timestamp_set), ba);
BLI_args_add(ba, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
+ /* GPU backend selection should be part of ARG_PASS_ENVIRONMENT for correct GPU context selection
+ * for anim player. */
+ BLI_args_add(ba, NULL, "--gpu-backend", CB(arg_handle_gpu_backend_set), NULL);
+
/* Pass: Background Mode & Settings
*
* Also and commands that exit after usage. */