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:
authorLukas Tönne <lukas.toenne@gmail.com>2021-07-18 14:14:23 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2021-07-18 14:14:23 +0300
commitca50a1f762703d477ee84cf494dec601fd540299 (patch)
treefbd86a77e77015d7cc6becc1255a63e436a45b2a
parentd35969a74ff7a71fc0ca233ae65a2f1c47eb9a25 (diff)
parente82c5c660778b3805f50f3f2901923692c17db2a (diff)
Merge branch 'master' into geometry-nodes-unnamed-attributesgeometry-nodes-unnamed-attributes
-rw-r--r--CMakeLists.txt31
-rw-r--r--build_files/build_environment/CMakeLists.txt2
-rw-r--r--build_files/build_environment/cmake/download.cmake2
-rw-r--r--build_files/build_environment/cmake/harvest.cmake4
-rw-r--r--build_files/build_environment/cmake/versions.cmake20
-rw-r--r--build_files/build_environment/cmake/wayland_protocols.cmake27
-rw-r--r--build_files/build_environment/cmake/zstd.cmake51
-rwxr-xr-xbuild_files/build_environment/install_deps.sh17
-rw-r--r--build_files/build_environment/patches/ffmpeg.diff29
-rw-r--r--build_files/cmake/cmake_consistency_check_config.py3
-rw-r--r--build_files/cmake/config/blender_full.cmake1
-rw-r--r--build_files/cmake/config/blender_release.cmake1
-rw-r--r--build_files/windows/autodetect_msvc.cmd4
-rw-r--r--doc/python_api/examples/bpy.app.handlers.2.py1
-rw-r--r--doc/python_api/examples/bpy.app.timers.5.py2
-rw-r--r--doc/python_api/examples/bpy.msgbus.1.py2
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.7.py2
-rw-r--r--doc/python_api/examples/gpu.6.py1
-rw-r--r--extern/audaspace/include/devices/SoftwareDevice.h6
-rw-r--r--extern/audaspace/include/respec/Mixer.h6
-rw-r--r--extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp6
-rw-r--r--extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h4
-rw-r--r--extern/audaspace/plugins/wasapi/WASAPIDevice.cpp197
-rw-r--r--extern/audaspace/plugins/wasapi/WASAPIDevice.h5
-rw-r--r--extern/audaspace/src/devices/SoftwareDevice.cpp22
-rw-r--r--extern/audaspace/src/respec/Mixer.cpp30
-rw-r--r--extern/glog/README.blender1
-rw-r--r--extern/glog/src/raw_logging.cc2
-rw-r--r--extern/glog/src/utilities.cc6
-rw-r--r--intern/atomic/intern/atomic_ops_unix.h6
-rw-r--r--intern/cycles/blender/addon/properties.py2
-rw-r--r--intern/cycles/blender/addon/ui.py4
-rw-r--r--intern/cycles/blender/blender_image.cpp6
-rw-r--r--intern/cycles/blender/blender_object.cpp12
-rw-r--r--intern/cycles/blender/blender_sync.cpp16
-rw-r--r--intern/cycles/blender/blender_viewport.cpp4
-rw-r--r--intern/cycles/kernel/bvh/bvh_util.h3
-rw-r--r--intern/cycles/kernel/geom/geom_curve_intersect.h12
-rw-r--r--intern/cycles/kernel/kernel_bake.h2
-rw-r--r--intern/cycles/kernel/svm/svm_vector_rotate.h11
-rw-r--r--intern/cycles/render/camera.h2
-rw-r--r--intern/cycles/render/image_vdb.cpp200
-rw-r--r--intern/cycles/render/scene.h2
-rw-r--r--intern/cycles/render/session.cpp183
-rw-r--r--intern/cycles/render/session.h3
-rw-r--r--intern/cycles/util/util_openvdb.h36
-rw-r--r--intern/ghost/CMakeLists.txt26
-rw-r--r--intern/ghost/GHOST_C-api.h139
-rw-r--r--intern/ghost/GHOST_IEvent.h2
-rw-r--r--intern/ghost/GHOST_ISystem.h28
-rw-r--r--intern/ghost/GHOST_ISystemPaths.h8
-rw-r--r--intern/ghost/GHOST_IWindow.h27
-rw-r--r--intern/ghost/GHOST_Path-api.h8
-rw-r--r--intern/ghost/GHOST_Rect.h50
-rw-r--r--intern/ghost/GHOST_Types.h57
-rw-r--r--intern/ghost/intern/GHOST_Buttons.h6
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp136
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.cpp31
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.h15
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.h14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.mm18
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerNULL.h14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerSDL.cpp14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerSDL.h14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.h14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.cpp14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.h14
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp4
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.cpp4
-rw-r--r--intern/ghost/intern/GHOST_Event.h6
-rw-r--r--intern/ghost/intern/GHOST_EventButton.h2
-rw-r--r--intern/ghost/intern/GHOST_EventCursor.h6
-rw-r--r--intern/ghost/intern/GHOST_EventDragnDrop.h2
-rw-r--r--intern/ghost/intern/GHOST_EventKey.h9
-rw-r--r--intern/ghost/intern/GHOST_EventManager.cpp9
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h4
-rw-r--r--intern/ghost/intern/GHOST_EventNDOF.h4
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.cpp2
-rw-r--r--intern/ghost/intern/GHOST_EventString.h2
-rw-r--r--intern/ghost/intern/GHOST_EventTrackpad.h10
-rw-r--r--intern/ghost/intern/GHOST_EventWheel.h2
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h14
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp12
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h16
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerUnix.cpp6
-rw-r--r--intern/ghost/intern/GHOST_Path-api.cpp8
-rw-r--r--intern/ghost/intern/GHOST_Rect.cpp10
-rw-r--r--intern/ghost/intern/GHOST_System.cpp8
-rw-r--r--intern/ghost/intern/GHOST_System.h14
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h34
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm95
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h26
-rw-r--r--intern/ghost/intern/GHOST_SystemPaths.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.mm16
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsUnix.cpp16
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsUnix.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.cpp16
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp50
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h24
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp83
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h26
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp58
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h28
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp66
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h26
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.cpp22
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h8
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h28
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp15
-rw-r--r--intern/ghost/intern/GHOST_Window.h49
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h73
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm96
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h28
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp39
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h30
-rw-r--r--intern/ghost/intern/GHOST_WindowViewCocoa.h325
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp47
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h32
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp90
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h38
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp32
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h30
-rw-r--r--intern/ghost/intern/GHOST_Wintab.h6
-rw-r--r--intern/ghost/intern/GHOST_XrAction.cpp2
-rw-r--r--intern/ghost/intern/GHOST_XrAction.h2
-rw-r--r--intern/ghost/intern/GHOST_XrSession.cpp2
-rw-r--r--intern/ghost/intern/GHOST_XrSession.h2
-rw-r--r--intern/ghost/test/gears/GHOST_C-Test.c8
-rw-r--r--intern/ghost/test/gears/GHOST_Test.cpp15
-rw-r--r--intern/ghost/test/multitest/EventToBuf.c2
-rw-r--r--intern/ghost/test/multitest/MultiTest.c14
-rw-r--r--intern/guardedalloc/intern/mallocn_intern.h10
-rw-r--r--intern/libmv/libmv/numeric/numeric.h2
-rw-r--r--intern/libmv/libmv/tracking/retrack_region_tracker.cc2
-rw-r--r--intern/numaapi/source/build_config.h13
-rw-r--r--release/scripts/freestyle/modules/freestyle/shaders.py6
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py1
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_cli.py1
-rw-r--r--release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py1
-rw-r--r--release/scripts/modules/bl_previews_utils/bl_previews_render.py1
-rw-r--r--release/scripts/modules/bl_rna_utils/data_path.py1
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py1
-rw-r--r--release/scripts/modules/bpy_extras/asset_utils.py14
-rw-r--r--release/scripts/modules/bpy_extras/node_shader_utils.py7
-rw-r--r--release/scripts/modules/console/complete_calltip.py2
-rw-r--r--release/scripts/presets/camera/1_inch.py2
-rw-r--r--release/scripts/presets/camera/1_slash_1.8_inch.py2
-rw-r--r--release/scripts/presets/camera/1_slash_2.3_inch.py2
-rw-r--r--release/scripts/presets/camera/1_slash_2.5_inch.py2
-rw-r--r--release/scripts/presets/camera/1_slash_2.7_inch.py2
-rw-r--r--release/scripts/presets/camera/1_slash_3.2_inch.py2
-rw-r--r--release/scripts/presets/camera/2_slash_3_inch.py2
-rw-r--r--release/scripts/presets/camera/APS-C.py2
-rw-r--r--release/scripts/presets/camera/APS-C_(Canon).py2
-rw-r--r--release/scripts/presets/camera/APS-H_(Canon).py2
-rw-r--r--release/scripts/presets/camera/Analog_16mm.py2
-rw-r--r--release/scripts/presets/camera/Analog_35mm.py2
-rw-r--r--release/scripts/presets/camera/Analog_65mm.py2
-rw-r--r--release/scripts/presets/camera/Analog_IMAX.py2
-rw-r--r--release/scripts/presets/camera/Analog_Super_16.py2
-rw-r--r--release/scripts/presets/camera/Analog_Super_35.py2
-rw-r--r--release/scripts/presets/camera/Arri_Alexa_65.py2
-rw-r--r--release/scripts/presets/camera/Arri_Alexa_LF.py2
-rw-r--r--release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py2
-rw-r--r--release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py2
-rw-r--r--release/scripts/presets/camera/Blackmagic_Pocket_4K.py2
-rw-r--r--release/scripts/presets/camera/Blackmagic_Pocket_6k.py2
-rw-r--r--release/scripts/presets/camera/Blackmagic_URSA_4.6K.py2
-rw-r--r--release/scripts/presets/camera/Foveon_(Sigma).py2
-rw-r--r--release/scripts/presets/camera/Fullframe.py2
-rw-r--r--release/scripts/presets/camera/MFT.py2
-rw-r--r--release/scripts/presets/camera/Medium-format_(Hasselblad).py2
-rw-r--r--release/scripts/presets/camera/RED_Dragon_5K.py2
-rw-r--r--release/scripts/presets/camera/RED_Dragon_6K.py2
-rw-r--r--release/scripts/presets/camera/RED_Helium_8K.py2
-rw-r--r--release/scripts/presets/camera/RED_Monstro_8K.py2
-rw-r--r--release/scripts/presets/keyconfig/Blender.py6
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py49
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py4
-rw-r--r--release/scripts/presets/tracking_camera/1_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/1_slash_1.8_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/1_slash_2.3_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/1_slash_2.5_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/1_slash_2.7_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/1_slash_3.2_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/2_slash_3_inch.py2
-rw-r--r--release/scripts/presets/tracking_camera/APS-C.py2
-rw-r--r--release/scripts/presets/tracking_camera/APS-C_(Canon).py2
-rw-r--r--release/scripts/presets/tracking_camera/APS-H_(Canon).py2
-rw-r--r--release/scripts/presets/tracking_camera/Analog_16mm.py2
-rw-r--r--release/scripts/presets/tracking_camera/Analog_35mm.py2
-rw-r--r--release/scripts/presets/tracking_camera/Analog_65mm.py2
-rw-r--r--release/scripts/presets/tracking_camera/Analog_IMAX.py2
-rw-r--r--release/scripts/presets/tracking_camera/Analog_Super_16.py2
-rw-r--r--release/scripts/presets/tracking_camera/Analog_Super_35.py2
-rw-r--r--release/scripts/presets/tracking_camera/Arri_Alexa_65.py2
-rw-r--r--release/scripts/presets/tracking_camera/Arri_Alexa_LF.py2
-rw-r--r--release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py2
-rw-r--r--release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py2
-rw-r--r--release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py2
-rw-r--r--release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py2
-rw-r--r--release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py2
-rw-r--r--release/scripts/presets/tracking_camera/Foveon_(Sigma).py2
-rw-r--r--release/scripts/presets/tracking_camera/Fullframe.py2
-rw-r--r--release/scripts/presets/tracking_camera/MFT.py2
-rw-r--r--release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py2
-rw-r--r--release/scripts/presets/tracking_camera/RED_Dragon_5K.py2
-rw-r--r--release/scripts/presets/tracking_camera/RED_Dragon_6K.py2
-rw-r--r--release/scripts/presets/tracking_camera/RED_Helium_8K.py2
-rw-r--r--release/scripts/presets/tracking_camera/RED_Monstro_8K.py2
-rw-r--r--release/scripts/startup/bl_operators/assets.py83
-rw-r--r--release/scripts/startup/bl_operators/node.py62
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py13
-rw-r--r--release/scripts/startup/bl_operators/spreadsheet.py14
-rw-r--r--release/scripts/startup/bl_operators/wm.py2
-rw-r--r--release/scripts/startup/bl_ui/__init__.py24
-rw-r--r--release/scripts/startup/bl_ui/properties_collection.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py1
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py18
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py10
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py27
-rw-r--r--release/scripts/startup/bl_ui/space_image.py5
-rw-r--r--release/scripts/startup/bl_ui/space_node.py93
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py1
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py15
-rw-r--r--release/scripts/startup/bl_ui/space_spreadsheet.py6
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py16
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py6
-rw-r--r--release/scripts/startup/keyingsets_builtins.py1
-rw-r--r--release/scripts/startup/nodeitems_builtins.py10
-rw-r--r--release/scripts/templates_py/image_processing.py4
-rw-r--r--release/scripts/templates_py/operator_mesh_add.py1
-rw-r--r--source/blender/blenfont/intern/blf_font.c6
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c2
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h4
-rw-r--r--source/blender/blenkernel/BKE_anim_data.h4
-rw-r--r--source/blender/blenkernel/BKE_animsys.h6
-rw-r--r--source/blender/blenkernel/BKE_armature.h17
-rw-r--r--source/blender/blenkernel/BKE_asset.h3
-rw-r--r--source/blender/blenkernel/BKE_attribute.h4
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h6
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h1
-rw-r--r--source/blender/blenkernel/BKE_context.h6
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h2
-rw-r--r--source/blender/blenkernel/BKE_deform.h14
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h41
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh14
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h38
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h6
-rw-r--r--source/blender/blenkernel/BKE_key.h2
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h2
-rw-r--r--source/blender/blenkernel/BKE_lib_remap.h2
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h4
-rw-r--r--source/blender/blenkernel/BKE_mesh_remap.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh_runtime.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh_types.h1
-rw-r--r--source/blender/blenkernel/BKE_nla.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h37
-rw-r--r--source/blender/blenkernel/BKE_node_ui_storage.hh133
-rw-r--r--source/blender/blenkernel/BKE_object.h10
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h2
-rw-r--r--source/blender/blenkernel/BKE_scene.h8
-rw-r--r--source/blender/blenkernel/BKE_screen.h6
-rw-r--r--source/blender/blenkernel/BKE_spline.hh12
-rw-r--r--source/blender/blenkernel/BKE_studiolight.h2
-rw-r--r--source/blender/blenkernel/BKE_tracking.h2
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h7
-rw-r--r--source/blender/blenkernel/BKE_volume.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt13
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc36
-rw-r--r--source/blender/blenkernel/intern/action.c40
-rw-r--r--source/blender/blenkernel/intern/action_mirror.c19
-rw-r--r--source/blender/blenkernel/intern/action_test.cc144
-rw-r--r--source/blender/blenkernel/intern/anim_data.c42
-rw-r--r--source/blender/blenkernel/intern/anim_path.c2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c133
-rw-r--r--source/blender/blenkernel/intern/anim_visualization.c4
-rw-r--r--source/blender/blenkernel/intern/appdir.c9
-rw-r--r--source/blender/blenkernel/intern/armature.c8
-rw-r--r--source/blender/blenkernel/intern/armature_deform.c20
-rw-r--r--source/blender/blenkernel/intern/armature_pose.cc57
-rw-r--r--source/blender/blenkernel/intern/armature_update.c14
-rw-r--r--source/blender/blenkernel/intern/asset.cc5
-rw-r--r--source/blender/blenkernel/intern/attribute.c6
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c3
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c4
-rw-r--r--source/blender/blenkernel/intern/bvhutils.cc (renamed from source/blender/blenkernel/intern/bvhutils.c)220
-rw-r--r--source/blender/blenkernel/intern/cachefile.c2
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/cloth.c19
-rw-r--r--source/blender/blenkernel/intern/collection.c16
-rw-r--r--source/blender/blenkernel/intern/colorband.c4
-rw-r--r--source/blender/blenkernel/intern/colortools.c8
-rw-r--r--source/blender/blenkernel/intern/constraint.c148
-rw-r--r--source/blender/blenkernel/intern/context.c30
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c3
-rw-r--r--source/blender/blenkernel/intern/curve.c12
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c2
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc2
-rw-r--r--source/blender/blenkernel/intern/customdata.c18
-rw-r--r--source/blender/blenkernel/intern/customdata_file.c4
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c6
-rw-r--r--source/blender/blenkernel/intern/deform.c190
-rw-r--r--source/blender/blenkernel/intern/displist.cc2
-rw-r--r--source/blender/blenkernel/intern/displist_tangent.c2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c29
-rw-r--r--source/blender/blenkernel/intern/editmesh.c19
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c2
-rw-r--r--source/blender/blenkernel/intern/editmesh_tangent.c3
-rw-r--r--source/blender/blenkernel/intern/effect.c4
-rw-r--r--source/blender/blenkernel/intern/fcurve.c8
-rw-r--r--source/blender/blenkernel/intern/fluid.c10
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c4
-rw-r--r--source/blender/blenkernel/intern/font.c4
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc83
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc6
-rw-r--r--source/blender/blenkernel/intern/gpencil.c99
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc (renamed from source/blender/blenkernel/intern/gpencil_geom.c)501
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c18
-rw-r--r--source/blender/blenkernel/intern/idprop.c10
-rw-r--r--source/blender/blenkernel/intern/idprop_utils.c2
-rw-r--r--source/blender/blenkernel/intern/image.c16
-rw-r--r--source/blender/blenkernel/intern/image_save.c2
-rw-r--r--source/blender/blenkernel/intern/ipo.c36
-rw-r--r--source/blender/blenkernel/intern/key.c12
-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.c237
-rw-r--r--source/blender/blenkernel/intern/layer_utils.c1
-rw-r--r--source/blender/blenkernel/intern/lib_id.c33
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c6
-rw-r--r--source/blender/blenkernel/intern/lib_override.c22
-rw-r--r--source/blender/blenkernel/intern/lib_query.c2
-rw-r--r--source/blender/blenkernel/intern/lib_remap.c6
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c2
-rw-r--r--source/blender/blenkernel/intern/main.c2
-rw-r--r--source/blender/blenkernel/intern/mask.c22
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c4
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c10
-rw-r--r--source/blender/blenkernel/intern/material.c8
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c4
-rw-r--r--source/blender/blenkernel/intern/mesh.c28
-rw-r--r--source/blender/blenkernel/intern/mesh_boolean_convert.cc45
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.cc (renamed from source/blender/blenkernel/intern/mesh_evaluate.c)72
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_merge.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc (renamed from source/blender/blenkernel/intern/mesh_normals.c)311
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c16
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c12
-rw-r--r--source/blender/blenkernel/intern/mesh_tangent.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c6
-rw-r--r--source/blender/blenkernel/intern/modifier.c2
-rw-r--r--source/blender/blenkernel/intern/movieclip.c6
-rw-r--r--source/blender/blenkernel/intern/multires_inline.h2
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_smooth.c2
-rw-r--r--source/blender/blenkernel/intern/multires_unsubdivide.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c21
-rw-r--r--source/blender/blenkernel/intern/node.cc126
-rw-r--r--source/blender/blenkernel/intern/node_ui_storage.cc169
-rw-r--r--source/blender/blenkernel/intern/object.c99
-rw-r--r--source/blender/blenkernel/intern/object_deform.c80
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc14
-rw-r--r--source/blender/blenkernel/intern/object_update.c23
-rw-r--r--source/blender/blenkernel/intern/ocean.c8
-rw-r--r--source/blender/blenkernel/intern/packedFile.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c6
-rw-r--r--source/blender/blenkernel/intern/particle.c8
-rw-r--r--source/blender/blenkernel/intern/particle_child.c2
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c4
-rw-r--r--source/blender/blenkernel/intern/particle_system.c16
-rw-r--r--source/blender/blenkernel/intern/pbvh.c6
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c2
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c8
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c18
-rw-r--r--source/blender/blenkernel/intern/scene.c57
-rw-r--r--source/blender/blenkernel/intern/screen.c22
-rw-r--r--source/blender/blenkernel/intern/shader_fx.c2
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c8
-rw-r--r--source/blender/blenkernel/intern/softbody.c30
-rw-r--r--source/blender/blenkernel/intern/sound.c2
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc4
-rw-r--r--source/blender/blenkernel/intern/spline_bezier.cc40
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc5
-rw-r--r--source/blender/blenkernel/intern/studiolight.c2
-rw-r--r--source/blender/blenkernel/intern/subdiv.c4
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/subdiv_converter.c4
-rw-r--r--source/blender/blenkernel/intern/subdiv_eval.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/text.c4
-rw-r--r--source/blender/blenkernel/intern/tracking.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c4
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c2
-rw-r--r--source/blender/blenkernel/intern/undo_system.c35
-rw-r--r--source/blender/blenkernel/intern/unit.c6
-rw-r--r--source/blender/blenkernel/intern/volume.cc2
-rw-r--r--source/blender/blenkernel/intern/workspace.c10
-rw-r--r--source/blender/blenlib/BLI_array_utils.h31
-rw-r--r--source/blender/blenlib/BLI_assert.h12
-rw-r--r--source/blender/blenlib/BLI_endian_switch_inline.h2
-rw-r--r--source/blender/blenlib/BLI_enumerable_thread_specific.hh51
-rw-r--r--source/blender/blenlib/BLI_function_ref.hh2
-rw-r--r--source/blender/blenlib/BLI_math_geom.h2
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h3
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h2
-rw-r--r--source/blender/blenlib/BLI_memarena.h2
-rw-r--r--source/blender/blenlib/BLI_memory_utils.hh6
-rw-r--r--source/blender/blenlib/BLI_mempool.h5
-rw-r--r--source/blender/blenlib/BLI_mesh_intersect.hh3
-rw-r--r--source/blender/blenlib/BLI_multi_value_map.hh6
-rw-r--r--source/blender/blenlib/BLI_scanfill.h6
-rw-r--r--source/blender/blenlib/BLI_set_slots.hh2
-rw-r--r--source/blender/blenlib/BLI_span.hh2
-rw-r--r--source/blender/blenlib/BLI_task.h7
-rw-r--r--source/blender/blenlib/BLI_task.hh22
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/intern/BLI_assert.c5
-rw-r--r--source/blender/blenlib/intern/BLI_filelist.c4
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c4
-rw-r--r--source/blender/blenlib/intern/BLI_ghash_utils.c4
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c14
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c53
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c4
-rw-r--r--source/blender/blenlib/intern/array_store.c8
-rw-r--r--source/blender/blenlib/intern/array_utils.c82
-rw-r--r--source/blender/blenlib/intern/bitmap_draw_2d.c2
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc6
-rw-r--r--source/blender/blenlib/intern/expr_pylike_eval.c2
-rw-r--r--source/blender/blenlib/intern/fileops.c4
-rw-r--r--source/blender/blenlib/intern/kdtree_impl.h2
-rw-r--r--source/blender/blenlib/intern/math_color.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c25
-rw-r--r--source/blender/blenlib/intern/math_interp.c2
-rw-r--r--source/blender/blenlib/intern/math_matrix.c26
-rw-r--r--source/blender/blenlib/intern/math_rotation.c6
-rw-r--r--source/blender/blenlib/intern/mesh_boolean.cc204
-rw-r--r--source/blender/blenlib/intern/mesh_intersect.cc257
-rw-r--r--source/blender/blenlib/intern/noise.c2
-rw-r--r--source/blender/blenlib/intern/path_util.c14
-rw-r--r--source/blender/blenlib/intern/polyfill_2d.c2
-rw-r--r--source/blender/blenlib/intern/polyfill_2d_beautify.c2
-rw-r--r--source/blender/blenlib/intern/scanfill.c4
-rw-r--r--source/blender/blenlib/intern/smallhash.c6
-rw-r--r--source/blender/blenlib/intern/sort.c2
-rw-r--r--source/blender/blenlib/intern/string_utf8.c16
-rw-r--r--source/blender/blenlib/intern/system.c6
-rw-r--r--source/blender/blenlib/intern/task_iterator.c31
-rw-r--r--source/blender/blenlib/intern/task_range.cc2
-rw-r--r--source/blender/blenlib/tests/BLI_array_utils_test.cc50
-rw-r--r--source/blender/blenlib/tests/BLI_delaunay_2d_test.cc8
-rw-r--r--source/blender/blenlib/tests/BLI_ghash_test.cc2
-rw-r--r--source/blender/blenlib/tests/BLI_hash_mm2a_test.cc2
-rw-r--r--source/blender/blenlib/tests/BLI_math_base_test.cc2
-rw-r--r--source/blender/blenlib/tests/BLI_mesh_intersect_test.cc2
-rw-r--r--source/blender/blenlib/tests/performance/BLI_task_performance_test.cc2
-rw-r--r--source/blender/blenloader/BLO_readfile.h2
-rw-r--r--source/blender/blenloader/CMakeLists.txt2
-rw-r--r--source/blender/blenloader/intern/readfile.c12
-rw-r--r--source/blender/blenloader/intern/undofile.c2
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/versioning_260.c6
-rw-r--r--source/blender/blenloader/intern/versioning_280.c4
-rw-r--r--source/blender/blenloader/intern/versioning_300.c91
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c6
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c11
-rw-r--r--source/blender/blentranslation/CMakeLists.txt2
-rw-r--r--source/blender/blentranslation/intern/blt_translation.c2
-rw-r--r--source/blender/blentranslation/msgfmt/msgfmt.c2
-rw-r--r--source/blender/bmesh/bmesh_class.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_delete.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_error.h37
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c12
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_normals.c20
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c56
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_query.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c2
-rw-r--r--source/blender/bmesh/operators/bmo_beautify.c2
-rw-r--r--source/blender/bmesh/operators/bmo_bisect_plane.c4
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c6
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c8
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c2
-rw-r--r--source/blender/bmesh/operators/bmo_create.c12
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c99
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c6
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_edgeloop.c4
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c23
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c4
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c8
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c6
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c2
-rw-r--r--source/blender/bmesh/operators/bmo_offset_edgeloops.c4
-rw-r--r--source/blender/bmesh/operators/bmo_planar_faces.c2
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c10
-rw-r--r--source/blender/bmesh/operators/bmo_rotate_edges.c4
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c6
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c20
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c2
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c20
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect_edges.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_path_uv.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c2
-rw-r--r--source/blender/compositor/CMakeLists.txt7
-rw-r--r--source/blender/compositor/COM_defines.h3
-rw-r--r--source/blender/compositor/intern/COM_BufferOperation.cc22
-rw-r--r--source/blender/compositor/intern/COM_BufferOperation.h7
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.cc2
-rw-r--r--source/blender/compositor/intern/COM_ConstantFolder.cc191
-rw-r--r--source/blender/compositor/intern/COM_ConstantFolder.h64
-rw-r--r--source/blender/compositor/intern/COM_Converter.cc7
-rw-r--r--source/blender/compositor/intern/COM_Debug.cc43
-rw-r--r--source/blender/compositor/intern/COM_Debug.h4
-rw-r--r--source/blender/compositor/intern/COM_ExecutionModel.cc6
-rw-r--r--source/blender/compositor/intern/COM_ExecutionModel.h9
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cc76
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h6
-rw-r--r--source/blender/compositor/intern/COM_FullFrameExecutionModel.cc100
-rw-r--r--source/blender/compositor/intern/COM_FullFrameExecutionModel.h13
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cc12
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h32
-rw-r--r--source/blender/compositor/intern/COM_MultiThreadedOperation.cc5
-rw-r--r--source/blender/compositor/intern/COM_MultiThreadedOperation.h3
-rw-r--r--source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc50
-rw-r--r--source/blender/compositor/intern/COM_MultiThreadedRowOperation.h60
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cc2
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cc28
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h36
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cc47
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.h8
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cc2
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cc4
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.h2
-rw-r--r--source/blender/compositor/intern/COM_compositor.cc2
-rw-r--r--source/blender/compositor/nodes/COM_CornerPinNode.cc2
-rw-r--r--source/blender/compositor/nodes/COM_IDMaskNode.cc26
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cc2
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cc2
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.cc6
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc18
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc18
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.cc81
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_ColorExposureOperation.cc14
-rw-r--r--source/blender/compositor/operations/COM_ColorExposureOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_ConstantOperation.cc28
-rw-r--r--source/blender/compositor/operations/COM_ConstantOperation.h36
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GammaOperation.cc15
-rw-r--r--source/blender/compositor/operations/COM_GammaOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_GlareBaseOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_IDMaskOperation.cc1
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_NormalizeOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_NormalizeOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.cc2
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cc68
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h27
-rw-r--r--source/blender/compositor/operations/COM_SMAAOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cc16
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.h1
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.cc3
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.cc3
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.h35
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cc2
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.cc65
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.h40
-rw-r--r--source/blender/compositor/operations/COM_VectorBlurOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.cc2
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h2
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h2
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h8
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc111
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc86
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc10
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.h2
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc5
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc15
-rw-r--r--source/blender/depsgraph/intern/depsgraph_physics.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc13
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc5
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc8
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc6
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc12
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h10
-rw-r--r--source/blender/draw/CMakeLists.txt28
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c20
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h16
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows_cascade.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c6
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lights_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/ssr_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl4
-rw-r--r--source/blender/draw/engines/external/external_engine.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c16
-rw-r--r--source/blender/draw/engines/image/image_engine.c41
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c14
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_mesh.c1
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_uv.c1
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c18
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h6
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c2
-rw-r--r--source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl2
-rw-r--r--source/blender/draw/engines/select/select_engine.c2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl4
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_antialiasing.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_cavity.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_shadow.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c2
-rw-r--r--source/blender/draw/intern/DRW_render.h6
-rw-r--r--source/blender/draw/intern/draw_cache.c18
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h2
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc16
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_extractors.c3552
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_private.h20
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.cc2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c19
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c6
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c21
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c8
-rw-r--r--source/blender/draw/intern/draw_cache_inline.h2
-rw-r--r--source/blender/draw/intern/draw_common.c8
-rw-r--r--source/blender/draw/intern/draw_common.h4
-rw-r--r--source/blender/draw/intern/draw_fluid.c2
-rw-r--r--source/blender/draw/intern/draw_hair.c4
-rw-r--r--source/blender/draw/intern/draw_manager.c8
-rw-r--r--source/blender/draw/intern/draw_manager.h4
-rw-r--r--source/blender/draw/intern/draw_manager_data.c8
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c12
-rw-r--r--source/blender/draw/intern/draw_shader.c2
-rw-r--r--source/blender/draw/intern/draw_view.c2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc241
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc265
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc140
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc236
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc157
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc101
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc200
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc119
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc127
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc228
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc654
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc115
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc415
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc141
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc295
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc93
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc266
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc136
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc191
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc189
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl6
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c4
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c19
-rw-r--r--source/blender/editors/animation/anim_draw.c2
-rw-r--r--source/blender/editors/animation/anim_filter.c10
-rw-r--r--source/blender/editors/animation/anim_markers.c4
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c2
-rw-r--r--source/blender/editors/animation/anim_ops.c84
-rw-r--r--source/blender/editors/animation/drivers.c4
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/animation/keyframes_general.c2
-rw-r--r--source/blender/editors/animation/keyframing.c66
-rw-r--r--source/blender/editors/animation/time_scrub_ui.c2
-rw-r--r--source/blender/editors/armature/CMakeLists.txt3
-rw-r--r--source/blender/editors/armature/armature_add.c16
-rw-r--r--source/blender/editors/armature/armature_edit.c12
-rw-r--r--source/blender/editors/armature/armature_intern.h4
-rw-r--r--source/blender/editors/armature/armature_naming.c4
-rw-r--r--source/blender/editors/armature/armature_ops.c2
-rw-r--r--source/blender/editors/armature/armature_relations.c6
-rw-r--r--source/blender/editors/armature/armature_select.c2
-rw-r--r--source/blender/editors/armature/armature_skinning.c2
-rw-r--r--source/blender/editors/armature/armature_utils.c2
-rw-r--r--source/blender/editors/armature/editarmature_undo.c2
-rw-r--r--source/blender/editors/armature/pose_backup.c139
-rw-r--r--source/blender/editors/armature/pose_edit.c16
-rw-r--r--source/blender/editors/armature/pose_lib_2.c638
-rw-r--r--source/blender/editors/armature/pose_select.c6
-rw-r--r--source/blender/editors/armature/pose_slide.c6
-rw-r--r--source/blender/editors/armature/pose_transform.c6
-rw-r--r--source/blender/editors/asset/CMakeLists.txt5
-rw-r--r--source/blender/editors/asset/asset_edit.cc88
-rw-r--r--source/blender/editors/asset/asset_list.cc637
-rw-r--r--source/blender/editors/asset/asset_ops.cc33
-rw-r--r--source/blender/editors/asset/asset_temp_id_consumer.cc113
-rw-r--r--source/blender/editors/curve/editcurve.c6
-rw-r--r--source/blender/editors/curve/editcurve_add.c2
-rw-r--r--source/blender/editors/curve/editcurve_paint.c2
-rw-r--r--source/blender/editors/curve/editcurve_undo.c2
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/curve/editfont_undo.c4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_draw_utils.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_presets.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_library_utils.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c2
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c4
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c27
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c82
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_armature.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_bake_animation.c7
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c51
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c31
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c15
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c18
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_weight_paint.c8
-rw-r--r--source/blender/editors/include/ED_anim_api.h8
-rw-r--r--source/blender/editors/include/ED_armature.h16
-rw-r--r--source/blender/editors/include/ED_asset.h63
-rw-r--r--source/blender/editors/include/ED_fileselect.h12
-rw-r--r--source/blender/editors/include/ED_gpencil.h7
-rw-r--r--source/blender/editors/include/ED_keyframing.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h14
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_particle.h2
-rw-r--r--source/blender/editors/include/ED_spreadsheet.h28
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/include/UI_interface.h125
-rw-r--r--source/blender/editors/include/UI_interface_icons.h5
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/CMakeLists.txt4
-rw-r--r--source/blender/editors/interface/interface.c73
-rw-r--r--source/blender/editors/interface/interface_context_menu.c22
-rw-r--r--source/blender/editors/interface/interface_draw.c11
-rw-r--r--source/blender/editors/interface/interface_handlers.c627
-rw-r--r--source/blender/editors/interface/interface_icons.c14
-rw-r--r--source/blender/editors/interface/interface_intern.h62
-rw-r--r--source/blender/editors/interface/interface_layout.c22
-rw-r--r--source/blender/editors/interface/interface_ops.c96
-rw-r--r--source/blender/editors/interface/interface_panel.c8
-rw-r--r--source/blender/editors/interface/interface_query.c115
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c2
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c2
-rw-r--r--source/blender/editors/interface/interface_region_popover.c2
-rw-r--r--source/blender/editors/interface/interface_region_popup.c2
-rw-r--r--source/blender/editors/interface/interface_region_search.c16
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c6
-rw-r--r--source/blender/editors/interface/interface_template_asset_view.cc272
-rw-r--r--source/blender/editors/interface/interface_template_list.cc1310
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c6
-rw-r--r--source/blender/editors/interface/interface_templates.c899
-rw-r--r--source/blender/editors/interface/interface_utils.c100
-rw-r--r--source/blender/editors/interface/interface_widgets.c156
-rw-r--r--source/blender/editors/interface/view2d.c10
-rw-r--r--source/blender/editors/interface/view2d_draw.c2
-rw-r--r--source/blender/editors/interface/view2d_edge_pan.c2
-rw-r--r--source/blender/editors/interface/view2d_ops.c8
-rw-r--r--source/blender/editors/io/io_alembic.c36
-rw-r--r--source/blender/editors/io/io_gpencil.h2
-rw-r--r--source/blender/editors/lattice/editlattice_select.c4
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c2
-rw-r--r--source/blender/editors/mask/mask_add.c10
-rw-r--r--source/blender/editors/mask/mask_draw.c2
-rw-r--r--source/blender/editors/mask/mask_ops.c2
-rw-r--r--source/blender/editors/mask/mask_shapekey.c4
-rw-r--r--source/blender/editors/mesh/editface.c4
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c8
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c10
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c6
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c6
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c5
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c2
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c4
-rw-r--r--source/blender/editors/mesh/editmesh_path.c1
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c4
-rw-r--r--source/blender/editors/mesh/editmesh_select.c11
-rw-r--r--source/blender/editors/mesh/editmesh_select_similar.c15
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c57
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c17
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c202
-rw-r--r--source/blender/editors/mesh/mesh_data.c7
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c5
-rw-r--r--source/blender/editors/mesh/meshtools.c33
-rw-r--r--source/blender/editors/metaball/editmball_undo.c2
-rw-r--r--source/blender/editors/object/object_add.c18
-rw-r--r--source/blender/editors/object/object_bake.c2
-rw-r--r--source/blender/editors/object/object_bake_api.c4
-rw-r--r--source/blender/editors/object/object_constraint.c6
-rw-r--r--source/blender/editors/object/object_data_transfer.c97
-rw-r--r--source/blender/editors/object/object_edit.c6
-rw-r--r--source/blender/editors/object/object_hook.c10
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/object/object_ops.c3
-rw-r--r--source/blender/editors/object/object_relations.c53
-rw-r--r--source/blender/editors/object/object_select.c4
-rw-r--r--source/blender/editors/object/object_transform.c490
-rw-r--r--source/blender/editors/object/object_vgroup.c208
-rw-r--r--source/blender/editors/physics/particle_edit.c8
-rw-r--r--source/blender/editors/physics/particle_object.c5
-rw-r--r--source/blender/editors/render/render_internal.c4
-rw-r--r--source/blender/editors/render/render_preview.c74
-rw-r--r--source/blender/editors/render/render_shading.c8
-rw-r--r--source/blender/editors/screen/area.c18
-rw-r--r--source/blender/editors/screen/area_query.c2
-rw-r--r--source/blender/editors/screen/glutil.c4
-rw-r--r--source/blender/editors/screen/screen_context.c26
-rw-r--r--source/blender/editors/screen/screen_edit.c6
-rw-r--r--source/blender/editors/screen/screen_ops.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c36
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c22
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c26
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c22
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c12
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_smooth.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c12
-rw-r--r--source/blender/editors/space_action/action_data.c4
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_edit.c8
-rw-r--r--source/blender/editors/space_action/action_select.c4
-rw-r--r--source/blender/editors/space_action/space_action.c2
-rw-r--r--source/blender/editors/space_api/spacetypes.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_clip/clip_editor.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_console/console_ops.c6
-rw-r--r--source/blender/editors/space_console/space_console.c2
-rw-r--r--source/blender/editors/space_file/file_draw.c73
-rw-r--r--source/blender/editors/space_file/file_intern.h12
-rw-r--r--source/blender/editors/space_file/file_ops.c74
-rw-r--r--source/blender/editors/space_file/filelist.c242
-rw-r--r--source/blender/editors/space_file/filelist.h18
-rw-r--r--source/blender/editors/space_file/filesel.c121
-rw-r--r--source/blender/editors/space_file/space_file.c68
-rw-r--r--source/blender/editors/space_graph/graph_draw.c9
-rw-r--r--source/blender/editors/space_graph/graph_edit.c6
-rw-r--r--source/blender/editors/space_graph/graph_select.c12
-rw-r--r--source/blender/editors/space_graph/graph_view.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_image/image_buttons.c18
-rw-r--r--source/blender/editors/space_image/image_edit.c4
-rw-r--r--source/blender/editors/space_image/image_ops.c27
-rw-r--r--source/blender/editors/space_image/image_undo.c2
-rw-r--r--source/blender/editors/space_info/info_ops.c9
-rw-r--r--source/blender/editors/space_info/info_report.c2
-rw-r--r--source/blender/editors/space_info/info_stats.c12
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_nla/nla_channels.c14
-rw-r--r--source/blender/editors/space_nla/nla_draw.c4
-rw-r--r--source/blender/editors/space_nla/nla_edit.c19
-rw-r--r--source/blender/editors/space_nla/nla_ops.c16
-rw-r--r--source/blender/editors/space_nla/nla_select.c4
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt18
-rw-r--r--source/blender/editors/space_node/drawnode.cc36
-rw-r--r--source/blender/editors/space_node/node_add.cc4
-rw-r--r--source/blender/editors/space_node/node_buttons.c223
-rw-r--r--source/blender/editors/space_node/node_draw.cc281
-rw-r--r--source/blender/editors/space_node/node_edit.cc151
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc88
-rw-r--r--source/blender/editors/space_node/node_gizmo.c6
-rw-r--r--source/blender/editors/space_node/node_intern.h11
-rw-r--r--source/blender/editors/space_node/node_ops.c3
-rw-r--r--source/blender/editors/space_node/node_relationships.cc50
-rw-r--r--source/blender/editors/space_node/node_select.cc15
-rw-r--r--source/blender/editors/space_node/node_templates.cc2
-rw-r--r--source/blender/editors/space_node/space_node.c10
-rw-r--r--source/blender/editors/space_outliner/outliner_context.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h2
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c35
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display.hh2
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_override_library.cc34
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_view_layer.cc91
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_id.cc2
-rw-r--r--source/blender/editors/space_script/space_script.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c16
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c32
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2
-rw-r--r--source/blender/editors/space_spreadsheet/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc44
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_context.cc301
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc27
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc6
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_draw.hh4
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc12
-rw-r--r--source/blender/editors/space_text/text_format_lua.c6
-rw-r--r--source/blender/editors/space_text/text_format_osl.c10
-rw-r--r--source/blender/editors/space_text/text_format_pov.c10
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c4
-rw-r--r--source/blender/editors/space_text/text_format_py.c10
-rw-r--r--source/blender/editors/space_text/text_ops.c4
-rw-r--r--source/blender/editors/space_text/text_undo.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c6
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c117
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c16
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c23
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_armature.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_light.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_fly.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_walk.c87
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c72
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c4
-rw-r--r--source/blender/editors/transform/transform.c6
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_convert.c5
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c4
-rw-r--r--source/blender/editors/transform/transform_convert_graph.c6
-rw-r--r--source/blender/editors/transform/transform_convert_mask.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c28
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_edge.c1
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_uv.c1
-rw-r--r--source/blender/editors/transform/transform_convert_object.c4
-rw-r--r--source/blender/editors/transform/transform_convert_particle.c2
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c15
-rw-r--r--source/blender/editors/transform/transform_data.h2
-rw-r--r--source/blender/editors/transform/transform_generics.c6
-rw-r--r--source/blender/editors/transform/transform_mode_edge_seq_slide.c2
-rw-r--r--source/blender/editors/transform/transform_mode_edge_slide.c6
-rw-r--r--source/blender/editors/transform/transform_mode_vert_slide.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c15
-rw-r--r--source/blender/editors/transform/transform_snap_object.c12
-rw-r--r--source/blender/editors/transform/transform_snap_sequencer.c7
-rw-r--r--source/blender/editors/undo/ed_undo.c19
-rw-r--r--source/blender/editors/util/ed_util.c3
-rw-r--r--source/blender/editors/util/ed_util_imbuf.c4
-rw-r--r--source/blender/editors/util/ed_util_ops.cc3
-rw-r--r--source/blender/editors/util/select_utils.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_islands.c1
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c17
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c6
-rw-r--r--source/blender/freestyle/intern/application/AppView.h2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.h2
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeLight.h2
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h2
-rw-r--r--source/blender/freestyle/intern/system/FreestyleConfig.h2
-rw-r--r--source/blender/freestyle/intern/system/RandGen.h2
-rw-r--r--source/blender/freestyle/intern/view_map/Silhouette.h2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapIO.cpp2
-rw-r--r--source/blender/freestyle/intern/winged_edge/Curvature.cpp4
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.cpp4
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.h4
-rw-r--r--source/blender/functions/FN_cpp_type.hh7
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c14
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c23
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c111
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c84
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c43
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c335
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h6
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c37
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h4
-rw-r--r--source/blender/gpu/CMakeLists.txt4
-rw-r--r--source/blender/gpu/GPU_primitive.h2
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c4
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c6
-rw-r--r--source/blender/gpu/intern/gpu_context.cc6
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.cc8
-rw-r--r--source/blender/gpu/intern/gpu_material_library.c4
-rw-r--r--source/blender/gpu/intern/gpu_material_library.h2
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c6
-rw-r--r--source/blender/gpu/intern/gpu_state.cc2
-rw-r--r--source/blender/gpu/intern/gpu_state_private.hh2
-rw-r--r--source/blender/gpu/intern/gpu_texture.cc6
-rw-r--r--source/blender/gpu/intern/gpu_texture_private.hh4
-rw-r--r--source/blender/gpu/intern/gpu_uniform_buffer.cc4
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.cc8
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c2
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc6
-rw-r--r--source/blender/gpu/opengl/gl_context.cc2
-rw-r--r--source/blender/gpu/opengl/gl_debug.cc8
-rw-r--r--source/blender/gpu/opengl/gl_drawlist.hh2
-rw-r--r--source/blender/gpu/opengl/gl_framebuffer.cc6
-rw-r--r--source/blender/gpu/opengl/gl_query.cc8
-rw-r--r--source/blender/gpu/opengl/gl_state.cc8
-rw-r--r--source/blender/gpu/opengl/gl_texture.cc4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl2
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/intern/bmp.c7
-rw-r--r--source/blender/imbuf/intern/colormanagement.c4
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp2
-rw-r--r--source/blender/imbuf/intern/indexer.c4
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp2
-rw-r--r--source/blender/imbuf/intern/scaling.c494
-rw-r--r--source/blender/imbuf/intern/targa.c2
-rw-r--r--source/blender/imbuf/intern/thumbs.c2
-rw-r--r--source/blender/imbuf/intern/thumbs_blend.c2
-rw-r--r--source/blender/io/alembic/ABC_alembic.h4
-rw-r--r--source/blender/io/alembic/exporter/abc_custom_props.cc2
-rw-r--r--source/blender/io/alembic/exporter/abc_export_capi.cc3
-rw-r--r--source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc2
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_abstract.cc2
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_instance.cc2
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.cc2
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.cc2
-rw-r--r--source/blender/io/collada/AnimationExporter.cpp12
-rw-r--r--source/blender/io/collada/AnimationImporter.cpp12
-rw-r--r--source/blender/io/collada/BCAnimationCurve.h2
-rw-r--r--source/blender/io/collada/ControllerExporter.cpp23
-rw-r--r--source/blender/io/collada/ControllerExporter.h10
-rw-r--r--source/blender/io/collada/DocumentImporter.cpp6
-rw-r--r--source/blender/io/collada/ImageExporter.cpp2
-rw-r--r--source/blender/io/collada/MeshImporter.cpp6
-rw-r--r--source/blender/io/collada/SkinInfo.cpp4
-rw-r--r--source/blender/io/collada/collada_internal.cpp2
-rw-r--r--source/blender/io/collada/collada_internal.h2
-rw-r--r--source/blender/io/collada/collada_utils.cpp8
-rw-r--r--source/blender/io/gpencil/gpencil_io.h2
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_base.cc23
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_base.hh6
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_import_svg.hh4
-rw-r--r--source/blender/io/usd/intern/usd_hierarchy_iterator.cc2
-rw-r--r--source/blender/io/usd/intern/usd_writer_abstract.cc2
-rw-r--r--source/blender/io/usd/intern/usd_writer_camera.cc2
-rw-r--r--source/blender/io/usd/intern/usd_writer_light.cc2
-rw-r--r--source/blender/makesdna/DNA_ID.h15
-rw-r--r--source/blender/makesdna/DNA_action_types.h6
-rw-r--r--source/blender/makesdna/DNA_asset_defaults.h7
-rw-r--r--source/blender/makesdna/DNA_asset_types.h57
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h26
-rw-r--r--source/blender/makesdna/DNA_curve_types.h4
-rw-r--r--source/blender/makesdna/DNA_defs.h2
-rw-r--r--source/blender/makesdna/DNA_fileglobal_types.h2
-rw-r--r--source/blender/makesdna/DNA_fluid_types.h8
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_defaults.h18
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h77
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h12
-rw-r--r--source/blender/makesdna/DNA_lattice_types.h5
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h6
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_defaults.h3
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h18
-rw-r--r--source/blender/makesdna/DNA_node_types.h43
-rw-r--r--source/blender/makesdna/DNA_object_types.h23
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h2
-rw-r--r--source/blender/makesdna/DNA_particle_types.h5
-rw-r--r--source/blender/makesdna/DNA_pointcache_types.h50
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h4
-rw-r--r--source/blender/makesdna/DNA_scene_types.h5
-rw-r--r--source/blender/makesdna/DNA_screen_types.h31
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h137
-rw-r--r--source/blender/makesdna/DNA_texture_types.h8
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h2
-rw-r--r--source/blender/makesdna/DNA_vfont_types.h2
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h6
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h10
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h7
-rw-r--r--source/blender/makesdna/intern/dna_defaults.c4
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c6
-rw-r--r--source/blender/makesdna/intern/dna_rename_defs.h1
-rw-r--r--source/blender/makesdna/intern/makesdna.c66
-rw-r--r--source/blender/makesrna/RNA_access.h4
-rw-r--r--source/blender/makesrna/RNA_enum_types.h17
-rw-r--r--source/blender/makesrna/RNA_types.h4
-rw-r--r--source/blender/makesrna/intern/makesrna.c6
-rw-r--r--source/blender/makesrna/intern/rna_ID.c110
-rw-r--r--source/blender/makesrna/intern/rna_access.c51
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c18
-rw-r--r--source/blender/makesrna/intern/rna_armature.c24
-rw-r--r--source/blender/makesrna/intern/rna_asset.c187
-rw-r--r--source/blender/makesrna/intern/rna_brush.c4
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c1
-rw-r--r--source/blender/makesrna/intern/rna_collection.c4
-rw-r--r--source/blender/makesrna/intern/rna_color.c2
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c60
-rw-r--r--source/blender/makesrna/intern/rna_context.c27
-rw-r--r--source/blender/makesrna/intern/rna_curve.c6
-rw-r--r--source/blender/makesrna/intern/rna_define.c6
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c8
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c4
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c256
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_internal.h15
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_key.c2
-rw-r--r--source/blender/makesrna/intern/rna_layer.c10
-rw-r--r--source/blender/makesrna/intern/rna_mask.c6
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c8
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c31
-rw-r--r--source/blender/makesrna/intern/rna_nla.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c176
-rw-r--r--source/blender/makesrna/intern/rna_object.c144
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c7
-rw-r--r--source/blender/makesrna/intern/rna_particle.c10
-rw-r--r--source/blender/makesrna/intern/rna_pose.c10
-rw-r--r--source/blender/makesrna/intern/rna_pose_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_rna.c24
-rw-r--r--source/blender/makesrna/intern/rna_scene.c47
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c7
-rw-r--r--source/blender/makesrna/intern/rna_screen.c2
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c99
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c38
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c4
-rw-r--r--source/blender/makesrna/intern/rna_space.c333
-rw-r--r--source/blender/makesrna/intern/rna_timeline.c10
-rw-r--r--source/blender/makesrna/intern/rna_ui.c48
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c182
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c15
-rw-r--r--source/blender/makesrna/intern/rna_wm.c21
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c26
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c20
-rwxr-xr-xsource/blender/makesrna/rna_cleanup/rna_cleaner.py2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c4
-rw-r--r--source/blender/modifiers/intern/MOD_array.c2
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_build.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c2
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c2
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c16
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc15
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c8
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc138
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc90
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.hh13
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c4
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c1
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c2
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c4
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_extrude.c16
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_nonmanifold.c15
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c99
-rw-r--r--source/blender/modifiers/intern/MOD_util.c23
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c11
-rw-r--r--source/blender/modifiers/intern/MOD_weld.c7
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c2
-rw-r--r--source/blender/nodes/CMakeLists.txt20
-rw-r--r--source/blender/nodes/NOD_function.h1
-rw-r--r--source/blender/nodes/NOD_geometry.h12
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh8
-rw-r--r--source/blender/nodes/NOD_geometry_nodes_eval_log.hh309
-rw-r--r--source/blender/nodes/NOD_static_types.h15
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c7
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_antialiasing.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_zcombine.c2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_to_int.cc95
-rw-r--r--source/blender/nodes/geometry/node_geometry_tree.cc30
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc13
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc223
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc20
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc146
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc241
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc17
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc76
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc47
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc (renamed from source/blender/nodes/geometry/nodes/node_geo_subdivide.cc)18
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_raycast.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_viewer.cc31
-rw-r--r--source/blender/nodes/intern/geometry_nodes_eval_log.cc361
-rw-r--r--source/blender/nodes/intern/node_common.c11
-rw-r--r--source/blender/nodes/intern/node_geometry_exec.cc16
-rw-r--r--source/blender/nodes/intern/node_socket.cc4
-rw-r--r--source/blender/nodes/intern/node_tree_ref.cc2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c2
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c7
-rw-r--r--source/blender/python/BPY_extern.h2
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c16
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c4
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c2
-rw-r--r--source/blender/python/generic/idprop_py_api.c2
-rw-r--r--source/blender/python/generic/imbuf_py_api.c2
-rw-r--r--source/blender/python/generic/py_capi_utils.c12
-rw-r--r--source/blender/python/gpu/gpu_py_uniformbuffer.c2
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c6
-rw-r--r--source/blender/python/intern/bpy_app_translations.c4
-rw-r--r--source/blender/python/intern/bpy_driver.c10
-rw-r--r--source/blender/python/intern/bpy_gizmo_wrap.c2
-rw-r--r--source/blender/python/intern/bpy_interface.c6
-rw-r--r--source/blender/python/intern/bpy_interface_atexit.c5
-rw-r--r--source/blender/python/intern/bpy_library_load.c5
-rw-r--r--source/blender/python/intern/bpy_msgbus.c8
-rw-r--r--source/blender/python/intern/bpy_operator.c10
-rw-r--r--source/blender/python/intern/bpy_props.c8
-rw-r--r--source/blender/python/intern/bpy_rna.c129
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c2
-rw-r--r--source/blender/python/intern/bpy_rna_array.c4
-rw-r--r--source/blender/python/intern/bpy_rna_gizmo.c4
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c4
-rw-r--r--source/blender/python/intern/bpy_utils_previews.c1
-rw-r--r--source/blender/python/mathutils/mathutils_Color.c4
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c8
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c9
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c2
-rw-r--r--source/blender/render/RE_texture.h2
-rw-r--r--source/blender/render/intern/bake.c16
-rw-r--r--source/blender/render/intern/engine.c6
-rw-r--r--source/blender/render/intern/pipeline.c10
-rw-r--r--source/blender/render/intern/render_result.c8
-rw-r--r--source/blender/render/intern/render_types.h2
-rw-r--r--source/blender/render/intern/texture_image.c10
-rw-r--r--source/blender/render/intern/texture_pointdensity.c8
-rw-r--r--source/blender/sequencer/CMakeLists.txt2
-rw-r--r--source/blender/sequencer/SEQ_clipboard.h4
-rw-r--r--source/blender/sequencer/SEQ_iterator.h4
-rw-r--r--source/blender/sequencer/SEQ_proxy.h2
-rw-r--r--source/blender/sequencer/SEQ_sequencer.h2
-rw-r--r--source/blender/sequencer/SEQ_time.h1
-rw-r--r--source/blender/sequencer/SEQ_transform.h2
-rw-r--r--source/blender/sequencer/intern/clipboard.c28
-rw-r--r--source/blender/sequencer/intern/effects.c4
-rw-r--r--source/blender/sequencer/intern/image_cache.c2
-rw-r--r--source/blender/sequencer/intern/iterator.c12
-rw-r--r--source/blender/sequencer/intern/modifier.c2
-rw-r--r--source/blender/sequencer/intern/render.c6
-rw-r--r--source/blender/sequencer/intern/sequencer.c4
-rw-r--r--source/blender/sequencer/intern/strip_add.c4
-rw-r--r--source/blender/sequencer/intern/strip_edit.c6
-rw-r--r--source/blender/sequencer/intern/strip_time.c11
-rw-r--r--source/blender/sequencer/intern/strip_transform.c4
-rw-r--r--source/blender/shader_fx/intern/FX_shader_flip.c4
-rw-r--r--source/blender/simulation/SIM_mass_spring.h2
-rw-r--r--source/blender/simulation/intern/ConstrainedConjugateGradient.h2
-rw-r--r--source/blender/simulation/intern/SIM_mass_spring.cpp6
-rw-r--r--source/blender/simulation/intern/hair_volume.cpp6
-rw-r--r--source/blender/simulation/intern/implicit_blender.c12
-rw-r--r--source/blender/simulation/intern/implicit_eigen.cpp8
-rw-r--r--source/blender/windowmanager/CMakeLists.txt2
-rw-r--r--source/blender/windowmanager/WM_api.h12
-rw-r--r--source/blender/windowmanager/WM_types.h11
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c2
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c4
-rw-r--r--source/blender/windowmanager/intern/wm.c4
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c10
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c4
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c1
-rw-r--r--source/blender/windowmanager/intern/wm_event_query.c5
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c24
-rw-r--r--source/blender/windowmanager/intern/wm_files.c12
-rw-r--r--source/blender/windowmanager/intern/wm_gesture_ops.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c15
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c18
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c10
-rw-r--r--source/blender/windowmanager/intern/wm_splash_screen.c2
-rw-r--r--source/blender/windowmanager/intern/wm_uilist_type.c95
-rw-r--r--source/blender/windowmanager/intern/wm_window.c18
-rw-r--r--source/blender/windowmanager/wm_event_types.h6
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_actions.c2
-rw-r--r--source/creator/creator_args.c2
-rw-r--r--tests/performance/api/__init__.py7
-rw-r--r--tests/performance/api/config.py259
-rw-r--r--tests/performance/api/device.py71
-rw-r--r--tests/performance/api/environment.py244
-rw-r--r--tests/performance/api/graph.py114
-rw-r--r--tests/performance/api/graph.template.html86
-rw-r--r--tests/performance/api/test.py73
-rwxr-xr-xtests/performance/benchmark299
-rw-r--r--tests/performance/tests/__init__.py1
-rw-r--r--tests/performance/tests/animation.py41
-rw-r--r--tests/performance/tests/blend_load.py42
-rw-r--r--tests/performance/tests/cycles.py92
-rw-r--r--tests/python/alembic_export_tests.py18
-rw-r--r--tests/python/bl_alembic_io_test.py1
-rw-r--r--tests/python/bl_animation_fcurves.py1
-rw-r--r--tests/python/bl_blendfile_library_overrides.py8
-rw-r--r--tests/python/bl_constraints.py64
-rw-r--r--tests/python/bl_pyapi_idprop.py1
-rw-r--r--tests/python/bl_run_operators_event_simulate.py35
-rw-r--r--tests/python/compositor_render_tests.py1
-rw-r--r--tests/python/cycles_render_tests.py1
-rw-r--r--tests/python/modules/mesh_test.py2
-rwxr-xr-xtests/python/modules/render_report.py2
-rw-r--r--tests/python/operators.py2
1441 files changed, 26425 insertions, 13745 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 297e32bd67e..c5992993f91 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -349,7 +349,7 @@ mark_as_advanced(WITH_SYSTEM_GLOG)
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
# Misc
-if(WIN32)
+if(WIN32 OR APPLE)
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
endif()
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
@@ -1705,22 +1705,18 @@ if(WITH_PYTHON)
endif()
endif()
-if(MSVC)
- string(APPEND CMAKE_CXX_FLAGS " /std:c++17")
- # Make MSVC properly report the value of the __cplusplus preprocessor macro
- # Available MSVC 15.7 (1914) and up, without this it reports 199711L regardless
- # of the C++ standard chosen above
- if(MSVC_VERSION GREATER 1913)
- string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus")
- endif()
-elseif(
- CMAKE_COMPILER_IS_GNUCC OR
- CMAKE_C_COMPILER_ID MATCHES "Clang" OR
- CMAKE_C_COMPILER_ID MATCHES "Intel"
-)
- string(APPEND CMAKE_CXX_FLAGS " -std=c++17")
-else()
- message(FATAL_ERROR "Unknown compiler ${CMAKE_C_COMPILER_ID}, can't enable C++17 build")
+# Select C++17 as the standard for C++ projects.
+set(CMAKE_CXX_STANDARD 17)
+# If C++17 is not available, downgrading to an earlier standard is NOT OK.
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+# Do not enable compiler specific language extentions.
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+# Make MSVC properly report the value of the __cplusplus preprocessor macro
+# Available MSVC 15.7 (1914) and up, without this it reports 199711L regardless
+# of the C++ standard chosen above.
+if(MSVC AND MSVC_VERSION GREATER 1913)
+ string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus")
endif()
# Visual Studio has all standards it supports available by default
@@ -1915,6 +1911,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_IK_ITASC)
info_cfg_option(WITH_IK_SOLVER)
info_cfg_option(WITH_INPUT_NDOF)
+ info_cfg_option(WITH_INPUT_IME)
info_cfg_option(WITH_INTERNATIONAL)
info_cfg_option(WITH_OPENCOLLADA)
info_cfg_option(WITH_OPENCOLORIO)
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index fb79eee62be..8c739dcd68e 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -56,6 +56,7 @@ else()
endif()
include(cmake/zlib.cmake)
+include(cmake/zstd.cmake)
include(cmake/openal.cmake)
include(cmake/png.cmake)
include(cmake/jpeg.cmake)
@@ -164,6 +165,7 @@ endif()
if(UNIX AND NOT APPLE)
include(cmake/libglu.cmake)
include(cmake/mesa.cmake)
+ include(cmake/wayland_protocols.cmake)
endif()
include(cmake/harvest.cmake)
diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake
index 27351ddee45..b4d96ea856f 100644
--- a/build_files/build_environment/cmake/download.cmake
+++ b/build_files/build_environment/cmake/download.cmake
@@ -87,7 +87,9 @@ download_source(LIBGLU)
download_source(MESA)
download_source(NASM)
download_source(XR_OPENXR_SDK)
+download_source(WL_PROTOCOLS)
download_source(ISPC)
download_source(GMP)
download_source(POTRACE)
download_source(HARU)
+download_source(ZSTD)
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake
index fc7e652a028..a19c332457d 100644
--- a/build_files/build_environment/cmake/harvest.cmake
+++ b/build_files/build_environment/cmake/harvest.cmake
@@ -126,6 +126,8 @@ if(UNIX AND NOT APPLE)
harvest(xml2/include xml2/include "*.h")
harvest(xml2/lib xml2/lib "*.a")
+
+ harvest(wayland-protocols/share/wayland-protocols wayland-protocols/share/wayland-protocols/ "*.xml")
else()
harvest(blosc/lib openvdb/lib "*.a")
harvest(xml2/lib opencollada/lib "*.a")
@@ -190,6 +192,8 @@ harvest(potrace/include potrace/include "*.h")
harvest(potrace/lib potrace/lib "*.a")
harvest(haru/include haru/include "*.h")
harvest(haru/lib haru/lib "*.a")
+harvest(zstd/include zstd/include "*.h")
+harvest(zstd/lib zstd/lib "*.a")
if(UNIX AND NOT APPLE)
harvest(libglu/lib mesa/lib "*.so*")
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index d93b8463b4b..a71fc4b85e4 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -216,9 +216,9 @@ set(OPENVDB_HASH 01b490be16cc0e15c690f9a153c21461)
set(OPENVDB_HASH_TYPE MD5)
set(OPENVDB_FILE openvdb-${OPENVDB_VERSION}.tar.gz)
-set(NANOVDB_GIT_UID e62f7a0bf1e27397223c61ddeaaf57edf111b77f)
+set(NANOVDB_GIT_UID dc37d8a631922e7bef46712947dc19b755f3e841)
set(NANOVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/${NANOVDB_GIT_UID}.tar.gz)
-set(NANOVDB_HASH 90919510bc6ccd630fedc56f748cb199)
+set(NANOVDB_HASH e7b9e863ec2f3b04ead171dec2322807)
set(NANOVDB_HASH_TYPE MD5)
set(NANOVDB_FILE nano-vdb-${NANOVDB_GIT_UID}.tar.gz)
@@ -456,12 +456,18 @@ set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
set(NASM_HASH_TYPE SHA256)
set(NASM_FILE nasm-${NASM_VERSION}.tar.gz)
-set(XR_OPENXR_SDK_VERSION 1.0.14)
+set(XR_OPENXR_SDK_VERSION 1.0.17)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
-set(XR_OPENXR_SDK_HASH 0df6b2fd6045423451a77ff6bc3e1a75)
+set(XR_OPENXR_SDK_HASH bf0fd8828837edff01047474e90013e1)
set(XR_OPENXR_SDK_HASH_TYPE MD5)
set(XR_OPENXR_SDK_FILE OpenXR-SDK-${XR_OPENXR_SDK_VERSION}.tar.gz)
+set(WL_PROTOCOLS_VERSION 1.21)
+set(WL_PROTOCOLS_FILE wayland-protocols-${WL_PROTOCOLS_VERSION}.tar.gz)
+set(WL_PROTOCOLS_URI https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/${WL_PROTOCOLS_VERSION}/${WL_PROTOCOLS_FILE})
+set(WL_PROTOCOLS_HASH af5ca07e13517cdbab33504492cef54a)
+set(WL_PROTOCOLS_HASH_TYPE MD5)
+
if(BLENDER_PLATFORM_ARM)
# Unreleased version with macOS arm support.
set(ISPC_URI https://github.com/ispc/ispc/archive/f5949c055eb9eeb93696978a3da4bfb3a6a30b35.zip)
@@ -494,5 +500,11 @@ set(HARU_HASH 4f916aa49c3069b3a10850013c507460)
set(HARU_HASH_TYPE MD5)
set(HARU_FILE libharu-${HARU_VERSION}.tar.gz)
+set(ZSTD_VERSION 1.5.0)
+set(ZSTD_URI https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}/zstd-${ZSTD_VERSION}.tar.gz)
+set(ZSTD_HASH 5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94)
+set(ZSTD_HASH_TYPE SHA256)
+set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz)
+
set(SSE2NEON_GIT https://github.com/DLTcollab/sse2neon.git)
set(SSE2NEON_GIT_HASH fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
diff --git a/build_files/build_environment/cmake/wayland_protocols.cmake b/build_files/build_environment/cmake/wayland_protocols.cmake
new file mode 100644
index 00000000000..02db453be42
--- /dev/null
+++ b/build_files/build_environment/cmake/wayland_protocols.cmake
@@ -0,0 +1,27 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+ExternalProject_Add(external_wayland_protocols
+ URL file://${PACKAGE_DIR}/${WL_PROTOCOLS_FILE}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH ${WL_PROTOCOLS_HASH_TYPE}=${WL_PROTOCOLS_HASH}
+ PREFIX ${BUILD_DIR}/wayland-protocols
+ CONFIGURE_COMMAND meson --prefix ${LIBDIR}/wayland-protocols . ../external_wayland_protocols -Dtests=false
+ BUILD_COMMAND ninja
+ INSTALL_COMMAND ninja install
+)
diff --git a/build_files/build_environment/cmake/zstd.cmake b/build_files/build_environment/cmake/zstd.cmake
new file mode 100644
index 00000000000..86cb2d016c6
--- /dev/null
+++ b/build_files/build_environment/cmake/zstd.cmake
@@ -0,0 +1,51 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(ZSTD_EXTRA_ARGS
+ -DZSTD_BUILD_PROGRAMS=OFF
+ -DZSTD_BUILD_SHARED=OFF
+ -DZSTD_BUILD_STATIC=ON
+ -DZSTD_BUILD_TESTS=OFF
+ -DZSTD_LEGACY_SUPPORT=OFF
+ -DZSTD_LZ4_SUPPORT=OFF
+ -DZSTD_LZMA_SUPPORT=OFF
+ -DZSTD_MULTITHREAD_SUPPORT=ON
+ -DZSTD_PROGRAMS_LINK_SHARED=OFF
+ -DZSTD_USE_STATIC_RUNTIME=OFF
+ -DZSTD_ZLIB_SUPPORT=OFF
+)
+
+ExternalProject_Add(external_zstd
+ URL file://${PACKAGE_DIR}/${ZSTD_FILE}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH ${ZSTD_HASH_TYPE}=${ZSTD_HASH}
+ PREFIX ${BUILD_DIR}/zstd
+ SOURCE_SUBDIR build/cmake
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/zstd ${DEFAULT_CMAKE_FLAGS} ${ZSTD_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/zstd
+)
+
+if(WIN32)
+ if(BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_zstd after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/zstd/lib/zstd_static${LIBEXT} ${HARVEST_TARGET}/zstd/lib/zstd_static${LIBEXT}
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/zstd/include/ ${HARVEST_TARGET}/zstd/include/
+ DEPENDEES install
+ )
+ endif()
+endif()
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 808e154955d..c5b7198d012 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -572,7 +572,7 @@ FFMPEG_FORCE_REBUILD=false
FFMPEG_SKIP=false
_ffmpeg_list_sep=";"
-XR_OPENXR_VERSION="1.0.14"
+XR_OPENXR_VERSION="1.0.17"
XR_OPENXR_VERSION_SHORT="1.0"
XR_OPENXR_VERSION_MIN="1.0.8"
XR_OPENXR_VERSION_MAX="2.0"
@@ -1073,7 +1073,7 @@ OPENVDB_SOURCE=( "https://github.com/AcademySoftwareFoundation/openvdb/archive/v
#~ OPENVDB_SOURCE_REPO_BRANCH="dev"
NANOVDB_USE_REPO=false
-NANOVDB_SOURCE_REPO_UID="e62f7a0bf1e27397223c61ddeaaf57edf111b77f"
+NANOVDB_SOURCE_REPO_UID="dc37d8a631922e7bef46712947dc19b755f3e841"
NANOVDB_SOURCE=( "https://github.com/AcademySoftwareFoundation/openvdb/archive/${NANOVDB_SOURCE_REPO_UID}.tar.gz" )
ALEMBIC_USE_REPO=false
@@ -1108,9 +1108,9 @@ FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
XR_OPENXR_USE_REPO=false
XR_OPENXR_SOURCE=("https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_VERSION}.tar.gz")
-#~ XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK.git")
-#~ XR_OPENXR_REPO_UID="5900c51562769b03bea699dc0352cae56acb6419d"
-#~ XR_OPENXR_REPO_BRANCH="master"
+XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK.git")
+XR_OPENXR_REPO_UID="bf21ccb1007bb531b45d9978919a56ea5059c245"
+XR_OPENXR_REPO_BRANCH="master"
# C++11 is required now
CXXFLAGS_BACK=$CXXFLAGS
@@ -1128,6 +1128,7 @@ Those libraries should be available as packages in all recent distributions (opt
* Basics of dev environment (cmake, gcc, svn , git, ...).
* libjpeg, libpng, libtiff, [openjpeg2], [libopenal].
* libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed).
+ * libwayland-client0, libwayland-cursor0, libwayland-egl1, libxkbcommon0, libdbus-1-3, libegl1 (Wayland)
* libsqlite3, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp.
* libsdl2, libglew, libpugixml, libpotrace, [libgmp], [libglewmx], fontconfig, [libharu/libhpdf].\""
@@ -2737,7 +2738,7 @@ _init_openvdb() {
_git=false
_inst=$INST/openvdb-$OPENVDB_VERSION_SHORT
_inst_shortcut=$INST/openvdb
-
+
_openvdb_source=$OPENVDB_SOURCE
if [ "$WITH_NANOVDB" = true ]; then
_openvdb_source=$NANOVDB_SOURCE
@@ -2842,7 +2843,7 @@ compile_OPENVDB() {
if [ -d $INST/blosc ]; then
cmake_d="$cmake_d -D Blosc_ROOT=$INST/blosc"
fi
-
+
cmake $cmake_d ..
make -j$THREADS install
@@ -3839,6 +3840,7 @@ install_DEB() {
_packages="gawk cmake cmake-curses-gui build-essential libjpeg-dev libpng-dev libtiff-dev \
git libfreetype6-dev libfontconfig-dev libx11-dev flex bison libxxf86vm-dev \
libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
+ libwayland-dev wayland-protocols libegl-dev libxkbcommon-dev libdbus-1-dev linux-libc-dev \
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \
libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
libsdl2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev \
@@ -4508,6 +4510,7 @@ install_RPM() {
_packages="gcc gcc-c++ git make cmake tar bzip2 xz findutils flex bison fontconfig-devel \
libtiff-devel libjpeg-devel libpng-devel sqlite-devel fftw-devel SDL2-devel \
libX11-devel libXi-devel libXcursor-devel libXrandr-devel libXinerama-devel \
+ wayland-devel wayland-protocols-devel mesa-libEGL-devel libxkbcommon-devel dbus-devel kernel-headers \
wget ncurses-devel readline-devel $OPENJPEG_DEV openal-soft-devel \
glew-devel yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV patch \
libxml2-devel yaml-cpp-devel tinyxml-devel jemalloc-devel \
diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff
index e195ca272de..5a50a3f8756 100644
--- a/build_files/build_environment/patches/ffmpeg.diff
+++ b/build_files/build_environment/patches/ffmpeg.diff
@@ -68,3 +68,32 @@
+
return ret;
}
+--- a/libavcodec/rl.c
++++ b/libavcodec/rl.c
+@@ -71,7 +71,7 @@ av_cold void ff_rl_init(RLTable *rl,
+ 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));
+ 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);
+@@ -80,8 +80,10 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
+ int qmul = q * 2;
+ int qadd = (q - 1) | 1;
+
+- if (!rl->rl_vlc[q])
++ if (!rl->rl_vlc[q]){
++ av_free(table);
+ return;
++ }
+
+ if (q == 0) {
+ qmul = 1;
+@@ -113,4 +115,5 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
+ rl->rl_vlc[q][i].run = run;
+ }
+ }
++ av_free(table);
+ }
diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py
index 8e626f8d056..bf842466add 100644
--- a/build_files/cmake/cmake_consistency_check_config.py
+++ b/build_files/cmake/cmake_consistency_check_config.py
@@ -8,6 +8,9 @@ IGNORE_SOURCE = (
# specific source files
"extern/audaspace/",
+ # Use for `WIN32` only.
+ "source/creator/blender_launcher_win32.c",
+
# specific source files
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp",
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index ee6413774aa..ccd5b47c776 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -29,6 +29,7 @@ set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
+set(WITH_INPUT_IME ON CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index 75aafd45c82..b8180d733de 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -30,6 +30,7 @@ set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
+set(WITH_INPUT_IME ON CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
diff --git a/build_files/windows/autodetect_msvc.cmd b/build_files/windows/autodetect_msvc.cmd
index 6cee4765b93..a4ab8929040 100644
--- a/build_files/windows/autodetect_msvc.cmd
+++ b/build_files/windows/autodetect_msvc.cmd
@@ -1,9 +1,9 @@
echo No explicit msvc version requested, autodetecting version.
-call "%~dp0\detect_msvc2017.cmd"
+call "%~dp0\detect_msvc2019.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
-call "%~dp0\detect_msvc2019.cmd"
+call "%~dp0\detect_msvc2017.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
call "%~dp0\detect_msvc2022.cmd"
diff --git a/doc/python_api/examples/bpy.app.handlers.2.py b/doc/python_api/examples/bpy.app.handlers.2.py
index aaaedeabecb..d514fa3fa4b 100644
--- a/doc/python_api/examples/bpy.app.handlers.2.py
+++ b/doc/python_api/examples/bpy.app.handlers.2.py
@@ -12,6 +12,7 @@ such cases, lock the interface (Render → Lock Interface or
Below is an example of a mesh that is altered from a handler:
"""
+
def frame_change_pre(scene):
# A triangle that shifts in the z direction
zshift = scene.frame_current * 0.1
diff --git a/doc/python_api/examples/bpy.app.timers.5.py b/doc/python_api/examples/bpy.app.timers.5.py
index 821a047d7c7..dda5ea12e73 100644
--- a/doc/python_api/examples/bpy.app.timers.5.py
+++ b/doc/python_api/examples/bpy.app.timers.5.py
@@ -16,10 +16,12 @@ execution_queue = queue.Queue()
def run_in_main_thread(function):
execution_queue.put(function)
+
def execute_queued_functions():
while not execution_queue.empty():
function = execution_queue.get()
function()
return 1.0
+
bpy.app.timers.register(execute_queued_functions)
diff --git a/doc/python_api/examples/bpy.msgbus.1.py b/doc/python_api/examples/bpy.msgbus.1.py
index 21198471ffa..8164272d521 100644
--- a/doc/python_api/examples/bpy.msgbus.1.py
+++ b/doc/python_api/examples/bpy.msgbus.1.py
@@ -31,11 +31,13 @@ owner = object()
subscribe_to = bpy.context.object.location
+
def msgbus_callback(*args):
# This will print:
# Something changed! (1, 2, 3)
print("Something changed!", args)
+
bpy.msgbus.subscribe_rna(
key=subscribe_to,
owner=owner,
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.7.py b/doc/python_api/examples/bpy.types.Depsgraph.7.py
index 11982730fc9..afea8dfd618 100644
--- a/doc/python_api/examples/bpy.types.Depsgraph.7.py
+++ b/doc/python_api/examples/bpy.types.Depsgraph.7.py
@@ -44,7 +44,7 @@ class OBJECT_OT_object_to_curve(bpy.types.Operator):
# Remove temporary curve.
obj.to_curve_clear()
# Invoke to_curve() with applying modifiers.
- curve_with_modifiers = obj.to_curve(depsgraph, apply_modifiers = True)
+ curve_with_modifiers = obj.to_curve(depsgraph, apply_modifiers=True)
self.report({'INFO'}, f"{len(curve_with_modifiers.splines)} splines in new curve with modifiers.")
# Remove temporary curve.
obj.to_curve_clear()
diff --git a/doc/python_api/examples/gpu.6.py b/doc/python_api/examples/gpu.6.py
index 334a606055a..be164a03028 100644
--- a/doc/python_api/examples/gpu.6.py
+++ b/doc/python_api/examples/gpu.6.py
@@ -21,6 +21,7 @@ batch = batch_for_shader(
},
)
+
def draw():
shader.bind()
shader.uniform_sampler("image", texture)
diff --git a/extern/audaspace/include/devices/SoftwareDevice.h b/extern/audaspace/include/devices/SoftwareDevice.h
index 209be9941b1..c3af5cfd902 100644
--- a/extern/audaspace/include/devices/SoftwareDevice.h
+++ b/extern/audaspace/include/devices/SoftwareDevice.h
@@ -266,6 +266,12 @@ protected:
void setSpecs(Specs specs);
/**
+ * Sets the audio output specification of the device.
+ * \param specs The output specification.
+ */
+ void setSpecs(DeviceSpecs specs);
+
+ /**
* Empty default constructor. To setup the device call the function create()
* and to uninitialize call destroy().
*/
diff --git a/extern/audaspace/include/respec/Mixer.h b/extern/audaspace/include/respec/Mixer.h
index 600467826cd..9880d5fdcae 100644
--- a/extern/audaspace/include/respec/Mixer.h
+++ b/extern/audaspace/include/respec/Mixer.h
@@ -88,6 +88,12 @@ public:
void setSpecs(Specs specs);
/**
+ * Sets the target specification for superposing.
+ * \param specs The target specification.
+ */
+ void setSpecs(DeviceSpecs specs);
+
+ /**
* Mixes a buffer.
* \param buffer The buffer to superpose.
* \param start The start sample of the buffer.
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
index 3ffe97661d8..cbfb5e96e6c 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
@@ -78,6 +78,7 @@ void PulseAudioDevice::runMixingThread()
if(shouldStop())
{
AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr);
+ AUD_pa_stream_flush(m_stream, nullptr, nullptr);
doStop();
return;
}
@@ -86,7 +87,10 @@ void PulseAudioDevice::runMixingThread()
if(AUD_pa_stream_is_corked(m_stream))
AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr);
- AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
+ // similar to AUD_pa_mainloop_iterate(m_mainloop, false, nullptr); except with a longer timeout
+ AUD_pa_mainloop_prepare(m_mainloop, 1 << 14);
+ AUD_pa_mainloop_poll(m_mainloop);
+ AUD_pa_mainloop_dispatch(m_mainloop);
}
}
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
index 4b9e1ffea2b..361aa518087 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
@@ -24,6 +24,7 @@ PULSEAUDIO_SYMBOL(pa_context_unref);
PULSEAUDIO_SYMBOL(pa_stream_begin_write);
PULSEAUDIO_SYMBOL(pa_stream_connect_playback);
PULSEAUDIO_SYMBOL(pa_stream_cork);
+PULSEAUDIO_SYMBOL(pa_stream_flush);
PULSEAUDIO_SYMBOL(pa_stream_is_corked);
PULSEAUDIO_SYMBOL(pa_stream_new);
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
@@ -35,3 +36,6 @@ PULSEAUDIO_SYMBOL(pa_mainloop_free);
PULSEAUDIO_SYMBOL(pa_mainloop_get_api);
PULSEAUDIO_SYMBOL(pa_mainloop_new);
PULSEAUDIO_SYMBOL(pa_mainloop_iterate);
+PULSEAUDIO_SYMBOL(pa_mainloop_prepare);
+PULSEAUDIO_SYMBOL(pa_mainloop_poll);
+PULSEAUDIO_SYMBOL(pa_mainloop_dispatch);
diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
index b4632ebb83e..a5382bb9692 100644
--- a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
+++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
@@ -31,65 +31,81 @@ template <class T> void SafeRelease(T **ppT)
}
}
-void WASAPIDevice::runMixingThread()
+HRESULT WASAPIDevice::setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size)
{
- UINT32 buffer_size;
+ const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
+
UINT32 padding;
UINT32 length;
data_t* buffer;
- IAudioRenderClient* render_client = nullptr;
+ HRESULT result;
- {
- std::lock_guard<ILockable> lock(*this);
+ if(FAILED(result = m_audio_client->GetBufferSize(&buffer_size)))
+ return result;
- const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
+ if(FAILED(result = m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
+ return result;
- if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
- goto init_error;
+ if(FAILED(result = m_audio_client->GetCurrentPadding(&padding)))
+ return result;
- if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
- goto init_error;
+ length = buffer_size - padding;
- if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
- goto init_error;
+ if(FAILED(result = render_client->GetBuffer(length, &buffer)))
+ return result;
- length = buffer_size - padding;
+ mix((data_t*)buffer, length);
- if(FAILED(render_client->GetBuffer(length, &buffer)))
- goto init_error;
+ if(FAILED(result = render_client->ReleaseBuffer(length, 0)))
+ return result;
- mix((data_t*)buffer, length);
+ m_audio_client->Start();
- if(FAILED(render_client->ReleaseBuffer(length, 0)))
- {
- init_error:
- SafeRelease(&render_client);
- doStop();
- return;
- }
- }
+ return result;
+}
- m_audio_client->Start();
+void WASAPIDevice::runMixingThread()
+{
+ UINT32 buffer_size;
+
+ IAudioRenderClient* render_client = nullptr;
+
+ std::chrono::milliseconds sleep_duration;
- auto sleepDuration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
+ bool run_init = true;
for(;;)
{
+ HRESULT result = S_OK;
+
{
+ UINT32 padding;
+ UINT32 length;
+ data_t* buffer;
std::lock_guard<ILockable> lock(*this);
- if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
+ if(run_init)
+ {
+ result = setupRenderClient(render_client, buffer_size);
+
+ if(FAILED(result))
+ goto stop_thread;
+
+ sleep_duration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
+ }
+
+ if(FAILED(result = m_audio_client->GetCurrentPadding(&padding)))
goto stop_thread;
length = buffer_size - padding;
- if(FAILED(render_client->GetBuffer(length, &buffer)))
+ if(FAILED(result = render_client->GetBuffer(length, &buffer)))
goto stop_thread;
mix((data_t*)buffer, length);
- if(FAILED(render_client->ReleaseBuffer(length, 0)))
+ if(FAILED(result = render_client->ReleaseBuffer(length, 0)))
goto stop_thread;
// stop thread
@@ -98,53 +114,51 @@ void WASAPIDevice::runMixingThread()
stop_thread:
m_audio_client->Stop();
SafeRelease(&render_client);
- doStop();
- return;
+
+ if(result == AUDCLNT_E_DEVICE_INVALIDATED)
+ {
+ DeviceSpecs specs = m_specs;
+ if(!setupDevice(specs))
+ result = S_FALSE;
+ else
+ {
+ setSpecs(specs);
+
+ run_init = true;
+ }
+ }
+
+ if(result != AUDCLNT_E_DEVICE_INVALIDATED)
+ {
+ doStop();
+ return;
+ }
}
}
- std::this_thread::sleep_for(sleepDuration);
+ std::this_thread::sleep_for(sleep_duration);
}
}
-WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
- m_imm_device_enumerator(nullptr),
- m_imm_device(nullptr),
- m_audio_client(nullptr),
-
- m_wave_format_extensible({})
+bool WASAPIDevice::setupDevice(DeviceSpecs &specs)
{
- // initialize COM if it hasn't happened yet
- CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ SafeRelease(&m_audio_client);
+ SafeRelease(&m_imm_device);
- const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
- const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
+ if(FAILED(m_imm_device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_imm_device)))
+ return false;
+
+ if(FAILED(m_imm_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audio_client))))
+ return false;
+
WAVEFORMATEXTENSIBLE wave_format_extensible_closest_match;
WAVEFORMATEXTENSIBLE* closest_match_pointer = &wave_format_extensible_closest_match;
- HRESULT result;
-
REFERENCE_TIME minimum_time = 0;
REFERENCE_TIME buffer_duration;
- if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(&m_imm_device_enumerator))))
- goto error;
-
- if(FAILED(m_imm_device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_imm_device)))
- goto error;
-
- if(FAILED(m_imm_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audio_client))))
- goto error;
-
- if(specs.channels == CHANNELS_INVALID)
- specs.channels = CHANNELS_STEREO;
- if(specs.format == FORMAT_INVALID)
- specs.format = FORMAT_FLOAT32;
- if(specs.rate == RATE_INVALID)
- specs.rate = RATE_48000;
-
switch(specs.format)
{
case FORMAT_U8:
@@ -203,12 +217,14 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
m_wave_format_extensible.Format.cbSize = 22;
m_wave_format_extensible.Samples.wValidBitsPerSample = m_wave_format_extensible.Format.wBitsPerSample;
- result = m_audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&m_wave_format_extensible), reinterpret_cast<WAVEFORMATEX**>(&closest_match_pointer));
+ HRESULT result = m_audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&m_wave_format_extensible), reinterpret_cast<WAVEFORMATEX**>(&closest_match_pointer));
if(result == S_FALSE)
{
+ bool errored = false;
+
if(closest_match_pointer->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
- goto error;
+ goto closest_match_error;
specs.channels = Channels(closest_match_pointer->Format.nChannels);
specs.rate = closest_match_pointer->Format.nSamplesPerSec;
@@ -220,7 +236,7 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
else if(closest_match_pointer->Format.wBitsPerSample == 64)
specs.format = FORMAT_FLOAT64;
else
- goto error;
+ goto closest_match_error;
}
else if(closest_match_pointer->SubFormat == KSDATAFORMAT_SUBTYPE_PCM)
{
@@ -239,44 +255,81 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
specs.format = FORMAT_S32;
break;
default:
- goto error;
+ goto closest_match_error;
break;
}
}
else
- goto error;
+ goto closest_match_error;
m_wave_format_extensible = *closest_match_pointer;
+ if(false)
+ {
+ closest_match_error:
+ errored = true;
+ }
+
if(closest_match_pointer != &wave_format_extensible_closest_match)
{
CoTaskMemFree(closest_match_pointer);
closest_match_pointer = &wave_format_extensible_closest_match;
}
+
+ if(errored)
+ return false;
}
else if(FAILED(result))
- goto error;
+ return false;
if(FAILED(m_audio_client->GetDevicePeriod(nullptr, &minimum_time)))
- goto error;
+ return false;
- buffer_duration = REFERENCE_TIME(buffersize) * REFERENCE_TIME(10000000) / REFERENCE_TIME(specs.rate);
+ buffer_duration = REFERENCE_TIME(m_buffersize) * REFERENCE_TIME(10000000) / REFERENCE_TIME(specs.rate);
if(minimum_time > buffer_duration)
buffer_duration = minimum_time;
- m_specs = specs;
-
if(FAILED(m_audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, buffer_duration, 0, reinterpret_cast<WAVEFORMATEX*>(&m_wave_format_extensible), nullptr)))
+ return false;
+
+ return true;
+}
+
+WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
+ m_buffersize(buffersize),
+ m_imm_device_enumerator(nullptr),
+ m_imm_device(nullptr),
+ m_audio_client(nullptr),
+
+ m_wave_format_extensible({})
+{
+ // initialize COM if it hasn't happened yet
+ CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+
+ const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
+ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
+
+ if(specs.channels == CHANNELS_INVALID)
+ specs.channels = CHANNELS_STEREO;
+ if(specs.format == FORMAT_INVALID)
+ specs.format = FORMAT_FLOAT32;
+ if(specs.rate == RATE_INVALID)
+ specs.rate = RATE_48000;
+
+ if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(&m_imm_device_enumerator))))
+ goto error;
+
+ if(!setupDevice(specs))
goto error;
+ m_specs = specs;
+
create();
return;
error:
- if(closest_match_pointer != &wave_format_extensible_closest_match)
- CoTaskMemFree(closest_match_pointer);
SafeRelease(&m_imm_device);
SafeRelease(&m_imm_device_enumerator);
SafeRelease(&m_audio_client);
diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.h b/extern/audaspace/plugins/wasapi/WASAPIDevice.h
index 375f03bd255..3b11adc98ef 100644
--- a/extern/audaspace/plugins/wasapi/WASAPIDevice.h
+++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.h
@@ -43,16 +43,21 @@ AUD_NAMESPACE_BEGIN
class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice
{
private:
+ int m_buffersize;
IMMDeviceEnumerator* m_imm_device_enumerator;
IMMDevice* m_imm_device;
IAudioClient* m_audio_client;
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
+ AUD_LOCAL HRESULT setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size);
+
/**
* Streaming thread main function.
*/
AUD_LOCAL void runMixingThread();
+ AUD_LOCAL bool setupDevice(DeviceSpecs& specs);
+
// delete copy constructor and operator=
WASAPIDevice(const WASAPIDevice&) = delete;
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp
index 7a2561515f4..e11b49a0967 100644
--- a/extern/audaspace/src/devices/SoftwareDevice.cpp
+++ b/extern/audaspace/src/devices/SoftwareDevice.cpp
@@ -756,6 +756,7 @@ void SoftwareDevice::mix(data_t* buffer, int length)
// get the buffer from the source
pos = 0;
len = length;
+ eos = false;
// update 3D Info
sound->update();
@@ -842,6 +843,27 @@ void SoftwareDevice::setSpecs(Specs specs)
{
sound->setSpecs(specs);
}
+
+ for(auto& sound : m_pausedSounds)
+ {
+ sound->setSpecs(specs);
+ }
+}
+
+void SoftwareDevice::setSpecs(DeviceSpecs specs)
+{
+ m_specs = specs;
+ m_mixer->setSpecs(specs);
+
+ for(auto& sound : m_playingSounds)
+ {
+ sound->setSpecs(specs.specs);
+ }
+
+ for(auto& sound : m_pausedSounds)
+ {
+ sound->setSpecs(specs.specs);
+ }
}
SoftwareDevice::SoftwareDevice()
diff --git a/extern/audaspace/src/respec/Mixer.cpp b/extern/audaspace/src/respec/Mixer.cpp
index ad8d885df4e..15872fbcff2 100644
--- a/extern/audaspace/src/respec/Mixer.cpp
+++ b/extern/audaspace/src/respec/Mixer.cpp
@@ -21,9 +21,25 @@
AUD_NAMESPACE_BEGIN
-Mixer::Mixer(DeviceSpecs specs) :
- m_specs(specs)
+Mixer::Mixer(DeviceSpecs specs)
{
+ setSpecs(specs);
+}
+
+DeviceSpecs Mixer::getSpecs() const
+{
+ return m_specs;
+}
+
+void Mixer::setSpecs(Specs specs)
+{
+ m_specs.specs = specs;
+}
+
+void Mixer::setSpecs(DeviceSpecs specs)
+{
+ m_specs = specs;
+
switch(m_specs.format)
{
case FORMAT_U8:
@@ -54,16 +70,6 @@ Mixer::Mixer(DeviceSpecs specs) :
}
}
-DeviceSpecs Mixer::getSpecs() const
-{
- return m_specs;
-}
-
-void Mixer::setSpecs(Specs specs)
-{
- m_specs.specs = specs;
-}
-
void Mixer::clear(int length)
{
m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs));
diff --git a/extern/glog/README.blender b/extern/glog/README.blender
index 5b4dab199bf..bc2ca9f958e 100644
--- a/extern/glog/README.blender
+++ b/extern/glog/README.blender
@@ -7,3 +7,4 @@ Local modifications:
checks for functions and so are needed.
* Added special definitions of HAVE_SNPRINTF and HAVE_LIB_GFLAGS
in Windows' specific config.h.
+* Silenced syscall deprecation warnings on macOS >= 10.12.
diff --git a/extern/glog/src/raw_logging.cc b/extern/glog/src/raw_logging.cc
index 3bbfda31868..15d14f6e4f5 100644
--- a/extern/glog/src/raw_logging.cc
+++ b/extern/glog/src/raw_logging.cc
@@ -59,7 +59,7 @@
# include <unistd.h>
#endif
-#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
+#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && (!(defined OS_MACOSX))
# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else
// Not so safe, but what can you do?
diff --git a/extern/glog/src/utilities.cc b/extern/glog/src/utilities.cc
index 25c4b760f1c..6387e14e123 100644
--- a/extern/glog/src/utilities.cc
+++ b/extern/glog/src/utilities.cc
@@ -259,7 +259,13 @@ pid_t GetTID() {
#endif
static bool lacks_gettid = false;
if (!lacks_gettid) {
+#ifdef OS_MACOSX
+ uint64_t tid64;
+ const int error = pthread_threadid_np(NULL, &tid64);
+ pid_t tid = error ? -1 : (pid_t)tid64;
+#else
pid_t tid = syscall(__NR_gettid);
+#endif
if (tid != -1) {
return tid;
}
diff --git a/intern/atomic/intern/atomic_ops_unix.h b/intern/atomic/intern/atomic_ops_unix.h
index dc1e71cda76..b08a0e9bc28 100644
--- a/intern/atomic/intern/atomic_ops_unix.h
+++ b/intern/atomic/intern/atomic_ops_unix.h
@@ -49,9 +49,9 @@
#include "atomic_ops_utils.h"
-#if defined(__arm__)
-/* Attempt to fix compilation error on Debian armel kernel.
- * arm7 architecture does have both 32 and 64bit atomics, however
+#if defined(__arm__) || defined(__riscv)
+/* Attempt to fix compilation error on Debian armel and RISC-V kernels.
+ * Both architectures do have both 32 and 64bit atomics, however
* its gcc doesn't have __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n defined.
*/
# define JE_FORCE_SYNC_COMPARE_AND_SWAP_1
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 71e2f9fc3a5..b014811211f 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -482,7 +482,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
transparent_max_bounces: IntProperty(
name="Transparent Max Bounces",
- description="Maximum number of transparent bounces",
+ description="Maximum number of transparent bounces. This is independent of maximum number of other bounces ",
min=0, max=1024,
default=8,
)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 3d990467f04..30892cdbbc0 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -485,10 +485,12 @@ class CYCLES_RENDER_PT_light_paths_max_bounces(CyclesButtonsPanel, Panel):
col = layout.column(align=True)
col.prop(cscene, "diffuse_bounces", text="Diffuse")
col.prop(cscene, "glossy_bounces", text="Glossy")
- col.prop(cscene, "transparent_max_bounces", text="Transparency")
col.prop(cscene, "transmission_bounces", text="Transmission")
col.prop(cscene, "volume_bounces", text="Volume")
+ col = layout.column(align=True)
+ col.prop(cscene, "transparent_max_bounces", text="Transparent")
+
class CYCLES_RENDER_PT_light_paths_clamping(CyclesButtonsPanel, Panel):
bl_label = "Clamping"
diff --git a/intern/cycles/blender/blender_image.cpp b/intern/cycles/blender/blender_image.cpp
index 3a9d159e461..f27275bd457 100644
--- a/intern/cycles/blender/blender_image.cpp
+++ b/intern/cycles/blender/blender_image.cpp
@@ -137,9 +137,9 @@ bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata,
/* Premultiply, byte images are always straight for Blender. */
unsigned char *cp = (unsigned char *)pixels;
for (size_t i = 0; i < num_pixels; i++, cp += channels) {
- cp[0] = (cp[0] * cp[3]) >> 8;
- cp[1] = (cp[1] * cp[3]) >> 8;
- cp[2] = (cp[2] * cp[3]) >> 8;
+ cp[0] = (cp[0] * cp[3]) / 255;
+ cp[1] = (cp[1] * cp[3]) / 255;
+ cp[2] = (cp[2] * cp[3]) / 255;
}
}
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 635392fb3d4..f5e8db2aee1 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -109,23 +109,23 @@ void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob
}
Geometry *geom = object->get_geometry();
- geom->set_use_motion_blur(false);
- geom->set_motion_steps(0);
- uint motion_steps;
+ int motion_steps = 0;
+ bool use_motion_blur = false;
if (need_motion == Scene::MOTION_BLUR) {
motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
- geom->set_motion_steps(motion_steps);
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
- geom->set_use_motion_blur(true);
+ use_motion_blur = true;
}
}
else {
motion_steps = 3;
- geom->set_motion_steps(motion_steps);
}
+ geom->set_use_motion_blur(use_motion_blur);
+ geom->set_motion_steps(motion_steps);
+
motion.resize(motion_steps, transform_empty());
if (motion_steps) {
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 3b3a193b3e8..ce399579e25 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -404,8 +404,6 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d)
Film *film = scene->film;
- vector<Pass> prevpasses = scene->passes;
-
if (b_v3d) {
film->set_display_pass(update_viewport_display_passes(b_v3d, scene->passes));
}
@@ -435,11 +433,6 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d)
break;
}
}
-
- if (!Pass::equals(prevpasses, scene->passes)) {
- film->tag_passes_update(scene, prevpasses, false);
- film->tag_modified();
- }
}
/* Render Layer */
@@ -749,10 +742,13 @@ vector<Pass> BlenderSync::sync_render_passes(BL::Scene &b_scene,
DENOISING_CLEAN_ALL_PASSES);
scene->film->set_denoising_prefiltered_pass(denoising.store_passes &&
denoising.type == DENOISER_NLM);
-
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
- scene->film->tag_passes_update(scene, passes);
- scene->integrator->tag_update(scene, Integrator::UPDATE_ALL);
+
+ if (!Pass::equals(passes, scene->passes)) {
+ scene->film->tag_passes_update(scene, passes);
+ scene->film->tag_modified();
+ scene->integrator->tag_update(scene, Integrator::UPDATE_ALL);
+ }
return passes;
}
diff --git a/intern/cycles/blender/blender_viewport.cpp b/intern/cycles/blender/blender_viewport.cpp
index 07408fee218..18bdfc74de0 100644
--- a/intern/cycles/blender/blender_viewport.cpp
+++ b/intern/cycles/blender/blender_viewport.cpp
@@ -40,8 +40,8 @@ BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d)
BL::View3DShading shading = b_v3d.shading();
PointerRNA cshading = RNA_pointer_get(&shading.ptr, "cycles");
- /* We only copy the shading parameters if we are in look dev mode. otherwise
- * defaults are being used. These defaults mimic normal render settings */
+ /* We only copy the shading parameters if we are in look-dev mode.
+ * Otherwise defaults are being used. These defaults mimic normal render settings. */
if (shading.type() == BL::View3DShading::type_RENDERED) {
use_scene_world = shading.use_scene_world_render();
use_scene_lights = shading.use_scene_lights_render();
diff --git a/intern/cycles/kernel/bvh/bvh_util.h b/intern/cycles/kernel/bvh/bvh_util.h
index 6c152cbb249..867ea3af8d1 100644
--- a/intern/cycles/kernel/bvh/bvh_util.h
+++ b/intern/cycles/kernel/bvh/bvh_util.h
@@ -86,8 +86,7 @@ ccl_device_inline float3 smooth_surface_offset(KernelGlobals *kg, ShaderData *sd
float3 P = V[0] * u + V[1] * v + V[2] * w; /* Local space */
float3 n = N[0] * u + N[1] * v + N[2] * w; /* We get away without normalization */
- n = normalize(
- transform_direction_transposed_auto(&sd->ob_itfm, n)); /* Normal x scale, world space */
+ object_normal_transform(kg, sd, &n); /* Normal x scale, world space */
/* Parabolic approximation */
float a = dot(N[2] - N[0], V[0] - V[2]);
diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h
index 40b2059194b..e25bf5b4660 100644
--- a/intern/cycles/kernel/geom/geom_curve_intersect.h
+++ b/intern/cycles/kernel/geom/geom_curve_intersect.h
@@ -237,7 +237,7 @@ ccl_device bool curve_intersect_iterative(const float3 ray_dir,
return false; /* Rejects NaNs */
}
- /* Backface culling. */
+ /* Back-face culling. */
const float3 R = normalize(Q - P);
const float3 U = dradiusdu * R + dPdu;
const float3 V = cross(dPdu, R);
@@ -458,10 +458,12 @@ ccl_device_inline bool cylinder_culling_test(const float2 p1, const float2 p2, c
return num * num <= r * r * den2;
}
-/*! Intersects a ray with a quad with backface culling
- * enabled. The quad v0,v1,v2,v3 is split into two triangles
- * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two
- * triangles gets intersected. */
+/**
+ * Intersects a ray with a quad with back-face culling
+ * enabled. The quad v0,v1,v2,v3 is split into two triangles
+ * v0,v1,v3 and v2,v3,v1. The edge v1,v2 decides which of the two
+ * triangles gets intersected.
+ */
ccl_device_inline bool ribbon_intersect_quad(const float ray_tfar,
const float3 quad_v0,
const float3 quad_v1,
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index bdedf0c20a8..d1f33a4d0f0 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -40,7 +40,7 @@ ccl_device_noinline void compute_light_pass(
/* Evaluate surface shader. */
shader_eval_surface(kg, sd, &state, NULL, state.flag);
- /* TODO, disable more closures we don't need besides transparent */
+ /* TODO: disable more closures we don't need besides transparent. */
shader_bsdf_disable_transparency(kg, sd);
/* Init ray. */
diff --git a/intern/cycles/kernel/svm/svm_vector_rotate.h b/intern/cycles/kernel/svm/svm_vector_rotate.h
index 79a4ec2c40e..50045752484 100644
--- a/intern/cycles/kernel/svm/svm_vector_rotate.h
+++ b/intern/cycles/kernel/svm/svm_vector_rotate.h
@@ -50,24 +50,29 @@ ccl_device void svm_node_vector_rotate(ShaderData *sd,
}
else {
float3 axis;
+ float axis_length;
switch (type) {
case NODE_VECTOR_ROTATE_TYPE_AXIS_X:
axis = make_float3(1.0f, 0.0f, 0.0f);
+ axis_length = 1.0f;
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
axis = make_float3(0.0f, 1.0f, 0.0f);
+ axis_length = 1.0f;
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
axis = make_float3(0.0f, 0.0f, 1.0f);
+ axis_length = 1.0f;
break;
default:
- axis = normalize(stack_load_float3(stack, axis_stack_offset));
+ axis = stack_load_float3(stack, axis_stack_offset);
+ axis_length = len(axis);
break;
}
float angle = stack_load_float(stack, angle_stack_offset);
angle = invert ? -angle : angle;
- result = (len_squared(axis) != 0.0f) ?
- rotate_around_axis(vector - center, axis, angle) + center :
+ result = (axis_length != 0.0f) ?
+ rotate_around_axis(vector - center, axis / axis_length, angle) + center :
vector;
}
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 7970381f338..5abb4750764 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -81,7 +81,7 @@ class Camera : public Node {
/* ** Rolling shutter effect. ** */
/* Defines rolling shutter effect type. */
NODE_SOCKET_API(RollingShutterType, rolling_shutter_type)
- /* Specifies exposure time of scanlines when using
+ /* Specifies exposure time of scan-lines when using
* rolling shutter effect.
*/
NODE_SOCKET_API(float, rolling_shutter_duration)
diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp
index fb6394e8917..4da11c8a140 100644
--- a/intern/cycles/render/image_vdb.cpp
+++ b/intern/cycles/render/image_vdb.cpp
@@ -16,8 +16,10 @@
#include "render/image_vdb.h"
+#include "util/util_logging.h"
+#include "util/util_openvdb.h"
+
#ifdef WITH_OPENVDB
-# include <openvdb/openvdb.h>
# include <openvdb/tools/Dense.h>
#endif
#ifdef WITH_NANOVDB
@@ -26,6 +28,57 @@
CCL_NAMESPACE_BEGIN
+#ifdef WITH_OPENVDB
+struct NumChannelsOp {
+ int num_channels = 0;
+
+ template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
+ bool operator()(const openvdb::GridBase::ConstPtr &)
+ {
+ num_channels = channels;
+ return true;
+ }
+};
+
+struct ToDenseOp {
+ openvdb::CoordBBox bbox;
+ void *pixels;
+
+ template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
+ bool operator()(const openvdb::GridBase::ConstPtr &grid)
+ {
+ openvdb::tools::Dense<FloatDataType, openvdb::tools::LayoutXYZ> dense(bbox,
+ (FloatDataType *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<GridType>(grid), dense);
+ return true;
+ }
+};
+
+# ifdef WITH_NANOVDB
+struct ToNanoOp {
+ nanovdb::GridHandle<> nanogrid;
+
+ template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
+ bool operator()(const openvdb::GridBase::ConstPtr &grid)
+ {
+ if constexpr (!std::is_same_v<GridType, openvdb::MaskGrid>) {
+ try {
+ nanogrid = nanovdb::openToNanoVDB(
+ FloatGridType(*openvdb::gridConstPtrCast<GridType>(grid)));
+ }
+ catch (const std::exception &e) {
+ VLOG(1) << "Error converting OpenVDB to NanoVDB grid: " << e.what();
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+};
+# endif
+#endif
+
VDBImageLoader::VDBImageLoader(const string &grid_name) : grid_name(grid_name)
{
}
@@ -41,98 +94,40 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
return false;
}
- bbox = grid->evalActiveVoxelBoundingBox();
- if (bbox.empty()) {
+ /* Get number of channels from type. */
+ NumChannelsOp op;
+ if (!openvdb::grid_type_operation(grid, op)) {
return false;
}
- /* Set dimensions. */
- openvdb::Coord dim = bbox.dim();
- metadata.width = dim.x();
- metadata.height = dim.y();
- metadata.depth = dim.z();
+ metadata.channels = op.num_channels;
/* Set data type. */
- if (grid->isType<openvdb::FloatGrid>()) {
- metadata.channels = 1;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
- }
-# endif
- }
- else if (grid->isType<openvdb::Vec3fGrid>()) {
- metadata.channels = 3;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
- }
-# endif
- }
- else if (grid->isType<openvdb::BoolGrid>()) {
- metadata.channels = 1;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
- }
-# endif
- }
- else if (grid->isType<openvdb::DoubleGrid>()) {
- metadata.channels = 1;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
- }
-# endif
- }
- else if (grid->isType<openvdb::Int32Grid>()) {
- metadata.channels = 1;
# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
+ if (features.has_nanovdb) {
+ /* NanoVDB expects no inactive leaf nodes. */
+ /*openvdb::FloatGrid &pruned_grid = *openvdb::gridPtrCast<openvdb::FloatGrid>(grid);
+ openvdb::tools::pruneInactive(pruned_grid.tree());
+ nanogrid = nanovdb::openToNanoVDB(pruned_grid);*/
+ ToNanoOp op;
+ if (!openvdb::grid_type_operation(grid, op)) {
+ return false;
}
-# endif
- }
- else if (grid->isType<openvdb::Int64Grid>()) {
- metadata.channels = 1;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
- }
-# endif
+ nanogrid = std::move(op.nanogrid);
}
- else if (grid->isType<openvdb::Vec3IGrid>()) {
- metadata.channels = 3;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
- }
-# endif
- }
- else if (grid->isType<openvdb::Vec3dGrid>()) {
- metadata.channels = 3;
-# ifdef WITH_NANOVDB
- if (features.has_nanovdb) {
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
- }
-# endif
- }
- else if (grid->isType<openvdb::MaskGrid>()) {
- metadata.channels = 1;
-# ifdef WITH_NANOVDB
- return false; // Unsupported
# endif
- }
- else {
+
+ /* Set dimensions. */
+ bbox = grid->evalActiveVoxelBoundingBox();
+ if (bbox.empty()) {
return false;
}
+ openvdb::Coord dim = bbox.dim();
+ metadata.width = dim.x();
+ metadata.height = dim.y();
+ metadata.depth = dim.z();
+
# ifdef WITH_NANOVDB
if (nanogrid) {
metadata.byte_size = nanogrid.size();
@@ -200,45 +195,10 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size
else
# endif
{
- if (grid->isType<openvdb::FloatGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::Vec3fGrid>()) {
- openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
- bbox, (openvdb::Vec3f *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::BoolGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::DoubleGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::Int32Grid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
- }
- else if (grid->isType<openvdb::Int64Grid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
- }
- else if (grid->isType<openvdb::Vec3IGrid>()) {
- openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
- bbox, (openvdb::Vec3f *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::Vec3dGrid>()) {
- openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
- bbox, (openvdb::Vec3f *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::MaskGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
- }
+ ToDenseOp op;
+ op.pixels = pixels;
+ op.bbox = bbox;
+ openvdb::grid_type_operation(grid, op);
}
return true;
#else
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index a6dab06f8f2..2e7fe50d5cf 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -209,7 +209,7 @@ class SceneParams {
int curve_subdivisions()
{
- /* Matching the tesselation rate limit in Embree. */
+ /* Matching the tessellation rate limit in Embree. */
return clamp(1 << hair_subdivisions, 1, 16);
}
};
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index ca90af77f6e..19d4a66353d 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -227,66 +227,25 @@ void Session::run_gpu()
progress.set_render_start_time();
while (!progress.get_cancel()) {
- /* advance to next tile */
- bool no_tiles = !tile_manager.next();
+ const bool no_tiles = !run_update_for_next_iteration();
- DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
if (no_tiles) {
- kernel_state = device->get_active_kernel_switch_state();
- }
-
- if (params.background) {
- /* if no work left and in background mode, we can stop immediately */
- if (no_tiles) {
+ if (params.background) {
+ /* if no work left and in background mode, we can stop immediately */
progress.set_status("Finished");
break;
}
}
- else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
- reset_gpu(tile_manager.params, params.samples);
+ if (run_wait_for_work(no_tiles)) {
+ continue;
}
- else {
- /* if in interactive mode, and we are either paused or done for now,
- * wait for pause condition notify to wake up again */
- thread_scoped_lock pause_lock(pause_mutex);
-
- if (!pause && !tile_manager.done()) {
- /* reset could have happened after no_tiles was set, before this lock.
- * in this case we shall not wait for pause condition
- */
- }
- else if (pause || no_tiles) {
- update_status_time(pause, no_tiles);
-
- while (1) {
- scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if (pause) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause, no_tiles);
- progress.set_update();
-
- if (!pause)
- break;
- }
- }
-
- if (progress.get_cancel())
- break;
+ if (progress.get_cancel()) {
+ break;
}
if (!no_tiles) {
- /* update scene */
- scoped_timer update_timer;
- if (update_scene()) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
-
if (!device->error_message().empty())
progress.set_error(device->error_message());
@@ -729,82 +688,27 @@ void Session::run_cpu()
last_update_time = time_dt();
last_display_time = last_update_time;
- {
- /* reset once to start */
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- reset_(delayed_reset.params, delayed_reset.samples);
- delayed_reset.do_reset = false;
- }
-
while (!progress.get_cancel()) {
- /* advance to next tile */
- bool no_tiles = !tile_manager.next();
+ const bool no_tiles = !run_update_for_next_iteration();
bool need_copy_to_display_buffer = false;
- DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
if (no_tiles) {
- kernel_state = device->get_active_kernel_switch_state();
- }
-
- if (params.background) {
- /* if no work left and in background mode, we can stop immediately */
- if (no_tiles) {
+ if (params.background) {
+ /* if no work left and in background mode, we can stop immediately */
progress.set_status("Finished");
break;
}
}
- else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
- reset_cpu(tile_manager.params, params.samples);
+ if (run_wait_for_work(no_tiles)) {
+ continue;
}
- else {
- /* if in interactive mode, and we are either paused or done for now,
- * wait for pause condition notify to wake up again */
- thread_scoped_lock pause_lock(pause_mutex);
-
- if (!pause && delayed_reset.do_reset) {
- /* reset once to start */
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- reset_(delayed_reset.params, delayed_reset.samples);
- delayed_reset.do_reset = false;
- }
- else if (pause || no_tiles) {
- update_status_time(pause, no_tiles);
-
- while (1) {
- scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if (pause) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause, no_tiles);
- progress.set_update();
-
- if (!pause)
- break;
- }
- }
-
- if (progress.get_cancel())
- break;
+ if (progress.get_cancel()) {
+ break;
}
if (!no_tiles) {
- /* update scene */
- scoped_timer update_timer;
- if (update_scene()) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
-
if (!device->error_message().empty())
progress.set_error(device->error_message());
@@ -894,6 +798,63 @@ void Session::run()
progress.set_update();
}
+bool Session::run_update_for_next_iteration()
+{
+ thread_scoped_lock scene_lock(scene->mutex);
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+
+ if (delayed_reset.do_reset) {
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset.do_reset = false;
+ }
+
+ const bool have_tiles = tile_manager.next();
+
+ if (have_tiles) {
+ scoped_timer update_timer;
+ if (update_scene()) {
+ profiler.reset(scene->shaders.size(), scene->objects.size());
+ }
+ progress.add_skip_time(update_timer, params.background);
+ }
+
+ return have_tiles;
+}
+
+bool Session::run_wait_for_work(bool no_tiles)
+{
+ /* In an offline rendering there is no pause, and no tiles will mean the job is fully done. */
+ if (params.background) {
+ return false;
+ }
+
+ thread_scoped_lock pause_lock(pause_mutex);
+
+ if (!pause && !no_tiles) {
+ return false;
+ }
+
+ update_status_time(pause, no_tiles);
+
+ while (true) {
+ scoped_timer pause_timer;
+ pause_cond.wait(pause_lock);
+ if (pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
+
+ update_status_time(pause, no_tiles);
+ progress.set_update();
+
+ if (!pause) {
+ break;
+ }
+ }
+
+ return no_tiles;
+}
+
bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
if (device_use_gl)
@@ -1012,8 +973,6 @@ void Session::wait()
bool Session::update_scene()
{
- thread_scoped_lock scene_lock(scene->mutex);
-
/* update camera if dimensions changed for progressive render. the camera
* knows nothing about progressive or cropped rendering, it just gets the
* image dimensions passed in */
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 43ff07e5884..bc3b8366c05 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -178,6 +178,9 @@ class Session {
void run();
+ bool run_update_for_next_iteration();
+ bool run_wait_for_work(bool no_tiles);
+
void update_status_time(bool show_pause = false, bool show_done = false);
void render(bool use_denoise);
diff --git a/intern/cycles/util/util_openvdb.h b/intern/cycles/util/util_openvdb.h
index a3ebb03e5a4..ae5326e3199 100644
--- a/intern/cycles/util/util_openvdb.h
+++ b/intern/cycles/util/util_openvdb.h
@@ -25,6 +25,42 @@ namespace openvdb {
using Vec4fTree = tree::Tree4<Vec4f, 5, 4, 3>::Type;
using Vec4fGrid = Grid<Vec4fTree>;
+/* Apply operation to known grid types. */
+template<typename OpType>
+bool grid_type_operation(const openvdb::GridBase::ConstPtr &grid, OpType &&op)
+{
+ if (grid->isType<openvdb::FloatGrid>()) {
+ return op.template operator()<openvdb::FloatGrid, openvdb::FloatGrid, float, 1>(grid);
+ }
+ else if (grid->isType<openvdb::Vec3fGrid>()) {
+ return op.template operator()<openvdb::Vec3fGrid, openvdb::Vec3fGrid, openvdb::Vec3f, 3>(grid);
+ }
+ else if (grid->isType<openvdb::BoolGrid>()) {
+ return op.template operator()<openvdb::BoolGrid, openvdb::FloatGrid, float, 1>(grid);
+ }
+ else if (grid->isType<openvdb::DoubleGrid>()) {
+ return op.template operator()<openvdb::DoubleGrid, openvdb::FloatGrid, float, 1>(grid);
+ }
+ else if (grid->isType<openvdb::Int32Grid>()) {
+ return op.template operator()<openvdb::Int32Grid, openvdb::FloatGrid, float, 1>(grid);
+ }
+ else if (grid->isType<openvdb::Int64Grid>()) {
+ return op.template operator()<openvdb::Int64Grid, openvdb::FloatGrid, float, 1>(grid);
+ }
+ else if (grid->isType<openvdb::Vec3IGrid>()) {
+ return op.template operator()<openvdb::Vec3IGrid, openvdb::Vec3fGrid, openvdb::Vec3f, 3>(grid);
+ }
+ else if (grid->isType<openvdb::Vec3dGrid>()) {
+ return op.template operator()<openvdb::Vec3dGrid, openvdb::Vec3fGrid, openvdb::Vec3f, 3>(grid);
+ }
+ else if (grid->isType<openvdb::MaskGrid>()) {
+ return op.template operator()<openvdb::MaskGrid, openvdb::FloatGrid, float, 1>(grid);
+ }
+ else {
+ return false;
+ }
+}
+
}; // namespace openvdb
#endif
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 77ec307e604..76cac1049fb 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -155,6 +155,9 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL)
endif()
elseif(APPLE AND NOT WITH_GHOST_X11)
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
list(APPEND SRC
intern/GHOST_DisplayManagerCocoa.mm
intern/GHOST_SystemCocoa.mm
@@ -285,16 +288,37 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
${dbus_INCLUDE_DIRS}
)
+ include(CheckSymbolExists)
+ set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
+ check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE)
+ if (HAVE_MEMFD_CREATE)
+ add_definitions(-DHAVE_MEMFD_CREATE)
+ endif()
+
list(APPEND SRC
intern/GHOST_SystemWayland.cpp
intern/GHOST_WindowWayland.cpp
intern/GHOST_SystemWayland.h
+ intern/GHOST_WaylandCursorSettings.h
intern/GHOST_WindowWayland.h
)
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
- pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
+
+ pkg_check_modules(wayland-protocols wayland-protocols>=1.15)
+ if (${wayland-protocols_FOUND})
+ pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
+ else()
+ find_path(WAYLAND_PROTOCOLS_DIR
+ NAMES unstable/xdg-decoration/xdg-decoration-unstable-v1.xml
+ PATH_SUFFIXES share/wayland-protocols
+ )
+ endif()
+
+ if (NOT EXISTS ${WAYLAND_PROTOCOLS_DIR})
+ message(FATAL_ERROR "path to wayland-protocols not found")
+ endif()
# Generate protocols bindings.
macro(generate_protocol_bindings NAME PROT_DEF)
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 2bd9af6df5c..db3f9bd561e 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -96,7 +96,7 @@ extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consu
* \param systemhandle: The handle to the system.
* \return The number of milliseconds.
*/
-extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
+extern uint64_t GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
/**
* Installs a timer.
@@ -110,8 +110,8 @@ extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
* \return A timer task (0 if timer task installation failed).
*/
extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
- GHOST_TUns64 delay,
- GHOST_TUns64 interval,
+ uint64_t delay,
+ uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData);
@@ -133,7 +133,7 @@ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
* \param systemhandle: The handle to the system.
* \return The number of displays.
*/
-extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle);
+extern uint8_t GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle);
/**
* Returns the dimensions of the main display on this system.
@@ -142,8 +142,8 @@ extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle);
* \param height: A pointer the height gets put in.
*/
extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
- GHOST_TUns32 *width,
- GHOST_TUns32 *height);
+ uint32_t *width,
+ uint32_t *height);
/**
* Returns the dimensions of all displays combine
@@ -154,8 +154,8 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height: A pointer the height gets put in.
*/
extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
- GHOST_TUns32 *width,
- GHOST_TUns32 *height);
+ uint32_t *width,
+ uint32_t *height);
/**
* Create a new window.
@@ -178,10 +178,10 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle parent_windowhandle,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_TDrawingContextType type,
@@ -360,13 +360,13 @@ extern GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle,
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
- GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
int hotY,
- GHOST_TUns8 canInvertColor);
+ bool canInvertColor);
/**
* Returns the visibility state of the cursor.
@@ -391,8 +391,8 @@ extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle,
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
- GHOST_TInt32 *x,
- GHOST_TInt32 *y);
+ int32_t *x,
+ int32_t *y);
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -403,8 +403,8 @@ extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y);
+ int32_t x,
+ int32_t y);
/**
* Grabs the cursor for a modal operation, to keep receiving
@@ -467,7 +467,7 @@ extern void GHOST_setNDOFDeadZone(float deadzone);
/**
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
*/
-extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept);
+extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool canAccept);
/**
* Returns the event type.
@@ -481,7 +481,7 @@ extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle);
* \param eventhandle: The handle to the event.
* \return The event generation time.
*/
-extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle);
+extern uint64_t GHOST_GetEventTime(GHOST_EventHandle eventhandle);
/**
* Returns the window this event was generated on,
@@ -507,7 +507,7 @@ extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhand
/**
* Changes the timer callback.
- * \param timertaskhandle: The handle to the timertask.
+ * \param timertaskhandle: The handle to the timer-task.
* \param timerProc: The timer callback.
*/
extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
@@ -515,14 +515,14 @@ extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
/**
* Returns the timer user data.
- * \param timertaskhandle: The handle to the timertask.
+ * \param timertaskhandle: The handle to the timer-task.
* \return The timer user data.
*/
extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle);
/**
* Changes the time user data.
- * \param timertaskhandle: The handle to the timertask.
+ * \param timertaskhandle: The handle to the timer-task.
* \param userdata: The timer user data.
*/
extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle,
@@ -595,7 +595,7 @@ void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle);
* \param width: The new width of the client area of the window.
* \return Indication of success.
*/
-extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOST_TUns32 width);
+extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, uint32_t width);
/**
* Resizes client rectangle height.
@@ -603,7 +603,7 @@ extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOS
* \param height: The new height of the client area of the window.
* \return Indication of success.
*/
-extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns32 height);
+extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, uint32_t height);
/**
* Resizes client rectangle.
@@ -613,8 +613,8 @@ extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHO
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
- GHOST_TUns32 width,
- GHOST_TUns32 height);
+ uint32_t width,
+ uint32_t height);
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -624,11 +624,8 @@ extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
* \param outX: The x-coordinate in the client rectangle.
* \param outY: The y-coordinate in the client rectangle.
*/
-extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
- GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 *outX,
- GHOST_TInt32 *outY);
+extern void GHOST_ScreenToClient(
+ GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY);
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -638,11 +635,8 @@ extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
* \param outX: The x-coordinate on the screen.
* \param outY: The y-coordinate on the screen.
*/
-extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
- GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 *outX,
- GHOST_TInt32 *outY);
+extern void GHOST_ClientToScreen(
+ GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY);
/**
* Returns the state of the window (normal, minimized, maximized).
@@ -667,7 +661,7 @@ extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle,
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle,
- GHOST_TUns8 isUnsavedChanges);
+ bool isUnsavedChanges);
/**
* Sets the order of the window (bottom, top).
@@ -758,14 +752,14 @@ extern void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI
* \param rectanglehandle: The handle to the rectangle.
* \return width of the rectangle
*/
-extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle);
+extern int32_t GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle);
/**
* Access to rectangle height.
* \param rectanglehandle: The handle to the rectangle.
* \return height of the rectangle
*/
-extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle);
+extern int32_t GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle);
/**
* Gets all members of the rectangle.
@@ -775,11 +769,8 @@ extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehand
* \param r: Pointer to return right coordinate in.
* \param b: Pointer to return bottom coordinate in.
*/
-extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 *l,
- GHOST_TInt32 *t,
- GHOST_TInt32 *r,
- GHOST_TInt32 *b);
+extern void GHOST_GetRectangle(
+ GHOST_RectangleHandle rectanglehandle, int32_t *l, int32_t *t, int32_t *r, int32_t *b);
/**
* Sets all members of the rectangle.
@@ -789,11 +780,8 @@ extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
* \param r: requested right coordinate of the rectangle.
* \param b: requested bottom coordinate of the rectangle.
*/
-extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 l,
- GHOST_TInt32 t,
- GHOST_TInt32 r,
- GHOST_TInt32 b);
+extern void GHOST_SetRectangle(
+ GHOST_RectangleHandle rectanglehandle, int32_t l, int32_t t, int32_t r, int32_t b);
/**
* Returns whether this rectangle is empty.
@@ -818,7 +806,7 @@ extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehand
* \param rectanglehandle: The handle to the rectangle.
* \param i: The amount of offset given to each extreme (negative values shrink the rectangle).
*/
-extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 i);
+extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, int32_t i);
/**
* Does a union of the rectangle given and this rectangle.
@@ -835,9 +823,7 @@ extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
* \param x: The x-coordinate of the point.
* \param y: The y-coordinate of the point.
*/
-extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y);
+extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, int32_t x, int32_t y);
/**
* Returns whether the point is inside this rectangle.
@@ -848,8 +834,8 @@ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
* \return Success value (true if point is inside).
*/
extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y);
+ int32_t x,
+ int32_t y);
/**
* Returns whether the rectangle is inside this rectangle.
@@ -868,8 +854,8 @@ extern GHOST_TVisibility GHOST_GetRectangleVisibility(
* \param cy: Requested center y-coordinate of the rectangle.
*/
extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 cx,
- GHOST_TInt32 cy);
+ int32_t cx,
+ int32_t cy);
/**
* Sets rectangle members.
@@ -881,11 +867,8 @@ extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
* \param w: requested width of the rectangle.
* \param h: requested height of the rectangle.
*/
-extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 cx,
- GHOST_TInt32 cy,
- GHOST_TInt32 w,
- GHOST_TInt32 h);
+extern void GHOST_SetRectangleCenter(
+ GHOST_RectangleHandle rectanglehandle, int32_t cx, int32_t cy, int32_t w, int32_t h);
/**
* Clips a rectangle.
@@ -903,14 +886,14 @@ extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
* \param selection: Boolean to return the selection instead, X11 only feature.
* \return clipboard data
*/
-extern GHOST_TUns8 *GHOST_getClipboard(int selection);
+extern char *GHOST_getClipboard(bool selection);
/**
* Put data to the Clipboard
* \param buffer: the string buffer to set.
* \param selection: Set the selection instead, X11 only feature.
*/
-extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection);
+extern void GHOST_putClipboard(const char *buffer, bool selection);
/**
* Toggles console
@@ -942,7 +925,7 @@ extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
/**
* Returns the suggested DPI for this window.
*/
-extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
+extern uint16_t GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
/**
* Enable IME attached to the given window, i.e. allows user-input
@@ -956,12 +939,8 @@ extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
* - true: Start a new composition.
* - false: Move the IME windows to the given position without finishing it.
*/
-extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y,
- GHOST_TInt32 w,
- GHOST_TInt32 h,
- int complete);
+extern void GHOST_BeginIME(
+ GHOST_WindowHandle windowhandle, int32_t x, int32_t y, int32_t w, int32_t h, bool complete);
/**
* Disable the IME attached to the given window, i.e. prohibits any user-input
* events from being dispatched to the IME.
@@ -1076,7 +1055,7 @@ void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_context, const char *acti
*/
int GHOST_XrCreateActions(GHOST_XrContextHandle xr_context,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionInfo *infos);
/**
@@ -1084,7 +1063,7 @@ int GHOST_XrCreateActions(GHOST_XrContextHandle xr_context,
*/
void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const char *const *action_names);
/**
@@ -1092,7 +1071,7 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context,
*/
int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionSpaceInfo *infos);
/**
@@ -1100,7 +1079,7 @@ int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context,
*/
void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionSpaceInfo *infos);
/**
@@ -1108,7 +1087,7 @@ void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context,
*/
int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionProfileInfo *infos);
/**
@@ -1116,7 +1095,7 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context,
*/
void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionProfileInfo *infos);
/**
@@ -1138,7 +1117,7 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set
int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context,
const char *action_set_name,
const char *action_name,
- const GHOST_TInt64 *duration,
+ const int64_t *duration,
const float *frequency,
const float *amplitude);
diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h
index c63064c123a..bcccd536ebd 100644
--- a/intern/ghost/GHOST_IEvent.h
+++ b/intern/ghost/GHOST_IEvent.h
@@ -58,7 +58,7 @@ class GHOST_IEvent {
* Returns the time this event was generated.
* \return The event generation time.
*/
- virtual GHOST_TUns64 getTime() = 0;
+ virtual uint64_t getTime() = 0;
/**
* Returns the window this event was generated on,
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 81b54cf5a0d..4c395f720df 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -177,7 +177,7 @@ class GHOST_ISystem {
* Based on ANSI clock() routine.
* \return The number of milliseconds.
*/
- virtual GHOST_TUns64 getMilliSeconds() const = 0;
+ virtual uint64_t getMilliSeconds() const = 0;
/**
* Installs a timer.
@@ -189,8 +189,8 @@ class GHOST_ISystem {
* \param userData: Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
- virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
- GHOST_TUns64 interval,
+ virtual GHOST_ITimerTask *installTimer(uint64_t delay,
+ uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL) = 0;
@@ -209,19 +209,19 @@ class GHOST_ISystem {
* Returns the number of displays on this system.
* \return The number of displays.
*/
- virtual GHOST_TUns8 getNumDisplays() const = 0;
+ virtual uint8_t getNumDisplays() const = 0;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- virtual void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const = 0;
+ virtual void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const = 0;
/**
* Returns the combine dimensions of all monitors.
* \return The dimension of the workspace.
*/
- virtual void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const = 0;
+ virtual void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const = 0;
/**
* Create a new window.
@@ -242,10 +242,10 @@ class GHOST_ISystem {
* \return The new window (or 0 if creation failed).
*/
virtual GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -365,7 +365,7 @@ class GHOST_ISystem {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const = 0;
+ virtual GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const = 0;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -374,7 +374,7 @@ class GHOST_ISystem {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0;
+ virtual GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) = 0;
/***************************************************************************************
* Access to mouse button and keyboard states.
@@ -431,12 +431,12 @@ class GHOST_ISystem {
* \return "unsigned char" from X11 XA_CUT_BUFFER0 buffer
*
*/
- virtual GHOST_TUns8 *getClipboard(bool selection) const = 0;
+ virtual char *getClipboard(bool selection) const = 0;
/**
* Put data to the Clipboard
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
+ virtual void putClipboard(const char *buffer, bool selection) const = 0;
/***************************************************************************************
* System Message Box.
diff --git a/intern/ghost/GHOST_ISystemPaths.h b/intern/ghost/GHOST_ISystemPaths.h
index 74285b7e0ce..8298f4b78e2 100644
--- a/intern/ghost/GHOST_ISystemPaths.h
+++ b/intern/ghost/GHOST_ISystemPaths.h
@@ -68,26 +68,26 @@ class GHOST_ISystemPaths {
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
- virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0;
+ virtual const char *getSystemDir(int version, const char *versionstr) const = 0;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
- virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
+ virtual const char *getUserDir(int version, const char *versionstr) const = 0;
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
- virtual const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const = 0;
+ virtual const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const = 0;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- virtual const GHOST_TUns8 *getBinaryDir() const = 0;
+ virtual const char *getBinaryDir() const = 0;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 1650b230812..f870791b345 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -108,20 +108,20 @@ class GHOST_IWindow {
* Resizes client rectangle width.
* \param width: The new width of the client area of the window.
*/
- virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
+ virtual GHOST_TSuccess setClientWidth(uint32_t width) = 0;
/**
* Resizes client rectangle height.
* \param height: The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
+ virtual GHOST_TSuccess setClientHeight(uint32_t height) = 0;
/**
* Resizes client rectangle.
* \param width: The new width of the client area of the window.
* \param height: The new height of the client area of the window.
*/
- virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
+ virtual GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) = 0;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -130,10 +130,7 @@ class GHOST_IWindow {
* \param outX: The x-coordinate in the client rectangle.
* \param outY: The y-coordinate in the client rectangle.
*/
- virtual void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const = 0;
+ virtual void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const = 0;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -142,10 +139,7 @@ class GHOST_IWindow {
* \param outX: The x-coordinate on the screen.
* \param outY: The y-coordinate on the screen.
*/
- virtual void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const = 0;
+ virtual void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const = 0;
/**
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
@@ -290,8 +284,8 @@ class GHOST_IWindow {
* \param hotY: The Y coordinate of the cursor hot-spot.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ virtual GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -319,7 +313,7 @@ class GHOST_IWindow {
virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode /*mode*/,
GHOST_TAxisFlag /*wrap_axis*/,
GHOST_Rect * /*bounds*/,
- GHOST_TInt32 /*mouse_ungrab_xy*/[2])
+ int32_t /*mouse_ungrab_xy*/[2])
{
return GHOST_kSuccess;
}
@@ -334,7 +328,7 @@ class GHOST_IWindow {
* Returns the recommended DPI for this window.
* \return The recommended DPI for this window.
*/
- virtual GHOST_TUns16 getDPIHint() = 0;
+ virtual uint16_t getDPIHint() = 0;
#ifdef WITH_INPUT_IME
/**
@@ -348,8 +342,7 @@ class GHOST_IWindow {
* - true: Start a new composition
* - false: Move the IME windows to the given position without finishing it.
*/
- virtual void beginIME(
- GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed) = 0;
+ virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed) = 0;
/**
* Disable the IME attached to the given window, i.e. prohibits any user-input
diff --git a/intern/ghost/GHOST_Path-api.h b/intern/ghost/GHOST_Path-api.h
index 36ea70838ca..81df2e607eb 100644
--- a/intern/ghost/GHOST_Path-api.h
+++ b/intern/ghost/GHOST_Path-api.h
@@ -48,25 +48,25 @@ extern GHOST_TSuccess GHOST_DisposeSystemPaths(void);
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
-extern const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr);
+extern const char *GHOST_getSystemDir(int version, const char *versionstr);
/**
* Determine the base dir in which user configuration is stored, including versioning.
* \return Unsigned char string pointing to user dir (eg ~).
*/
-extern const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr);
+extern const char *GHOST_getUserDir(int version, const char *versionstr);
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
-extern const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type);
+extern const char *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type);
/**
* Determine the dir in which the binary file is found.
* \return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/).
*/
-extern const GHOST_TUns8 *GHOST_getBinaryDir(void);
+extern const char *GHOST_getBinaryDir(void);
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h
index dae2a2a8cbb..1c67ca3d2e0 100644
--- a/intern/ghost/GHOST_Rect.h
+++ b/intern/ghost/GHOST_Rect.h
@@ -42,7 +42,7 @@ class GHOST_Rect {
* \param r: requested right coordinate of the rectangle.
* \param b: requested bottom coordinate of the rectangle.
*/
- GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0)
+ GHOST_Rect(int32_t l = 0, int32_t t = 0, int32_t r = 0, int32_t b = 0)
: m_l(l), m_t(t), m_r(r), m_b(b)
{
}
@@ -58,13 +58,13 @@ class GHOST_Rect {
* Access to rectangle width.
* \return width of the rectangle.
*/
- virtual inline GHOST_TInt32 getWidth() const;
+ virtual inline int32_t getWidth() const;
/**
* Access to rectangle height.
* \return height of the rectangle.
*/
- virtual inline GHOST_TInt32 getHeight() const;
+ virtual inline int32_t getHeight() const;
/**
* Sets all members of the rectangle.
@@ -73,7 +73,7 @@ class GHOST_Rect {
* \param r: requested right coordinate of the rectangle.
* \param b: requested bottom coordinate of the rectangle.
*/
- virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b);
+ virtual inline void set(int32_t l, int32_t t, int32_t r, int32_t b);
/**
* Returns whether this rectangle is empty.
@@ -95,7 +95,7 @@ class GHOST_Rect {
* The method avoids negative insets making the rectangle invalid
* \param i: The amount of offset given to each extreme (negative values shrink the rectangle).
*/
- virtual void inset(GHOST_TInt32 i);
+ virtual void inset(int32_t i);
/**
* Does a union of the rectangle given and this rectangle.
@@ -109,17 +109,14 @@ class GHOST_Rect {
* \param x: The x-coordinate of the point.
* \param y: The y-coordinate of the point.
*/
- virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y);
+ virtual inline void unionPoint(int32_t x, int32_t y);
/**
* Grows the rectangle to included a point.
* \param x: The x-coordinate of the point.
* \param y: The y-coordinate of the point.
*/
- virtual inline void wrapPoint(GHOST_TInt32 &x,
- GHOST_TInt32 &y,
- GHOST_TInt32 ofs,
- GHOST_TAxisFlag axis);
+ virtual inline void wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis);
/**
* Returns whether the point is inside this rectangle.
@@ -128,7 +125,7 @@ class GHOST_Rect {
* \param y: y-coordinate of point to test.
* \return boolean value (true if point is inside).
*/
- virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const;
+ virtual inline bool isInside(int32_t x, int32_t y) const;
/**
* Returns whether the rectangle is inside this rectangle.
@@ -143,7 +140,7 @@ class GHOST_Rect {
* \param cx: requested center x-coordinate of the rectangle.
* \param cy: requested center y-coordinate of the rectangle.
*/
- virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy);
+ virtual void setCenter(int32_t cx, int32_t cy);
/**
* Sets rectangle members.
@@ -154,7 +151,7 @@ class GHOST_Rect {
* \param w: requested width of the rectangle.
* \param h: requested height of the rectangle.
*/
- virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h);
+ virtual void setCenter(int32_t cx, int32_t cy, int32_t w, int32_t h);
/**
* Clips a rectangle.
@@ -166,30 +163,30 @@ class GHOST_Rect {
virtual bool clip(GHOST_Rect &r) const;
/** Left coordinate of the rectangle */
- GHOST_TInt32 m_l;
+ int32_t m_l;
/** Top coordinate of the rectangle */
- GHOST_TInt32 m_t;
+ int32_t m_t;
/** Right coordinate of the rectangle */
- GHOST_TInt32 m_r;
+ int32_t m_r;
/** Bottom coordinate of the rectangle */
- GHOST_TInt32 m_b;
+ int32_t m_b;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_Rect")
#endif
};
-inline GHOST_TInt32 GHOST_Rect::getWidth() const
+inline int32_t GHOST_Rect::getWidth() const
{
return m_r - m_l;
}
-inline GHOST_TInt32 GHOST_Rect::getHeight() const
+inline int32_t GHOST_Rect::getHeight() const
{
return m_b - m_t;
}
-inline void GHOST_Rect::set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b)
+inline void GHOST_Rect::set(int32_t l, int32_t t, int32_t r, int32_t b)
{
m_l = l;
m_t = t;
@@ -219,7 +216,7 @@ inline void GHOST_Rect::unionRect(const GHOST_Rect &r)
m_b = r.m_b;
}
-inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y)
+inline void GHOST_Rect::unionPoint(int32_t x, int32_t y)
{
if (x < m_l)
m_l = x;
@@ -231,13 +228,10 @@ inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y)
m_b = y;
}
-inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x,
- GHOST_TInt32 &y,
- GHOST_TInt32 ofs,
- GHOST_TAxisFlag axis)
+inline void GHOST_Rect::wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis)
{
- GHOST_TInt32 w = getWidth();
- GHOST_TInt32 h = getHeight();
+ int32_t w = getWidth();
+ int32_t h = getHeight();
/* highly unlikely but avoid eternal loop */
if (w - ofs * 2 <= 0 || h - ofs * 2 <= 0) {
@@ -258,7 +252,7 @@ inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x,
}
}
-inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const
+inline bool GHOST_Rect::isInside(int32_t x, int32_t y) const
{
return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b);
}
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 7efbd00c2eb..ff93de4f203 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -23,6 +23,8 @@
#pragma once
+#include <stdint.h>
+
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
@@ -56,13 +58,6 @@ GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
GHOST_DECLARE_HANDLE(GHOST_XrContextHandle);
-typedef char GHOST_TInt8;
-typedef unsigned char GHOST_TUns8;
-typedef short GHOST_TInt16;
-typedef unsigned short GHOST_TUns16;
-typedef int GHOST_TInt32;
-typedef unsigned int GHOST_TUns32;
-
typedef struct {
int flags;
} GHOST_GLSettings;
@@ -78,14 +73,6 @@ typedef enum GHOST_DialogOptions {
GHOST_DialogError = (1 << 1),
} GHOST_DialogOptions;
-#ifdef _MSC_VER
-typedef __int64 GHOST_TInt64;
-typedef unsigned __int64 GHOST_TUns64;
-#else
-typedef long long GHOST_TInt64;
-typedef unsigned long long GHOST_TUns64;
-#endif
-
typedef void *GHOST_TUserDataPtr;
typedef enum { GHOST_kFailure = 0, GHOST_kSuccess } GHOST_TSuccess;
@@ -436,9 +423,9 @@ typedef void *GHOST_TEventDataPtr;
typedef struct {
/** The x-coordinate of the cursor position. */
- GHOST_TInt32 x;
+ int32_t x;
/** The y-coordinate of the cursor position. */
- GHOST_TInt32 y;
+ int32_t y;
/** Associated tablet data. */
GHOST_TabletData tablet;
} GHOST_TEventCursorData;
@@ -452,7 +439,7 @@ typedef struct {
typedef struct {
/** Displacement of a mouse wheel. */
- GHOST_TInt32 z;
+ int32_t z;
} GHOST_TEventWheelData;
typedef enum {
@@ -468,13 +455,13 @@ typedef struct {
/** The event subtype */
GHOST_TTrackpadEventSubTypes subtype;
/** The x-location of the trackpad event */
- GHOST_TInt32 x;
+ int32_t x;
/** The y-location of the trackpad event */
- GHOST_TInt32 y;
+ int32_t y;
/** The x-delta or value of the trackpad event */
- GHOST_TInt32 deltaX;
+ int32_t deltaX;
/** The y-delta (currently only for scroll subtype) of the trackpad event */
- GHOST_TInt32 deltaY;
+ int32_t deltaY;
/** The delta is inverted from the device due to system preferences. */
char isDirectionInverted;
} GHOST_TEventTrackpadData;
@@ -488,9 +475,9 @@ typedef enum {
typedef struct {
/** The x-coordinate of the cursor position. */
- GHOST_TInt32 x;
+ int32_t x;
/** The y-coordinate of the cursor position. */
- GHOST_TInt32 y;
+ int32_t y;
/** The dropped item type */
GHOST_TDragnDropTypes dataType;
/** The "dropped content" */
@@ -515,7 +502,7 @@ typedef struct {
typedef struct {
int count;
- GHOST_TUns8 **strings;
+ uint8_t **strings;
} GHOST_TStringArray;
typedef enum {
@@ -587,13 +574,13 @@ typedef enum {
typedef struct {
/** Number of pixels on a line. */
- GHOST_TUns32 xPixels;
+ uint32_t xPixels;
/** Number of lines. */
- GHOST_TUns32 yPixels;
+ uint32_t yPixels;
/** Number of bits per pixel. */
- GHOST_TUns32 bpp;
+ uint32_t bpp;
/** Refresh rate (in Hertz). */
- GHOST_TUns32 frequency;
+ uint32_t frequency;
} GHOST_DisplaySetting;
#ifdef _WIN32
@@ -613,10 +600,10 @@ typedef int GHOST_TEmbedderWindowID;
*/
#ifdef __cplusplus
class GHOST_ITimerTask;
-typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask *task, GHOST_TUns64 time);
+typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask *task, uint64_t time);
#else
struct GHOST_TimerTaskHandle__;
-typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_TUns64 time);
+typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, uint64_t time);
#endif
#ifdef WITH_XR_OPENXR
@@ -724,7 +711,7 @@ typedef enum GHOST_XrActionType {
typedef struct GHOST_XrActionInfo {
const char *name;
GHOST_XrActionType type;
- GHOST_TUns32 count_subaction_paths;
+ uint32_t count_subaction_paths;
const char **subaction_paths;
/** States for each subaction path. */
void *states;
@@ -735,7 +722,7 @@ typedef struct GHOST_XrActionInfo {
typedef struct GHOST_XrActionSpaceInfo {
const char *action_name;
- GHOST_TUns32 count_subaction_paths;
+ uint32_t count_subaction_paths;
const char **subaction_paths;
/** Poses for each subaction path. */
const GHOST_XrPose *poses;
@@ -743,14 +730,14 @@ typedef struct GHOST_XrActionSpaceInfo {
typedef struct GHOST_XrActionBindingInfo {
const char *action_name;
- GHOST_TUns32 count_interaction_paths;
+ uint32_t count_interaction_paths;
/** Interaction path: User (sub-action) path + component path. */
const char **interaction_paths;
} GHOST_XrActionBindingInfo;
typedef struct GHOST_XrActionProfileInfo {
const char *profile_path;
- GHOST_TUns32 count_bindings;
+ uint32_t count_bindings;
const GHOST_XrActionBindingInfo *bindings;
} GHOST_XrActionProfileInfo;
diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h
index e77bab4f2ec..b216d9f2839 100644
--- a/intern/ghost/intern/GHOST_Buttons.h
+++ b/intern/ghost/intern/GHOST_Buttons.h
@@ -57,7 +57,7 @@ struct GHOST_Buttons {
*/
void clear();
- GHOST_TUns8 m_ButtonLeft : 1;
- GHOST_TUns8 m_ButtonMiddle : 1;
- GHOST_TUns8 m_ButtonRight : 1;
+ uint8_t m_ButtonLeft : 1;
+ uint8_t m_ButtonMiddle : 1;
+ uint8_t m_ButtonRight : 1;
};
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 955f35274ea..cb409595e50 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -84,7 +84,7 @@ GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhand
return GHOST_kSuccess;
}
-GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle)
+uint64_t GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -92,8 +92,8 @@ GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle)
}
GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
- GHOST_TUns64 delay,
- GHOST_TUns64 interval,
+ uint64_t delay,
+ uint64_t interval,
GHOST_TimerProcPtr timerproc,
GHOST_TUserDataPtr userdata)
{
@@ -111,7 +111,7 @@ GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
return system->removeTimer(timertask);
}
-GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle)
+uint8_t GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -119,8 +119,8 @@ GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle)
}
void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
- GHOST_TUns32 *width,
- GHOST_TUns32 *height)
+ uint32_t *width,
+ uint32_t *height)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -128,8 +128,8 @@ void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
}
void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
- GHOST_TUns32 *width,
- GHOST_TUns32 *height)
+ uint32_t *width,
+ uint32_t *height)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -156,10 +156,10 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle parent_windowhandle,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_TDrawingContextType type,
@@ -317,13 +317,13 @@ GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle,
}
GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
- GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
int hotY,
- GHOST_TUns8 canInvertColor)
+ bool canInvertColor)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -344,18 +344,14 @@ GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, int vi
return window->setCursorVisibility(visible ? true : false);
}
-GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
- GHOST_TInt32 *x,
- GHOST_TInt32 *y)
+GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, int32_t *x, int32_t *y)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return system->getCursorPosition(*x, *y);
}
-GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, int32_t x, int32_t y)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -370,7 +366,7 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
GHOST_Rect bounds_rect;
- GHOST_TInt32 mouse_xy[2];
+ int32_t mouse_xy[2];
if (bounds) {
bounds_rect = GHOST_Rect(bounds[0], bounds[1], bounds[2], bounds[3]);
@@ -420,7 +416,7 @@ void GHOST_setNDOFDeadZone(float deadzone)
}
#endif
-void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept)
+void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool canAccept)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -434,7 +430,7 @@ GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle)
return event->getType();
}
-GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle)
+uint64_t GHOST_GetEventTime(GHOST_EventHandle eventhandle)
{
GHOST_IEvent *event = (GHOST_IEvent *)eventhandle;
@@ -555,14 +551,14 @@ void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle)
delete (GHOST_Rect *)rectanglehandle;
}
-GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOST_TUns32 width)
+GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, uint32_t width)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
return window->setClientWidth(width);
}
-GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns32 height)
+GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, uint32_t height)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -570,30 +566,24 @@ GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns
}
GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
- GHOST_TUns32 width,
- GHOST_TUns32 height)
+ uint32_t width,
+ uint32_t height)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
return window->setClientSize(width, height);
}
-void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
- GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 *outX,
- GHOST_TInt32 *outY)
+void GHOST_ScreenToClient(
+ GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
window->screenToClient(inX, inY, *outX, *outY);
}
-void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
- GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 *outX,
- GHOST_TInt32 *outY)
+void GHOST_ClientToScreen(
+ GHOST_WindowHandle windowhandle, int32_t inX, int32_t inY, int32_t *outX, int32_t *outY)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -614,8 +604,7 @@ GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, GHOST_TWind
return window->setState(state);
}
-GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle,
- GHOST_TUns8 isUnsavedChanges)
+GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, bool isUnsavedChanges)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -703,21 +692,18 @@ void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI api)
system->setTabletAPI(api);
}
-GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
+int32_t GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
{
return ((GHOST_Rect *)rectanglehandle)->getWidth();
}
-GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
+int32_t GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
{
return ((GHOST_Rect *)rectanglehandle)->getHeight();
}
-void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 *l,
- GHOST_TInt32 *t,
- GHOST_TInt32 *r,
- GHOST_TInt32 *b)
+void GHOST_GetRectangle(
+ GHOST_RectangleHandle rectanglehandle, int32_t *l, int32_t *t, int32_t *r, int32_t *b)
{
GHOST_Rect *rect = (GHOST_Rect *)rectanglehandle;
@@ -727,11 +713,8 @@ void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
*b = rect->m_b;
}
-void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 l,
- GHOST_TInt32 t,
- GHOST_TInt32 r,
- GHOST_TInt32 b)
+void GHOST_SetRectangle(
+ GHOST_RectangleHandle rectanglehandle, int32_t l, int32_t t, int32_t r, int32_t b)
{
((GHOST_Rect *)rectanglehandle)->set(l, t, r, b);
}
@@ -756,7 +739,7 @@ GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle)
return result;
}
-void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 i)
+void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, int32_t i)
{
((GHOST_Rect *)rectanglehandle)->inset(i);
}
@@ -767,16 +750,12 @@ void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
((GHOST_Rect *)rectanglehandle)->unionRect(*(GHOST_Rect *)anotherrectanglehandle);
}
-void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y)
+void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle, int32_t x, int32_t y)
{
((GHOST_Rect *)rectanglehandle)->unionPoint(x, y);
}
-GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y)
+GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, int32_t x, int32_t y)
{
GHOST_TSuccess result = GHOST_kFailure;
@@ -796,18 +775,13 @@ GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectangleha
return visible;
}
-void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 cx,
- GHOST_TInt32 cy)
+void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle, int32_t cx, int32_t cy)
{
((GHOST_Rect *)rectanglehandle)->setCenter(cx, cy);
}
-void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
- GHOST_TInt32 cx,
- GHOST_TInt32 cy,
- GHOST_TInt32 w,
- GHOST_TInt32 h)
+void GHOST_SetRectangleCenter(
+ GHOST_RectangleHandle rectanglehandle, int32_t cx, int32_t cy, int32_t w, int32_t h)
{
((GHOST_Rect *)rectanglehandle)->setCenter(cx, cy, w, h);
}
@@ -823,13 +797,13 @@ GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
return result;
}
-GHOST_TUns8 *GHOST_getClipboard(int selection)
+char *GHOST_getClipboard(bool selection)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->getClipboard(selection);
}
-void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection)
+void GHOST_putClipboard(const char *buffer, bool selection)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
system->putClipboard(buffer, selection);
@@ -861,7 +835,7 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
-GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle)
+uint16_t GHOST_GetDPIHint(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
return window->getDPIHint();
@@ -869,12 +843,8 @@ GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle)
#ifdef WITH_INPUT_IME
-void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
- GHOST_TInt32 x,
- GHOST_TInt32 y,
- GHOST_TInt32 w,
- GHOST_TInt32 h,
- int complete)
+void GHOST_BeginIME(
+ GHOST_WindowHandle windowhandle, int32_t x, int32_t y, int32_t w, int32_t h, bool complete)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
window->beginIME(x, y, w, h, complete);
@@ -972,7 +942,7 @@ void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_contexthandle, const char
int GHOST_XrCreateActions(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionInfo *infos)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
@@ -983,7 +953,7 @@ int GHOST_XrCreateActions(GHOST_XrContextHandle xr_contexthandle,
void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const char *const *action_names)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
@@ -993,7 +963,7 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle,
int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionSpaceInfo *infos)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
@@ -1005,7 +975,7 @@ int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle,
void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionSpaceInfo *infos)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
@@ -1015,7 +985,7 @@ void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle,
int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionProfileInfo *infos)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
@@ -1027,7 +997,7 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle,
void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
- GHOST_TUns32 count,
+ uint32_t count,
const GHOST_XrActionProfileInfo *infos)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
@@ -1054,7 +1024,7 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_contexthandle, const char *acti
int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
const char *action_name,
- const GHOST_TInt64 *duration,
+ const int64_t *duration,
const float *frequency,
const float *amplitude)
{
diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp
index d8321bb1732..fe12a76753d 100644
--- a/intern/ghost/intern/GHOST_DisplayManager.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManager.cpp
@@ -49,20 +49,20 @@ GHOST_TSuccess GHOST_DisplayManager::initialize(void)
return success;
}
-GHOST_TSuccess GHOST_DisplayManager::getNumDisplays(GHOST_TUns8 & /*numDisplays*/) const
+GHOST_TSuccess GHOST_DisplayManager::getNumDisplays(uint8_t & /*numDisplays*/) const
{
// Don't know if we have a display...
return GHOST_kFailure;
}
-GHOST_TSuccess GHOST_DisplayManager::getNumDisplaySettings(GHOST_TUns8 display,
- GHOST_TInt32 &numSettings) const
+GHOST_TSuccess GHOST_DisplayManager::getNumDisplaySettings(uint8_t display,
+ int32_t &numSettings) const
{
GHOST_TSuccess success;
GHOST_ASSERT(m_settingsInitialized,
"GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false");
- GHOST_TUns8 numDisplays;
+ uint8_t numDisplays;
success = getNumDisplays(numDisplays);
if (success == GHOST_kSuccess) {
if (display < numDisplays) {
@@ -75,18 +75,18 @@ GHOST_TSuccess GHOST_DisplayManager::getNumDisplaySettings(GHOST_TUns8 display,
return success;
}
-GHOST_TSuccess GHOST_DisplayManager::getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+GHOST_TSuccess GHOST_DisplayManager::getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const
{
GHOST_TSuccess success;
GHOST_ASSERT(m_settingsInitialized,
"GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false");
- GHOST_TUns8 numDisplays;
+ uint8_t numDisplays;
success = getNumDisplays(numDisplays);
if (success == GHOST_kSuccess) {
- if (display < numDisplays && ((GHOST_TUns8)index < m_settings[display].size())) {
+ if (display < numDisplays && ((uint8_t)index < m_settings[display].size())) {
setting = m_settings[display][index];
}
else {
@@ -97,18 +97,18 @@ GHOST_TSuccess GHOST_DisplayManager::getDisplaySetting(GHOST_TUns8 display,
}
GHOST_TSuccess GHOST_DisplayManager::getCurrentDisplaySetting(
- GHOST_TUns8 /*display*/, GHOST_DisplaySetting & /*setting*/) const
+ uint8_t /*display*/, GHOST_DisplaySetting & /*setting*/) const
{
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_DisplayManager::setCurrentDisplaySetting(
- GHOST_TUns8 /*display*/, const GHOST_DisplaySetting & /*setting*/)
+ uint8_t /*display*/, const GHOST_DisplaySetting & /*setting*/)
{
return GHOST_kFailure;
}
-GHOST_TSuccess GHOST_DisplayManager::findMatch(GHOST_TUns8 display,
+GHOST_TSuccess GHOST_DisplayManager::findMatch(uint8_t display,
const GHOST_DisplaySetting &setting,
GHOST_DisplaySetting &match) const
{
@@ -157,17 +157,16 @@ GHOST_TSuccess GHOST_DisplayManager::findMatch(GHOST_TUns8 display,
GHOST_TSuccess GHOST_DisplayManager::initializeSettings(void)
{
- GHOST_TUns8 numDisplays;
+ uint8_t numDisplays;
GHOST_TSuccess success = getNumDisplays(numDisplays);
if (success == GHOST_kSuccess) {
- for (GHOST_TUns8 display = 0; (display < numDisplays) && (success == GHOST_kSuccess);
- display++) {
+ for (uint8_t display = 0; (display < numDisplays) && (success == GHOST_kSuccess); display++) {
GHOST_DisplaySettings displaySettings;
m_settings.push_back(displaySettings);
- GHOST_TInt32 numSettings;
+ int32_t numSettings;
success = getNumDisplaySettings(display, numSettings);
if (success == GHOST_kSuccess) {
- GHOST_TInt32 index;
+ int32_t index;
GHOST_DisplaySetting setting;
for (index = 0; (index < numSettings) && (success == GHOST_kSuccess); index++) {
success = getDisplaySetting(display, index, setting);
diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h
index 26bc687a179..609dfa72dc6 100644
--- a/intern/ghost/intern/GHOST_DisplayManager.h
+++ b/intern/ghost/intern/GHOST_DisplayManager.h
@@ -55,7 +55,7 @@ class GHOST_DisplayManager {
* \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
+ virtual GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const;
/**
* Returns the number of display settings for this display device.
@@ -63,8 +63,7 @@ class GHOST_DisplayManager {
* \param numSettings: The number of settings of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display,
- GHOST_TInt32 &numSettings) const;
+ virtual GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const;
/**
* Returns the current setting for this display device.
@@ -73,8 +72,8 @@ class GHOST_DisplayManager {
* \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+ virtual GHOST_TSuccess getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const;
/**
@@ -83,7 +82,7 @@ class GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
+ virtual GHOST_TSuccess getCurrentDisplaySetting(uint8_t display,
GHOST_DisplaySetting &setting) const;
/**
@@ -94,7 +93,7 @@ class GHOST_DisplayManager {
* \param setting: The setting of the display device to be matched and activated.
* \return Indication of success.
*/
- virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
+ virtual GHOST_TSuccess setCurrentDisplaySetting(uint8_t display,
const GHOST_DisplaySetting &setting);
protected:
@@ -107,7 +106,7 @@ class GHOST_DisplayManager {
* \param match: The optimal display setting.
* \return Indication of success.
*/
- GHOST_TSuccess findMatch(GHOST_TUns8 display,
+ GHOST_TSuccess findMatch(uint8_t display,
const GHOST_DisplaySetting &setting,
GHOST_DisplaySetting &match) const;
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
index 745ad457796..cea124a601d 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
@@ -46,7 +46,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
* \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
- GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
+ GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const;
/**
* Returns the number of display settings for this display device.
@@ -54,7 +54,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
* \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const;
/**
* Returns the current setting for this display device.
@@ -63,8 +63,8 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
* \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+ GHOST_TSuccess getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const;
/**
@@ -73,8 +73,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
- GHOST_DisplaySetting &setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const;
/**
* Changes the current setting for this display device.
@@ -82,8 +81,7 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
- const GHOST_DisplaySetting &setting);
+ GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting);
protected:
// Do not cache values as OS X supports screen hot plug
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
index d899bb1c3c7..b983f5a9a4d 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
@@ -29,26 +29,26 @@ GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(void)
{
}
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8 &numDisplays) const
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(uint8_t &numDisplays) const
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- numDisplays = (GHOST_TUns8)[[NSScreen screens] count];
+ numDisplays = (uint8_t)[[NSScreen screens] count];
[pool drain];
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 display,
- GHOST_TInt32 &numSettings) const
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(uint8_t display,
+ int32_t &numSettings) const
{
- numSettings = (GHOST_TInt32)3; // Width, Height, BitsPerPixel
+ numSettings = (int32_t)3; // Width, Height, BitsPerPixel
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const
{
NSScreen *askedDisplay;
@@ -86,7 +86,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display,
}
GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(
- GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
+ uint8_t display, GHOST_DisplaySetting &setting) const
{
NSScreen *askedDisplay;
@@ -127,7 +127,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(
}
GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(
- GHOST_TUns8 display, const GHOST_DisplaySetting &setting)
+ uint8_t display, const GHOST_DisplaySetting &setting)
{
GHOST_ASSERT(
(display == kMainDisplay),
diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h
index 4ca06faec12..6b9e9a5a30e 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerNULL.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h
@@ -31,25 +31,25 @@ class GHOST_DisplayManagerNULL : public GHOST_DisplayManager {
GHOST_DisplayManagerNULL(GHOST_SystemNULL *system) : GHOST_DisplayManager(), m_system(system)
{ /* nop */
}
- GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const
+ GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const
{
return GHOST_kFailure;
}
- GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const
+ GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const
{
return GHOST_kFailure;
}
- GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+ GHOST_TSuccess getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const
{
return GHOST_kFailure;
}
- GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
+ GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const
{
- return getDisplaySetting(display, GHOST_TInt32(0), setting);
+ return getDisplaySetting(display, int32_t(0), setting);
}
- GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting &setting)
+ GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting)
{
return GHOST_kSuccess;
}
diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
index 11134ad1054..18adf948e3b 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
@@ -33,14 +33,14 @@ GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system)
memset(&m_mode, 0, sizeof(m_mode));
}
-GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplays(GHOST_TUns8 &numDisplays) const
+GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplays(uint8_t &numDisplays) const
{
numDisplays = SDL_GetNumVideoDisplays();
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(GHOST_TUns8 display,
- GHOST_TInt32 &numSettings) const
+GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(uint8_t display,
+ int32_t &numSettings) const
{
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
@@ -66,8 +66,8 @@ static void ghost_mode_to_sdl(const GHOST_DisplaySetting &setting, SDL_DisplayMo
mode->refresh_rate = setting.frequency;
}
-GHOST_TSuccess GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+GHOST_TSuccess GHOST_DisplayManagerSDL::getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const
{
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
@@ -81,7 +81,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display,
}
GHOST_TSuccess GHOST_DisplayManagerSDL::getCurrentDisplaySetting(
- GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
+ uint8_t display, GHOST_DisplaySetting &setting) const
{
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(display, &mode);
@@ -98,7 +98,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::getCurrentDisplayModeSDL(SDL_DisplayMode
}
GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting(
- GHOST_TUns8 display, const GHOST_DisplaySetting &setting)
+ uint8_t display, const GHOST_DisplaySetting &setting)
{
/*
* Mode switching code ported from Quake 2 version 3.21 and bzflag version
diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.h b/intern/ghost/intern/GHOST_DisplayManagerSDL.h
index 9a79a842057..a719368275c 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerSDL.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.h
@@ -37,21 +37,19 @@ class GHOST_DisplayManagerSDL : public GHOST_DisplayManager {
public:
GHOST_DisplayManagerSDL(GHOST_SystemSDL *system);
- GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
+ GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const;
- GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const;
- GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+ GHOST_TSuccess getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const;
- GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
- GHOST_DisplaySetting &setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const;
GHOST_TSuccess getCurrentDisplayModeSDL(SDL_DisplayMode &mode) const;
- GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
- const GHOST_DisplaySetting &setting);
+ GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting);
private:
GHOST_SystemSDL *m_system;
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
index 3557c4cd0c5..2895ddd68a9 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -35,7 +35,7 @@ GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
{
}
-GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8 &numDisplays) const
+GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(uint8_t &numDisplays) const
{
numDisplays = ::GetSystemMetrics(SM_CMONITORS);
return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
@@ -54,8 +54,8 @@ static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd)
* the information that was cached the last time the function was called with iModeNum
* set to zero.
*/
-GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display,
- GHOST_TInt32 &numSettings) const
+GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(uint8_t display,
+ int32_t &numSettings) const
{
DISPLAY_DEVICE display_device;
if (!get_dd(display, &display_device))
@@ -69,8 +69,8 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 disp
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const
{
DISPLAY_DEVICE display_device;
@@ -111,13 +111,13 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display,
}
GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(
- GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
+ uint8_t display, GHOST_DisplaySetting &setting) const
{
return getDisplaySetting(display, ENUM_CURRENT_SETTINGS, setting);
}
GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
- GHOST_TUns8 display, const GHOST_DisplaySetting &setting)
+ uint8_t display, const GHOST_DisplaySetting &setting)
{
DISPLAY_DEVICE display_device;
if (!get_dd(display, &display_device))
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
index 2de866b04ec..31cde2fc63d 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
@@ -45,7 +45,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
* \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
- GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
+ GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const;
/**
* Returns the number of display settings for this display device.
@@ -53,7 +53,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
* \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const;
/**
* Returns the current setting for this display device.
@@ -62,8 +62,8 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
* \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+ GHOST_TSuccess getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const;
/**
@@ -72,8 +72,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
- GHOST_DisplaySetting &setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const;
/**
* Changes the current setting for this display device.
@@ -81,8 +80,7 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
- const GHOST_DisplaySetting &setting);
+ GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting);
protected:
};
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
index f1acf74ca41..2ebdf8b3f2a 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
@@ -40,14 +40,14 @@ GHOST_DisplayManagerX11::GHOST_DisplayManagerX11(GHOST_SystemX11 *system)
/* nothing to do. */
}
-GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplays(GHOST_TUns8 &numDisplays) const
+GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplays(uint8_t &numDisplays) const
{
numDisplays = m_system->getNumDisplays();
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplaySettings(GHOST_TUns8 display,
- GHOST_TInt32 &numSettings) const
+GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplaySettings(uint8_t display,
+ int32_t &numSettings) const
{
#ifdef WITH_X11_XF86VMODE
int majorVersion, minorVersion;
@@ -88,8 +88,8 @@ static int calculate_rate(XF86VidModeModeInfo *info)
}
#endif
-GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const
{
Display *dpy = m_system->getXDisplay();
@@ -140,7 +140,7 @@ GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(GHOST_TUns8 display,
}
GHOST_TSuccess GHOST_DisplayManagerX11::getCurrentDisplaySetting(
- GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
+ uint8_t display, GHOST_DisplaySetting &setting) const
{
/* According to the xf86vidmodegetallmodelines man page,
* "The first element of the array corresponds to the current video mode."
@@ -149,7 +149,7 @@ GHOST_TSuccess GHOST_DisplayManagerX11::getCurrentDisplaySetting(
}
GHOST_TSuccess GHOST_DisplayManagerX11::setCurrentDisplaySetting(
- GHOST_TUns8 /*display*/, const GHOST_DisplaySetting &setting)
+ uint8_t /*display*/, const GHOST_DisplaySetting &setting)
{
#ifdef WITH_X11_XF86VMODE
/* Mode switching code ported from SDL:
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h
index e0fc1cc1210..52702a397d7 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h
@@ -43,7 +43,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
* \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
- GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
+ GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const;
/**
* Returns the number of display settings for this display device.
@@ -51,7 +51,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
* \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const;
+ GHOST_TSuccess getNumDisplaySettings(uint8_t display, int32_t &numSettings) const;
/**
* Returns the current setting for this display device.
@@ -60,8 +60,8 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
* \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
- GHOST_TInt32 index,
+ GHOST_TSuccess getDisplaySetting(uint8_t display,
+ int32_t index,
GHOST_DisplaySetting &setting) const;
/**
@@ -70,8 +70,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
- GHOST_DisplaySetting &setting) const;
+ GHOST_TSuccess getCurrentDisplaySetting(uint8_t display, GHOST_DisplaySetting &setting) const;
/**
* Changes the current setting for this display device.
@@ -79,8 +78,7 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
* \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
- GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
- const GHOST_DisplaySetting &setting);
+ GHOST_TSuccess setCurrentDisplaySetting(uint8_t display, const GHOST_DisplaySetting &setting);
private:
GHOST_SystemX11 *m_system;
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index ab4b48da9b4..c51bd58898b 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -242,7 +242,7 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject)
strArray = (GHOST_TStringArray *)::malloc(sizeof(GHOST_TStringArray));
strArray->count = 0;
- strArray->strings = (GHOST_TUns8 **)::malloc(totfiles * sizeof(GHOST_TUns8 *));
+ strArray->strings = (uint8_t **)::malloc(totfiles * sizeof(uint8_t *));
for (UINT nfile = 0; nfile < totfiles; nfile++) {
if (::DragQueryFileW(hdrop, nfile, fpath, MAX_PATH) > 0) {
@@ -251,7 +251,7 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *pDataObject)
}
// Just ignore paths that could not be converted verbatim.
- strArray->strings[nvalid] = (GHOST_TUns8 *)temp_path;
+ strArray->strings[nvalid] = (uint8_t *)temp_path;
strArray->count = nvalid + 1;
nvalid++;
}
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp
index a62db31c952..8758a27930e 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp
@@ -216,7 +216,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr
strArray = (GHOST_TStringArray *)malloc(sizeof(GHOST_TStringArray));
strArray->count = 0;
- strArray->strings = (GHOST_TUns8 **)malloc(totPaths * sizeof(GHOST_TUns8 *));
+ strArray->strings = (uint8_t **)malloc(totPaths * sizeof(uint8_t *));
curLength = 0;
for (int i = 0; i <= dropBufferSize; i++) {
@@ -230,7 +230,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr
decodedPath = FileUrlDecode(curPath);
if (decodedPath) {
- strArray->strings[strArray->count] = (GHOST_TUns8 *)decodedPath;
+ strArray->strings[strArray->count] = (uint8_t *)decodedPath;
strArray->count++;
}
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
index 5016ca0e117..0194afd559c 100644
--- a/intern/ghost/intern/GHOST_Event.h
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -37,7 +37,7 @@ class GHOST_Event : public GHOST_IEvent {
* \param type: The type of this event.
* \param window: The generating window (or NULL if system event).
*/
- GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window)
+ GHOST_Event(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window)
: m_type(type), m_time(msec), m_window(window), m_data(NULL)
{
}
@@ -55,7 +55,7 @@ class GHOST_Event : public GHOST_IEvent {
* Returns the time this event was generated.
* \return The event generation time.
*/
- GHOST_TUns64 getTime()
+ uint64_t getTime()
{
return m_time;
}
@@ -83,7 +83,7 @@ class GHOST_Event : public GHOST_IEvent {
/** Type of this event. */
GHOST_TEventType m_type;
/** The time this event was generated. */
- GHOST_TUns64 m_time;
+ uint64_t m_time;
/** Pointer to the generating window. */
GHOST_IWindow *m_window;
/** Pointer to the event data. */
diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h
index 02804efdcba..02563254a82 100644
--- a/intern/ghost/intern/GHOST_EventButton.h
+++ b/intern/ghost/intern/GHOST_EventButton.h
@@ -40,7 +40,7 @@ class GHOST_EventButton : public GHOST_Event {
* \param button: The state of the buttons were at the time of the event.
* \param tablet: The tablet data associated with this event.
*/
- GHOST_EventButton(GHOST_TUns64 time,
+ GHOST_EventButton(uint64_t time,
GHOST_TEventType type,
GHOST_IWindow *window,
GHOST_TButtonMask button,
diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h
index d83ff6af6ce..facbab0855d 100644
--- a/intern/ghost/intern/GHOST_EventCursor.h
+++ b/intern/ghost/intern/GHOST_EventCursor.h
@@ -39,11 +39,11 @@ class GHOST_EventCursor : public GHOST_Event {
* \param y: The y-coordinate of the location the cursor was at the time of the event.
* \param tablet: The tablet data associated with this event.
*/
- GHOST_EventCursor(GHOST_TUns64 msec,
+ GHOST_EventCursor(uint64_t msec,
GHOST_TEventType type,
GHOST_IWindow *window,
- GHOST_TInt32 x,
- GHOST_TInt32 y,
+ int32_t x,
+ int32_t y,
const GHOST_TabletData &tablet)
: GHOST_Event(msec, type, window), m_cursorEventData({x, y, tablet})
{
diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h
index a86b8302bf5..537717b1717 100644
--- a/intern/ghost/intern/GHOST_EventDragnDrop.h
+++ b/intern/ghost/intern/GHOST_EventDragnDrop.h
@@ -72,7 +72,7 @@ class GHOST_EventDragnDrop : public GHOST_Event {
* \param y: The y-coordinate of the location the cursor was at the time of the event.
* \param data: The "content" dropped in the window.
*/
- GHOST_EventDragnDrop(GHOST_TUns64 time,
+ GHOST_EventDragnDrop(uint64_t time,
GHOST_TEventType type,
GHOST_TDragnDropTypes dataType,
GHOST_IWindow *window,
diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h
index 1e6a3284a51..93e6f0380da 100644
--- a/intern/ghost/intern/GHOST_EventKey.h
+++ b/intern/ghost/intern/GHOST_EventKey.h
@@ -39,11 +39,8 @@ class GHOST_EventKey : public GHOST_Event {
* \param type: The type of key event.
* \param key: The key code of the key.
*/
- GHOST_EventKey(GHOST_TUns64 msec,
- GHOST_TEventType type,
- GHOST_IWindow *window,
- GHOST_TKey key,
- bool is_repeat)
+ GHOST_EventKey(
+ uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TKey key, bool is_repeat)
: GHOST_Event(msec, type, window)
{
m_keyEventData.key = key;
@@ -60,7 +57,7 @@ class GHOST_EventKey : public GHOST_Event {
* \param key: The key code of the key.
* \param ascii: The ascii code for the key event.
*/
- GHOST_EventKey(GHOST_TUns64 msec,
+ GHOST_EventKey(uint64_t msec,
GHOST_TEventType type,
GHOST_IWindow *window,
GHOST_TKey key,
diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp
index f16d90899b9..15befb9afcb 100644
--- a/intern/ghost/intern/GHOST_EventManager.cpp
+++ b/intern/ghost/intern/GHOST_EventManager.cpp
@@ -28,7 +28,6 @@
#include "GHOST_EventManager.h"
#include "GHOST_Debug.h"
#include <algorithm>
-#include <stdio.h> // [mce] temp debug
GHOST_EventManager::GHOST_EventManager()
{
@@ -46,14 +45,14 @@ GHOST_EventManager::~GHOST_EventManager()
}
}
-GHOST_TUns32 GHOST_EventManager::getNumEvents()
+uint32_t GHOST_EventManager::getNumEvents()
{
- return (GHOST_TUns32)m_events.size();
+ return (uint32_t)m_events.size();
}
-GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
+uint32_t GHOST_EventManager::getNumEvents(GHOST_TEventType type)
{
- GHOST_TUns32 numEvents = 0;
+ uint32_t numEvents = 0;
TEventStack::iterator p;
for (p = m_events.begin(); p != m_events.end(); ++p) {
if ((*p)->getType() == type) {
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
index a372eb96a99..ba936e449f5 100644
--- a/intern/ghost/intern/GHOST_EventManager.h
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -53,14 +53,14 @@ class GHOST_EventManager {
* Returns the number of events currently on the stack.
* \return The number of events on the stack.
*/
- GHOST_TUns32 getNumEvents();
+ uint32_t getNumEvents();
/**
* Returns the number of events of a certain type currently on the stack.
* \param type: The type of events to be counted.
* \return The number of events on the stack of this type.
*/
- GHOST_TUns32 getNumEvents(GHOST_TEventType type);
+ uint32_t getNumEvents(GHOST_TEventType type);
/**
* Pushes an event on the stack.
diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h
index 64e67434b74..10f39f4be66 100644
--- a/intern/ghost/intern/GHOST_EventNDOF.h
+++ b/intern/ghost/intern/GHOST_EventNDOF.h
@@ -31,7 +31,7 @@ class GHOST_EventNDOFMotion : public GHOST_Event {
GHOST_TEventNDOFMotionData m_axisData;
public:
- GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow *window)
+ GHOST_EventNDOFMotion(uint64_t time, GHOST_IWindow *window)
: GHOST_Event(time, GHOST_kEventNDOFMotion, window)
{
m_data = &m_axisData;
@@ -43,7 +43,7 @@ class GHOST_EventNDOFButton : public GHOST_Event {
GHOST_TEventNDOFButtonData m_buttonData;
public:
- GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow *window)
+ GHOST_EventNDOFButton(uint64_t time, GHOST_IWindow *window)
: GHOST_Event(time, GHOST_kEventNDOFButton, window)
{
m_data = &m_buttonData;
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
index fb34b1d3b1a..48043fa709b 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.cpp
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -39,7 +39,7 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event)
if (event->getType() == GHOST_kEventWindowUpdate)
return false;
- std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime()
+ std::cout << "GHOST_EventPrinter::processEvent, time: " << (int32_t)event->getTime()
<< ", type: ";
switch (event->getType()) {
case GHOST_kEventUnknown:
diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h
index 6dd2ffb2e86..a457c2e058a 100644
--- a/intern/ghost/intern/GHOST_EventString.h
+++ b/intern/ghost/intern/GHOST_EventString.h
@@ -38,7 +38,7 @@ class GHOST_EventString : public GHOST_Event {
* \param window: The generating window (or NULL if system event).
* \param data_ptr: Pointer to the (un-formatted) data associated with the event.
*/
- GHOST_EventString(GHOST_TUns64 msec,
+ GHOST_EventString(uint64_t msec,
GHOST_TEventType type,
GHOST_IWindow *window,
GHOST_TEventDataPtr data_ptr)
diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h
index d4f9d0f2b55..58420f6d713 100644
--- a/intern/ghost/intern/GHOST_EventTrackpad.h
+++ b/intern/ghost/intern/GHOST_EventTrackpad.h
@@ -39,13 +39,13 @@ class GHOST_EventTrackpad : public GHOST_Event {
* \param x: The x-delta of the pan event.
* \param y: The y-delta of the pan event.
*/
- GHOST_EventTrackpad(GHOST_TUns64 msec,
+ GHOST_EventTrackpad(uint64_t msec,
GHOST_IWindow *window,
GHOST_TTrackpadEventSubTypes subtype,
- GHOST_TInt32 x,
- GHOST_TInt32 y,
- GHOST_TInt32 deltaX,
- GHOST_TInt32 deltaY,
+ int32_t x,
+ int32_t y,
+ int32_t deltaX,
+ int32_t deltaY,
bool isDirectionInverted)
: GHOST_Event(msec, GHOST_kEventTrackpad, window)
{
diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h
index ea62e02d08d..666b3c7aba6 100644
--- a/intern/ghost/intern/GHOST_EventWheel.h
+++ b/intern/ghost/intern/GHOST_EventWheel.h
@@ -39,7 +39,7 @@ class GHOST_EventWheel : public GHOST_Event {
* \param window: The window of this event.
* \param z: The displacement of the mouse wheel.
*/
- GHOST_EventWheel(GHOST_TUns64 msec, GHOST_IWindow *window, GHOST_TInt32 z)
+ GHOST_EventWheel(uint64_t msec, GHOST_IWindow *window, int32_t z)
: GHOST_Event(msec, GHOST_kEventWheel, window)
{
m_wheelEventData.z = z;
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index 0c851e067e8..4af988aef6e 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -44,7 +44,7 @@ class GHOST_EventIME : public GHOST_Event {
* \param type: The type of key event.
* \param key: The key code of the key.
*/
- GHOST_EventIME(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata)
+ GHOST_EventIME(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata)
: GHOST_Event(msec, type, window)
{
this->m_data = customdata;
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
index e94ccef08c0..f951cae3a41 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.h
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -72,17 +72,17 @@ struct GHOST_ModifierKeys {
bool equals(const GHOST_ModifierKeys &keys) const;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_LeftShift : 1;
+ uint8_t m_LeftShift : 1;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_RightShift : 1;
+ uint8_t m_RightShift : 1;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_LeftAlt : 1;
+ uint8_t m_LeftAlt : 1;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_RightAlt : 1;
+ uint8_t m_RightAlt : 1;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_LeftControl : 1;
+ uint8_t m_LeftControl : 1;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_RightControl : 1;
+ uint8_t m_RightControl : 1;
/** Bitfield that stores the appropriate key state. */
- GHOST_TUns8 m_OS : 1;
+ uint8_t m_OS : 1;
};
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index dda78c0ac5b..079ad67f737 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -279,14 +279,14 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
return m_deviceType != NDOF_UnknownDevice;
}
-void GHOST_NDOFManager::updateTranslation(const int t[3], GHOST_TUns64 time)
+void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time)
{
memcpy(m_translation, t, sizeof(m_translation));
m_motionTime = time;
m_motionEventPending = true;
}
-void GHOST_NDOFManager::updateRotation(const int r[3], GHOST_TUns64 time)
+void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time)
{
memcpy(m_rotation, r, sizeof(m_rotation));
m_motionTime = time;
@@ -295,7 +295,7 @@ void GHOST_NDOFManager::updateRotation(const int r[3], GHOST_TUns64 time)
void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
bool press,
- GHOST_TUns64 time,
+ uint64_t time,
GHOST_IWindow *window)
{
GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_LAST,
@@ -316,7 +316,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
bool press,
- GHOST_TUns64 time,
+ uint64_t time,
GHOST_IWindow *window)
{
GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
@@ -329,7 +329,7 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
m_system.pushEvent(event);
}
-void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time)
+void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time)
{
GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow();
@@ -371,7 +371,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64
}
}
-void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time)
+void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time)
{
button_bits &= m_buttonMask; // discard any "garbage" bits
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index d0b49bc13c2..7be129c327c 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -130,13 +130,13 @@ class GHOST_NDOFManager {
// rotations are + when CCW, - when CW
// each platform is responsible for getting axis data into this form
// these values should not be scaled (just shuffled or flipped)
- void updateTranslation(const int t[3], GHOST_TUns64 time);
- void updateRotation(const int r[3], GHOST_TUns64 time);
+ void updateTranslation(const int t[3], uint64_t time);
+ void updateRotation(const int r[3], uint64_t time);
// the latest raw button data from the device
// use HID button encoding (not NDOF_ButtonT)
- void updateButton(int button_number, bool press, GHOST_TUns64 time);
- void updateButtons(int button_bits, GHOST_TUns64 time);
+ void updateButton(int button_number, bool press, uint64_t time);
+ void updateButtons(int button_bits, uint64_t time);
// NDOFButton events are sent immediately
// processes and sends most recent raw data as an NDOFMotion event
@@ -147,8 +147,8 @@ class GHOST_NDOFManager {
GHOST_System &m_system;
private:
- void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow *);
- void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow *);
+ 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;
@@ -159,8 +159,8 @@ class GHOST_NDOFManager {
int m_rotation[3];
int m_buttons; // bit field
- GHOST_TUns64 m_motionTime; // in milliseconds
- GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent
+ uint64_t m_motionTime; // in milliseconds
+ uint64_t m_prevMotionTime; // time of most recent Motion event sent
GHOST_TProgress m_motionState;
bool m_motionEventPending;
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
index 5274b2d1ba9..63a38fd9297 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
+++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
@@ -195,7 +195,7 @@ static void DeviceEvent(uint32_t unused, uint32_t msg_type, void *msg_arg)
// device state is broadcast to all clients; only react if sent to us
if (s->client == clientID) {
// TODO: is s->time compatible with GHOST timestamps? if so use that instead.
- GHOST_TUns64 now = ghost_system->getMilliSeconds();
+ uint64_t now = ghost_system->getMilliSeconds();
switch (s->command) {
case kConnexionCmdHandleAxis: {
diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
index 8ed0af1fc29..983bb38307e 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
@@ -97,7 +97,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
switch (e.type) {
case SPNAV_EVENT_MOTION: {
/* convert to blender view coords */
- GHOST_TUns64 now = m_system.getMilliSeconds();
+ uint64_t now = m_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};
@@ -109,7 +109,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
break;
}
case SPNAV_EVENT_BUTTON:
- GHOST_TUns64 now = m_system.getMilliSeconds();
+ uint64_t now = m_system.getMilliSeconds();
updateButton(e.button.bnum, e.button.press, now);
break;
}
@@ -118,7 +118,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
#ifdef USE_FINISH_GLITCH_WORKAROUND
if (motion_test_prev == true && motion_test == false) {
- GHOST_TUns64 now = m_system.getMilliSeconds();
+ uint64_t now = m_system.getMilliSeconds();
const int v[3] = {0, 0, 0};
updateTranslation(v, now);
diff --git a/intern/ghost/intern/GHOST_Path-api.cpp b/intern/ghost/intern/GHOST_Path-api.cpp
index c82e9819f3c..4f4d1d5a1c8 100644
--- a/intern/ghost/intern/GHOST_Path-api.cpp
+++ b/intern/ghost/intern/GHOST_Path-api.cpp
@@ -38,25 +38,25 @@ GHOST_TSuccess GHOST_DisposeSystemPaths(void)
return GHOST_ISystemPaths::dispose();
}
-const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr)
+const char *GHOST_getSystemDir(int version, const char *versionstr)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
return systemPaths ? systemPaths->getSystemDir(version, versionstr) : NULL;
}
-const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr)
+const char *GHOST_getUserDir(int version, const char *versionstr)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
return systemPaths ? systemPaths->getUserDir(version, versionstr) : NULL; /* shouldn't be NULL */
}
-const GHOST_TUns8 *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type)
+const char *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
return systemPaths ? systemPaths->getUserSpecialDir(type) : NULL; /* shouldn't be NULL */
}
-const GHOST_TUns8 *GHOST_getBinaryDir()
+const char *GHOST_getBinaryDir()
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
return systemPaths ? systemPaths->getBinaryDir() : NULL; /* shouldn't be NULL */
diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp
index c5b9bc44468..8ef9486f35a 100644
--- a/intern/ghost/intern/GHOST_Rect.cpp
+++ b/intern/ghost/intern/GHOST_Rect.cpp
@@ -23,7 +23,7 @@
#include "GHOST_Rect.h"
-void GHOST_Rect::inset(GHOST_TInt32 i)
+void GHOST_Rect::inset(int32_t i)
{
if (i > 0) {
// Grow the rectangle
@@ -34,7 +34,7 @@ void GHOST_Rect::inset(GHOST_TInt32 i)
}
else if (i < 0) {
// Shrink the rectangle, check for insets larger than half the size
- GHOST_TInt32 i2 = i * 2;
+ int32_t i2 = i * 2;
if (getWidth() > i2) {
m_l += i;
m_r -= i;
@@ -82,9 +82,9 @@ GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect &r) const
return v;
}
-void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy)
+void GHOST_Rect::setCenter(int32_t cx, int32_t cy)
{
- GHOST_TInt32 offset = cx - (m_l + (m_r - m_l) / 2);
+ int32_t offset = cx - (m_l + (m_r - m_l) / 2);
m_l += offset;
m_r += offset;
offset = cy - (m_t + (m_b - m_t) / 2);
@@ -92,7 +92,7 @@ void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy)
m_b += offset;
}
-void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h)
+void GHOST_Rect::setCenter(int32_t cx, int32_t cy, int32_t w, int32_t h)
{
long w_2, h_2;
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 46c50045b80..f6659cf50dc 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -56,19 +56,19 @@ GHOST_System::~GHOST_System()
exit();
}
-GHOST_TUns64 GHOST_System::getMilliSeconds() const
+uint64_t GHOST_System::getMilliSeconds() const
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
-GHOST_ITimerTask *GHOST_System::installTimer(GHOST_TUns64 delay,
- GHOST_TUns64 interval,
+GHOST_ITimerTask *GHOST_System::installTimer(uint64_t delay,
+ uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData)
{
- GHOST_TUns64 millis = getMilliSeconds();
+ uint64_t millis = getMilliSeconds();
GHOST_TimerTask *timer = new GHOST_TimerTask(millis + delay, interval, timerProc, userData);
if (timer) {
if (m_timerManager->addTimer(timer) == GHOST_kSuccess) {
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 87ba0ae9c8c..9164687c5b5 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -75,7 +75,7 @@ class GHOST_System : public GHOST_ISystem {
* Based on ANSI clock() routine.
* \return The number of milliseconds.
*/
- virtual GHOST_TUns64 getMilliSeconds() const;
+ virtual uint64_t getMilliSeconds() const;
/**
* Installs a timer.
@@ -89,8 +89,8 @@ class GHOST_System : public GHOST_ISystem {
* \param userData: Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
- GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
- GHOST_TUns64 interval,
+ GHOST_ITimerTask *installTimer(uint64_t delay,
+ uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL);
@@ -210,8 +210,8 @@ class GHOST_System : public GHOST_ISystem {
/**
* Inherited from GHOST_ISystem but left pure virtual
* <pre>
- * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0;
- * GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+ * GHOST_TSuccess getCursorPosition(int32_t& x, int32_t& y) const = 0;
+ * GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)
* </pre>
*/
@@ -308,14 +308,14 @@ class GHOST_System : public GHOST_ISystem {
* \return Returns the clipboard data
*
*/
- virtual GHOST_TUns8 *getClipboard(bool selection) const = 0;
+ virtual char *getClipboard(bool selection) const = 0;
/**
* Put data to the Clipboard
* \param buffer: The buffer to copy to the clipboard.
* \param selection: The clipboard to copy too only used on X11.
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
+ virtual void putClipboard(const char *buffer, bool selection) const = 0;
/**
* Show a system message box
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index cee6398b5a6..48a64b155fc 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -59,7 +59,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* Based on ANSI clock() routine.
* \return The number of milliseconds.
*/
- GHOST_TUns64 getMilliSeconds() const;
+ uint64_t getMilliSeconds() const;
/***************************************************************************************
* Display/window management functionality
@@ -69,18 +69,18 @@ class GHOST_SystemCocoa : public GHOST_System {
* Returns the number of displays on this system.
* \return The number of displays.
*/
- GHOST_TUns8 getNumDisplays() const;
+ uint8_t getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const;
/** Returns the combine dimensions of all monitors.
* \return The dimension of the workspace.
*/
- void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const;
/**
* Create a new window.
@@ -100,10 +100,10 @@ class GHOST_SystemCocoa : public GHOST_System {
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -137,7 +137,7 @@ class GHOST_SystemCocoa : public GHOST_System {
bool processEvents(bool waitForEvent);
/**
- * Handle User request to quit, from Menu bar Quit, and Cmd+Q
+ * Handle User request to quit, from Menu bar Quit, and Command+Q
* Display alert panel if changes performed since last save
*/
void handleQuitRequest();
@@ -175,7 +175,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -183,7 +183,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y);
/***************************************************************************************
* Access to mouse button and keyboard states.
@@ -208,14 +208,14 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param selection: Indicate which buffer to return.
* \return Returns the selected buffer
*/
- GHOST_TUns8 *getClipboard(bool selection) const;
+ char *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param buffer: The buffer to be copied.
* \param selection: Indicates which buffer to copy too, only used on X11.
*/
- void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(const char *buffer, bool selection) const;
/**
* Handles a window event. Called by GHOST_WindowCocoa window delegate
@@ -288,10 +288,10 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setMouseCursorPosition(int32_t x, int32_t y);
/** Start time at initialization. */
- GHOST_TUns64 m_start_time;
+ uint64_t m_start_time;
/** Event has been processed directly by Cocoa (or NDOF manager)
* and has sent a ghost event to be dispatched */
@@ -302,14 +302,14 @@ class GHOST_SystemCocoa : public GHOST_System {
bool m_needDelayedApplicationBecomeActiveEventProcessing;
/** State of the modifiers. */
- GHOST_TUns32 m_modifierMask;
+ uint32_t m_modifierMask;
/** Ignores window size messages (when window is dragged). */
bool m_ignoreWindowSizedMessages;
/** Temporarily ignore momentum scroll events */
bool m_ignoreMomentumScroll;
- /** Is the scroll wheel event generated by a multitouch trackpad or mouse? */
+ /** Is the scroll wheel event generated by a multi-touch track-pad or mouse? */
bool m_multiTouchScroll;
/** To prevent multiple warp, we store the time of the last warp event
* and ignore mouse moved events generated before that. */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 97c5652f112..0f10d5815f4 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -520,7 +520,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
sysctl(mib, 2, &boottime, &len, NULL, 0);
m_start_time = ((boottime.tv_sec * 1000) + (boottime.tv_usec / 1000));
- // Detect multitouch trackpad
+ /* Detect multi-touch track-pad. */
mib[0] = CTL_HW;
mib[1] = HW_MODEL;
sysctl(mib, 2, NULL, &len, NULL, 0);
@@ -655,7 +655,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
#pragma mark window management
-GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
+uint64_t GHOST_SystemCocoa::getMilliSeconds() const
{
// Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
struct timeval currentTime;
@@ -667,7 +667,7 @@ GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
return ((currentTime.tv_sec * 1000) + (currentTime.tv_usec / 1000) - m_start_time);
}
-GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
+uint8_t GHOST_SystemCocoa::getNumDisplays() const
{
// Note that OS X supports monitor hot plug
// We do not support multiple monitors at the moment
@@ -676,7 +676,7 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
}
}
-void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemCocoa::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
@autoreleasepool {
// Get visible frame, that is frame excluding dock and top menu bar
@@ -693,17 +693,17 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns
}
}
-void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemCocoa::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{
/* TODO! */
getMainDisplayDimensions(width, height);
}
GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -721,7 +721,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
NSWindowStyleMaskMiniaturizable)];
- GHOST_TInt32 bottom = (contentRect.size.height - 1) - height - top;
+ int32_t bottom = (contentRect.size.height - 1) - height - top;
// Ensures window top left is inside this available rect
left = left > contentRect.origin.x ? left : contentRect.origin.x;
@@ -791,20 +791,20 @@ GHOST_TSuccess GHOST_SystemCocoa::disposeContext(GHOST_IContext *context)
/**
* \note : returns coordinates in Cocoa screen coordinates
*/
-GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(int32_t &x, int32_t &y) const
{
NSPoint mouseLoc = [NSEvent mouseLocation];
// Returns the mouse location in screen coordinates
- x = (GHOST_TInt32)mouseLoc.x;
- y = (GHOST_TInt32)mouseLoc.y;
+ x = (int32_t)mouseLoc.x;
+ y = (int32_t)mouseLoc.y;
return GHOST_kSuccess;
}
/**
* \note : expect Cocoa screen coordinates
*/
-GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(int32_t x, int32_t y)
{
GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)m_windowManager->getActiveWindow();
if (!window)
@@ -824,7 +824,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(int32_t x, int32_t y)
{
float xf = (float)x, yf = (float)y;
GHOST_WindowCocoa *window = (GHOST_WindowCocoa *)m_windowManager->getActiveWindow();
@@ -897,7 +897,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
GHOST_TimerManager* timerMgr = getTimerManager();
if (waitForEvent) {
- GHOST_TUns64 next = timerMgr->nextFireTime();
+ uint64_t next = timerMgr->nextFireTime();
double timeOut;
if (next == GHOST_kFireTimeNever) {
@@ -1132,7 +1132,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
break;
case GHOST_kEventDraggingDropDone: {
- GHOST_TUns8 *temp_buff;
+ uint8_t *temp_buff;
GHOST_TStringArray *strArray;
NSArray *droppedArray;
size_t pastedTextSize;
@@ -1157,13 +1157,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
return GHOST_kFailure;
}
- strArray->strings = (GHOST_TUns8 **)malloc(strArray->count * sizeof(GHOST_TUns8 *));
+ strArray->strings = (uint8_t **)malloc(strArray->count * sizeof(uint8_t *));
for (i = 0; i < strArray->count; i++) {
droppedStr = [droppedArray objectAtIndex:i];
pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- temp_buff = (GHOST_TUns8 *)malloc(pastedTextSize + 1);
+ temp_buff = (uint8_t *)malloc(pastedTextSize + 1);
if (!temp_buff) {
strArray->count = i;
@@ -1185,7 +1185,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
droppedStr = (NSString *)data;
pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- temp_buff = (GHOST_TUns8 *)malloc(pastedTextSize + 1);
+ temp_buff = (uint8_t *)malloc(pastedTextSize + 1);
if (temp_buff == NULL) {
return GHOST_kFailure;
@@ -1204,9 +1204,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
NSImage *droppedImg = (NSImage *)data;
NSSize imgSize = [droppedImg size];
ImBuf *ibuf = NULL;
- GHOST_TUns8 *rasterRGB = NULL;
- GHOST_TUns8 *rasterRGBA = NULL;
- GHOST_TUns8 *toIBuf = NULL;
+ uint8_t *rasterRGB = NULL;
+ uint8_t *rasterRGBA = NULL;
+ uint8_t *toIBuf = NULL;
int x, y, to_i, from_i;
NSBitmapImageRep *blBitmapFormatImageRGB, *blBitmapFormatImageRGBA, *bitmapImage = nil;
NSEnumerator *enumerator;
@@ -1232,8 +1232,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0) &&
![bitmapImage isPlanar]) {
/* Try a fast copy if the image is a meshed RGBA 32bit bitmap. */
- toIBuf = (GHOST_TUns8 *)ibuf->rect;
- rasterRGB = (GHOST_TUns8 *)[bitmapImage bitmapData];
+ toIBuf = (uint8_t *)ibuf->rect;
+ rasterRGB = (uint8_t *)[bitmapImage bitmapData];
for (y = 0; y < imgSize.height; y++) {
to_i = (imgSize.height - y - 1) * imgSize.width;
from_i = y * imgSize.width;
@@ -1270,7 +1270,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
[bitmapImage draw];
[NSGraphicsContext restoreGraphicsState];
- rasterRGB = (GHOST_TUns8 *)[blBitmapFormatImageRGB bitmapData];
+ rasterRGB = (uint8_t *)[blBitmapFormatImageRGB bitmapData];
if (rasterRGB == NULL) {
[bitmapImage release];
[blBitmapFormatImageRGB release];
@@ -1299,7 +1299,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
[bitmapImage draw];
[NSGraphicsContext restoreGraphicsState];
- rasterRGBA = (GHOST_TUns8 *)[blBitmapFormatImageRGBA bitmapData];
+ rasterRGBA = (uint8_t *)[blBitmapFormatImageRGBA bitmapData];
if (rasterRGBA == NULL) {
[bitmapImage release];
[blBitmapFormatImageRGB release];
@@ -1309,7 +1309,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
}
/* Copy the image to ibuf, flipping it vertically. */
- toIBuf = (GHOST_TUns8 *)ibuf->rect;
+ toIBuf = (uint8_t *)ibuf->rect;
for (y = 0; y < imgSize.height; y++) {
for (x = 0; x < imgSize.width; x++) {
to_i = (imgSize.height - y - 1) * imgSize.width + x;
@@ -1563,7 +1563,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
switch (grab_mode) {
case GHOST_kGrabHide: // Cursor hidden grab operation : no cursor move
{
- GHOST_TInt32 x_warp, y_warp, x_accum, y_accum, x, y;
+ int32_t x_warp, y_warp, x_accum, y_accum, x, y;
window->getCursorGrabInitPos(x_warp, y_warp);
window->screenToClientIntern(x_warp, y_warp, x_warp, y_warp);
@@ -1593,8 +1593,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
NSPoint mousePos = [event locationInWindow];
- GHOST_TInt32 x_mouse = mousePos.x;
- GHOST_TInt32 y_mouse = mousePos.y;
+ int32_t x_mouse = mousePos.x;
+ int32_t y_mouse = mousePos.y;
GHOST_Rect bounds, windowBounds, correctedBounds;
/* fallback to window bounds */
@@ -1610,19 +1610,19 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t;
// Get accumulation from previous mouse warps
- GHOST_TInt32 x_accum, y_accum;
+ int32_t x_accum, y_accum;
window->getCursorGrabAccum(x_accum, y_accum);
// Warp mouse cursor if needed
- GHOST_TInt32 warped_x_mouse = x_mouse;
- GHOST_TInt32 warped_y_mouse = y_mouse;
+ int32_t warped_x_mouse = x_mouse;
+ int32_t warped_y_mouse = y_mouse;
correctedBounds.wrapPoint(
warped_x_mouse, warped_y_mouse, 4, window->getCursorGrabAxis());
// Set new cursor position
if (x_mouse != warped_x_mouse || y_mouse != warped_y_mouse) {
- GHOST_TInt32 warped_x, warped_y;
+ int32_t warped_x, warped_y;
window->clientToScreenIntern(warped_x_mouse, warped_y_mouse, warped_x, warped_y);
setMouseCursorPosition(warped_x, warped_y); /* wrap */
window->setCursorGrabAccum(x_accum + (x_mouse - warped_x_mouse),
@@ -1633,7 +1633,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
// Generate event
- GHOST_TInt32 x, y;
+ int32_t x, y;
window->clientToScreenIntern(x_mouse + x_accum, y_mouse + y_accum, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000,
GHOST_kEventCursorMove,
@@ -1646,7 +1646,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
default: {
// Normal cursor operation: send mouse position in window
NSPoint mousePos = [event locationInWindow];
- GHOST_TInt32 x, y;
+ int32_t x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000,
@@ -1690,7 +1690,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
/* Standard scroll-wheel case, if no swiping happened,
* and no momentum (kinetic scroll) works. */
if (!m_multiTouchScroll && momentumPhase == NSEventPhaseNone) {
- GHOST_TInt32 delta;
+ int32_t delta;
double deltaF = [event deltaY];
@@ -1704,7 +1704,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
else {
NSPoint mousePos = [event locationInWindow];
- GHOST_TInt32 x, y;
+ int32_t x, y;
double dx;
double dy;
@@ -1734,7 +1734,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case NSEventTypeMagnify: {
NSPoint mousePos = [event locationInWindow];
- GHOST_TInt32 x, y;
+ int32_t x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000,
window,
@@ -1748,7 +1748,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case NSEventTypeSmartMagnify: {
NSPoint mousePos = [event locationInWindow];
- GHOST_TInt32 x, y;
+ int32_t x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad(
[event timestamp] * 1000, window, GHOST_kTrackpadEventSmartMagnify, x, y, 0, 0, false));
@@ -1756,7 +1756,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case NSEventTypeRotate: {
NSPoint mousePos = [event locationInWindow];
- GHOST_TInt32 x, y;
+ int32_t x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000,
window,
@@ -1933,9 +1933,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
#pragma mark Clipboard get/set
-GHOST_TUns8 *GHOST_SystemCocoa::getClipboard(bool selection) const
+char *GHOST_SystemCocoa::getClipboard(bool selection) const
{
- GHOST_TUns8 *temp_buff;
+ char *temp_buff;
size_t pastedTextSize;
@autoreleasepool {
@@ -1950,14 +1950,13 @@ GHOST_TUns8 *GHOST_SystemCocoa::getClipboard(bool selection) const
pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- temp_buff = (GHOST_TUns8 *)malloc(pastedTextSize + 1);
+ temp_buff = (char *)malloc(pastedTextSize + 1);
if (temp_buff == NULL) {
return NULL;
}
- strncpy(
- (char *)temp_buff, [textPasted cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
+ strncpy(temp_buff, [textPasted cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
temp_buff[pastedTextSize] = '\0';
@@ -1970,7 +1969,7 @@ GHOST_TUns8 *GHOST_SystemCocoa::getClipboard(bool selection) const
}
}
-void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const
+void GHOST_SystemCocoa::putClipboard(const char *buffer, bool selection) const
{
if (selection)
return; // for copying the selection, used on X11
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index faeffffed9e..5dbc42b53a2 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -52,33 +52,33 @@ class GHOST_SystemNULL : public GHOST_System {
{
return GHOST_kSuccess;
}
- GHOST_TUns8 *getClipboard(bool selection) const
+ char *getClipboard(bool selection) const
{
return NULL;
}
- void putClipboard(GHOST_TInt8 *buffer, bool selection) const
+ void putClipboard(const char *buffer, bool selection) const
{ /* nop */
}
- GHOST_TUns64 getMilliSeconds() const
+ uint64_t getMilliSeconds() const
{
return 0;
}
- GHOST_TUns8 getNumDisplays() const
+ uint8_t getNumDisplays() const
{
- return GHOST_TUns8(1);
+ return uint8_t(1);
}
- GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+ GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const
{
return GHOST_kFailure;
}
- GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)
{
return GHOST_kFailure;
}
- void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+ void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{ /* nop */
}
- void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+ void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{ /* nop */
}
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings)
@@ -106,10 +106,10 @@ class GHOST_SystemNULL : public GHOST_System {
}
GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h
index ab53b2813cd..5bd52d44b42 100644
--- a/intern/ghost/intern/GHOST_SystemPaths.h
+++ b/intern/ghost/intern/GHOST_SystemPaths.h
@@ -49,20 +49,20 @@ class GHOST_SystemPaths : public GHOST_ISystemPaths {
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
- virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0;
+ virtual const char *getSystemDir(int version, const char *versionstr) const = 0;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
- virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0;
+ virtual const char *getUserDir(int version, const char *versionstr) const = 0;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- virtual const GHOST_TUns8 *getBinaryDir() const = 0;
+ virtual const char *getBinaryDir() const = 0;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
index 14633d46f03..1af63fc9b56 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
@@ -46,26 +46,26 @@ class GHOST_SystemPathsCocoa : public GHOST_SystemPaths {
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/blender/).
*/
- const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
+ const char *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/.blender/).
*/
- const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
+ const char *getUserDir(int version, const char *versionstr) const;
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
- const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
+ const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- const GHOST_TUns8 *getBinaryDir() const;
+ const char *getBinaryDir() const;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
index 7c6184837bf..3b29d5106f6 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.mm
@@ -36,7 +36,7 @@ GHOST_SystemPathsCocoa::~GHOST_SystemPathsCocoa()
#pragma mark Base directories retrieval
-const GHOST_TUns8 *GHOST_SystemPathsCocoa::getSystemDir(int, const char *versionstr) const
+const char *GHOST_SystemPathsCocoa::getSystemDir(int, const char *versionstr) const
{
static char tempPath[512] = "";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -60,10 +60,10 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getSystemDir(int, const char *version
versionstr);
[pool drain];
- return (GHOST_TUns8 *)tempPath;
+ return tempPath;
}
-const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionstr) const
+const char *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionstr) const
{
static char tempPath[512] = "";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -87,10 +87,10 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserDir(int, const char *versionst
versionstr);
[pool drain];
- return (GHOST_TUns8 *)tempPath;
+ return tempPath;
}
-const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
+const char *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
{
static char tempPath[512] = "";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -138,12 +138,12 @@ const GHOST_TUns8 *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialD
(char *)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding], sizeof(tempPath));
[pool drain];
- return (GHOST_TUns8 *)tempPath;
+ return tempPath;
}
-const GHOST_TUns8 *GHOST_SystemPathsCocoa::getBinaryDir() const
+const char *GHOST_SystemPathsCocoa::getBinaryDir() const
{
- static GHOST_TUns8 tempPath[512] = "";
+ static char tempPath[512] = "";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *basePath;
diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
index 86f3a0a31fb..b58799e9c2a 100644
--- a/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsUnix.cpp
@@ -55,18 +55,18 @@ GHOST_SystemPathsUnix::~GHOST_SystemPathsUnix()
{
}
-const GHOST_TUns8 *GHOST_SystemPathsUnix::getSystemDir(int, const char *versionstr) const
+const char *GHOST_SystemPathsUnix::getSystemDir(int, const char *versionstr) const
{
/* no prefix assumes a portable build which only uses bundled scripts */
if (static_path) {
static string system_path = string(static_path) + "/blender/" + versionstr;
- return (GHOST_TUns8 *)system_path.c_str();
+ return system_path.c_str();
}
return NULL;
}
-const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const
+const char *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const
{
static string user_path = "";
static int last_version = 0;
@@ -86,7 +86,7 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *ve
return NULL;
}
}
- return (GHOST_TUns8 *)user_path.c_str();
+ return user_path.c_str();
}
else {
if (user_path.empty() || last_version != version) {
@@ -107,11 +107,11 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserDir(int version, const char *ve
}
}
- return (const GHOST_TUns8 *)user_path.c_str();
+ return user_path.c_str();
}
}
-const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
+const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
{
const char *type_str;
@@ -164,10 +164,10 @@ const GHOST_TUns8 *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDi
}
path = path_stream.str();
- return path[0] ? (const GHOST_TUns8 *)path.c_str() : NULL;
+ return path[0] ? path.c_str() : NULL;
}
-const GHOST_TUns8 *GHOST_SystemPathsUnix::getBinaryDir() const
+const char *GHOST_SystemPathsUnix::getBinaryDir() const
{
return NULL;
}
diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.h b/intern/ghost/intern/GHOST_SystemPathsUnix.h
index bc9272ecd8f..37fb432e9e8 100644
--- a/intern/ghost/intern/GHOST_SystemPathsUnix.h
+++ b/intern/ghost/intern/GHOST_SystemPathsUnix.h
@@ -44,26 +44,26 @@ class GHOST_SystemPathsUnix : public GHOST_SystemPaths {
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg `/usr/share/blender/`).
*/
- const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
+ const char *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg `~/.config/.blender/`).
*/
- const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
+ const char *getUserDir(int version, const char *versionstr) const;
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
- const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
+ const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- const GHOST_TUns8 *getBinaryDir() const;
+ const char *getBinaryDir() const;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
index 47e71b0d733..580cfcac7ba 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
@@ -38,7 +38,7 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32()
{
}
-const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const
+const char *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const
{
/* 1 utf-16 might translate into 3 utf-8. 2 utf-16 translates into 4 utf-8. */
static char knownpath[MAX_PATH * 3 + 128] = {0};
@@ -52,13 +52,13 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *version
CoTaskMemFree(knownpath_16);
strcat(knownpath, "\\Blender Foundation\\Blender\\");
strcat(knownpath, versionstr);
- return (GHOST_TUns8 *)knownpath;
+ return knownpath;
}
return NULL;
}
-const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const
+const char *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const
{
static char knownpath[MAX_PATH * 3 + 128] = {0};
PWSTR knownpath_16 = NULL;
@@ -71,13 +71,13 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionst
CoTaskMemFree(knownpath_16);
strcat(knownpath, "\\Blender Foundation\\Blender\\");
strcat(knownpath, versionstr);
- return (GHOST_TUns8 *)knownpath;
+ return knownpath;
}
return NULL;
}
-const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
+const char *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
{
GUID folderid;
@@ -114,21 +114,21 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialD
if (hResult == S_OK) {
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
CoTaskMemFree(knownpath_16);
- return (GHOST_TUns8 *)knownpath;
+ return knownpath;
}
CoTaskMemFree(knownpath_16);
return NULL;
}
-const GHOST_TUns8 *GHOST_SystemPathsWin32::getBinaryDir() const
+const char *GHOST_SystemPathsWin32::getBinaryDir() const
{
static char fullname[MAX_PATH * 3] = {0};
wchar_t fullname_16[MAX_PATH * 3];
if (GetModuleFileNameW(0, fullname_16, MAX_PATH)) {
conv_utf_16_to_8(fullname_16, fullname, MAX_PATH * 3);
- return (GHOST_TUns8 *)fullname;
+ return fullname;
}
return NULL;
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h
index 45e03e744a5..c9f7f6b987f 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.h
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h
@@ -53,26 +53,26 @@ class GHOST_SystemPathsWin32 : public GHOST_SystemPaths {
* "unpack and run" path, then look for properly installed path, including versioning.
* \return Unsigned char string pointing to system dir (eg /usr/share/).
*/
- const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const;
+ const char *getSystemDir(int version, const char *versionstr) const;
/**
* Determine the base dir in which user configuration is stored, including versioning.
* If needed, it will create the base directory.
* \return Unsigned char string pointing to user dir (eg ~/).
*/
- const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const;
+ const char *getUserDir(int version, const char *versionstr) const;
/**
* Determine a special ("well known") and easy to reach user directory.
* \return Unsigned char string pointing to user dir (eg `~/Documents/`).
*/
- const GHOST_TUns8 *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
+ const char *getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const;
/**
* Determine the directory of the current binary
* \return Unsigned char string pointing to the binary dir
*/
- const GHOST_TUns8 *getBinaryDir() const;
+ const char *getBinaryDir() const;
/**
* Add the file to the operating system most recently used files
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index eccef18bee2..f2f1b26b8e5 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -50,10 +50,10 @@ GHOST_SystemSDL::~GHOST_SystemSDL()
}
GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -118,23 +118,23 @@ GHOST_TSuccess GHOST_SystemSDL::init()
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
-void GHOST_SystemSDL::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemSDL::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{
SDL_DisplayMode mode;
- SDL_GetDesktopDisplayMode(0, &mode); /* note, always 0 display */
+ SDL_GetDesktopDisplayMode(0, &mode); /* NOTE: always 0 display. */
width = mode.w;
height = mode.h;
}
-void GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemSDL::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
SDL_DisplayMode mode;
- SDL_GetCurrentDisplayMode(0, &mode); /* note, always 0 display */
+ SDL_GetCurrentDisplayMode(0, &mode); /* NOTE: always 0 display. */
width = mode.w;
height = mode.h;
}
-GHOST_TUns8 GHOST_SystemSDL::getNumDisplays() const
+uint8_t GHOST_SystemSDL::getNumDisplays() const
{
return SDL_GetNumVideoDisplays();
}
@@ -356,15 +356,15 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
int x_win, y_win;
SDL_GetWindowPosition(sdl_win, &x_win, &y_win);
- GHOST_TInt32 x_root = sdl_sub_evt.x + x_win;
- GHOST_TInt32 y_root = sdl_sub_evt.y + y_win;
+ int32_t x_root = sdl_sub_evt.x + x_win;
+ int32_t y_root = sdl_sub_evt.y + y_win;
#if 0
if (window->getCursorGrabMode() != GHOST_kGrabDisable &&
window->getCursorGrabMode() != GHOST_kGrabNormal) {
- GHOST_TInt32 x_new = x_root;
- GHOST_TInt32 y_new = y_root;
- GHOST_TInt32 x_accum, y_accum;
+ int32_t x_new = x_root;
+ int32_t y_new = y_root;
+ int32_t x_accum, y_accum;
GHOST_Rect bounds;
/* fallback to window bounds */
@@ -468,8 +468,8 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
assert(window != NULL);
GHOST_TKey gkey = convertSDLKey(sdl_sub_evt.keysym.scancode);
- /* note, the sdl_sub_evt.keysym.sym is truncated,
- * for unicode support ghost has to be modified */
+ /* NOTE: the `sdl_sub_evt.keysym.sym` is truncated,
+ * for unicode support ghost has to be modified. */
/* printf("%d\n", sym); */
if (sym > 127) {
switch (sym) {
@@ -611,7 +611,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
}
}
-GHOST_TSuccess GHOST_SystemSDL::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+GHOST_TSuccess GHOST_SystemSDL::getCursorPosition(int32_t &x, int32_t &y) const
{
int x_win, y_win;
SDL_Window *win = SDL_GetMouseFocus();
@@ -625,7 +625,7 @@ GHOST_TSuccess GHOST_SystemSDL::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemSDL::setCursorPosition(int32_t x, int32_t y)
{
int x_win, y_win;
SDL_Window *win = SDL_GetMouseFocus();
@@ -668,14 +668,14 @@ bool GHOST_SystemSDL::processEvents(bool waitForEvent)
GHOST_TimerManager *timerMgr = getTimerManager();
if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) {
- GHOST_TUns64 next = timerMgr->nextFireTime();
+ uint64_t next = timerMgr->nextFireTime();
if (next == GHOST_kFireTimeNever) {
SDL_WaitEventTimeout(NULL, -1);
// SleepTillEvent(m_display, -1);
}
else {
- GHOST_TInt64 maxSleep = next - getMilliSeconds();
+ int64_t maxSleep = next - getMilliSeconds();
if (maxSleep >= 0) {
SDL_WaitEventTimeout(NULL, next - getMilliSeconds());
@@ -743,17 +743,17 @@ GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons &buttons) const
return GHOST_kSuccess;
}
-GHOST_TUns8 *GHOST_SystemSDL::getClipboard(bool selection) const
+char *GHOST_SystemSDL::getClipboard(bool selection) const
{
- return (GHOST_TUns8 *)SDL_GetClipboardText();
+ return (char *)SDL_GetClipboardText();
}
-void GHOST_SystemSDL::putClipboard(GHOST_TInt8 *buffer, bool selection) const
+void GHOST_SystemSDL::putClipboard(const char *buffer, bool selection) const
{
SDL_SetClipboardText(buffer);
}
-GHOST_TUns64 GHOST_SystemSDL::getMilliSeconds()
+uint64_t GHOST_SystemSDL::getMilliSeconds()
{
- return GHOST_TUns64(SDL_GetTicks()); /* note, 32 -> 64bits */
+ return uint64_t(SDL_GetTicks()); /* NOTE: 32 -> 64bits. */
}
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 1c92762ea01..051bb6777b1 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -56,21 +56,21 @@ class GHOST_SystemSDL : public GHOST_System {
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
- GHOST_TUns8 *getClipboard(bool selection) const;
+ char *getClipboard(bool selection) const;
- void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(const char *buffer, bool selection) const;
- GHOST_TUns64 getMilliSeconds();
+ uint64_t getMilliSeconds();
- GHOST_TUns8 getNumDisplays() const;
+ uint8_t getNumDisplays() const;
- GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const;
- GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y);
- void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const;
- void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
@@ -80,10 +80,10 @@ class GHOST_SystemSDL : public GHOST_System {
GHOST_TSuccess init();
GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index f54a022f249..38700845405 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -47,12 +47,20 @@
#include <xkbcommon/xkbcommon.h>
#include <fcntl.h>
-#include <linux/input-event-codes.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cstring>
+/* selected input event code defines from 'linux/input-event-codes.h'
+ * We include some of the button input event codes here, since the header is
+ * only available in more recent kernel versions. The event codes are used to
+ * to differentiate from which mouse button an event comes from.
+ */
+#define BTN_LEFT 0x110
+#define BTN_RIGHT 0x111
+#define BTN_MIDDLE 0x112
+
struct buffer_t {
void *data;
size_t size;
@@ -468,7 +476,7 @@ static const zwp_relative_pointer_v1_listener relative_pointer_listener = {
static void dnd_events(const input_t *const input, const GHOST_TEventType event)
{
- const GHOST_TUns64 time = input->system->getMilliSeconds();
+ const uint64_t time = input->system->getMilliSeconds();
GHOST_IWindow *const window = static_cast<GHOST_WindowWayland *>(
wl_surface_get_user_data(input->focus_pointer));
for (const std::string &type : mime_preference_order) {
@@ -718,10 +726,9 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>(
malloc(sizeof(GHOST_TStringArray)));
flist->count = int(uris.size());
- flist->strings = static_cast<GHOST_TUns8 **>(malloc(uris.size() * sizeof(GHOST_TUns8 *)));
+ flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *)));
for (size_t i = 0; i < uris.size(); i++) {
- flist->strings[i] = static_cast<GHOST_TUns8 *>(
- malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8)));
+ flist->strings[i] = static_cast<uint8_t *>(malloc((uris[i].size() + 1) * sizeof(uint8_t)));
memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1);
}
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
@@ -1171,7 +1178,7 @@ static void keyboard_key(void *data,
.key_data = key_data,
});
- auto cb = [](GHOST_ITimerTask *task, GHOST_TUns64 /*time*/) {
+ auto cb = [](GHOST_ITimerTask *task, uint64_t /*time*/) {
struct key_repeat_payload_t *payload = static_cast<key_repeat_payload_t *>(
task->getUserData());
payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(),
@@ -1511,14 +1518,14 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
return GHOST_kFailure;
}
-GHOST_TUns8 *GHOST_SystemWayland::getClipboard(bool /*selection*/) const
+char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const
{
- GHOST_TUns8 *clipboard = static_cast<GHOST_TUns8 *>(malloc((selection.size() + 1)));
+ char *clipboard = static_cast<char *>(malloc((selection.size() + 1)));
memcpy(clipboard, selection.data(), selection.size() + 1);
return clipboard;
}
-void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) const
+void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const
{
if (!d->data_device_manager || d->inputs.empty()) {
return;
@@ -1545,12 +1552,12 @@ void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/)
}
}
-GHOST_TUns8 GHOST_SystemWayland::getNumDisplays() const
+uint8_t GHOST_SystemWayland::getNumDisplays() const
{
- return d ? GHOST_TUns8(d->outputs.size()) : 0;
+ return d ? uint8_t(d->outputs.size()) : 0;
}
-GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const
{
if (!d->inputs.empty() && (d->inputs[0]->focus_pointer != nullptr)) {
x = d->inputs[0]->x;
@@ -1562,12 +1569,12 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TIn
}
}
-GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/)
+GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(int32_t /*x*/, int32_t /*y*/)
{
return GHOST_kFailure;
}
-void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemWayland::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
if (getNumDisplays() > 0) {
/* We assume first output as main. */
@@ -1576,7 +1583,7 @@ void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TU
}
}
-void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{
getMainDisplayDimensions(width, height);
}
@@ -1640,10 +1647,10 @@ GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context)
}
GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -1780,8 +1787,8 @@ GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(GHOST_TStandardCursor cursorS
return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty());
}
-GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -1797,13 +1804,43 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap,
static const int32_t stride = sizex * 4; /* ARGB */
cursor->file_buffer->size = size_t(stride * sizey);
+#ifdef HAVE_MEMFD_CREATE
const int fd = memfd_create("blender-cursor-custom", MFD_CLOEXEC | MFD_ALLOW_SEALING);
- fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK);
- posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size));
+ if (fd >= 0) {
+ fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
+ }
+#else
+ char *path = getenv("XDG_RUNTIME_DIR");
+ if (!path) {
+ errno = ENOENT;
+ return GHOST_kFailure;
+ }
+
+ char *tmpname;
+ asprintf(&tmpname, "%s/%s", path, "blender-XXXXXX");
+ const int fd = mkostemp(tmpname, O_CLOEXEC);
+ if (fd >= 0) {
+ unlink(tmpname);
+ }
+ free(tmpname);
+#endif
+
+ if (fd < 0) {
+ return GHOST_kFailure;
+ }
+
+ if (posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size)) != 0) {
+ return GHOST_kFailure;
+ }
cursor->file_buffer->data = mmap(
nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (cursor->file_buffer->data == MAP_FAILED) {
+ close(fd);
+ return GHOST_kFailure;
+ }
+
struct wl_shm_pool *pool = wl_shm_create_pool(d->shm, fd, int32_t(cursor->file_buffer->size));
wl_buffer *buffer = wl_shm_pool_create_buffer(
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index 3a08a0d3b16..9f02afb9d5a 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -59,29 +59,29 @@ class GHOST_SystemWayland : public GHOST_System {
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override;
- GHOST_TUns8 *getClipboard(bool selection) const override;
+ char *getClipboard(bool selection) const override;
- void putClipboard(GHOST_TInt8 *buffer, bool selection) const override;
+ void putClipboard(const char *buffer, bool selection) const override;
- GHOST_TUns8 getNumDisplays() const override;
+ uint8_t getNumDisplays() const override;
- GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override;
+ GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const override;
- GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override;
+ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) override;
- void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override;
+ void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override;
- void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override;
+ void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -107,8 +107,8 @@ class GHOST_SystemWayland : public GHOST_System {
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape);
- GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index a7cb4aee837..4f5e957077d 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -169,21 +169,21 @@ GHOST_SystemWin32::~GHOST_SystemWin32()
toggleConsole(1);
}
-GHOST_TUns64 GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const
+uint64_t GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const
{
// Calculate the time passed since system initialization.
__int64 delta = (perf_ticks - m_start) * 1000;
- GHOST_TUns64 t = (GHOST_TUns64)(delta / m_freq);
+ uint64_t t = (uint64_t)(delta / m_freq);
return t;
}
-GHOST_TUns64 GHOST_SystemWin32::tickCountToMillis(__int64 ticks) const
+uint64_t GHOST_SystemWin32::tickCountToMillis(__int64 ticks) const
{
return ticks - m_lfstart;
}
-GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
+uint64_t GHOST_SystemWin32::getMilliSeconds() const
{
// Hardware does not support high resolution timers. We will use GetTickCount instead then.
if (!m_hasPerformanceCounter) {
@@ -197,31 +197,31 @@ GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
return performanceCounterToMillis(count);
}
-GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
+uint8_t GHOST_SystemWin32::getNumDisplays() const
{
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
- GHOST_TUns8 numDisplays;
+ uint8_t numDisplays;
m_displayManager->getNumDisplays(numDisplays);
return numDisplays;
}
-void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemWin32::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
width = ::GetSystemMetrics(SM_CXSCREEN);
height = ::GetSystemMetrics(SM_CYSCREEN);
}
-void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemWin32::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{
width = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -410,8 +410,8 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
#if 1
::Sleep(1);
#else
- GHOST_TUns64 next = timerMgr->nextFireTime();
- GHOST_TInt64 maxSleep = next - getMilliSeconds();
+ uint64_t next = timerMgr->nextFireTime();
+ int64_t maxSleep = next - getMilliSeconds();
if (next == GHOST_kFireTimeNever) {
::WaitMessage();
@@ -448,7 +448,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
return hasEventHandled;
}
-GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(int32_t &x, int32_t &y) const
{
POINT point;
if (::GetCursorPos(&point)) {
@@ -459,7 +459,7 @@ GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt3
return GHOST_kFailure;
}
-GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y)
{
if (!::GetActiveWindow())
return GHOST_kFailure;
@@ -1029,7 +1029,7 @@ void GHOST_SystemWin32::processPointerEvent(
case WM_POINTERUPDATE:
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
* Only contiguous move events are coalesced. */
- for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
+ for (uint32_t i = pointerInfo.size(); i-- > 0;) {
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
GHOST_kEventCursorMove,
window,
@@ -1079,7 +1079,7 @@ void GHOST_SystemWin32::processPointerEvent(
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
{
- GHOST_TInt32 x_screen, y_screen;
+ int32_t x_screen, y_screen;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
@@ -1090,9 +1090,9 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
system->getCursorPosition(x_screen, y_screen);
if (window->getCursorGrabModeIsWarp()) {
- GHOST_TInt32 x_new = x_screen;
- GHOST_TInt32 y_new = y_screen;
- GHOST_TInt32 x_accum, y_accum;
+ int32_t x_new = x_screen;
+ int32_t y_new = y_screen;
+ int32_t x_accum, y_accum;
GHOST_Rect bounds;
/* Fallback to window bounds. */
@@ -1197,8 +1197,8 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
// Don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
// composition.
else if (MapVirtualKeyW(vk, 2) != 0) {
- // todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
- // Could be up to 24 utf8 bytes.
+ /* TODO: #ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
+ * Could be up to 24 utf8 bytes. */
if ((r = ToUnicodeEx(
vk, raw.data.keyboard.MakeCode, state, utf16, 2, 0, system->m_keylayout))) {
if ((r > 0 && r < 3)) {
@@ -1322,7 +1322,7 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
{
bool eventSent = false;
- GHOST_TUns64 now = getMilliSeconds();
+ uint64_t now = getMilliSeconds();
static bool firstEvent = true;
if (firstEvent) { // determine exactly which device is plugged in
@@ -1627,7 +1627,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
processPointerEvent(msg, window, wParam, lParam, eventHandled);
break;
case WM_POINTERLEAVE: {
- GHOST_TUns32 pointerId = GET_POINTERID_WPARAM(wParam);
+ uint32_t pointerId = GET_POINTERID_WPARAM(wParam);
POINTER_INFO pointerInfo;
if (!GetPointerInfo(pointerId, &pointerInfo)) {
break;
@@ -2002,7 +2002,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
return lResult;
}
-GHOST_TUns8 *GHOST_SystemWin32::getClipboard(bool selection) const
+char *GHOST_SystemWin32::getClipboard(bool selection) const
{
char *temp_buff;
@@ -2026,7 +2026,7 @@ GHOST_TUns8 *GHOST_SystemWin32::getClipboard(bool selection) const
GlobalUnlock(hData);
CloseClipboard();
- return (GHOST_TUns8 *)temp_buff;
+ return temp_buff;
}
else if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
char *buffer;
@@ -2052,14 +2052,14 @@ GHOST_TUns8 *GHOST_SystemWin32::getClipboard(bool selection) const
GlobalUnlock(hData);
CloseClipboard();
- return (GHOST_TUns8 *)temp_buff;
+ return temp_buff;
}
else {
return NULL;
}
}
-void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
+void GHOST_SystemWin32::putClipboard(const char *buffer, bool selection) const
{
if (selection) {
return;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 7dd61421d4c..6c786aedfb1 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -69,14 +69,14 @@ class GHOST_SystemWin32 : public GHOST_System {
* system process.
* \return The number of milliseconds since the start of the system process.
*/
- GHOST_TUns64 performanceCounterToMillis(__int64 perf_ticks) const;
+ uint64_t performanceCounterToMillis(__int64 perf_ticks) const;
/**
* This method converts system ticks into milliseconds since the start of the
* system process.
* \return The number of milliseconds since the start of the system process.
*/
- GHOST_TUns64 tickCountToMillis(__int64 ticks) const;
+ uint64_t tickCountToMillis(__int64 ticks) const;
/**
* Returns the system time.
@@ -84,7 +84,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* This overloaded method uses the high frequency timer if available.
* \return The number of milliseconds.
*/
- GHOST_TUns64 getMilliSeconds() const;
+ uint64_t getMilliSeconds() const;
/***************************************************************************************
** Display/window management functionality
@@ -94,19 +94,19 @@ class GHOST_SystemWin32 : public GHOST_System {
* Returns the number of displays on this system.
* \return The number of displays.
*/
- GHOST_TUns8 getNumDisplays() const;
+ uint8_t getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const;
/**
* Returns the dimensions of all displays on this system.
* \return The dimension of the main display.
*/
- void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const;
/**
* Create a new window.
@@ -126,10 +126,10 @@ class GHOST_SystemWin32 : public GHOST_System {
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -189,7 +189,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
@@ -197,7 +197,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
- GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y);
/***************************************************************************************
** Access to mouse button and keyboard states.
@@ -222,14 +222,14 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param selection: Used by X11 only.
* \return Returns the Clipboard.
*/
- GHOST_TUns8 *getClipboard(bool selection) const;
+ char *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard.
* \param selection: Used by X11 only.
* \return No return.
*/
- void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(const char *buffer, bool selection) const;
/**
* Show a system message box
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index c5564e9880e..172fcbeb3de 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -186,7 +186,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_
}
/* Taking care not to overflow the `tv.tv_sec * 1000`. */
- m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+ m_start_time = uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
/* Use detectable auto-repeat, mac and windows also do this. */
int use_xkb;
@@ -279,7 +279,7 @@ GHOST_TSuccess GHOST_SystemX11::init()
return GHOST_kFailure;
}
-GHOST_TUns64 GHOST_SystemX11::getMilliSeconds() const
+uint64_t GHOST_SystemX11::getMilliSeconds() const
{
timeval tv;
if (gettimeofday(&tv, NULL) == -1) {
@@ -287,24 +287,24 @@ GHOST_TUns64 GHOST_SystemX11::getMilliSeconds() const
}
/* Taking care not to overflow the tv.tv_sec * 1000 */
- return GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
+ return uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
}
-GHOST_TUns8 GHOST_SystemX11::getNumDisplays() const
+uint8_t GHOST_SystemX11::getNumDisplays() const
{
- return GHOST_TUns8(1);
+ return uint8_t(1);
}
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
-void GHOST_SystemX11::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemX11::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
if (m_display) {
- /* note, for this to work as documented,
+ /* NOTE(campbell): for this to work as documented,
* we would need to use Xinerama check r54370 for code that did this,
- * we've since removed since its not worth the extra dep - campbell */
+ * we've since removed since its not worth the extra dependency. */
getAllDisplayDimensions(width, height);
}
}
@@ -313,7 +313,7 @@ void GHOST_SystemX11::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
-void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+void GHOST_SystemX11::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{
if (m_display) {
width = DisplayWidth(m_display, DefaultScreen(m_display));
@@ -339,10 +339,10 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -570,7 +570,7 @@ GHOST_WindowX11 *GHOST_SystemX11::findGhostWindow(Window xwind) const
return NULL;
}
-static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep)
+static void SleepTillEvent(Display *display, int64_t maxSleep)
{
int fd = ConnectionNumber(display);
fd_set fds;
@@ -649,13 +649,13 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
GHOST_TimerManager *timerMgr = getTimerManager();
if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
- GHOST_TUns64 next = timerMgr->nextFireTime();
+ uint64_t next = timerMgr->nextFireTime();
if (next == GHOST_kFireTimeNever) {
SleepTillEvent(m_display, -1);
}
else {
- GHOST_TInt64 maxSleep = next - getMilliSeconds();
+ int64_t maxSleep = next - getMilliSeconds();
if (maxSleep >= 0)
SleepTillEvent(m_display, next - getMilliSeconds());
@@ -965,9 +965,9 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
bool is_tablet = window->GetTabletData().Active != GHOST_kTabletModeNone;
if (is_tablet == false && window->getCursorGrabModeIsWarp()) {
- GHOST_TInt32 x_new = xme.x_root;
- GHOST_TInt32 y_new = xme.y_root;
- GHOST_TInt32 x_accum, y_accum;
+ int32_t x_new = xme.x_root;
+ int32_t y_new = xme.y_root;
+ int32_t x_accum, y_accum;
GHOST_Rect bounds;
/* fallback to window bounds */
@@ -1638,8 +1638,8 @@ GHOST_TSuccess GHOST_SystemX11::getButtons(GHOST_Buttons &buttons) const
}
static GHOST_TSuccess getCursorPosition_impl(Display *display,
- GHOST_TInt32 &x,
- GHOST_TInt32 &y,
+ int32_t &x,
+ int32_t &y,
Window *child_return)
{
int rx, ry, wx, wy;
@@ -1664,13 +1664,13 @@ static GHOST_TSuccess getCursorPosition_impl(Display *display,
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemX11::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+GHOST_TSuccess GHOST_SystemX11::getCursorPosition(int32_t &x, int32_t &y) const
{
Window child_return;
return getCursorPosition_impl(m_display, x, y, &child_return);
}
-GHOST_TSuccess GHOST_SystemX11::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y)
{
/* This is a brute force move in screen coordinates
@@ -2136,14 +2136,14 @@ void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt,
return;
}
-GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
+char *GHOST_SystemX11::getClipboard(bool selection) const
{
Atom sseln;
Atom target = m_atom.UTF8_STRING;
Window owner;
/* from xclip.c doOut() v0.11 */
- unsigned char *sel_buf;
+ char *sel_buf;
unsigned long sel_len = 0;
XEvent evt;
unsigned int context = XCLIB_XCOUT_NONE;
@@ -2162,13 +2162,13 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
owner = XGetSelectionOwner(m_display, sseln);
if (owner == win) {
if (sseln == m_atom.CLIPBOARD) {
- sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1);
- strcpy((char *)sel_buf, txt_cut_buffer);
+ sel_buf = (char *)malloc(strlen(txt_cut_buffer) + 1);
+ strcpy(sel_buf, txt_cut_buffer);
return sel_buf;
}
else {
- sel_buf = (unsigned char *)malloc(strlen(txt_select_buffer) + 1);
- strcpy((char *)sel_buf, txt_select_buffer);
+ sel_buf = (char *)malloc(strlen(txt_select_buffer) + 1);
+ strcpy(sel_buf, txt_select_buffer);
return sel_buf;
}
}
@@ -2187,7 +2187,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
}
/* fetch the selection, or part of it */
- getClipboard_xcout(&evt, sseln, target, &sel_buf, &sel_len, &context);
+ getClipboard_xcout(&evt, sseln, target, (unsigned char **)&sel_buf, &sel_len, &context);
if (restore_this_event) {
restore_events.push_back(evt);
@@ -2228,8 +2228,8 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
if (sel_len) {
/* Only print the buffer out, and free it, if it's not empty. */
- unsigned char *tmp_data = (unsigned char *)malloc(sel_len + 1);
- memcpy((char *)tmp_data, (char *)sel_buf, sel_len);
+ char *tmp_data = (char *)malloc(sel_len + 1);
+ memcpy(tmp_data, (char *)sel_buf, sel_len);
tmp_data[sel_len] = '\0';
if (sseln == m_atom.STRING)
@@ -2242,7 +2242,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
return NULL;
}
-void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
+void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const
{
Window m_window, owner;
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index ed5e945f69e..15ccde4a14b 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -98,25 +98,25 @@ class GHOST_SystemX11 : public GHOST_System {
* Returns the number of milliseconds since the start of the system process.
* \return The number of milliseconds.
*/
- GHOST_TUns64 getMilliSeconds() const;
+ uint64_t getMilliSeconds() const;
/**
* Returns the number of displays on this system.
* \return The number of displays.
*/
- GHOST_TUns8 getNumDisplays() const;
+ uint8_t getNumDisplays() const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
- void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const;
/**
* Returns the dimensions of all displays on this system.
* \return The dimension of the main display.
*/
- void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const;
+ void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const;
/**
* Create a new window.
@@ -136,10 +136,10 @@ class GHOST_SystemX11 : public GHOST_System {
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
@@ -168,9 +168,9 @@ class GHOST_SystemX11 : public GHOST_System {
*/
bool processEvents(bool waitForEvent);
- GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+ GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const;
- GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
+ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y);
/**
* Returns the state of all modifier keys.
@@ -222,14 +222,14 @@ class GHOST_SystemX11 : public GHOST_System {
* \param selection: Get selection, X11 only feature.
* \return Returns the Clipboard indicated by Flag.
*/
- GHOST_TUns8 *getClipboard(bool selection) const;
+ char *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param buffer: The buffer to copy to the clipboard.
* \param selection: Set the selection into the clipboard, X11 only feature.
*/
- void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(const char *buffer, bool selection) const;
/**
* Show a system message box
@@ -351,7 +351,7 @@ class GHOST_SystemX11 : public GHOST_System {
std::vector<GHOST_WindowX11 *> m_dirty_windows;
/** Start time at initialization. */
- GHOST_TUns64 m_start_time;
+ uint64_t m_start_time;
/** A vector of keyboard key masks. */
char m_keyboard_vector[32];
diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp
index 22f646320ce..195135f5f85 100644
--- a/intern/ghost/intern/GHOST_TimerManager.cpp
+++ b/intern/ghost/intern/GHOST_TimerManager.cpp
@@ -40,9 +40,9 @@ GHOST_TimerManager::~GHOST_TimerManager()
disposeTimers();
}
-GHOST_TUns32 GHOST_TimerManager::getNumTimers()
+uint32_t GHOST_TimerManager::getNumTimers()
{
- return (GHOST_TUns32)m_timers.size();
+ return (uint32_t)m_timers.size();
}
bool GHOST_TimerManager::getTimerFound(GHOST_TimerTask *timer)
@@ -81,13 +81,13 @@ GHOST_TSuccess GHOST_TimerManager::removeTimer(GHOST_TimerTask *timer)
return success;
}
-GHOST_TUns64 GHOST_TimerManager::nextFireTime()
+uint64_t GHOST_TimerManager::nextFireTime()
{
- GHOST_TUns64 smallest = GHOST_kFireTimeNever;
+ uint64_t smallest = GHOST_kFireTimeNever;
TTimerVector::iterator iter;
for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) {
- GHOST_TUns64 next = (*iter)->getNext();
+ uint64_t next = (*iter)->getNext();
if (next < smallest)
smallest = next;
@@ -96,7 +96,7 @@ GHOST_TUns64 GHOST_TimerManager::nextFireTime()
return smallest;
}
-bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time)
+bool GHOST_TimerManager::fireTimers(uint64_t time)
{
TTimerVector::iterator iter;
bool anyProcessed = false;
@@ -109,20 +109,20 @@ bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time)
return anyProcessed;
}
-bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task)
+bool GHOST_TimerManager::fireTimer(uint64_t time, GHOST_TimerTask *task)
{
- GHOST_TUns64 next = task->getNext();
+ uint64_t next = task->getNext();
// Check if the timer should be fired
if (time > next) {
// Fire the timer
GHOST_TimerProcPtr timerProc = task->getTimerProc();
- GHOST_TUns64 start = task->getStart();
+ uint64_t start = task->getStart();
timerProc(task, time - start);
// Update the time at which we will fire it again
- GHOST_TUns64 interval = task->getInterval();
- GHOST_TUns64 numCalls = (next - start) / interval;
+ uint64_t interval = task->getInterval();
+ uint64_t numCalls = (next - start) / interval;
numCalls++;
next = start + numCalls * interval;
task->setNext(next);
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
index 3ca62202e5e..6261218a023 100644
--- a/intern/ghost/intern/GHOST_TimerManager.h
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -51,7 +51,7 @@ class GHOST_TimerManager {
* Returns the number of timer tasks.
* \return The number of events on the stack.
*/
- GHOST_TUns32 getNumTimers();
+ uint32_t getNumTimers();
/**
* Returns whether this timer task ins in our list.
@@ -80,14 +80,14 @@ class GHOST_TimerManager {
* \return The soonest time the next timer would fire,
* or GHOST_kFireTimeNever if no timers exist.
*/
- GHOST_TUns64 nextFireTime();
+ uint64_t nextFireTime();
/**
* Checks all timer tasks to see if they are expired and fires them if needed.
* \param time: The current time.
* \return True if any timers were fired.
*/
- bool fireTimers(GHOST_TUns64 time);
+ bool fireTimers(uint64_t time);
/**
* Checks this timer task to see if they are expired and fires them if needed.
@@ -95,7 +95,7 @@ class GHOST_TimerManager {
* \param task: The timer task to check and optionally fire.
* \return True if the timer fired.
*/
- bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task);
+ bool fireTimer(uint64_t time, GHOST_TimerTask *task);
protected:
/**
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index 9c81d3d2637..e2812c6312b 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -38,8 +38,8 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* \param timerProc: The callback invoked when the interval expires.
* \param userData: The timer user data.
*/
- GHOST_TimerTask(GHOST_TUns64 start,
- GHOST_TUns64 interval,
+ GHOST_TimerTask(uint64_t start,
+ uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL)
: m_start(start),
@@ -55,7 +55,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Returns the timer start time.
* \return The timer start time.
*/
- inline GHOST_TUns64 getStart() const
+ inline uint64_t getStart() const
{
return m_start;
}
@@ -64,7 +64,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Changes the timer start time.
* \param start: The timer start time.
*/
- void setStart(GHOST_TUns64 start)
+ void setStart(uint64_t start)
{
m_start = start;
}
@@ -73,7 +73,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Returns the timer interval.
* \return The timer interval.
*/
- inline GHOST_TUns64 getInterval() const
+ inline uint64_t getInterval() const
{
return m_interval;
}
@@ -82,7 +82,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Changes the timer interval.
* \param interval: The timer interval.
*/
- void setInterval(GHOST_TUns64 interval)
+ void setInterval(uint64_t interval)
{
m_interval = interval;
}
@@ -91,7 +91,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Returns the time the timerProc will be called.
* \return The time the timerProc will be called.
*/
- inline GHOST_TUns64 getNext() const
+ inline uint64_t getNext() const
{
return m_next;
}
@@ -100,7 +100,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Changes the time the timerProc will be called.
* \param next: The time the timerProc will be called.
*/
- void setNext(GHOST_TUns64 next)
+ void setNext(uint64_t next)
{
m_next = next;
}
@@ -145,7 +145,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Returns the auxiliary storage room.
* \return The auxiliary storage room.
*/
- inline GHOST_TUns32 getAuxData() const
+ inline uint32_t getAuxData() const
{
return m_auxData;
}
@@ -154,20 +154,20 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
* Changes the auxiliary storage room.
* \param auxData: The auxiliary storage room.
*/
- void setAuxData(GHOST_TUns32 auxData)
+ void setAuxData(uint32_t auxData)
{
m_auxData = auxData;
}
protected:
/** The time the timer task was started. */
- GHOST_TUns64 m_start;
+ uint64_t m_start;
/** The interval between calls. */
- GHOST_TUns64 m_interval;
+ uint64_t m_interval;
/** The time the timerProc will be called. */
- GHOST_TUns64 m_next;
+ uint64_t m_next;
/** The callback invoked when the timer expires. */
GHOST_TimerProcPtr m_timerProc;
@@ -176,5 +176,5 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
GHOST_TUserDataPtr m_userData;
/** Auxiliary storage room. */
- GHOST_TUns32 m_auxData;
+ uint32_t m_auxData;
};
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index ca19e251279..6009d7dbcfc 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -31,8 +31,8 @@
#include <assert.h>
-GHOST_Window::GHOST_Window(GHOST_TUns32 width,
- GHOST_TUns32 height,
+GHOST_Window::GHOST_Window(uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
const bool wantStereoVisual,
const bool /*exclusive*/)
@@ -143,7 +143,7 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode,
GHOST_TAxisFlag wrap_axis,
GHOST_Rect *bounds,
- GHOST_TInt32 mouse_ungrab_xy[2])
+ int32_t mouse_ungrab_xy[2])
{
if (m_cursorGrab == mode)
return GHOST_kSuccess;
@@ -192,13 +192,8 @@ GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape)
}
}
-GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizex,
- int sizey,
- int hotX,
- int hotY,
- bool canInvertColor)
+GHOST_TSuccess GHOST_Window::setCustomCursorShape(
+ uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
{
if (setWindowCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor)) {
m_cursorShape = GHOST_kStandardCursorCustom;
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 3542c6f2bcf..f061e07b3c8 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -48,8 +48,8 @@ class GHOST_Window : public GHOST_IWindow {
* \param stereoVisual: Stereo visual for quad buffered stereo.
* \param exclusive: Use to show the window ontop and ignore others (used full-screen).
*/
- GHOST_Window(GHOST_TUns32 width,
- GHOST_TUns32 height,
+ GHOST_Window(uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
const bool wantStereoVisual = false,
const bool exclusive = false);
@@ -62,13 +62,13 @@ class GHOST_Window : public GHOST_IWindow {
* virtual std::string getTitle() const = 0;
* virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
* virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
- * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
- * virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
- * virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
+ * virtual GHOST_TSuccess setClientWidth(uint32_t width) = 0;
+ * virtual GHOST_TSuccess setClientHeight(uint32_t height) = 0;
+ * virtual GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) = 0;
* virtual void screenToClient(
- * GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
+ * int32_t inX, int32_t inY, int32_t& outX, int32_t& outY) const = 0;
* virtual void clientToScreen(
- * GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
+ * int32_t inX, int32_t inY, int32_t& outX, int32_t& outY) const = 0;
* virtual GHOST_TWindowState getState() const = 0;
* virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
* virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
@@ -126,8 +126,8 @@ class GHOST_Window : public GHOST_IWindow {
* \param hotY: The Y coordinate of the cursor hot-spot.
* \return Indication of success.
*/
- GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -142,9 +142,9 @@ class GHOST_Window : public GHOST_IWindow {
inline GHOST_TGrabCursorMode getCursorGrabMode() const;
inline bool getCursorGrabModeIsWarp() const;
inline GHOST_TAxisFlag getCursorGrabAxis() const;
- inline void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
- inline void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
- inline void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
+ inline void getCursorGrabInitPos(int32_t &x, int32_t &y) const;
+ inline void getCursorGrabAccum(int32_t &x, int32_t &y) const;
+ inline void setCursorGrabAccum(int32_t x, int32_t y);
/**
* Shows or hides the cursor.
@@ -161,7 +161,7 @@ class GHOST_Window : public GHOST_IWindow {
GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode,
GHOST_TAxisFlag wrap_axis,
GHOST_Rect *bounds,
- GHOST_TInt32 mouse_ungrab_xy[2]);
+ int32_t mouse_ungrab_xy[2]);
/**
* Gets the cursor grab region, if unset the window is used.
@@ -292,14 +292,13 @@ class GHOST_Window : public GHOST_IWindow {
* Returns the recommended DPI for this window.
* \return The recommended DPI for this window.
*/
- virtual inline GHOST_TUns16 getDPIHint()
+ virtual inline uint16_t getDPIHint()
{
return 96;
}
#ifdef WITH_INPUT_IME
- virtual void beginIME(
- GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed)
+ virtual void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
{
/* do nothing temporarily if not in windows */
}
@@ -343,8 +342,8 @@ class GHOST_Window : public GHOST_IWindow {
* Sets the cursor shape on the window using
* native window system calls.
*/
- virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ virtual GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int szx,
int szy,
int hotX,
@@ -369,10 +368,10 @@ class GHOST_Window : public GHOST_IWindow {
GHOST_TAxisFlag m_cursorGrabAxis;
/** Initial grab location. */
- GHOST_TInt32 m_cursorGrabInitPos[2];
+ int32_t m_cursorGrabInitPos[2];
/** Accumulated offset from m_cursorGrabInitPos. */
- GHOST_TInt32 m_cursorGrabAccumPos[2];
+ int32_t m_cursorGrabAccumPos[2];
/** Wrap the cursor within this region. */
GHOST_Rect m_cursorGrabBounds;
@@ -396,9 +395,9 @@ class GHOST_Window : public GHOST_IWindow {
bool m_wantStereoVisual;
/** Full-screen width */
- GHOST_TUns32 m_fullScreenWidth;
+ uint32_t m_fullScreenWidth;
/** Full-screen height */
- GHOST_TUns32 m_fullScreenHeight;
+ uint32_t m_fullScreenHeight;
/* OSX only, retina screens */
float m_nativePixelSize;
@@ -432,19 +431,19 @@ inline GHOST_TAxisFlag GHOST_Window::getCursorGrabAxis() const
return m_cursorGrabAxis;
}
-inline void GHOST_Window::getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+inline void GHOST_Window::getCursorGrabInitPos(int32_t &x, int32_t &y) const
{
x = m_cursorGrabInitPos[0];
y = m_cursorGrabInitPos[1];
}
-inline void GHOST_Window::getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+inline void GHOST_Window::getCursorGrabAccum(int32_t &x, int32_t &y) const
{
x = m_cursorGrabAccumPos[0];
y = m_cursorGrabAccumPos[1];
}
-inline void GHOST_Window::setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y)
+inline void GHOST_Window::setCursorGrabAccum(int32_t x, int32_t y)
{
m_cursorGrabAccumPos[0] = x;
m_cursorGrabAccumPos[1] = y;
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index 3cfe46a080b..0fd70514ac6 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -29,6 +29,9 @@
#endif // __APPLE__
#include "GHOST_Window.h"
+#ifdef WITH_INPUT_IME
+# include "GHOST_Event.h"
+#endif
@class CAMetalLayer;
@class CocoaMetalView;
@@ -57,10 +60,10 @@ class GHOST_WindowCocoa : public GHOST_Window {
*/
GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 bottom,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t bottom,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
@@ -116,20 +119,20 @@ class GHOST_WindowCocoa : public GHOST_Window {
* Resizes client rectangle width.
* \param width: The new width of the client area of the window.
*/
- GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(uint32_t width);
/**
* Resizes client rectangle height.
* \param height: The new height of the client area of the window.
*/
- GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(uint32_t height);
/**
* Resizes client rectangle.
* \param width: The new width of the client area of the window.
* \param height: The new height of the client area of the window.
*/
- GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(uint32_t width, uint32_t height);
/**
* Returns the state of the window (normal, minimized, maximized).
@@ -151,10 +154,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
* \param outX: The x-coordinate in the client rectangle.
* \param outY: The y-coordinate in the client rectangle.
*/
- void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -163,10 +163,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
* \param outX: The x-coordinate on the screen.
* \param outY: The y-coordinate on the screen.
*/
- void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -176,10 +173,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
* \param outX: The x-coordinate on the screen.
* \param outY: The y-coordinate on the screen.
*/
- void clientToScreenIntern(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void clientToScreenIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates,
@@ -189,10 +183,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
* \param outX: The x-coordinate on the screen.
* \param outY: The y-coordinate on the screen.
*/
- void screenToClientIntern(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void screenToClientIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Gets the screen the window is displayed in
@@ -263,6 +254,11 @@ class GHOST_WindowCocoa : public GHOST_Window {
return m_immediateDraw;
}
+#ifdef WITH_INPUT_IME
+ void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed);
+ void endIME();
+#endif /* WITH_INPUT_IME */
+
protected:
/**
* \param type: The type of rendering context create.
@@ -299,8 +295,8 @@ class GHOST_WindowCocoa : public GHOST_Window {
* Sets the cursor shape on the window using
* native window system calls.
*/
- GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -326,3 +322,30 @@ class GHOST_WindowCocoa : public GHOST_Window {
bool m_debug_context; // for debug messages during context setup
bool m_is_dialog;
};
+
+#ifdef WITH_INPUT_IME
+class GHOST_EventIME : public GHOST_Event {
+ public:
+ /**
+ * Constructor.
+ * \param msec: The time this event was generated.
+ * \param type: The type of key event.
+ * \param key: The key code of the key.
+ */
+ GHOST_EventIME(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata)
+ : GHOST_Event(msec, type, window)
+ {
+ this->m_data = customdata;
+ }
+};
+
+typedef int GHOST_ImeStateFlagCocoa;
+enum {
+ GHOST_IME_INPUT_FOCUSED = (1 << 0),
+ GHOST_IME_ENABLED = (1 << 1),
+ GHOST_IME_COMPOSING = (1 << 2),
+ GHOST_IME_KEY_CONTROL_CHAR = (1 << 3),
+ GHOST_IME_COMPOSITION_EVENT = (1 << 4), // For Korean input
+ GHOST_IME_RESULT_EVENT = (1 << 5) // For Korean input
+};
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index d082fa99ad8..0c3b3062126 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -284,10 +284,10 @@
GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 bottom,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t bottom,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual,
@@ -570,13 +570,13 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect &bounds) const
[pool drain];
}
-GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
+GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(uint32_t width)
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
GHOST_Rect cBnds, wBnds;
getClientBounds(cBnds);
- if (((GHOST_TUns32)cBnds.getWidth()) != width) {
+ if (((uint32_t)cBnds.getWidth()) != width) {
NSSize size;
size.width = width;
size.height = cBnds.getHeight();
@@ -586,13 +586,13 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(uint32_t height)
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
GHOST_Rect cBnds, wBnds;
getClientBounds(cBnds);
- if (((GHOST_TUns32)cBnds.getHeight()) != height) {
+ if (((uint32_t)cBnds.getHeight()) != height) {
NSSize size;
size.width = cBnds.getWidth();
size.height = height;
@@ -602,14 +602,13 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowCocoa::setClientSize(uint32_t width, uint32_t height)
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
GHOST_Rect cBnds, wBnds;
getClientBounds(cBnds);
- if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
- (((GHOST_TUns32)cBnds.getHeight()) != height)) {
+ if ((((uint32_t)cBnds.getWidth()) != width) || (((uint32_t)cBnds.getHeight()) != height)) {
NSSize size;
size.width = width;
size.height = height;
@@ -654,10 +653,10 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const
return state;
}
-void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowCocoa::screenToClient(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid");
@@ -669,10 +668,10 @@ void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX,
outY = (cBnds.getHeight() - 1) - outY;
}
-void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowCocoa::clientToScreen(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid");
@@ -684,10 +683,10 @@ void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX,
clientToScreenIntern(inX, inY, outX, outY);
}
-void GHOST_WindowCocoa::screenToClientIntern(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowCocoa::screenToClientIntern(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
NSRect screenCoord;
NSRect baseCoord;
@@ -701,10 +700,10 @@ void GHOST_WindowCocoa::screenToClientIntern(GHOST_TInt32 inX,
outY = baseCoord.origin.y;
}
-void GHOST_WindowCocoa::clientToScreenIntern(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowCocoa::clientToScreenIntern(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
NSRect screenCoord;
NSRect baseCoord;
@@ -1127,9 +1126,9 @@ GHOST_TSuccess GHOST_WindowCocoa::hasCursorShape(GHOST_TStandardCursor shape)
return success;
}
-/* Reverse the bits in a GHOST_TUns8 */
+/* Reverse the bits in a uint8_t */
#if 0
-static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
+static uint8_t uns8ReverseBits(uint8_t ch)
{
ch= ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA);
ch= ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC);
@@ -1138,8 +1137,8 @@ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
}
#endif
-/** Reverse the bits in a GHOST_TUns16 */
-static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
+/** Reverse the bits in a uint16_t */
+static uint16_t uns16ReverseBits(uint16_t shrt)
{
shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA);
shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC);
@@ -1148,20 +1147,15 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
return shrt;
}
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizex,
- int sizey,
- int hotX,
- int hotY,
- bool canInvertColor)
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(
+ uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
{
int y, nbUns16;
NSPoint hotSpotPoint;
NSBitmapImageRep *cursorImageRep;
NSImage *cursorImage;
NSSize imSize;
- GHOST_TUns16 *cursorBitmap;
+ uint16_t *cursorBitmap;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -1182,7 +1176,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
bytesPerRow:(sizex / 8 + (sizex % 8 > 0 ? 1 : 0))
bitsPerPixel:1];
- cursorBitmap = (GHOST_TUns16 *)[cursorImageRep bitmapData];
+ cursorBitmap = (uint16_t *)[cursorImageRep bitmapData];
nbUns16 = [cursorImageRep bytesPerPlane] / 2;
for (y = 0; y < nbUns16; y++) {
@@ -1221,3 +1215,25 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
[pool drain];
return GHOST_kSuccess;
}
+
+#ifdef WITH_INPUT_IME
+void GHOST_WindowCocoa::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
+{
+ if (m_openGLView) {
+ [m_openGLView beginIME:x y:y w:w h:h completed:completed];
+ }
+ else {
+ [m_metalView beginIME:x y:y w:w h:h completed:completed];
+ }
+}
+
+void GHOST_WindowCocoa::endIME()
+{
+ if (m_openGLView) {
+ [m_openGLView endIME];
+ }
+ else {
+ [m_metalView endIME];
+ }
+}
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index aca06ba75b5..a3f9e2f0a13 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -36,10 +36,10 @@ class GHOST_WindowNULL : public GHOST_Window {
GHOST_WindowNULL(GHOST_SystemNULL *system,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
const GHOST_IWindow *parentWindow,
GHOST_TDrawingContextType type,
@@ -66,8 +66,8 @@ class GHOST_WindowNULL : public GHOST_Window {
{
return GHOST_kSuccess;
}
- GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -95,30 +95,24 @@ class GHOST_WindowNULL : public GHOST_Window {
void getClientBounds(GHOST_Rect &bounds) const
{ /* nothing */
}
- GHOST_TSuccess setClientWidth(GHOST_TUns32 width)
+ GHOST_TSuccess setClientWidth(uint32_t width)
{
return GHOST_kFailure;
}
- GHOST_TSuccess setClientHeight(GHOST_TUns32 height)
+ GHOST_TSuccess setClientHeight(uint32_t height)
{
return GHOST_kFailure;
}
- GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+ GHOST_TSuccess setClientSize(uint32_t width, uint32_t height)
{
return GHOST_kFailure;
}
- void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
{
outX = inX;
outY = inY;
}
- void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
{
outX = inX;
outY = inY;
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index ff0c506feb7..fa1fcee2911 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -28,10 +28,10 @@
GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual,
@@ -175,7 +175,7 @@ void GHOST_WindowSDL::getClientBounds(GHOST_Rect &bounds) const
bounds.m_b = y + h;
}
-GHOST_TSuccess GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width)
+GHOST_TSuccess GHOST_WindowSDL::setClientWidth(uint32_t width)
{
int height;
SDL_GetWindowSize(m_sdl_win, NULL, &height);
@@ -183,7 +183,7 @@ GHOST_TSuccess GHOST_WindowSDL::setClientWidth(GHOST_TUns32 width)
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowSDL::setClientHeight(uint32_t height)
{
int width;
SDL_GetWindowSize(m_sdl_win, &width, NULL);
@@ -191,16 +191,13 @@ GHOST_TSuccess GHOST_WindowSDL::setClientHeight(GHOST_TUns32 height)
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_WindowSDL::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowSDL::setClientSize(uint32_t width, uint32_t height)
{
SDL_SetWindowSize(m_sdl_win, width, height);
return GHOST_kSuccess;
}
-void GHOST_WindowSDL::screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowSDL::screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
{
/* XXXSDL_WEAK_ABS_COORDS */
int x_win, y_win;
@@ -209,10 +206,7 @@ void GHOST_WindowSDL::screenToClient(GHOST_TInt32 inX,
outX = inX - x_win;
outY = inY - y_win;
}
-void GHOST_WindowSDL::clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowSDL::clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
{
/* XXXSDL_WEAK_ABS_COORDS */
int x_win, y_win;
@@ -556,7 +550,7 @@ static SDL_Cursor *sdl_ghost_CreateCursor(
return cursor;
}
-/* TODO, this is currently never freed but it won't leak either. */
+/* TODO: this is currently never freed but it won't leak either. */
static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape)
{
if (sdl_std_cursor_array[0] == NULL) {
@@ -576,7 +570,7 @@ static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape)
DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault);
DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow);
DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow);
- DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); // TODO, replace this one.
+ DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); /* TODO: replace this one. */
DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy);
DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp);
DEF_CURSOR(watch, GHOST_kStandardCursorWait);
@@ -622,13 +616,8 @@ GHOST_TSuccess GHOST_WindowSDL::hasCursorShape(GHOST_TStandardCursor shape)
return (getStandardCursorShape(shape)) ? GHOST_kSuccess : GHOST_kFailure;
}
-GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizex,
- int sizey,
- int hotX,
- int hotY,
- bool canInvertColor)
+GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape(
+ uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
{
if (m_sdl_custom_cursor) {
SDL_FreeCursor(m_sdl_custom_cursor);
@@ -647,7 +636,7 @@ GHOST_TSuccess GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
return GHOST_kSuccess;
}
-GHOST_TUns16 GHOST_WindowSDL::getDPIHint()
+uint16_t GHOST_WindowSDL::getDPIHint()
{
int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win);
if (displayIndex < 0) {
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index bfe07af1c70..d2eedecc506 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -48,10 +48,10 @@ class GHOST_WindowSDL : public GHOST_Window {
public:
GHOST_WindowSDL(GHOST_SystemSDL *system,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
@@ -95,8 +95,8 @@ class GHOST_WindowSDL : public GHOST_Window {
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor shape);
- GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -109,21 +109,15 @@ class GHOST_WindowSDL : public GHOST_Window {
std::string getTitle() const;
- GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(uint32_t width);
- GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(uint32_t height);
- GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(uint32_t width, uint32_t height);
- void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
- void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
GHOST_TSuccess setState(GHOST_TWindowState state);
@@ -146,5 +140,5 @@ class GHOST_WindowSDL : public GHOST_Window {
return GHOST_kFailure;
}
- GHOST_TUns16 getDPIHint();
+ uint16_t getDPIHint();
};
diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h
index f47e02704b2..fa629528809 100644
--- a/intern/ghost/intern/GHOST_WindowViewCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h
@@ -17,6 +17,11 @@
* All rights reserved.
*/
+/* The Carbon API is still needed to check if the Input Source (Input Method or IME) is valid. */
+#ifdef WITH_INPUT_IME
+# import <Carbon/Carbon.h>
+#endif
+
/* NSView subclass for drawing and handling input.
*
* COCOA_VIEW_BASE_CLASS will be either NSView or NSOpenGLView depending if
@@ -25,7 +30,7 @@
* Objective-C does not have multiple inheritance. */
// We need to subclass it in order to give Cocoa the feeling key events are trapped
-@interface COCOA_VIEW_CLASS : COCOA_VIEW_BASE_CLASS <NSTextInput>
+@interface COCOA_VIEW_CLASS : COCOA_VIEW_BASE_CLASS <NSTextInputClient>
{
GHOST_SystemCocoa *systemCocoa;
GHOST_WindowCocoa *associatedWindow;
@@ -33,10 +38,27 @@
bool composing;
NSString *composing_text;
- bool immediate_draw;
+#ifdef WITH_INPUT_IME
+ struct {
+ GHOST_ImeStateFlagCocoa state_flag;
+ NSRect candidate_window_position;
+
+ /* Event data. */
+ GHOST_TEventImeData event;
+ std::string result;
+ std::string composite;
+ std::string combined_result;
+ } ime;
+#endif
}
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa
windowCocoa:(GHOST_WindowCocoa *)winCocoa;
+
+#ifdef WITH_INPUT_IME
+- (void)beginIME:(int32_t)x y:(int32_t)y w:(int32_t)w h:(int32_t)h completed:(bool)completed;
+
+- (void)endIME;
+#endif
@end
@implementation COCOA_VIEW_CLASS
@@ -50,7 +72,21 @@
composing = false;
composing_text = nil;
- immediate_draw = false;
+#ifdef WITH_INPUT_IME
+ ime.state_flag = 0;
+ ime.candidate_window_position = NSZeroRect;
+ ime.event.cursor_position = -1;
+ ime.event.target_start = -1;
+ ime.event.target_end = -1;
+
+ /* Register a function to be executed when Input Method is changed using
+ * 'Control + Space' or language-specific keys (such as 'Eisu / Kana' key for Japanese).*/
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center addObserver:self
+ selector:@selector(ImeDidChangeCallback:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+#endif
}
- (BOOL)acceptsFirstResponder
@@ -66,20 +102,38 @@
// The trick to prevent Cocoa from complaining (beeping)
- (void)keyDown:(NSEvent *)event
{
- systemCocoa->handleKeyEvent(event);
+#ifdef WITH_INPUT_IME
+ [self checkKeyCodeIsControlChar:event];
+ const bool ime_process = [self isProcessedByIme];
+#else
+ const bool ime_process = false;
+#endif
+
+ if (!ime_process) {
+ systemCocoa->handleKeyEvent(event);
+ }
/* Start or continue composing? */
if ([[event characters] length] == 0 || [[event charactersIgnoringModifiers] length] == 0 ||
- composing) {
+ composing || ime_process) {
composing = YES;
// interpret event to call insertText
- NSMutableArray *events;
- events = [[NSMutableArray alloc] initWithCapacity:1];
- [events addObject:event];
- [self interpretKeyEvents:events]; // calls insertText
- [events removeObject:event];
- [events release];
+ [self interpretKeyEvents:[NSArray arrayWithObject:event]]; // calls insertText
+
+#ifdef WITH_INPUT_IME
+ // For Korean input, control characters are also processed by handleKeyEvent.
+ const int controlCharForKorean = (GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT |
+ GHOST_IME_KEY_CONTROL_CHAR);
+ if (((ime.state_flag & controlCharForKorean) == controlCharForKorean)) {
+ systemCocoa->handleKeyEvent(event);
+ }
+
+ ime.state_flag &= ~(GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT);
+
+ ime.combined_result.clear();
+#endif
+
return;
}
}
@@ -207,24 +261,90 @@
}
}
-- (void)insertText:(id)chars
+// Processes the Result String sent from the Input Method.
+- (void)insertText:(id)chars replacementRange:(NSRange)replacementRange
{
[self composing_free];
+
+#ifdef WITH_INPUT_IME
+ if (ime.state_flag & GHOST_IME_ENABLED) {
+ if (!(ime.state_flag & GHOST_IME_COMPOSING)) {
+ [self processImeEvent:GHOST_kEventImeCompositionStart];
+ }
+
+ // For Chinese and Korean input, insertText may be executed twice with a single keyDown.
+ if (ime.state_flag & GHOST_IME_RESULT_EVENT) {
+ ime.combined_result += [self convertNSString:chars];
+ }
+ else {
+ ime.combined_result = [self convertNSString:chars];
+ }
+
+ [self setImeResult:ime.combined_result];
+
+ /* For Korean input, both "Result Event" and "Composition Event"
+ * can occur in a single keyDown. */
+ if (![self ime_did_composition]) {
+ [self processImeEvent:GHOST_kEventImeComposition];
+ }
+ ime.state_flag |= GHOST_IME_RESULT_EVENT;
+
+ [self processImeEvent:GHOST_kEventImeCompositionEnd];
+ ime.state_flag &= ~GHOST_IME_COMPOSING;
+ }
+#endif
}
-- (void)setMarkedText:(id)chars selectedRange:(NSRange)range
+// Processes the Composition String sent from the Input Method.
+- (void)setMarkedText:(id)chars
+ selectedRange:(NSRange)range
+ replacementRange:(NSRange)replacementRange
{
[self composing_free];
- if ([chars length] == 0)
+
+ if ([chars length] == 0) {
+#ifdef WITH_INPUT_IME
+ // Processes when the last Composition String is deleted.
+ if (ime.state_flag & GHOST_IME_COMPOSING) {
+ [self setImeResult:std::string()];
+ [self processImeEvent:GHOST_kEventImeComposition];
+ [self processImeEvent:GHOST_kEventImeCompositionEnd];
+ ime.state_flag &= ~GHOST_IME_COMPOSING;
+ }
+#endif
+
return;
+ }
// start composing
composing = YES;
composing_text = [chars copy];
+ // chars of markedText by Input Method is an instance of NSAttributedString
+ if ([chars isKindOfClass:[NSAttributedString class]]) {
+ composing_text = [[chars string] copy];
+ }
+
// if empty, cancel
if ([composing_text length] == 0)
[self composing_free];
+
+#ifdef WITH_INPUT_IME
+ if (ime.state_flag & GHOST_IME_ENABLED) {
+ if (!(ime.state_flag & GHOST_IME_COMPOSING)) {
+ ime.state_flag |= GHOST_IME_COMPOSING;
+ [self processImeEvent:GHOST_kEventImeCompositionStart];
+ }
+
+ [self setImeComposition:composing_text selectedRange:range];
+
+ // For Korean input, setMarkedText may be executed twice with a single keyDown.
+ if (![self ime_did_composition]) {
+ ime.state_flag |= GHOST_IME_COMPOSITION_EVENT;
+ [self processImeEvent:GHOST_kEventImeComposition];
+ }
+ }
+#endif
}
- (void)unmarkText
@@ -246,12 +366,8 @@
return composing;
}
-- (NSInteger)conversationIdentifier
-{
- return (NSInteger)self;
-}
-
-- (NSAttributedString *)attributedSubstringFromRange:(NSRange)range
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range
+ actualRange:(NSRangePointer)actualRange
{
return [[[NSAttributedString alloc] init] autorelease];
}
@@ -272,8 +388,14 @@
return NSMakeRange(0, length);
}
-- (NSRect)firstRectForCharacterRange:(NSRange)range
+// Specify the position where the Chinese and Japanese candidate windows are displayed.
+- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange
{
+#ifdef WITH_INPUT_IME
+ if (ime.state_flag & GHOST_IME_ENABLED) {
+ return ime.candidate_window_position;
+ }
+#endif
return NSZeroRect;
}
@@ -287,4 +409,165 @@
return [NSArray array];
}
+#ifdef WITH_INPUT_IME
+- (void)checkImeEnabled
+{
+ ime.state_flag &= ~GHOST_IME_ENABLED;
+
+ if (ime.state_flag & GHOST_IME_INPUT_FOCUSED) {
+ /* Since there are no functions in Cocoa API,
+ * we will use the functions in the Carbon API. */
+ TISInputSourceRef currentKeyboardInputSource = TISCopyCurrentKeyboardInputSource();
+ bool ime_enabled = !CFBooleanGetValue((CFBooleanRef)TISGetInputSourceProperty(
+ currentKeyboardInputSource, kTISPropertyInputSourceIsASCIICapable));
+ CFRelease(currentKeyboardInputSource);
+
+ if (ime_enabled) {
+ ime.state_flag |= GHOST_IME_ENABLED;
+ return;
+ }
+ }
+ return;
+}
+
+- (void)ImeDidChangeCallback:(NSNotification *)notification
+{
+ [self checkImeEnabled];
+}
+
+- (void)setImeCandidateWinPos:(int32_t)x y:(int32_t)y w:(int32_t)w h:(int32_t)h
+{
+ int32_t outX, outY;
+ associatedWindow->clientToScreen(x, y, outX, outY);
+ ime.candidate_window_position = NSMakeRect((CGFloat)outX, (CGFloat)outY, (CGFloat)w, (CGFloat)h);
+}
+
+- (void)beginIME:(int32_t)x y:(int32_t)y w:(int32_t)w h:(int32_t)h completed:(bool)completed
+{
+ ime.state_flag |= GHOST_IME_INPUT_FOCUSED;
+ [self checkImeEnabled];
+ [self setImeCandidateWinPos:x y:y w:w h:h];
+}
+
+- (void)endIME
+{
+ ime.state_flag = 0;
+ ime.result.clear();
+ ime.composite.clear();
+
+ [self unmarkText];
+ [[NSTextInputContext currentInputContext] discardMarkedText];
+}
+
+- (void)processImeEvent:(GHOST_TEventType)imeEventType
+{
+ ime.event.result_len = (GHOST_TUserDataPtr)ime.result.size();
+ ime.event.result = (GHOST_TUserDataPtr)ime.result.c_str();
+ ime.event.composite_len = (GHOST_TUserDataPtr)ime.composite.size();
+ ime.event.composite = (GHOST_TUserDataPtr)ime.composite.c_str();
+
+ GHOST_Event *event = new GHOST_EventIME(
+ systemCocoa->getMilliSeconds(), imeEventType, associatedWindow, &ime.event);
+ systemCocoa->pushEvent(event);
+}
+
+- (std::string)convertNSString:(NSString *)inString
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ std::string str([inString UTF8String]);
+ [pool drain];
+ return str;
+}
+
+- (void)setImeComposition:(NSString *)inString selectedRange:(NSRange)range
+{
+ ime.composite = [self convertNSString:inString];
+
+ // For Korean input, both "Result Event" and "Composition Event" can occur in a single keyDown.
+ if (!(ime.state_flag & GHOST_IME_RESULT_EVENT)) {
+ ime.result.clear();
+ }
+
+ /* The target string is equivalent to the string in selectedRange of setMarkedText.
+ * The cursor is displayed at the beginning of the target string. */
+ char *front_string = (char *)[[inString substringWithRange:NSMakeRange(0, range.location)]
+ UTF8String];
+ char *selected_string = (char *)[[inString substringWithRange:range] UTF8String];
+ ime.event.cursor_position = strlen(front_string);
+ ime.event.target_start = ime.event.cursor_position;
+ ime.event.target_end = ime.event.target_start + strlen(selected_string);
+}
+
+- (void)setImeResult:(std::string)result
+{
+ ime.result = result;
+ ime.composite.clear();
+ ime.event.cursor_position = -1;
+ ime.event.target_start = -1;
+ ime.event.target_end = -1;
+}
+
+- (void)checkKeyCodeIsControlChar:(NSEvent *)event
+{
+ ime.state_flag &= ~GHOST_IME_KEY_CONTROL_CHAR;
+ switch ([event keyCode]) {
+ case kVK_ANSI_KeypadEnter:
+ case kVK_ANSI_KeypadClear:
+ case kVK_F1:
+ case kVK_F2:
+ case kVK_F3:
+ case kVK_F4:
+ case kVK_F5:
+ case kVK_F6:
+ case kVK_F7:
+ case kVK_F8:
+ case kVK_F9:
+ case kVK_F10:
+ case kVK_F11:
+ case kVK_F12:
+ case kVK_F13:
+ case kVK_F14:
+ case kVK_F15:
+ case kVK_F16:
+ case kVK_F17:
+ case kVK_F18:
+ case kVK_F19:
+ case kVK_F20:
+ case kVK_UpArrow:
+ case kVK_DownArrow:
+ case kVK_LeftArrow:
+ case kVK_RightArrow:
+ case kVK_Return:
+ case kVK_Delete:
+ case kVK_ForwardDelete:
+ case kVK_Escape:
+ case kVK_Tab:
+ case kVK_Home:
+ case kVK_End:
+ case kVK_PageUp:
+ case kVK_PageDown:
+ case kVK_VolumeUp:
+ case kVK_VolumeDown:
+ case kVK_Mute:
+ ime.state_flag |= GHOST_IME_KEY_CONTROL_CHAR;
+ return;
+ }
+}
+
+- (bool)ime_did_composition
+{
+ return (ime.state_flag & GHOST_IME_COMPOSITION_EVENT) ||
+ (ime.state_flag & GHOST_IME_RESULT_EVENT);
+}
+
+/* Even if IME is enabled, when not composing, control characters
+ * (such as arrow, enter, delete) are handled by handleKeyEvent. */
+- (bool)isProcessedByIme
+{
+ return (
+ (ime.state_flag & GHOST_IME_ENABLED) &&
+ ((ime.state_flag & GHOST_IME_COMPOSING) || !(ime.state_flag & GHOST_IME_KEY_CONTROL_CHAR)));
+}
+#endif /* WITH_INPUT_IME */
+
@end
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 5be7724fd86..d0c8cfb9e73 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -36,7 +36,7 @@ struct window_t {
wl_surface *surface;
// outputs on which the window is currently shown on
std::unordered_set<const output_t *> outputs;
- GHOST_TUns16 dpi = 0;
+ uint16_t dpi = 0;
int scale = 1;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
@@ -205,10 +205,10 @@ GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorS
GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
const char *title,
- GHOST_TInt32 /*left*/,
- GHOST_TInt32 /*top*/,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t /*left*/,
+ int32_t /*top*/,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
const GHOST_IWindow *parentWindow,
GHOST_TDrawingContextType type,
@@ -344,13 +344,8 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor s
return ok;
}
-GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizex,
- int sizey,
- int hotX,
- int hotY,
- bool canInvertColor)
+GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(
+ uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
{
return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
}
@@ -377,35 +372,35 @@ void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const
bounds.set(0, 0, w->width, w->height);
}
-GHOST_TSuccess GHOST_WindowWayland::setClientWidth(GHOST_TUns32 width)
+GHOST_TSuccess GHOST_WindowWayland::setClientWidth(uint32_t width)
{
- return setClientSize(width, GHOST_TUns32(w->height));
+ return setClientSize(width, uint32_t(w->height));
}
-GHOST_TSuccess GHOST_WindowWayland::setClientHeight(GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowWayland::setClientHeight(uint32_t height)
{
- return setClientSize(GHOST_TUns32(w->width), height);
+ return setClientSize(uint32_t(w->width), height);
}
-GHOST_TSuccess GHOST_WindowWayland::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowWayland::setClientSize(uint32_t width, uint32_t height)
{
wl_egl_window_resize(w->egl_window, int(width), int(height), 0, 0);
return GHOST_kSuccess;
}
-void GHOST_WindowWayland::screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowWayland::screenToClient(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
outX = inX;
outY = inY;
}
-void GHOST_WindowWayland::clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowWayland::clientToScreen(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
outX = inX;
outY = inY;
@@ -426,7 +421,7 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
delete w;
}
-GHOST_TUns16 GHOST_WindowWayland::getDPIHint()
+uint16_t GHOST_WindowWayland::getDPIHint()
{
return w->dpi;
}
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index dbddc7c469e..afbdf1268ee 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -29,9 +29,9 @@
class GHOST_SystemWayland;
+struct output_t;
struct window_t;
struct wl_surface;
-struct output_t;
class GHOST_WindowWayland : public GHOST_Window {
public:
@@ -39,10 +39,10 @@ class GHOST_WindowWayland : public GHOST_Window {
GHOST_WindowWayland(GHOST_SystemWayland *system,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
const GHOST_IWindow *parentWindow,
GHOST_TDrawingContextType type,
@@ -52,7 +52,7 @@ class GHOST_WindowWayland : public GHOST_Window {
~GHOST_WindowWayland() override;
- GHOST_TUns16 getDPIHint() override;
+ uint16_t getDPIHint() override;
GHOST_TSuccess close();
@@ -77,8 +77,8 @@ class GHOST_WindowWayland : public GHOST_Window {
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override;
- GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -93,21 +93,15 @@ class GHOST_WindowWayland : public GHOST_Window {
void getClientBounds(GHOST_Rect &bounds) const override;
- GHOST_TSuccess setClientWidth(GHOST_TUns32 width) override;
+ GHOST_TSuccess setClientWidth(uint32_t width) override;
- GHOST_TSuccess setClientHeight(GHOST_TUns32 height) override;
+ GHOST_TSuccess setClientHeight(uint32_t height) override;
- GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) override;
+ GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) override;
- void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const override;
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override;
- void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const override;
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override;
GHOST_TSuccess setWindowCursorVisibility(bool visible) override;
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 1b73b765b49..b5d0fd8e6db 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -56,10 +56,10 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
bool wantStereoVisual,
@@ -306,9 +306,13 @@ void GHOST_WindowWin32::setTitle(const char *title)
std::string GHOST_WindowWin32::getTitle() const
{
- char buf[s_maxTitleLength]; /* CHANGE + never used yet. */
- ::GetWindowText(m_hWnd, buf, s_maxTitleLength);
- return std::string(buf);
+ std::wstring wtitle(::GetWindowTextLengthW(m_hWnd) + 1, L'\0');
+ ::GetWindowTextW(m_hWnd, &wtitle[0], wtitle.capacity());
+
+ std::string title(count_utf_8_from_16(wtitle.c_str()) + 1, '\0');
+ conv_utf_16_to_8(wtitle.c_str(), &title[0], title.capacity());
+
+ return title;
}
void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const
@@ -350,12 +354,12 @@ void GHOST_WindowWin32::getClientBounds(GHOST_Rect &bounds) const
}
}
-GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width)
+GHOST_TSuccess GHOST_WindowWin32::setClientWidth(uint32_t width)
{
GHOST_TSuccess success;
GHOST_Rect cBnds, wBnds;
getClientBounds(cBnds);
- if (cBnds.getWidth() != (GHOST_TInt32)width) {
+ if (cBnds.getWidth() != (int32_t)width) {
getWindowBounds(wBnds);
int cx = wBnds.getWidth() + width - cBnds.getWidth();
int cy = wBnds.getHeight();
@@ -369,12 +373,12 @@ GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width)
return success;
}
-GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowWin32::setClientHeight(uint32_t height)
{
GHOST_TSuccess success;
GHOST_Rect cBnds, wBnds;
getClientBounds(cBnds);
- if (cBnds.getHeight() != (GHOST_TInt32)height) {
+ if (cBnds.getHeight() != (int32_t)height) {
getWindowBounds(wBnds);
int cx = wBnds.getWidth();
int cy = wBnds.getHeight() + height - cBnds.getHeight();
@@ -388,12 +392,12 @@ GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height)
return success;
}
-GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowWin32::setClientSize(uint32_t width, uint32_t height)
{
GHOST_TSuccess success;
GHOST_Rect cBnds, wBnds;
getClientBounds(cBnds);
- if ((cBnds.getWidth() != (GHOST_TInt32)width) || (cBnds.getHeight() != (GHOST_TInt32)height)) {
+ if ((cBnds.getWidth() != (int32_t)width) || (cBnds.getHeight() != (int32_t)height)) {
getWindowBounds(wBnds);
int cx = wBnds.getWidth() + width - cBnds.getWidth();
int cy = wBnds.getHeight() + height - cBnds.getHeight();
@@ -419,10 +423,10 @@ GHOST_TWindowState GHOST_WindowWin32::getState() const
return GHOST_kWindowStateNormal;
}
-void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowWin32::screenToClient(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
POINT point = {inX, inY};
::ScreenToClient(m_hWnd, &point);
@@ -430,10 +434,10 @@ void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX,
outY = point.y;
}
-void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowWin32::clientToScreen(int32_t inX,
+ int32_t inY,
+ int32_t &outX,
+ int32_t &outY) const
{
POINT point = {inX, inY};
::ClientToScreen(m_hWnd, &point);
@@ -662,7 +666,7 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
// Convert GHOST cursor to Windows OEM cursor
HANDLE cursor = NULL;
HMODULE module = ::GetModuleHandle(0);
- GHOST_TUns32 flags = LR_SHARED | LR_DEFAULTSIZE;
+ uint32_t flags = LR_SHARED | LR_DEFAULTSIZE;
int cx = 0, cy = 0;
switch (shape) {
@@ -831,7 +835,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
/* use to generate a mouse move event, otherwise the last event
* blender gets can be outside the screen causing menus not to show
* properly unless the user moves the mouse */
- GHOST_TInt32 pos[2];
+ int32_t pos[2];
m_system->getCursorPosition(pos[0], pos[1]);
m_system->setCursorPosition(pos[0], pos[1]);
}
@@ -863,10 +867,10 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
{
- GHOST_TInt32 pointerId = GET_POINTERID_WPARAM(wParam);
- GHOST_TInt32 isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
+ int32_t pointerId = GET_POINTERID_WPARAM(wParam);
+ int32_t isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
- GHOST_TUns32 outCount = 0;
+ uint32_t outCount = 0;
if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) {
return GHOST_kFailure;
@@ -879,7 +883,7 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
return GHOST_kFailure;
}
- for (GHOST_TUns32 i = 0; i < outCount; i++) {
+ for (uint32_t i = 0; i < outCount; i++) {
POINTER_INFO pointerApiInfo = pointerPenInfo[i].pointerInfo;
// Obtain the basic information from the event
outPointerInfo[i].pointerId = pointerId;
@@ -960,7 +964,7 @@ void GHOST_WindowWin32::loadWintab(bool enable)
/* Focus Wintab if cursor is inside this window. This ensures Wintab is enabled when the
* tablet is used to change the Tablet API. */
- GHOST_TInt32 x, y;
+ int32_t x, y;
if (m_system->getCursorPosition(x, y)) {
GHOST_Rect rect;
getClientBounds(rect);
@@ -1008,7 +1012,7 @@ GHOST_TabletData GHOST_WindowWin32::getTabletData()
}
}
-GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
+uint16_t GHOST_WindowWin32::getDPIHint()
{
if (m_user32) {
GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow)::GetProcAddress(
@@ -1022,8 +1026,8 @@ GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
return USER_DEFAULT_SCREEN_DPI;
}
-/** Reverse the bits in a GHOST_TUns8 */
-static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
+/** Reverse the bits in a uint8_t */
+static uint8_t uns8ReverseBits(uint8_t ch)
{
ch = ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA);
ch = ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC);
@@ -1032,8 +1036,8 @@ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
}
#if 0 /* UNUSED */
-/** Reverse the bits in a GHOST_TUns16 */
-static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
+/** Reverse the bits in a uint16_t */
+static uint16_t uns16ReverseBits(uint16_t shrt)
{
shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA);
shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC);
@@ -1043,17 +1047,12 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
}
#endif
-GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
- int sizeX,
- int sizeY,
- int hotX,
- int hotY,
- bool canInvertColor)
+GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(
+ uint8_t *bitmap, uint8_t *mask, int sizeX, int sizeY, int hotX, int hotY, bool canInvertColor)
{
- GHOST_TUns32 andData[32];
- GHOST_TUns32 xorData[32];
- GHOST_TUns32 fullBitRow, fullMaskRow;
+ uint32_t andData[32];
+ uint32_t xorData[32];
+ uint32_t fullBitRow, fullMaskRow;
int x, y, cols;
cols = sizeX / 8; /* Number of whole bytes per row (width of bitmap/mask). */
@@ -1111,10 +1110,9 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
}
#ifdef WITH_INPUT_IME
-void GHOST_WindowWin32::beginIME(
- GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed)
+void GHOST_WindowWin32::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
{
- m_imeInput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), (bool)completed);
+ m_imeInput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), completed);
}
void GHOST_WindowWin32::endIME()
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 119092a001a..40a658bf88b 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -47,11 +47,11 @@ typedef BOOL(API *GHOST_WIN32_AdjustWindowRectExForDpi)(
LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi);
struct GHOST_PointerInfoWin32 {
- GHOST_TInt32 pointerId;
- GHOST_TInt32 isPrimary;
+ int32_t pointerId;
+ int32_t isPrimary;
GHOST_TButtonMask buttonMask;
POINT pixelLocation;
- GHOST_TUns64 time;
+ uint64_t time;
GHOST_TabletData tabletData;
};
@@ -83,10 +83,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
*/
GHOST_WindowWin32(GHOST_SystemWin32 *system,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
bool wantStereoVisual = false,
@@ -152,20 +152,20 @@ class GHOST_WindowWin32 : public GHOST_Window {
* Resizes client rectangle width.
* \param width: The new width of the client area of the window.
*/
- GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(uint32_t width);
/**
* Resizes client rectangle height.
* \param height: The new height of the client area of the window.
*/
- GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(uint32_t height);
/**
* Resizes client rectangle.
* \param width: The new width of the client area of the window.
* \param height: The new height of the client area of the window.
*/
- GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(uint32_t width, uint32_t height);
/**
* Returns the state of the window (normal, minimized, maximized).
@@ -180,10 +180,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
* \param outX: The x-coordinate in the client rectangle.
* \param outY: The y-coordinate in the client rectangle.
*/
- void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Converts a point in screen coordinates to client rectangle coordinates
@@ -192,10 +189,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
* \param outX: The x-coordinate on the screen.
* \param outY: The y-coordinate on the screen.
*/
- void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
/**
* Sets the state of the window (normal, minimized, maximized).
@@ -309,7 +303,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
return GHOST_kFailure;
}
- GHOST_TUns16 getDPIHint() override;
+ uint16_t getDPIHint() override;
/** True if the mouse is either over or captured by the window. */
bool m_mousePresent;
@@ -323,7 +317,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
return &m_imeInput;
}
- void beginIME(GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed);
+ void beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed);
void endIME();
#endif /* WITH_INPUT_IME */
@@ -359,8 +353,8 @@ class GHOST_WindowWin32 : public GHOST_Window {
* Sets the cursor shape on the window using
* native window system calls.
*/
- GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index ea798441adb..0ade7a52891 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -213,10 +213,10 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display,
GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_WindowX11 *parentWindow,
GHOST_TDrawingContextType type,
@@ -622,7 +622,7 @@ void GHOST_WindowX11::getClientBounds(GHOST_Rect &bounds) const
Window root_return;
int x_return, y_return;
unsigned int w_return, h_return, border_w_return, depth_return;
- GHOST_TInt32 screen_x, screen_y;
+ int32_t screen_x, screen_y;
XGetGeometry(m_display,
m_window,
@@ -642,7 +642,7 @@ void GHOST_WindowX11::getClientBounds(GHOST_Rect &bounds) const
bounds.m_b = bounds.m_t + h_return;
}
-GHOST_TSuccess GHOST_WindowX11::setClientWidth(GHOST_TUns32 width)
+GHOST_TSuccess GHOST_WindowX11::setClientWidth(uint32_t width)
{
XWindowChanges values;
unsigned int value_mask = CWWidth;
@@ -652,7 +652,7 @@ GHOST_TSuccess GHOST_WindowX11::setClientWidth(GHOST_TUns32 width)
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_WindowX11::setClientHeight(GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowX11::setClientHeight(uint32_t height)
{
XWindowChanges values;
unsigned int value_mask = CWHeight;
@@ -661,7 +661,7 @@ GHOST_TSuccess GHOST_WindowX11::setClientHeight(GHOST_TUns32 height)
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_WindowX11::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+GHOST_TSuccess GHOST_WindowX11::setClientSize(uint32_t width, uint32_t height)
{
XWindowChanges values;
unsigned int value_mask = CWWidth | CWHeight;
@@ -671,10 +671,7 @@ GHOST_TSuccess GHOST_WindowX11::setClientSize(GHOST_TUns32 width, GHOST_TUns32 h
return GHOST_kSuccess;
}
-void GHOST_WindowX11::screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowX11::screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
{
/* This is correct! */
@@ -687,10 +684,7 @@ void GHOST_WindowX11::screenToClient(GHOST_TInt32 inX,
outY = ay;
}
-void GHOST_WindowX11::clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const
+void GHOST_WindowX11::clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
{
int ax, ay;
Window temp;
@@ -1590,8 +1584,8 @@ GHOST_TSuccess GHOST_WindowX11::hasCursorShape(GHOST_TStandardCursor shape)
return getStandardCursor(shape, xcursor);
}
-GHOST_TSuccess GHOST_WindowX11::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+GHOST_TSuccess GHOST_WindowX11::setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
@@ -1679,7 +1673,7 @@ GHOST_TSuccess GHOST_WindowX11::endFullScreen() const
return GHOST_kSuccess;
}
-GHOST_TUns16 GHOST_WindowX11::getDPIHint()
+uint16_t GHOST_WindowX11::getDPIHint()
{
/* Try to read DPI setting set using xrdb */
char *resMan = XResourceManagerString(m_display);
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 01699e9d1ce..9f3d48dfafc 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -68,10 +68,10 @@ class GHOST_WindowX11 : public GHOST_Window {
GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
const char *title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
+ int32_t left,
+ int32_t top,
+ uint32_t width,
+ uint32_t height,
GHOST_TWindowState state,
GHOST_WindowX11 *parentWindow,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
@@ -93,21 +93,15 @@ class GHOST_WindowX11 : public GHOST_Window {
bool isDialog() const;
- GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+ GHOST_TSuccess setClientWidth(uint32_t width);
- GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+ GHOST_TSuccess setClientHeight(uint32_t height);
- GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+ GHOST_TSuccess setClientSize(uint32_t width, uint32_t height);
- void screenToClient(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
- void clientToScreen(GHOST_TInt32 inX,
- GHOST_TInt32 inY,
- GHOST_TInt32 &outX,
- GHOST_TInt32 &outY) const;
+ void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const;
GHOST_TWindowState getState() const;
@@ -182,7 +176,7 @@ class GHOST_WindowX11 : public GHOST_Window {
GHOST_TSuccess setDialogHints(GHOST_WindowX11 *parentWindow);
- GHOST_TUns16 getDPIHint();
+ uint16_t getDPIHint();
protected:
/**
@@ -216,8 +210,8 @@ class GHOST_WindowX11 : public GHOST_Window {
* Sets the cursor shape on the window using
* native window system calls (Arbitrary size/color).
*/
- GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
- GHOST_TUns8 *mask,
+ GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap,
+ uint8_t *mask,
int sizex,
int sizey,
int hotX,
diff --git a/intern/ghost/intern/GHOST_Wintab.h b/intern/ghost/intern/GHOST_Wintab.h
index 75017aa67d9..443c726d270 100644
--- a/intern/ghost/intern/GHOST_Wintab.h
+++ b/intern/ghost/intern/GHOST_Wintab.h
@@ -56,10 +56,10 @@ typedef std::unique_ptr<std::remove_pointer_t<HMODULE>, decltype(&::FreeLibrary)
typedef std::unique_ptr<std::remove_pointer_t<HCTX>, GHOST_WIN32_WTClose> unique_hctx;
struct GHOST_WintabInfoWin32 {
- GHOST_TInt32 x, y;
+ int32_t x, y;
GHOST_TEventType type;
GHOST_TButtonMask button;
- GHOST_TUns64 time;
+ uint64_t time;
GHOST_TabletData tabletData;
};
@@ -178,7 +178,7 @@ class GHOST_Wintab {
bool m_focused = false;
/** Pressed button map. */
- GHOST_TUns8 m_buttons = 0;
+ uint8_t m_buttons = 0;
/** Range of a coordinate space. */
struct Range {
diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp
index b10e001df47..9c4f7fbc7d8 100644
--- a/intern/ghost/intern/GHOST_XrAction.cpp
+++ b/intern/ghost/intern/GHOST_XrAction.cpp
@@ -329,7 +329,7 @@ void GHOST_XrAction::updateState(XrSession session,
void GHOST_XrAction::applyHapticFeedback(XrSession session,
const char *action_name,
- const GHOST_TInt64 &duration,
+ const int64_t &duration,
const float &frequency,
const float &amplitude)
{
diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h
index bdc6cafb4a9..32445c616bd 100644
--- a/intern/ghost/intern/GHOST_XrAction.h
+++ b/intern/ghost/intern/GHOST_XrAction.h
@@ -91,7 +91,7 @@ class GHOST_XrAction {
const XrTime &predicted_display_time);
void applyHapticFeedback(XrSession session,
const char *action_name,
- const GHOST_TInt64 &duration,
+ const int64_t &duration,
const float &frequency,
const float &amplitude);
void stopHapticFeedback(XrSession session, const char *action_name);
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index a7438fae13c..35280e77e22 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -772,7 +772,7 @@ bool GHOST_XrSession::syncActions(const char *action_set_name)
bool GHOST_XrSession::applyHapticAction(const char *action_set_name,
const char *action_name,
- const GHOST_TInt64 &duration,
+ const int64_t &duration,
const float &frequency,
const float &amplitude)
{
diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h
index a2d3cf2e385..c871b98da46 100644
--- a/intern/ghost/intern/GHOST_XrSession.h
+++ b/intern/ghost/intern/GHOST_XrSession.h
@@ -81,7 +81,7 @@ class GHOST_XrSession {
bool syncActions(const char *action_set_name = nullptr);
bool applyHapticAction(const char *action_set_name,
const char *action_name,
- const GHOST_TInt64 &duration,
+ const int64_t &duration,
const float &frequency,
const float &amplitude);
void stopHapticAction(const char *action_set_name, const char *action_name);
diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c
index 8cd1b5acb89..3257c42118e 100644
--- a/intern/ghost/test/gears/GHOST_C-Test.c
+++ b/intern/ghost/test/gears/GHOST_C-Test.c
@@ -46,7 +46,7 @@
# include <GL/gl.h>
#endif /* defined(WIN32) || defined(__APPLE__) */
-static void gearsTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time);
+static void gearsTimerProc(GHOST_TimerTaskHandle task, uint64_t time);
int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData);
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
@@ -60,7 +60,7 @@ static GHOST_WindowHandle sFullScreenWindow = NULL;
static GHOST_TimerTaskHandle sTestTimer;
static GHOST_TimerTaskHandle sGearsTimer;
-static void testTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time)
+static void testTimerProc(GHOST_TimerTaskHandle task, uint64_t time)
{
printf("timer1, time=%d\n", (int)time);
}
@@ -274,7 +274,7 @@ static void setViewPortGL(GHOST_WindowHandle hWindow)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-w, w, -h, h, 5.0, 60.0);
- /* glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); */
+ // glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -40.0);
@@ -501,7 +501,7 @@ int main(int argc, char **argv)
return 0;
}
-static void gearsTimerProc(GHOST_TimerTaskHandle hTask, GHOST_TUns64 time)
+static void gearsTimerProc(GHOST_TimerTaskHandle hTask, uint64_t time)
{
GHOST_WindowHandle hWindow = NULL;
fAngle += 2.0;
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
index c9c497aacb4..c1cb5f29e2e 100644
--- a/intern/ghost/test/gears/GHOST_Test.cpp
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -54,7 +54,7 @@
static bool nVidiaWindows; // very dirty but hey, it's for testing only
-static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 time);
+static void gearsTimerProc(GHOST_ITimerTask *task, uint64_t time);
static class Application *fApp;
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
@@ -71,7 +71,7 @@ void StereoProjection(float left,
float dist,
float eye);
-static void testTimerProc(GHOST_ITimerTask * /*task*/, GHOST_TUns64 time)
+static void testTimerProc(GHOST_ITimerTask * /*task*/, uint64_t time)
{
std::cout << "timer1, time=" << (int)time << "\n";
}
@@ -345,7 +345,7 @@ void StereoProjection(float left,
float zero_plane,
float dist,
float eye)
-/* Perform the perspective projection for one eye's subfield.
+/* Perform the perspective projection for one eye's sub-field.
* The projection is in the direction of the negative z axis.
*
* -6.0, 6.0, -4.8, 4.8,
@@ -365,8 +365,8 @@ void StereoProjection(float left,
* of zero parallax.
*
* -0.31
- * eye = half the eye separation; positive for the right eye subfield,
- * negative for the left eye subfield.
+ * eye = half the eye separation; positive for the right eye sub-field,
+ * negative for the left eye sub-field.
*/
{
float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw, dx, dy, n_over_d;
@@ -392,8 +392,7 @@ void StereoProjection(float left,
glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far);
glTranslatef(-xmid - eye, -ymid, -zero_plane - dist);
- return;
-} /* stereoproj */
+}
class Application : public GHOST_IEventConsumer {
public:
@@ -731,7 +730,7 @@ int main(int /*argc*/, char ** /*argv*/)
return 0;
}
-static void gearsTimerProc(GHOST_ITimerTask *task, GHOST_TUns64 /*time*/)
+static void gearsTimerProc(GHOST_ITimerTask *task, uint64_t /*time*/)
{
fAngle += 2.0;
view_roty += 1.0;
diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c
index 788c0221753..44ea07bd880 100644
--- a/intern/ghost/test/multitest/EventToBuf.c
+++ b/intern/ghost/test/multitest/EventToBuf.c
@@ -203,7 +203,7 @@ static char *keytype_to_string(GHOST_TKey key)
void event_to_buf(GHOST_EventHandle evt, char buf[128])
{
GHOST_TEventType type = GHOST_GetEventType(evt);
- double time = (double)((GHOST_TInt64)GHOST_GetEventTime(evt)) / 1000;
+ double time = (double)((int64_t)GHOST_GetEventTime(evt)) / 1000;
GHOST_WindowHandle win = GHOST_GetEventWindow(evt);
void *data = GHOST_GetEventData(evt);
char *pos = buf;
diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c
index ccbbbceb5b6..0e6602d9510 100644
--- a/intern/ghost/test/multitest/MultiTest.c
+++ b/intern/ghost/test/multitest/MultiTest.c
@@ -302,12 +302,12 @@ static void mainwindow_handle(void *priv, GHOST_EventHandle evt)
/**/
-static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time)
+static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, uint64_t time)
{
MainWindow *mw = GHOST_GetTimerTaskUserData(task);
char buf[64];
- sprintf(buf, "timer: %6.2f", (double)((GHOST_TInt64)time) / 1000);
+ sprintf(buf, "timer: %6.2f", (double)((int64_t)time) / 1000);
mainwindow_log(mw, buf);
}
@@ -570,7 +570,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
- GHOST_TUns32 screensize[2];
+ uint32_t screensize[2];
GHOST_WindowHandle win;
GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]);
@@ -701,11 +701,11 @@ static void extrawindow_do_key(ExtraWindow *ew, GHOST_TKey key, int press)
}
}
-static void extrawindow_spin_cursor(ExtraWindow *ew, GHOST_TUns64 time)
+static void extrawindow_spin_cursor(ExtraWindow *ew, uint64_t time)
{
- GHOST_TUns8 bitmap[16][2];
- GHOST_TUns8 mask[16][2];
- double ftime = (double)((GHOST_TInt64)time) / 1000;
+ uint8_t bitmap[16][2];
+ uint8_t mask[16][2];
+ double ftime = (double)((int64_t)time) / 1000;
float angle = fmod(ftime, 1.0) * 3.1415 * 2;
int i;
diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h
index aa956150484..e4bd3d533a3 100644
--- a/intern/guardedalloc/intern/mallocn_intern.h
+++ b/intern/guardedalloc/intern/mallocn_intern.h
@@ -53,14 +53,8 @@ size_t malloc_usable_size(void *ptr);
# undef USE_MALLOC_USABLE_SIZE
#endif
-/* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */
-#if defined(WIN64)
-# define SIZET_FORMAT "%I64u"
-# define SIZET_ARG(a) ((unsigned long long)(a))
-#else
-# define SIZET_FORMAT "%lu"
-# define SIZET_ARG(a) ((unsigned long)(a))
-#endif
+#define SIZET_FORMAT "%zu"
+#define SIZET_ARG(a) ((size_t)(a))
#define SIZET_ALIGN_4(len) ((len + 3) & ~(size_t)3)
diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h
index e3d44226338..e3ebdb5a4bb 100644
--- a/intern/libmv/libmv/numeric/numeric.h
+++ b/intern/libmv/libmv/numeric/numeric.h
@@ -43,7 +43,7 @@ inline void sincos(double x, double* sinx, double* cosx) {
# endif
#endif // !__MINGW64__
-#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__)
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
inline long lround(double d) {
return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
}
diff --git a/intern/libmv/libmv/tracking/retrack_region_tracker.cc b/intern/libmv/libmv/tracking/retrack_region_tracker.cc
index 9152078053c..124a032cdff 100644
--- a/intern/libmv/libmv/tracking/retrack_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/retrack_region_tracker.cc
@@ -37,7 +37,7 @@ bool RetrackRegionTracker::Track(const FloatImage& image1,
}
// Now track x2 and y2 backward, to get xx1 and yy1 which, if the track is
// good, should match x1 and y1 (but may not if the track is bad).
- double xx1 = *x2, yy1 = *x2;
+ double xx1 = *x2, yy1 = *y2;
if (!tracker_->Track(image2, image1, *x2, *y2, &xx1, &yy1)) {
return false;
}
diff --git a/intern/numaapi/source/build_config.h b/intern/numaapi/source/build_config.h
index fdd6ff704c3..49d82aa3e87 100644
--- a/intern/numaapi/source/build_config.h
+++ b/intern/numaapi/source/build_config.h
@@ -324,6 +324,16 @@
# define ARCH_CPU_ARM64 1
# define ARCH_CPU_64_BITS 1
# define ARCH_CPU_LITTLE_ENDIAN 1
+#elif defined(__riscv) && __riscv_xlen == 32
+# define ARCH_CPU_RISCV_FAMILY 1
+# define ARCH_CPU_RISCV32 1
+# define ARCH_CPU_64_BITS 0
+# define ARCH_CPU_LITTLE_ENDIAN 1
+#elif defined(__riscv) && __riscv_xlen == 64
+# define ARCH_CPU_RISCV_FAMILY 1
+# define ARCH_CPU_RISCV64 1
+# define ARCH_CPU_64_BITS 1
+# define ARCH_CPU_LITTLE_ENDIAN 1
#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__)
# define ARCH_CPU_32_BITS 1
# define ARCH_CPU_LITTLE_ENDIAN 1
@@ -381,6 +391,9 @@
#if !defined(ARCH_CPU_PPC64_FAMILY)
# define ARCH_CPU_PPC64_FAMILY 0
#endif
+#if !defined(ARCH_CPU_RISCV_FAMILY)
+# define ARCH_CPU_RISCV_FAMILY 0
+#endif
#if !defined(ARCH_CPU_S390_FAMILY)
# define ARCH_CPU_S390_FAMILY 0
#endif
diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py
index 28b8aa9b23e..95e1c873657 100644
--- a/release/scripts/freestyle/modules/freestyle/shaders.py
+++ b/release/scripts/freestyle/modules/freestyle/shaders.py
@@ -1153,11 +1153,9 @@ class RoundCapShader(StrokeShader):
return
# calculate the number of additional vertices to form caps
thickness_beg = sum(stroke[0].attribute.thickness)
- caplen_beg = thickness_beg / 2.0
nverts_beg = max(5, int(thickness_beg))
thickness_end = sum(stroke[-1].attribute.thickness)
- caplen_end = (thickness_end) / 2.0
nverts_end = max(5, int(thickness_end))
# adjust the total number of stroke vertices
@@ -1169,7 +1167,7 @@ class RoundCapShader(StrokeShader):
# reshape the cap at the beginning of the stroke
q, attr = buffer[1]
p, attr = buffer[0]
- direction = (p - q).normalized() * caplen_beg
+ direction = (p - q).normalized() * thickness_beg
n = 1.0 / nverts_beg
R, L = attr.thickness
for t, svert in zip(range(nverts_beg, 0, -1), stroke):
@@ -1180,7 +1178,7 @@ class RoundCapShader(StrokeShader):
# reshape the cap at the end of the stroke
q, attr = buffer[-2]
p, attr = buffer[-1]
- direction = (p - q).normalized() * caplen_beg
+ direction = (p - q).normalized() * thickness_end
n = 1.0 / nverts_end
R, L = attr.thickness
for t, svert in zip(range(nverts_end, 0, -1), reversed(stroke)):
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index f63b6990cdd..fda93682dc5 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -781,7 +781,6 @@ class I18nMessages:
print("Could not import bpy, find_best_messages_matches must be run from whithin Blender.")
return
-
# Build helper mappings.
# Note it's user responsibility to know when to invalidate (and hence force rebuild) this cache!
if self._reverse_cache is None:
diff --git a/release/scripts/modules/bl_i18n_utils/utils_cli.py b/release/scripts/modules/bl_i18n_utils/utils_cli.py
index d3750d5e9a4..e18491fa042 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_cli.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_cli.py
@@ -140,6 +140,7 @@ def main():
args.func(args=args, settings=settings)
+
if __name__ == "__main__":
print("\n\n *** Running {} *** \n".format(__file__))
main()
diff --git a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
index aff1108568b..26f38cf09fc 100644
--- a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
+++ b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
@@ -449,6 +449,5 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
)
kmi.properties.skip_depressed = True
-
wm.keyconfigs.update()
return keymap
diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
index 51ea53c0eba..17577a9a9f2 100644
--- a/release/scripts/modules/bl_previews_utils/bl_previews_render.py
+++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
@@ -37,6 +37,7 @@ OBJECT_TYPES_RENDER = {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}
def ids_nolib(bids):
return (bid for bid in bids if not bid.library)
+
def ids_nolib_with_preview(bids):
return (bid for bid in bids if (not bid.library and bid.preview))
diff --git a/release/scripts/modules/bl_rna_utils/data_path.py b/release/scripts/modules/bl_rna_utils/data_path.py
index 42942b7a295..439dfcae12a 100644
--- a/release/scripts/modules/bl_rna_utils/data_path.py
+++ b/release/scripts/modules/bl_rna_utils/data_path.py
@@ -23,6 +23,7 @@ __all__ = (
"decompose_data_path",
)
+
class _TokenizeDataPath:
"""
Class to split up tokens of a data-path.
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index e6c7bca3e3c..58b20d9e3c8 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -155,6 +155,7 @@ def _test_import(module_name, loaded_modules):
# This supports the case of loading a new preferences file which may reset scripts path.
_sys_path_ensure_paths = set()
+
def _sys_path_ensure_prepend(path):
if path not in _sys.path:
_sys.path.insert(0, path)
diff --git a/release/scripts/modules/bpy_extras/asset_utils.py b/release/scripts/modules/bpy_extras/asset_utils.py
index 1656c21a137..2cd5dddefbc 100644
--- a/release/scripts/modules/bpy_extras/asset_utils.py
+++ b/release/scripts/modules/bpy_extras/asset_utils.py
@@ -31,6 +31,7 @@ __all__ = (
"SpaceAssetInfo",
)
+
class SpaceAssetInfo:
@classmethod
def is_asset_browser(cls, space_data: bpy.types.Space):
@@ -46,6 +47,7 @@ class SpaceAssetInfo:
active_file = context.active_file
return active_file.asset_data if active_file else None
+
class AssetBrowserPanel:
bl_space_type = 'FILE_BROWSER'
@@ -53,6 +55,18 @@ class AssetBrowserPanel:
def poll(cls, context):
return SpaceAssetInfo.is_asset_browser_poll(context)
+
+class AssetBrowserSpecificCategoryPanel(AssetBrowserPanel):
+ asset_categories = set() # Set of strings like 'ANIMATIONS', see `asset_category_items` in rna_space.c
+
+ @classmethod
+ def poll(cls, context):
+ return (
+ SpaceAssetInfo.is_asset_browser_poll(context)
+ and context.space_data.params.asset_category in cls.asset_categories
+ )
+
+
class AssetMetaDataPanel:
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'TOOL_PROPS'
diff --git a/release/scripts/modules/bpy_extras/node_shader_utils.py b/release/scripts/modules/bpy_extras/node_shader_utils.py
index 54124fd4ca6..e37c1a17152 100644
--- a/release/scripts/modules/bpy_extras/node_shader_utils.py
+++ b/release/scripts/modules/bpy_extras/node_shader_utils.py
@@ -681,7 +681,10 @@ class ShaderImageTextureWrapper():
tree = self.owner_shader.material.node_tree
node_image = tree.nodes.new(type='ShaderNodeTexImage')
- self.owner_shader._grid_to_location(-1, 0 + self.grid_row_diff, dst_node=node_image, ref_node=self.node_dst)
+ self.owner_shader._grid_to_location(
+ -1, 0 + self.grid_row_diff,
+ dst_node=node_image, ref_node=self.node_dst,
+ )
tree.links.new(node_image.outputs["Alpha" if self.use_alpha else "Color"], self.socket_dst)
if self.use_alpha:
@@ -778,7 +781,7 @@ class ShaderImageTextureWrapper():
socket_dst = self.node_image.inputs["Vector"]
# If not already existing, we need to create texcoords -> mapping link (from UV).
socket_src = (socket_dst.links[0].from_socket if socket_dst.is_linked
- else self.owner_shader.node_texcoords.outputs['UV'])
+ else self.owner_shader.node_texcoords.outputs['UV'])
tree = self.owner_shader.material.node_tree
node_mapping = tree.nodes.new(type='ShaderNodeMapping')
diff --git a/release/scripts/modules/console/complete_calltip.py b/release/scripts/modules/console/complete_calltip.py
index 706af67905b..60daa1d2045 100644
--- a/release/scripts/modules/console/complete_calltip.py
+++ b/release/scripts/modules/console/complete_calltip.py
@@ -41,7 +41,7 @@ RE_DEF_COMPLETE = re.compile(
# allow empty string
'''|)'''
# allow opening bracket(s)
- '''(?:\(|\s)*)$''')
+ r'''(?:\(|\s)*)$''')
def reduce_newlines(text):
diff --git a/release/scripts/presets/camera/1_inch.py b/release/scripts/presets/camera/1_inch.py
index 72b039fb978..97e87b8c5a7 100644
--- a/release/scripts/presets/camera/1_inch.py
+++ b/release/scripts/presets/camera/1_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 13.2
bpy.context.camera.sensor_height = 8.80
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/1_slash_1.8_inch.py b/release/scripts/presets/camera/1_slash_1.8_inch.py
index 38e09182de6..8b0dc3cea1d 100644
--- a/release/scripts/presets/camera/1_slash_1.8_inch.py
+++ b/release/scripts/presets/camera/1_slash_1.8_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 7.18
bpy.context.camera.sensor_height = 5.32
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/1_slash_2.3_inch.py b/release/scripts/presets/camera/1_slash_2.3_inch.py
index 4d55738f4ed..bd6808da082 100644
--- a/release/scripts/presets/camera/1_slash_2.3_inch.py
+++ b/release/scripts/presets/camera/1_slash_2.3_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 6.17
bpy.context.camera.sensor_height = 4.55
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/1_slash_2.5_inch.py b/release/scripts/presets/camera/1_slash_2.5_inch.py
index cbdb6f3cbe0..90f60e7d7f0 100644
--- a/release/scripts/presets/camera/1_slash_2.5_inch.py
+++ b/release/scripts/presets/camera/1_slash_2.5_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 5.76
bpy.context.camera.sensor_height = 4.29
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/1_slash_2.7_inch.py b/release/scripts/presets/camera/1_slash_2.7_inch.py
index 5ccfa4ab555..4a9591803d0 100644
--- a/release/scripts/presets/camera/1_slash_2.7_inch.py
+++ b/release/scripts/presets/camera/1_slash_2.7_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 5.37
bpy.context.camera.sensor_height = 4.04
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/1_slash_3.2_inch.py b/release/scripts/presets/camera/1_slash_3.2_inch.py
index 1963f7ec048..5f31b9ec49c 100644
--- a/release/scripts/presets/camera/1_slash_3.2_inch.py
+++ b/release/scripts/presets/camera/1_slash_3.2_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 4.54
bpy.context.camera.sensor_height = 3.42
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/2_slash_3_inch.py b/release/scripts/presets/camera/2_slash_3_inch.py
index 25b46016800..eb463a31af7 100644
--- a/release/scripts/presets/camera/2_slash_3_inch.py
+++ b/release/scripts/presets/camera/2_slash_3_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 8.8
bpy.context.camera.sensor_height = 6.6
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/APS-C.py b/release/scripts/presets/camera/APS-C.py
index 84e40825248..4031e8bae71 100644
--- a/release/scripts/presets/camera/APS-C.py
+++ b/release/scripts/presets/camera/APS-C.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 23.6
bpy.context.camera.sensor_height = 15.6
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/APS-C_(Canon).py b/release/scripts/presets/camera/APS-C_(Canon).py
index 55f20ce0eac..484929a54e7 100644
--- a/release/scripts/presets/camera/APS-C_(Canon).py
+++ b/release/scripts/presets/camera/APS-C_(Canon).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 22.30
bpy.context.camera.sensor_height = 14.90
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/APS-H_(Canon).py b/release/scripts/presets/camera/APS-H_(Canon).py
index d63f733280b..d3b61d1aa46 100644
--- a/release/scripts/presets/camera/APS-H_(Canon).py
+++ b/release/scripts/presets/camera/APS-H_(Canon).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 27.90
bpy.context.camera.sensor_height = 18.60
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Analog_16mm.py b/release/scripts/presets/camera/Analog_16mm.py
index aa98eaf2408..a290839c8e0 100644
--- a/release/scripts/presets/camera/Analog_16mm.py
+++ b/release/scripts/presets/camera/Analog_16mm.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 10.26
bpy.context.camera.sensor_height = 7.49
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Analog_35mm.py b/release/scripts/presets/camera/Analog_35mm.py
index a0dee1f0166..fe3338dd292 100644
--- a/release/scripts/presets/camera/Analog_35mm.py
+++ b/release/scripts/presets/camera/Analog_35mm.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 22
bpy.context.camera.sensor_height = 16
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Analog_65mm.py b/release/scripts/presets/camera/Analog_65mm.py
index 8de91ac0ee3..d6eb9c32283 100644
--- a/release/scripts/presets/camera/Analog_65mm.py
+++ b/release/scripts/presets/camera/Analog_65mm.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 52.45
bpy.context.camera.sensor_height = 23.01
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Analog_IMAX.py b/release/scripts/presets/camera/Analog_IMAX.py
index 5a445f3de8c..b71b910dee0 100644
--- a/release/scripts/presets/camera/Analog_IMAX.py
+++ b/release/scripts/presets/camera/Analog_IMAX.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 71.41
bpy.context.camera.sensor_height = 52.63
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Analog_Super_16.py b/release/scripts/presets/camera/Analog_Super_16.py
index a340a31dc25..f76238c69d3 100644
--- a/release/scripts/presets/camera/Analog_Super_16.py
+++ b/release/scripts/presets/camera/Analog_Super_16.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 12.35
bpy.context.camera.sensor_height = 7.42
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Analog_Super_35.py b/release/scripts/presets/camera/Analog_Super_35.py
index 3c8f1837253..b22ff545c68 100644
--- a/release/scripts/presets/camera/Analog_Super_35.py
+++ b/release/scripts/presets/camera/Analog_Super_35.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 24.89
bpy.context.camera.sensor_height = 18.66
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Arri_Alexa_65.py b/release/scripts/presets/camera/Arri_Alexa_65.py
index b1467709949..24d03e022ae 100644
--- a/release/scripts/presets/camera/Arri_Alexa_65.py
+++ b/release/scripts/presets/camera/Arri_Alexa_65.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 54.12
bpy.context.camera.sensor_height = 25.58
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Arri_Alexa_LF.py b/release/scripts/presets/camera/Arri_Alexa_LF.py
index 1cde94fce8d..430fdc996a6 100644
--- a/release/scripts/presets/camera/Arri_Alexa_LF.py
+++ b/release/scripts/presets/camera/Arri_Alexa_LF.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 36.70
bpy.context.camera.sensor_height = 25.54
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py b/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py
index 0f61d35a0f9..90998bc0da0 100644
--- a/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py
+++ b/release/scripts/presets/camera/Arri_Alexa_Mini_&_SXT.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 29.90
bpy.context.camera.sensor_height = 15.77
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py b/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py
index 260bfbaf94f..bb2b172919e 100644
--- a/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py
+++ b/release/scripts/presets/camera/Blackmagic_Pocket_&_Studio.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 12.48
bpy.context.camera.sensor_height = 7.02
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_4K.py b/release/scripts/presets/camera/Blackmagic_Pocket_4K.py
index dc057397828..4b735283c8b 100644
--- a/release/scripts/presets/camera/Blackmagic_Pocket_4K.py
+++ b/release/scripts/presets/camera/Blackmagic_Pocket_4K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 18.96
bpy.context.camera.sensor_height = 10.00
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_Pocket_6k.py b/release/scripts/presets/camera/Blackmagic_Pocket_6k.py
index a483f3d5f98..1a882f05786 100644
--- a/release/scripts/presets/camera/Blackmagic_Pocket_6k.py
+++ b/release/scripts/presets/camera/Blackmagic_Pocket_6k.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 23.10
bpy.context.camera.sensor_height = 12.99
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py b/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py
index c71e42d72d3..767d16984d8 100644
--- a/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py
+++ b/release/scripts/presets/camera/Blackmagic_URSA_4.6K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 25.34
bpy.context.camera.sensor_height = 14.25
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Foveon_(Sigma).py b/release/scripts/presets/camera/Foveon_(Sigma).py
index e6a1a0ed344..6b35f29acaf 100644
--- a/release/scripts/presets/camera/Foveon_(Sigma).py
+++ b/release/scripts/presets/camera/Foveon_(Sigma).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 20.70
bpy.context.camera.sensor_height = 13.80
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Fullframe.py b/release/scripts/presets/camera/Fullframe.py
index 95fb4afc10b..c8017331b28 100644
--- a/release/scripts/presets/camera/Fullframe.py
+++ b/release/scripts/presets/camera/Fullframe.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 36
bpy.context.camera.sensor_height = 24
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/MFT.py b/release/scripts/presets/camera/MFT.py
index bc0dd49baa8..7441f1aea76 100644
--- a/release/scripts/presets/camera/MFT.py
+++ b/release/scripts/presets/camera/MFT.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 17.3
bpy.context.camera.sensor_height = 13.0
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/Medium-format_(Hasselblad).py b/release/scripts/presets/camera/Medium-format_(Hasselblad).py
index e9b16024b79..d03a4f22db7 100644
--- a/release/scripts/presets/camera/Medium-format_(Hasselblad).py
+++ b/release/scripts/presets/camera/Medium-format_(Hasselblad).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 44
bpy.context.camera.sensor_height = 33
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/RED_Dragon_5K.py b/release/scripts/presets/camera/RED_Dragon_5K.py
index fa95a98f8c4..e8b990d4d00 100644
--- a/release/scripts/presets/camera/RED_Dragon_5K.py
+++ b/release/scripts/presets/camera/RED_Dragon_5K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 25.60
bpy.context.camera.sensor_height = 13.5
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/RED_Dragon_6K.py b/release/scripts/presets/camera/RED_Dragon_6K.py
index 80f7ad1bbb8..982e2ab8e00 100644
--- a/release/scripts/presets/camera/RED_Dragon_6K.py
+++ b/release/scripts/presets/camera/RED_Dragon_6K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 30.70
bpy.context.camera.sensor_height = 15.80
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/RED_Helium_8K.py b/release/scripts/presets/camera/RED_Helium_8K.py
index 0f61d35a0f9..90998bc0da0 100644
--- a/release/scripts/presets/camera/RED_Helium_8K.py
+++ b/release/scripts/presets/camera/RED_Helium_8K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 29.90
bpy.context.camera.sensor_height = 15.77
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/camera/RED_Monstro_8K.py b/release/scripts/presets/camera/RED_Monstro_8K.py
index 86c382624ab..1c8bc11dfaa 100644
--- a/release/scripts/presets/camera/RED_Monstro_8K.py
+++ b/release/scripts/presets/camera/RED_Monstro_8K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 40.96
bpy.context.camera.sensor_height = 21.60
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/keyconfig/Blender.py b/release/scripts/presets/keyconfig/Blender.py
index 222ee43432f..eb66c961472 100644
--- a/release/scripts/presets/keyconfig/Blender.py
+++ b/release/scripts/presets/keyconfig/Blender.py
@@ -103,8 +103,8 @@ class Prefs(bpy.types.KeyConfigPreferences):
v3d_tilde_action: EnumProperty(
name="Tilde Action",
items=(
- ('OBJECT_SWITCH', "Object Switch",
- "Switch the active object under the cursor (when not in object mode)",
+ ('VIEW', "Navigate",
+ "View operations (useful for keyboards without a numpad)",
0),
('GIZMO', "Gizmos",
"Control transform gizmos",
@@ -113,7 +113,7 @@ class Prefs(bpy.types.KeyConfigPreferences):
description=(
"Action when 'Tilde' is pressed"
),
- default='OBJECT_SWITCH',
+ default='VIEW',
update=update_fn,
)
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 7f1039a975b..3527e993173 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -730,6 +730,8 @@ def km_user_interface(_params):
("anim.keyingset_button_add", {"type": 'K', "value": 'PRESS'}, None),
("anim.keyingset_button_remove", {"type": 'K', "value": 'PRESS', "alt": True}, None),
("ui.reset_default_button", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("all", True)]}),
+ # UI lists (polls check if there's a UI list under the cursor).
+ ("ui.list_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
])
return keymap
@@ -1084,7 +1086,13 @@ def km_view3d(params):
{"properties": [("use_all_regions", True), ("center", False)]}),
("view3d.view_all", {"type": 'C', "value": 'PRESS', "shift": True},
{"properties": [("center", True)]}),
- op_menu_pie("VIEW3D_MT_view_pie", {"type": 'D', "value": 'CLICK_DRAG'}),
+ op_menu_pie(
+ "VIEW3D_MT_view_pie" if params.v3d_tilde_action == 'VIEW' else "VIEW3D_MT_transform_gizmo_pie",
+ {"type": 'ACCENT_GRAVE', "value": params.pie_value},
+ ),
+ *(() if not params.use_pie_click_drag else
+ (("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'CLICK'}, None),)),
+ ("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "shift": True}, None),
("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "shift": True}, None),
# Numpad views.
("view3d.view_camera", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
@@ -1328,32 +1336,6 @@ def km_view3d(params):
op_tool_cycle("builtin.select_box", {"type": 'W', "value": 'PRESS'}),
])
- # Tilda key.
- if params.use_pie_click_drag:
- items.extend([
- ("object.transfer_mode",
- {"type": 'ACCENT_GRAVE', "value": 'CLICK' if params.use_pie_click_drag else 'PRESS'},
- None),
- op_menu_pie(
- "VIEW3D_MT_transform_gizmo_pie",
- {"type": 'ACCENT_GRAVE', "value": 'CLICK_DRAG'},
- )
- ])
- else:
- if params.v3d_tilde_action == 'OBJECT_SWITCH':
- items.append(
- ("object.transfer_mode",
- {"type": 'ACCENT_GRAVE', "value": 'PRESS'},
- {"properties": [("use_eyedropper", False)]})
- )
- else:
- items.append(
- op_menu_pie(
- "VIEW3D_MT_transform_gizmo_pie",
- {"type": 'ACCENT_GRAVE', "value": 'PRESS'},
- )
- )
-
return keymap
@@ -2679,7 +2661,8 @@ def km_sequencer(params):
{"properties": [("side", 'LEFT')]}),
("sequencer.select_side_of_frame", {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
{"properties": [("side", 'RIGHT')]}),
-
+ ("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
+ {"properties": [("data_path", 'tool_settings.use_snap_sequencer')]}),
*_template_items_context_menu("SEQUENCER_MT_context_menu", params.context_menu_event),
])
@@ -4113,7 +4096,7 @@ def km_pose(params):
("pose.bone_layers", {"type": 'M', "value": 'PRESS'}, None),
("transform.bbone_resize", {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True}, None),
("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None),
- ("anim.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None),
("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
("poselib.browse_interactive", {"type": 'L', "value": 'PRESS', "alt": True}, None),
("poselib.pose_add", {"type": 'L', "value": 'PRESS', "shift": True}, None),
@@ -4185,7 +4168,7 @@ def km_object_mode(params):
("wm.context_toggle", {"type": 'PERIOD', "value": 'PRESS', "ctrl": True},
{"properties": [("data_path", 'tool_settings.use_transform_data_origin')]}),
("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None),
- ("anim.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None),
("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
("collection.create", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
("collection.objects_remove", {"type": 'G', "value": 'PRESS', "ctrl": True, "alt": True}, None),
@@ -5071,6 +5054,11 @@ def km_object_non_modal(params):
("object.origin_set", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
])
else:
+ items.extend([
+ # NOTE: this shortcut (while not temporary) is not ideal, see: T89757.
+ ("object.transfer_mode", {"type": 'Q', "value": 'PRESS', "alt": True}, None),
+ ])
+
if params.use_pie_click_drag:
items.extend([
("object.mode_set", {"type": 'TAB', "value": 'CLICK'},
@@ -5551,6 +5539,7 @@ def km_view3d_walk_modal(_params):
("DECELERATE", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "any": True, "repeat": True}, None),
("ACCELERATE", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "any": True}, None),
("DECELERATE", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "any": True}, None),
+ ("AXIS_LOCK_Z", {"type": 'Z', "value": 'PRESS'}, None),
])
return keymap
diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
index b0144672745..714126903d8 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -3015,7 +3015,7 @@ def km_pose(params):
("anim.keyframe_insert_by_name", {"type": 'R', "value": 'PRESS', "shift": True},
{"properties": [("type", 'Scaling')]}),
- ("anim.keyframe_delete", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("anim.keyframe_delete_v3d", {"type": 'S', "value": 'PRESS', "alt": True}, None),
("anim.keying_set_active_set", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
*_template_items_context_menu("VIEW3D_MT_pose_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
# Tools
@@ -3086,7 +3086,7 @@ def km_object_mode(params):
{"properties": [("type", 'Rotation')]}),
("anim.keyframe_insert_by_name", {"type": 'R', "value": 'PRESS', "shift": True},
{"properties": [("type", 'Scaling')]}),
- ("anim.keyframe_delete", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("anim.keyframe_delete_v3d", {"type": 'S', "value": 'PRESS', "alt": True}, None),
("anim.keying_set_active_set", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
*_template_items_context_menu("VIEW3D_MT_object_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("object.move_to_collection", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
diff --git a/release/scripts/presets/tracking_camera/1_inch.py b/release/scripts/presets/tracking_camera/1_inch.py
index 72b039fb978..97e87b8c5a7 100644
--- a/release/scripts/presets/tracking_camera/1_inch.py
+++ b/release/scripts/presets/tracking_camera/1_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 13.2
bpy.context.camera.sensor_height = 8.80
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py b/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py
index 38e09182de6..8b0dc3cea1d 100644
--- a/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py
+++ b/release/scripts/presets/tracking_camera/1_slash_1.8_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 7.18
bpy.context.camera.sensor_height = 5.32
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py b/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py
index 4d55738f4ed..bd6808da082 100644
--- a/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py
+++ b/release/scripts/presets/tracking_camera/1_slash_2.3_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 6.17
bpy.context.camera.sensor_height = 4.55
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py b/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py
index cbdb6f3cbe0..90f60e7d7f0 100644
--- a/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py
+++ b/release/scripts/presets/tracking_camera/1_slash_2.5_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 5.76
bpy.context.camera.sensor_height = 4.29
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py b/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py
index 5ccfa4ab555..4a9591803d0 100644
--- a/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py
+++ b/release/scripts/presets/tracking_camera/1_slash_2.7_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 5.37
bpy.context.camera.sensor_height = 4.04
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py b/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py
index 1963f7ec048..5f31b9ec49c 100644
--- a/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py
+++ b/release/scripts/presets/tracking_camera/1_slash_3.2_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 4.54
bpy.context.camera.sensor_height = 3.42
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/2_slash_3_inch.py b/release/scripts/presets/tracking_camera/2_slash_3_inch.py
index 25b46016800..eb463a31af7 100644
--- a/release/scripts/presets/tracking_camera/2_slash_3_inch.py
+++ b/release/scripts/presets/tracking_camera/2_slash_3_inch.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 8.8
bpy.context.camera.sensor_height = 6.6
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/APS-C.py b/release/scripts/presets/tracking_camera/APS-C.py
index 84e40825248..4031e8bae71 100644
--- a/release/scripts/presets/tracking_camera/APS-C.py
+++ b/release/scripts/presets/tracking_camera/APS-C.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 23.6
bpy.context.camera.sensor_height = 15.6
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/APS-C_(Canon).py b/release/scripts/presets/tracking_camera/APS-C_(Canon).py
index 55f20ce0eac..484929a54e7 100644
--- a/release/scripts/presets/tracking_camera/APS-C_(Canon).py
+++ b/release/scripts/presets/tracking_camera/APS-C_(Canon).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 22.30
bpy.context.camera.sensor_height = 14.90
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/APS-H_(Canon).py b/release/scripts/presets/tracking_camera/APS-H_(Canon).py
index d63f733280b..d3b61d1aa46 100644
--- a/release/scripts/presets/tracking_camera/APS-H_(Canon).py
+++ b/release/scripts/presets/tracking_camera/APS-H_(Canon).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 27.90
bpy.context.camera.sensor_height = 18.60
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Analog_16mm.py b/release/scripts/presets/tracking_camera/Analog_16mm.py
index aa98eaf2408..a290839c8e0 100644
--- a/release/scripts/presets/tracking_camera/Analog_16mm.py
+++ b/release/scripts/presets/tracking_camera/Analog_16mm.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 10.26
bpy.context.camera.sensor_height = 7.49
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Analog_35mm.py b/release/scripts/presets/tracking_camera/Analog_35mm.py
index a0dee1f0166..fe3338dd292 100644
--- a/release/scripts/presets/tracking_camera/Analog_35mm.py
+++ b/release/scripts/presets/tracking_camera/Analog_35mm.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 22
bpy.context.camera.sensor_height = 16
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Analog_65mm.py b/release/scripts/presets/tracking_camera/Analog_65mm.py
index 8de91ac0ee3..d6eb9c32283 100644
--- a/release/scripts/presets/tracking_camera/Analog_65mm.py
+++ b/release/scripts/presets/tracking_camera/Analog_65mm.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 52.45
bpy.context.camera.sensor_height = 23.01
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Analog_IMAX.py b/release/scripts/presets/tracking_camera/Analog_IMAX.py
index 5a445f3de8c..b71b910dee0 100644
--- a/release/scripts/presets/tracking_camera/Analog_IMAX.py
+++ b/release/scripts/presets/tracking_camera/Analog_IMAX.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 71.41
bpy.context.camera.sensor_height = 52.63
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Analog_Super_16.py b/release/scripts/presets/tracking_camera/Analog_Super_16.py
index a340a31dc25..f76238c69d3 100644
--- a/release/scripts/presets/tracking_camera/Analog_Super_16.py
+++ b/release/scripts/presets/tracking_camera/Analog_Super_16.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 12.35
bpy.context.camera.sensor_height = 7.42
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Analog_Super_35.py b/release/scripts/presets/tracking_camera/Analog_Super_35.py
index 3c8f1837253..b22ff545c68 100644
--- a/release/scripts/presets/tracking_camera/Analog_Super_35.py
+++ b/release/scripts/presets/tracking_camera/Analog_Super_35.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 24.89
bpy.context.camera.sensor_height = 18.66
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Arri_Alexa_65.py b/release/scripts/presets/tracking_camera/Arri_Alexa_65.py
index b1467709949..24d03e022ae 100644
--- a/release/scripts/presets/tracking_camera/Arri_Alexa_65.py
+++ b/release/scripts/presets/tracking_camera/Arri_Alexa_65.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 54.12
bpy.context.camera.sensor_height = 25.58
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py b/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py
index 1cde94fce8d..430fdc996a6 100644
--- a/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py
+++ b/release/scripts/presets/tracking_camera/Arri_Alexa_LF.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 36.70
bpy.context.camera.sensor_height = 25.54
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py b/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py
index 0f61d35a0f9..90998bc0da0 100644
--- a/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py
+++ b/release/scripts/presets/tracking_camera/Arri_Alexa_Mini_&_SXT.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 29.90
bpy.context.camera.sensor_height = 15.77
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py
index 260bfbaf94f..bb2b172919e 100644
--- a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py
+++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_&_Studio.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 12.48
bpy.context.camera.sensor_height = 7.02
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py
index dc057397828..4b735283c8b 100644
--- a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py
+++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_4K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 18.96
bpy.context.camera.sensor_height = 10.00
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py
index a483f3d5f98..1a882f05786 100644
--- a/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py
+++ b/release/scripts/presets/tracking_camera/Blackmagic_Pocket_6k.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 23.10
bpy.context.camera.sensor_height = 12.99
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py b/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py
index c71e42d72d3..767d16984d8 100644
--- a/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py
+++ b/release/scripts/presets/tracking_camera/Blackmagic_URSA_4.6K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 25.34
bpy.context.camera.sensor_height = 14.25
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Foveon_(Sigma).py b/release/scripts/presets/tracking_camera/Foveon_(Sigma).py
index e6a1a0ed344..6b35f29acaf 100644
--- a/release/scripts/presets/tracking_camera/Foveon_(Sigma).py
+++ b/release/scripts/presets/tracking_camera/Foveon_(Sigma).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 20.70
bpy.context.camera.sensor_height = 13.80
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Fullframe.py b/release/scripts/presets/tracking_camera/Fullframe.py
index 95fb4afc10b..c8017331b28 100644
--- a/release/scripts/presets/tracking_camera/Fullframe.py
+++ b/release/scripts/presets/tracking_camera/Fullframe.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 36
bpy.context.camera.sensor_height = 24
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/MFT.py b/release/scripts/presets/tracking_camera/MFT.py
index bc0dd49baa8..7441f1aea76 100644
--- a/release/scripts/presets/tracking_camera/MFT.py
+++ b/release/scripts/presets/tracking_camera/MFT.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 17.3
bpy.context.camera.sensor_height = 13.0
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py b/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py
index e9b16024b79..d03a4f22db7 100644
--- a/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py
+++ b/release/scripts/presets/tracking_camera/Medium-format_(Hasselblad).py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 44
bpy.context.camera.sensor_height = 33
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/RED_Dragon_5K.py b/release/scripts/presets/tracking_camera/RED_Dragon_5K.py
index fa95a98f8c4..e8b990d4d00 100644
--- a/release/scripts/presets/tracking_camera/RED_Dragon_5K.py
+++ b/release/scripts/presets/tracking_camera/RED_Dragon_5K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 25.60
bpy.context.camera.sensor_height = 13.5
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/RED_Dragon_6K.py b/release/scripts/presets/tracking_camera/RED_Dragon_6K.py
index 80f7ad1bbb8..982e2ab8e00 100644
--- a/release/scripts/presets/tracking_camera/RED_Dragon_6K.py
+++ b/release/scripts/presets/tracking_camera/RED_Dragon_6K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 30.70
bpy.context.camera.sensor_height = 15.80
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/RED_Helium_8K.py b/release/scripts/presets/tracking_camera/RED_Helium_8K.py
index 0f61d35a0f9..90998bc0da0 100644
--- a/release/scripts/presets/tracking_camera/RED_Helium_8K.py
+++ b/release/scripts/presets/tracking_camera/RED_Helium_8K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 29.90
bpy.context.camera.sensor_height = 15.77
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/presets/tracking_camera/RED_Monstro_8K.py b/release/scripts/presets/tracking_camera/RED_Monstro_8K.py
index 86c382624ab..1c8bc11dfaa 100644
--- a/release/scripts/presets/tracking_camera/RED_Monstro_8K.py
+++ b/release/scripts/presets/tracking_camera/RED_Monstro_8K.py
@@ -1,4 +1,4 @@
import bpy
bpy.context.camera.sensor_width = 40.96
bpy.context.camera.sensor_height = 21.60
-bpy.context.camera.sensor_fit = 'HORIZONTAL' \ No newline at end of file
+bpy.context.camera.sensor_fit = 'HORIZONTAL'
diff --git a/release/scripts/startup/bl_operators/assets.py b/release/scripts/startup/bl_operators/assets.py
index 48f07a03773..d2655784afd 100644
--- a/release/scripts/startup/bl_operators/assets.py
+++ b/release/scripts/startup/bl_operators/assets.py
@@ -18,7 +18,9 @@
# <pep8 compliant>
from __future__ import annotations
+from pathlib import Path
+import bpy
from bpy.types import Operator
from bpy_extras.asset_utils import (
@@ -72,7 +74,88 @@ class ASSET_OT_tag_remove(Operator):
return {'FINISHED'}
+class ASSET_OT_open_containing_blend_file(Operator):
+ """Open the blend file that contains the active asset"""
+
+ bl_idname = "asset.open_containing_blend_file"
+ bl_label = "Open Blend File"
+ bl_options = {'REGISTER'}
+
+ _process = None # Optional[subprocess.Popen]
+
+ @classmethod
+ def poll(cls, context):
+ asset_file_handle = getattr(context, 'asset_file_handle', None)
+ asset_library = getattr(context, 'asset_library', None)
+
+ if not asset_library:
+ cls.poll_message_set("No asset library selected")
+ return False
+ if not asset_file_handle:
+ cls.poll_message_set("No asset selected")
+ return False
+ if asset_file_handle.local_id:
+ cls.poll_message_set("Selected asset is contained in the current file")
+ return False
+ return True
+
+ def execute(self, context):
+ asset_file_handle = context.asset_file_handle
+ asset_library = context.asset_library
+
+ if asset_file_handle.local_id:
+ self.report({'WARNING'}, "This asset is stored in the current blend file")
+ return {'CANCELLED'}
+
+ asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library)
+ self.open_in_new_blender(asset_lib_path)
+
+ wm = context.window_manager
+ self._timer = wm.event_timer_add(0.1, window=context.window)
+ wm.modal_handler_add(self)
+
+ return {'RUNNING_MODAL'}
+
+ def modal(self, context, event):
+ if event.type != 'TIMER':
+ return {'PASS_THROUGH'}
+
+ if self._process is None:
+ self.report({'ERROR'}, "Unable to find any running process")
+ self.cancel(context)
+ return {'CANCELLED'}
+
+ returncode = self._process.poll()
+ if returncode is None:
+ # Process is still running.
+ return {'RUNNING_MODAL'}
+
+ if returncode:
+ self.report({'WARNING'}, "Blender subprocess exited with error code %d" % returncode)
+
+ # TODO(Sybren): Replace this with a generic "reload assets" operator
+ # that can run outside of the Asset Browser context.
+ if bpy.ops.file.refresh.poll():
+ bpy.ops.file.refresh()
+ if bpy.ops.asset.list_refresh.poll():
+ bpy.ops.asset.list_refresh()
+
+ self.cancel(context)
+ return {'FINISHED'}
+
+ def cancel(self, context):
+ wm = context.window_manager
+ wm.event_timer_remove(self._timer)
+
+ def open_in_new_blender(self, filepath):
+ import subprocess
+
+ cli_args = [bpy.app.binary_path, str(filepath)]
+ self._process = subprocess.Popen(cli_args)
+
+
classes = (
ASSET_OT_tag_add,
ASSET_OT_tag_remove,
+ ASSET_OT_open_containing_blend_file,
)
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 3cefaf6929b..2959232fa51 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -306,67 +306,6 @@ class NODE_OT_tree_path_parent(Operator):
return {'FINISHED'}
-class NODE_OT_active_preview_toggle(Operator):
- '''Toggle active preview state of node'''
- bl_idname = "node.active_preview_toggle"
- bl_label = "Toggle Active Preview"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- space = context.space_data
- if space is None:
- return False
- if space.type != 'NODE_EDITOR':
- return False
- if space.edit_tree is None:
- return False
- if space.edit_tree.nodes.active is None:
- return False
- return True
-
- def execute(self, context):
- node_editor = context.space_data
- ntree = node_editor.edit_tree
- active_node = ntree.nodes.active
-
- if active_node.active_preview:
- self._disable_preview(context, active_node)
- else:
- self._enable_preview(context, node_editor, ntree, active_node)
-
- return {'FINISHED'}
-
- @classmethod
- def _enable_preview(cls, context, node_editor, ntree, active_node):
- spreadsheets = cls._find_unpinned_spreadsheets(context)
-
- for spreadsheet in spreadsheets:
- spreadsheet.set_geometry_node_context(node_editor, active_node)
-
- for node in ntree.nodes:
- node.active_preview = False
- active_node.active_preview = True
-
- @classmethod
- def _disable_preview(cls, context, active_node):
- spreadsheets = cls._find_unpinned_spreadsheets(context)
- for spreadsheet in spreadsheets:
- spreadsheet.context_path.clear()
-
- active_node.active_preview = False
-
- @staticmethod
- def _find_unpinned_spreadsheets(context):
- spreadsheets = []
- for window in context.window_manager.windows:
- for area in window.screen.areas:
- space = area.spaces.active
- if space.type == 'SPREADSHEET' and not space.is_pinned:
- spreadsheets.append(space)
- return spreadsheets
-
-
classes = (
NodeSetting,
@@ -375,5 +314,4 @@ classes = (
NODE_OT_add_search,
NODE_OT_collapse_hide_unused_toggle,
NODE_OT_tree_path_parent,
- NODE_OT_active_preview_toggle,
)
diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index 48a02a4c5c6..8f678896e61 100644
--- a/release/scripts/startup/bl_operators/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -108,14 +108,13 @@ class SequencerSplitMulticam(Operator):
if s.multicam_source == camera or camera >= s.channel:
return {'FINISHED'}
- if not s.select:
- s.select = True
-
cfra = context.scene.frame_current
- bpy.ops.sequencer.split(frame=cfra, type='SOFT', side='RIGHT')
- for s in context.scene.sequence_editor.sequences_all:
- if s.select and s.type == 'MULTICAM' and s.frame_final_start <= cfra and cfra < s.frame_final_end:
- context.scene.sequence_editor.active_strip = s
+ right_strip = s.split(frame=cfra, split_method='SOFT')
+
+ if right_strip:
+ s.select = False
+ right_strip.select = True
+ context.scene.sequence_editor.active_strip = right_strip
context.scene.sequence_editor.active_strip.multicam_source = camera
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/spreadsheet.py b/release/scripts/startup/bl_operators/spreadsheet.py
index 5cc83d4eddd..b5098d63dac 100644
--- a/release/scripts/startup/bl_operators/spreadsheet.py
+++ b/release/scripts/startup/bl_operators/spreadsheet.py
@@ -20,6 +20,7 @@ from __future__ import annotations
from bpy.types import Operator
+
class SPREADSHEET_OT_toggle_pin(Operator):
'''Turn on or off pinning'''
bl_idname = "spreadsheet.toggle_pin"
@@ -47,18 +48,7 @@ class SPREADSHEET_OT_toggle_pin(Operator):
def unpin(self, context):
space = context.space_data
space.is_pinned = False
-
- space.context_path.clear()
-
- # Try to find a node with an active preview in any open editor.
- if space.object_eval_state == 'EVALUATED':
- node_editors = self.find_geometry_node_editors(context)
- for node_editor in node_editors:
- ntree = node_editor.edit_tree
- for node in ntree.nodes:
- if node.active_preview:
- space.set_geometry_node_context(node_editor, node)
- return
+ space.context_path.guess()
def find_geometry_node_editors(self, context):
editors = []
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 2cc7b828c11..6a3830ad1e4 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -135,7 +135,7 @@ def context_path_decompose(data_path):
if base_path:
assert(base_path.startswith("."))
- base_path= base_path[1:]
+ base_path = base_path[1:]
if prop_attr:
assert(prop_attr.startswith("."))
prop_attr = prop_attr[1:]
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index ef705f8fe37..25484e905c3 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -117,13 +117,15 @@ def register():
for cls in mod.classes:
register_class(cls)
- # space_userprefs.py
from bpy.props import (
EnumProperty,
StringProperty,
)
- from bpy.types import WindowManager
+ from bpy.types import (
+ WindowManager,
+ )
+ # space_userprefs.py
def addon_filter_items(_self, _context):
import addon_utils
@@ -234,3 +236,21 @@ class UI_UL_list(bpy.types.UIList):
bpy.utils.register_class(UI_UL_list)
+
+
+class UI_MT_list_item_context_menu(bpy.types.Menu):
+ """
+ UI List item context menu definition. Scripts can append/prepend this to
+ add own operators to the context menu. They must check context though, so
+ their items only draw in a valid context and for the correct UI list.
+ """
+
+ bl_label = "List Item"
+ bl_idname = "UI_MT_list_item_context_menu"
+
+ def draw(self, context):
+ # Dummy function. This type is just for scripts to append their own
+ # context menu items.
+ pass
+
+bpy.utils.register_class(UI_MT_list_item_context_menu)
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py
index 27de80bb88d..b51d7157c06 100644
--- a/release/scripts/startup/bl_ui/properties_collection.py
+++ b/release/scripts/startup/bl_ui/properties_collection.py
@@ -35,7 +35,7 @@ def lineart_make_line_type_entry(col, line_type, text_disp, expand, search_from)
if line_type.use and expand:
col.prop_search(line_type, "layer", search_from,
"layers", icon='GREASEPENCIL')
- col.prop_search(line_type, "material", search_from,
+ col.prop_search(line_type, "material", search_from,
"materials", icon='SHADING_TEXTURE')
@@ -90,7 +90,7 @@ class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
row = layout.row(align=True, heading="Masks")
row.active = collection.lineart_use_intersection_mask
- for i in range(0,8):
+ for i in range(8):
row.prop(collection, "lineart_intersection_mask", index=i, text=str(i), toggle=True)
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index a88def34767..2a0cf56534c 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -505,6 +505,7 @@ class ConstraintButtonsPanel:
self.target_template(layout, con)
+ layout.prop(con, "remove_target_shear")
layout.prop(con, "mix_mode", text="Mix")
self.space_template(layout, con)
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
index e71ea2f31a4..b273eee4e19 100644
--- a/release/scripts/startup/bl_ui/properties_data_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -93,8 +93,8 @@ class GPENCIL_MT_layer_context_menu(Menu):
gpd = ob.data
gpl = gpd.layers.active
- layout.operator("gpencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').mode='ALL'
- layout.operator("gpencil.layer_duplicate", text="Duplicate Empty Keyframes").mode='EMPTY'
+ layout.operator("gpencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').mode = 'ALL'
+ layout.operator("gpencil.layer_duplicate", text="Duplicate Empty Keyframes").mode = 'EMPTY'
layout.separator()
@@ -113,8 +113,8 @@ class GPENCIL_MT_layer_context_menu(Menu):
layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down")
layout.separator()
- layout.operator("gpencil.layer_duplicate_object", text="Copy Layer to Selected").only_active=True
- layout.operator("gpencil.layer_duplicate_object", text="Copy All Layers to Selected").only_active=False
+ layout.operator("gpencil.layer_duplicate_object", text="Copy Layer to Selected").only_active = True
+ layout.operator("gpencil.layer_duplicate_object", text="Copy All Layers to Selected").only_active = False
class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index fb8aedd1f49..d9ad094ac4f 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -41,7 +41,6 @@ class MESH_MT_vertex_group_context_menu(Menu):
).sort_type = 'BONE_HIERARCHY'
layout.separator()
layout.operator("object.vertex_group_copy", icon='DUPLICATE')
- layout.operator("object.vertex_group_copy_to_linked")
layout.operator("object.vertex_group_copy_to_selected")
layout.separator()
layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT').use_topology = False
@@ -647,7 +646,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
if len(colliding_names) == 0:
return
- layout.label(text="Name Collisions: {}".format(", ".join(colliding_names)), icon='INFO')
+ layout.label(text="Name collisions: {}".format(", ".join(colliding_names)), icon='ERROR')
classes = (
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 0da0716e850..de743033036 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -847,6 +847,7 @@ class GreasePencilLayerRelationsPanel:
col.enabled = bool(gpl.viewlayer_render)
col.prop(gpl, "use_viewlayer_masks")
+
class GreasePencilLayerDisplayPanel:
def draw(self, context):
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 96920af1c7e..afbc3abf302 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -72,8 +72,9 @@ class CLIP_PT_marker_display(Panel):
col.prop(view, "show_marker_pattern", text="Pattern")
col.prop(view, "show_marker_search", text="Search")
- col.active = view.show_track_path
col.prop(view, "show_track_path", text="Path")
+ col = col.column()
+ col.active = view.show_track_path
col.prop(view, "path_length", text="Length")
col = row.column()
@@ -113,7 +114,6 @@ class CLIP_PT_clip_display(Panel):
row = layout.row()
col = row.column()
col.prop(sc.clip_user, "use_render_undistorted", text="Render Undistorted")
- col.prop(sc, "lock_selection", text="Lock to Selection")
col = row.column()
col.prop(sc, "show_stable", text="Show Stable")
col.prop(sc, "show_grid", text="Grid")
@@ -190,7 +190,7 @@ class CLIP_HT_header(Header):
row.prop(sc, "pivot_point", text="", icon_only=True)
row = layout.row(align=True)
icon = 'LOCKED' if sc.lock_selection else 'UNLOCKED'
- row.prop(sc, "lock_selection", icon=icon, text="")
+ row.operator("clip.lock_selection_toggle", icon=icon, text="", depress=sc.lock_selection)
row.popover(panel='CLIP_PT_display')
elif sc.view == 'GRAPH':
@@ -250,7 +250,7 @@ class CLIP_HT_header(Header):
row.popover(panel='CLIP_PT_mask_display')
row = layout.row(align=True)
icon = 'LOCKED' if sc.lock_selection else 'UNLOCKED'
- row.prop(sc, "lock_selection", icon=icon, text="")
+ row.operator("clip.lock_selection_toggle", icon=icon, text="", depress=sc.lock_selection)
row.popover(panel='CLIP_PT_display')
def draw(self, context):
@@ -1477,9 +1477,13 @@ class CLIP_MT_track(Menu):
layout.separator()
- layout.operator("clip.solve_camera",
- text="Solve Camera Motion" if tracking_object.is_camera
- else "Solve Object Motion")
+ layout.operator(
+ "clip.solve_camera",
+ text=(
+ "Solve Camera Motion" if tracking_object.is_camera else
+ "Solve Object Motion"
+ ),
+ )
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index ffb7b9e5c20..84d1c36c53d 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -609,9 +609,9 @@ class DOPESHEET_MT_context_menu(Menu):
layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type")
if st.mode != 'GPENCIL':
- layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
- layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
- layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode")
+ layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
+ layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
+ layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode")
layout.separator()
@@ -625,8 +625,8 @@ class DOPESHEET_MT_context_menu(Menu):
layout.operator("action.delete")
if st.mode == 'GPENCIL':
- layout.operator("gpencil.interpolate_reverse")
- layout.operator("gpencil.frame_clean_duplicate", text="Delete Duplicate Frames")
+ layout.operator("gpencil.interpolate_reverse")
+ layout.operator("gpencil.frame_clean_duplicate", text="Delete Duplicate Frames")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 1ad88744b16..8ca93d2406c 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -552,6 +552,10 @@ class FILEBROWSER_MT_context_menu(Menu):
sub.operator_context = 'EXEC_DEFAULT'
sub.operator("file.delete", text="Delete")
+ active_asset = asset_utils.SpaceAssetInfo.get_active_asset(context)
+ if active_asset:
+ layout.operator("asset.open_containing_blend_file")
+
layout.separator()
sub = layout.row()
@@ -592,15 +596,28 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
def draw(self, context):
layout = self.layout
- active_file = context.active_file
- active_asset = asset_utils.SpaceAssetInfo.get_active_asset(context)
+ asset_file_handle = context.asset_file_handle
- if not active_file or not active_asset:
+ if asset_file_handle is None:
layout.label(text="No asset selected", icon='INFO')
return
- # If the active file is an ID, use its name directly so renaming is possible from right here.
- layout.prop(context.id if context.id is not None else active_file, "name", text="")
+ asset_library = context.asset_library
+ asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library)
+
+ if asset_file_handle.local_id:
+ # If the active file is an ID, use its name directly so renaming is possible from right here.
+ layout.prop(asset_file_handle.local_id, "name", text="")
+ row = layout.row()
+ row.label(text="Source: Current File")
+ else:
+ layout.prop(asset_file_handle, "name", text="")
+ col = layout.column(align=True) # Just to reduce margin.
+ col.label(text="Source:")
+ row = col.row()
+ row.label(text=asset_lib_path)
+
+ row.operator("asset.open_containing_blend_file", text="", icon='TOOL_SETTINGS')
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 3fafa328289..0fceb864ac2 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -257,8 +257,9 @@ class IMAGE_MT_image_flip(Menu):
def draw(self, _context):
layout = self.layout
- layout.operator("image.flip", text="Horizontally").use_flip_horizontal = True
- layout.operator("image.flip", text="Vertically").use_flip_vertical = True
+ layout.operator("image.flip", text="Horizontally").use_flip_x = True
+ layout.operator("image.flip", text="Vertically").use_flip_y = True
+
class IMAGE_MT_image_invert(Menu):
bl_label = "Invert"
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 1208ca0a64a..fba86676ad4 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -694,6 +694,97 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
layout.template_node_socket(color=color)
+class NodeTreeInterfacePanel:
+ def draw_socket_list(self, context, in_out, sockets_propname, active_socket_propname):
+ layout = self.layout
+
+ snode = context.space_data
+ tree = snode.edit_tree
+ sockets = getattr(tree, sockets_propname)
+ active_socket_index = getattr(tree, active_socket_propname)
+ active_socket = sockets[active_socket_index] if active_socket_index >= 0 else None
+
+ split = layout.row()
+
+ split.template_list("NODE_UL_interface_sockets", in_out, tree, sockets_propname, tree, active_socket_propname)
+
+ ops_col = split.column()
+
+ add_remove_col = ops_col.column(align=True)
+ props = add_remove_col.operator("node.tree_socket_add", icon='ADD', text="")
+ props.in_out = in_out
+ props = add_remove_col.operator("node.tree_socket_remove", icon='REMOVE', text="")
+ props.in_out = in_out
+
+ ops_col.separator()
+
+ up_down_col = ops_col.column(align=True)
+ props = up_down_col.operator("node.tree_socket_move", icon='TRIA_UP', text="")
+ props.in_out = in_out
+ props.direction = 'UP'
+ props = up_down_col.operator("node.tree_socket_move", icon='TRIA_DOWN', text="")
+ props.in_out = in_out
+ props.direction = 'DOWN'
+
+ if active_socket is not None:
+ # Mimicking property split.
+ layout.use_property_split = False
+ layout.use_property_decorate = False
+ layout_row = layout.row(align=True)
+ layout_split = layout_row.split(factor=0.4, align=True)
+
+ label_column = layout_split.column(align=True)
+ label_column.alignment = 'RIGHT'
+ # Menu to change the socket type.
+ label_column.label(text="Type")
+
+ property_row = layout_split.row(align=True)
+ props = property_row.operator_menu_enum(
+ "node.tree_socket_change_type",
+ "socket_type",
+ text=active_socket.bl_label if active_socket.bl_label else active_socket.bl_idname
+ )
+ props.in_out = in_out
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ layout.prop(active_socket, "name")
+ # Display descriptions only for Geometry Nodes, since it's only used in the modifier panel.
+ if tree.type == 'GEOMETRY':
+ layout.prop(active_socket, "description")
+ active_socket.draw(context, layout)
+
+
+class NODE_PT_node_tree_interface_inputs(NodeTreeInterfacePanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'UI'
+ bl_category = "Group"
+ bl_label = "Inputs"
+
+ @classmethod
+ def poll(cls, context):
+ snode = context.space_data
+ return snode.edit_tree is not None
+
+ def draw(self, context):
+ self.draw_socket_list(context, "IN", "inputs", "active_input")
+
+class NODE_PT_node_tree_interface_outputs(NodeTreeInterfacePanel, Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'UI'
+ bl_category = "Group"
+ bl_label = "Outputs"
+
+ @classmethod
+ def poll(cls, context):
+ snode = context.space_data
+ return snode.edit_tree is not None
+
+ def draw(self, context):
+ self.draw_socket_list(context, "OUT", "outputs", "active_output")
+
+
# Grease Pencil properties
class NODE_PT_annotation(AnnotationDataPanel, Panel):
bl_space_type = 'NODE_EDITOR'
@@ -752,6 +843,8 @@ classes = (
NODE_PT_quality,
NODE_PT_annotation,
NODE_UL_interface_sockets,
+ NODE_PT_node_tree_interface_inputs,
+ NODE_PT_node_tree_interface_outputs,
node_panel(EEVEE_MATERIAL_PT_settings),
node_panel(MATERIAL_PT_viewport),
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 7a694108e14..ba91b6e8d50 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -442,7 +442,6 @@ class OUTLINER_PT_filter(Panel):
row.prop(space, "use_filter_lib_override_system", text="System Overrides")
-
classes = (
OUTLINER_HT_header,
OUTLINER_MT_editor_menus,
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index ab05461f185..55714e0b0a5 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -400,7 +400,7 @@ class SEQUENCER_MT_view(Menu):
layout.menu("SEQUENCER_MT_proxy")
layout.operator_context = 'INVOKE_DEFAULT'
-
+
layout.separator()
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("sequencer.refresh_all", icon='FILE_REFRESH', text="Refresh All")
@@ -467,6 +467,7 @@ class SEQUENCER_MT_select_handle(Menu):
layout.operator("sequencer.select_handles", text="Left Neighbor").side = 'LEFT_NEIGHBOR'
layout.operator("sequencer.select_handles", text="Right Neighbor").side = 'RIGHT_NEIGHBOR'
+
class SEQUENCER_MT_select_channel(Menu):
bl_label = "Select Channel"
@@ -1415,7 +1416,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel):
split.label(text="%dx%d" % size, translate=False)
else:
split.label(text="None")
- #FPS
+ # FPS
if elem.orig_fps:
split = col.split(factor=0.5, align=False)
split.alignment = 'RIGHT'
@@ -1424,7 +1425,6 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel):
split.label(text="%.2f" % elem.orig_fps, translate=False)
-
class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
bl_label = "Scene"
bl_category = "Strip"
@@ -1857,7 +1857,7 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel):
@classmethod
def poll(cls, context):
show_developer_ui = context.preferences.view.show_developer_ui
- return cls.has_sequencer(context) and context.scene.sequence_editor and show_developer_ui
+ return cls.has_sequencer(context) and context.scene.sequence_editor and show_developer_ui
def draw(self, context):
layout = self.layout
@@ -2286,14 +2286,15 @@ class SEQUENCER_PT_snapping(Panel):
layout.use_property_decorate = False
col = layout.column(heading="Snap to", align=True)
- col.prop(sequencer_tool_settings, "snap_seq_element", expand=True)
+ col.prop(sequencer_tool_settings, "snap_to_current_frame")
+ col.prop(sequencer_tool_settings, "snap_to_hold_offset")
col = layout.column(heading="Ignore", align=True)
col.prop(sequencer_tool_settings, "snap_ignore_muted", text="Muted Strips")
- col.prop(sequencer_tool_settings, "snap_ignore_sound",text="Sound Strips")
+ col.prop(sequencer_tool_settings, "snap_ignore_sound", text="Sound Strips")
col = layout.column()
- col.prop(sequencer_tool_settings, "snap_distance", slider=True, text="Distance")
+ col.prop(sequencer_tool_settings, "use_snap_current_frame_to_strips")
classes = (
diff --git a/release/scripts/startup/bl_ui/space_spreadsheet.py b/release/scripts/startup/bl_ui/space_spreadsheet.py
index 178be9ef0b7..afdbfea5091 100644
--- a/release/scripts/startup/bl_ui/space_spreadsheet.py
+++ b/release/scripts/startup/bl_ui/space_spreadsheet.py
@@ -54,8 +54,11 @@ class SPREADSHEET_HT_header(bpy.types.Header):
pin_icon = 'PINNED' if space.is_pinned else 'UNPINNED'
layout.operator("spreadsheet.toggle_pin", text="", icon=pin_icon, emboss=False)
+ if space.object_eval_state == 'VIEWER_NODE' and len(context_path) < 3:
+ layout.label(text="No active viewer node.", icon='INFO')
+
layout.separator_spacer()
-
+
row = layout.row(align=True)
sub = row.row(align=True)
sub.active = self.selection_filter_available(space)
@@ -112,6 +115,7 @@ class SPREADSHEET_HT_header(bpy.types.Header):
return False
return True
+
classes = (
SPREADSHEET_HT_header,
)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index f9359a8b4a0..7e6fde1ebaf 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -1391,7 +1391,6 @@ class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel):
row.separator()
row.label(text="Path")
-
for i, library in enumerate(paths.asset_libraries):
name_col.prop(library, "name", text="")
row = path_col.row()
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 80cede9ee5a..df41445ee6f 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2765,23 +2765,27 @@ class VIEW3D_MT_make_single_user(Menu):
props = layout.operator("object.make_single_user", text="Object")
props.object = True
- props.obdata = props.material = props.animation = False
+ props.obdata = props.material = props.animation = props.obdata_animation = False
props = layout.operator("object.make_single_user", text="Object & Data")
props.object = props.obdata = True
- props.material = props.animation = False
+ props.material = props.animation = props.obdata_animation = False
props = layout.operator("object.make_single_user", text="Object & Data & Materials")
props.object = props.obdata = props.material = True
- props.animation = False
+ props.animation = props.obdata_animation = False
props = layout.operator("object.make_single_user", text="Materials")
props.material = True
- props.object = props.obdata = props.animation = False
+ props.object = props.obdata = props.animation = props.obdata_animation = False
props = layout.operator("object.make_single_user", text="Object Animation")
props.animation = True
- props.object = props.obdata = props.material = False
+ props.object = props.obdata = props.material = props.obdata_animation = False
+
+ props = layout.operator("object.make_single_user", text="Object Data Animation")
+ props.obdata_animation = props.obdata = True
+ props.object = props.material = props.animation = False
class VIEW3D_MT_object_convert(Menu):
@@ -3129,7 +3133,6 @@ class VIEW3D_MT_mask(Menu):
layout.menu("VIEW3D_MT_random_mask", text="Random Mask")
-
class VIEW3D_MT_face_sets(Menu):
bl_label = "Face Sets"
@@ -3259,6 +3262,7 @@ class VIEW3D_MT_random_mask(Menu):
op = layout.operator("sculpt.mask_init", text='Per Loose Part')
op.mode = 'RANDOM_PER_LOOSE_PART'
+
class VIEW3D_MT_particle(Menu):
bl_label = "Particle"
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index bc385faf378..46fed79332d 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1731,7 +1731,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
- if tool and tool.idname != 'builtin_brush.Tint':
+ if tool and tool.idname != 'builtin_brush.Tint':
return False
gptool = brush.gpencil_tool
@@ -2057,7 +2057,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
- if tool and tool.idname in('builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'):
+ if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
return False
if brush.gpencil_tool == 'TINT':
@@ -2118,7 +2118,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
- if tool and tool.idname in('builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'):
+ if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
return False
if brush.gpencil_tool == 'TINT':
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 2fc2d966ea9..ceffeaaff6c 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -383,6 +383,7 @@ class BUILTIN_KSI_Available(KeyingSetInfo):
###############################
+
class WholeCharacterMixin:
# these prefixes should be avoided, as they are not really bones
# that animators should be touching (or need to touch)
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 8ae5d95f639..15c54fe18f9 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -508,14 +508,17 @@ geometry_node_categories = [
NodeItem("GeometryNodeCurveResample"),
NodeItem("GeometryNodeMeshToCurve"),
NodeItem("GeometryNodeCurveToPoints"),
+ NodeItem("GeometryNodeCurveEndpoints"),
NodeItem("GeometryNodeCurveLength"),
NodeItem("GeometryNodeCurveReverse"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
+ NodeItem("GeometryNodeCurvePrimitiveLine"),
NodeItem("GeometryNodeCurvePrimitiveCircle"),
NodeItem("GeometryNodeCurveStar"),
NodeItem("GeometryNodeCurveSpiral"),
NodeItem("GeometryNodeCurveQuadraticBezier"),
+ NodeItem("GeometryNodeCurvePrimitiveQuadrilateral"),
NodeItem("GeometryNodeCurvePrimitiveBezierSegment"),
]),
GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[
@@ -547,7 +550,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeTriangulate"),
NodeItem("GeometryNodeEdgeSplit"),
NodeItem("GeometryNodeSubdivisionSurface"),
- NodeItem("GeometryNodeSubdivide"),
+ NodeItem("GeometryNodeMeshSubdivide"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[
NodeItem("GeometryNodeMeshCircle"),
@@ -559,6 +562,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeMeshLine"),
NodeItem("GeometryNodeMeshUVSphere"),
]),
+
GeometryNodeCategory("GEO_POINT", "Point", items=[
NodeItem("GeometryNodePointDistribute"),
NodeItem("GeometryNodePointInstance"),
@@ -574,6 +578,7 @@ geometry_node_categories = [
NodeItem("ShaderNodeMath"),
NodeItem("FunctionNodeBooleanMath"),
NodeItem("FunctionNodeFloatCompare"),
+ NodeItem("FunctionNodeFloatToInt"),
NodeItem("GeometryNodeSwitch"),
]),
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
@@ -583,6 +588,9 @@ geometry_node_categories = [
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeVectorRotate"),
]),
+ GeometryNodeCategory("GEO_OUTPUT", "Output", items=[
+ NodeItem("GeometryNodeViewer"),
+ ]),
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
NodeItem("GeometryNodePointsToVolume"),
NodeItem("GeometryNodeVolumeToMesh"),
diff --git a/release/scripts/templates_py/image_processing.py b/release/scripts/templates_py/image_processing.py
index 2392faf440c..ab14436ad8e 100644
--- a/release/scripts/templates_py/image_processing.py
+++ b/release/scripts/templates_py/image_processing.py
@@ -20,9 +20,9 @@ input_image.pixels.foreach_get(pixel_data.ravel())
# Do whatever image processing you want using numpy here:
# Example 1: Inverse red green and blue channels.
-pixel_data[:,:,:3] = 1.0 - pixel_data[:,:,:3]
+pixel_data[:, :, :3] = 1.0 - pixel_data[:, :, :3]
# Example 2: Change gamma on the red channel.
-pixel_data[:,:,0] = np.power(pixel_data[:,:,0], 1.5)
+pixel_data[:, :, 0] = np.power(pixel_data[:, :, 0], 1.5)
# Create output image.
if output_image_name in bpy.data.images:
diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
index aa5b9ebf880..3fc7636459b 100644
--- a/release/scripts/templates_py/operator_mesh_add.py
+++ b/release/scripts/templates_py/operator_mesh_add.py
@@ -6,6 +6,7 @@ from bpy.props import (
FloatProperty,
)
+
def add_box(width, height, depth):
"""
This function takes inputs and returns vertex and face arrays.
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index b7c226ada1d..2c7ffbe8e42 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -351,8 +351,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font,
* characters.
*/
-/* Note,
- * blf_font_ensure_ascii_table(font, gc); must be called before this macro */
+/* NOTE: `blf_font_ensure_ascii_table(font, gc);` must be called before this macro. */
#define BLF_UTF8_NEXT_FAST(_font, _gc, _g, _str, _i, _c, _glyph_ascii_table) \
if (((_c) = (_str)[_i]) < 0x80) { \
@@ -376,8 +375,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font,
ft_kerning_default : \
(FT_UInt)FT_KERNING_UNFITTED)
-/* Note,
- * blf_font_ensure_ascii_kerning(font, gc, kern_mode); must be called before this macro */
+/* NOTE: `blf_font_ensure_ascii_kerning(font, gc, kern_mode);` must be called before this macro. */
#define BLF_KERNING_STEP_FAST(_font, _kern_mode, _g_prev, _g, _c_prev, _c, _pen_x) \
{ \
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 2ec0ca22865..3f01501fda4 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -406,7 +406,7 @@ static void blf_texture_draw(const unsigned char color[4],
float y2)
{
/* Only one vertex per glyph, geometry shader expand it into a quad. */
- /* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
+ /* TODO: Get rid of Geom Shader because it's not optimal AT ALL for the GPU. */
copy_v4_fl4(GPU_vertbuf_raw_step(&g_batch.pos_step),
x1 + g_batch.ofs[0],
y1 + g_batch.ofs[1],
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 684296381eb..904b7bb8718 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -55,7 +55,7 @@
*/
/*
- * Note: This structure is read-only, for all practical purposes.
+ * NOTE: This structure is read-only, for all practical purposes.
* At some point in the future, we may want to consider
* creating a replacement structure that implements a proper
* abstract mesh kernel interface. Or, we can leave this
@@ -89,7 +89,7 @@ struct Object;
struct Scene;
/*
- * Note: all mface interfaces now officially operate on tessellated data.
+ * NOTE: all mface interfaces now officially operate on tessellated data.
* Also, the mface origindex layer indexes mpolys, not mfaces.
*/
diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h
index 6c07708b5ef..14ab9f21424 100644
--- a/source/blender/blenkernel/BKE_anim_data.h
+++ b/source/blender/blenkernel/BKE_anim_data.h
@@ -50,8 +50,8 @@ bool id_can_have_animdata(const struct ID *id);
/* Get AnimData from the given ID-block */
struct AnimData *BKE_animdata_from_id(struct ID *id);
-/* Add AnimData to the given ID-block */
-struct AnimData *BKE_animdata_add_id(struct ID *id);
+/* Ensure AnimData is present in the ID-block (when supported). */
+struct AnimData *BKE_animdata_ensure_id(struct ID *id);
/* Set active action used by AnimData from the given ID-block */
bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 030560015a9..07da9d75e59 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -268,6 +268,12 @@ void animsys_evaluate_action(struct PointerRNA *ptr,
const struct AnimationEvalContext *anim_eval_context,
bool flush_to_original);
+/* Evaluate action, and blend the result into the current values (instead of overwriting fully). */
+void animsys_blend_in_action(struct PointerRNA *ptr,
+ struct bAction *act,
+ const AnimationEvalContext *anim_eval_context,
+ float blend_factor);
+
/* Evaluate Action Group */
void animsys_evaluate_action_group(struct PointerRNA *ptr,
struct bAction *act,
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 86aa18e5739..e13475fd78c 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -28,7 +28,6 @@ extern "C" {
#endif
struct AnimationEvalContext;
-struct bAction;
struct BMEditMesh;
struct Bone;
struct Depsgraph;
@@ -39,6 +38,7 @@ struct Mesh;
struct Object;
struct PoseTree;
struct Scene;
+struct bAction;
struct bArmature;
struct bConstraint;
struct bGPDstroke;
@@ -207,9 +207,18 @@ void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
/* Evaluate the action and apply it to the pose. If any pose bones are selected, only FCurves that
* relate to those bones are evaluated. */
-void BKE_pose_apply_action(struct Object *ob,
- struct bAction *action,
- struct AnimationEvalContext *anim_eval_context);
+void BKE_pose_apply_action_selected_bones(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context);
+/* Evaluate the action and apply it to the pose. Ignore selection state of the bones. */
+void BKE_pose_apply_action_all_bones(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context);
+
+void BKE_pose_apply_action_blend(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context,
+ float blend_factor);
void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3]);
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3]);
diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h
index d1f543b1f38..50eb2859279 100644
--- a/source/blender/blenkernel/BKE_asset.h
+++ b/source/blender/blenkernel/BKE_asset.h
@@ -26,6 +26,7 @@
extern "C" {
#endif
+struct AssetLibraryReference;
struct BlendDataReader;
struct BlendWriter;
struct ID;
@@ -45,6 +46,8 @@ struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(struct AssetMetaData *
const char *name);
void BKE_asset_metadata_tag_remove(struct AssetMetaData *asset_data, struct AssetTag *tag);
+void BKE_asset_library_reference_init_default(struct AssetLibraryReference *library_ref);
+
struct PreviewImage *BKE_asset_metadata_preview_get_from_id(const struct AssetMetaData *asset_data,
const struct ID *owner_id);
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
index 6a1f1feb14f..5fda30224c6 100644
--- a/source/blender/blenkernel/BKE_attribute.h
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -39,8 +39,8 @@ struct ReportList;
/* Attribute.domain */
/**
- * \warning: Careful when changing existing items. Arrays may be initialized from this (e.g.
- * #DATASET_layout_hierarchy).
+ * \warning Careful when changing existing items.
+ * Arrays may be initialized from this (e.g. #DATASET_layout_hierarchy).
*/
typedef enum AttributeDomain {
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index d5baeb08ccc..28903c4787c 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,13 +39,13 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 7
+#define BLENDER_FILE_SUBVERSION 12
/* 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
* was written with too new a version. */
-#define BLENDER_FILE_MIN_VERSION 290
-#define BLENDER_FILE_MIN_SUBVERSION 0
+#define BLENDER_FILE_MIN_VERSION 300
+#define BLENDER_FILE_MIN_SUBVERSION 11
/** User readable version string. */
const char *BKE_blender_version_string(void);
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 78908908343..8be2fcbdb83 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -218,7 +218,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
ThreadMutex *mesh_eval_mutex);
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
- struct Mesh *mesh,
+ const struct Mesh *mesh,
const BVHCacheType bvh_cache_type,
const int tree_type);
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index f47cdf32ca0..0326386e5c1 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -76,6 +76,7 @@ struct Collection *BKE_collection_duplicate(struct Main *bmain,
/* Master Collection for Scene */
+#define BKE_SCENE_COLLECTION_NAME "Scene Collection"
struct Collection *BKE_collection_master_add(void);
/* Collection Objects */
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 50aa6027840..8917580689d 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -23,6 +23,9 @@
* \ingroup bke
*/
+/* XXX temporary, until AssetHandle is designed properly and queries can return a pointer to it. */
+#include "DNA_asset_types.h"
+
#include "DNA_listBase.h"
#include "DNA_object_enums.h"
#include "RNA_types.h"
@@ -357,6 +360,9 @@ 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);
+const struct AssetLibraryReference *CTX_wm_asset_library(const bContext *C);
+struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid);
+
bool CTX_wm_interface_locked(const bContext *C);
/* Gets pointer to the dependency graph.
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index d861baba14d..a2544e43c3d 100644
--- a/source/blender/blenkernel/BKE_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -112,7 +112,7 @@ enum {
};
/* How to map a source layer to a destination layer, for types supporting multi-layers.
- * Note: if no matching layer can be found, it will be created. */
+ * NOTE: if no matching layer can be found, it will be created. */
enum {
DT_LAYERS_ACTIVE_DST = -1, /* Only for DT_LAYERS_FROMSEL_ACTIVE. */
DT_LAYERS_NAME_DST = -2,
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index 8b5fdf69bb0..f4221d57428 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -30,6 +30,7 @@ extern "C" {
struct BlendDataReader;
struct BlendWriter;
+struct ID;
struct ListBase;
struct MDeformVert;
struct MEdge;
@@ -38,6 +39,18 @@ struct MPoly;
struct Object;
struct bDeformGroup;
+bool BKE_object_supports_vertex_groups(const struct Object *ob);
+const struct ListBase *BKE_object_defgroup_list(const struct Object *ob);
+struct ListBase *BKE_object_defgroup_list_mutable(struct Object *ob);
+
+int BKE_object_defgroup_count(const struct Object *ob);
+int BKE_object_defgroup_active_index_get(const struct Object *ob);
+void BKE_object_defgroup_active_index_set(struct Object *ob, const int new_index);
+
+const struct ListBase *BKE_id_defgroup_list_get(const struct ID *id);
+struct ListBase *BKE_id_defgroup_list_get_mutable(struct ID *id);
+int BKE_id_defgroup_name_index(const struct ID *id, const char *name);
+
struct bDeformGroup *BKE_object_defgroup_new(struct Object *ob, const char *name);
void BKE_defgroup_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
struct bDeformGroup *BKE_defgroup_duplicate(const struct bDeformGroup *ingroup);
@@ -171,6 +184,7 @@ void BKE_defvert_blend_write(struct BlendWriter *writer, int count, struct MDefo
void BKE_defvert_blend_read(struct BlendDataReader *reader,
int count,
struct MDeformVert *mdverts);
+void BKE_defbase_blend_write(struct BlendWriter *writer, const ListBase *defbase);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index e31a0a16408..ffd8ac42c63 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -24,7 +24,7 @@
* only concerned with low level operations on the #BMEditMesh structure.
*/
-#include "BKE_customdata.h"
+#include "DNA_customdata_types.h"
#include "bmesh.h"
#ifdef __cplusplus
@@ -32,8 +32,8 @@ extern "C" {
#endif
struct BMLoop;
-struct BMesh;
struct BMPartialUpdate;
+struct BMesh;
struct BMeshCalcTessellation_Params;
struct BoundBox;
struct Depsgraph;
@@ -44,38 +44,39 @@ struct Scene;
/**
* This structure is used for mesh edit-mode.
*
- * through this, you get access to both the edit #BMesh,
- * its tessellation, and various stuff that doesn't belong in the BMesh
- * struct itself.
+ * Through this, you get access to both the edit #BMesh, its tessellation,
+ * and various data that doesn't belong in the #BMesh struct itself
+ * (mostly related to mesh evaluation).
*
- * the entire derivedmesh and modifier system works with this structure,
- * and not BMesh. Mesh->edit_bmesh stores a pointer to this structure. */
+ * The entire modifier system works with this structure, and not #BMesh.
+ * #Mesh.edit_bmesh stores a pointer to this structure. */
typedef struct BMEditMesh {
struct BMesh *bm;
- /* This is for undoing failed operations. */
- struct BMEditMesh *emcopy;
- int emcopyusers;
-
- /* we store tessellations as triplets of three loops,
- * which each define a triangle. */
+ /**
+ * Face triangulation (tessellation) is stored as triplets of three loops,
+ * which each define a triangle.
+ *
+ * \see #MLoopTri as the documentation gives useful hints that apply to this data too.
+ */
struct BMLoop *(*looptris)[3];
int tottri;
struct Mesh *mesh_eval_final, *mesh_eval_cage;
- /** Cached cage bounding box for selection. */
+ /** Cached cage bounding box of `mesh_eval_cage` for selection. */
struct BoundBox *bb_cage;
/** Evaluated mesh data-mask. */
CustomData_MeshMasks lastDataMask;
- /* Selection mode. */
+ /** Selection mode (#SCE_SELECT_VERTEX, #SCE_SELECT_EDGE & #SCE_SELECT_FACE). */
short selectmode;
+ /** The active material (assigned to newly created faces). */
short mat_nr;
- /* Temp variables for x-mirror editing. */
- int mirror_cdlayer; /* -1 is invalid */
+ /** Temp variables for x-mirror editing (-1 when the layer does not exist). */
+ int mirror_cdlayer;
/**
* ID data is older than edit-mode data.
@@ -98,11 +99,11 @@ void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em,
void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em);
-BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate);
+BMEditMesh *BKE_editmesh_create(BMesh *bm);
BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
BMEditMesh *BKE_editmesh_from_object(struct Object *ob);
-void BKE_editmesh_free_derivedmesh(BMEditMesh *em);
-void BKE_editmesh_free(BMEditMesh *em);
+void BKE_editmesh_free_derived_caches(BMEditMesh *em);
+void BKE_editmesh_free_data(BMEditMesh *em);
float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
struct BMEditMesh *em,
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 82c9a31dfce..42e9ce82278 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -35,12 +35,12 @@
#include "BKE_geometry_set.h"
struct Collection;
+struct Curve;
+struct CurveEval;
struct Mesh;
struct Object;
struct PointCloud;
struct Volume;
-struct Curve;
-struct CurveEval;
enum class GeometryOwnershipType {
/* The geometry is owned. This implies that it can be changed. */
@@ -325,10 +325,6 @@ class MeshComponent : public GeometryComponent {
private:
Mesh *mesh_ = nullptr;
GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
- /* Due to historical design choices, vertex group data is stored in the mesh, but the vertex
- * group names are stored on an object. Since we don't have an object here, we copy over the
- * names into this map. */
- blender::Map<std::string, int> vertex_group_names_;
public:
MeshComponent();
@@ -338,14 +334,8 @@ class MeshComponent : public GeometryComponent {
void clear();
bool has_mesh() const;
void replace(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
- void replace_mesh_but_keep_vertex_group_names(
- Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
Mesh *release();
- void copy_vertex_group_names_from_object(const struct Object &object);
- const blender::Map<std::string, int> &vertex_group_names() const;
- blender::Map<std::string, int> &vertex_group_names();
-
const Mesh *get_for_read() const;
Mesh *get_for_write();
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 657e66729e1..92e70b41e7b 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -49,22 +49,22 @@ struct bGPDlayer_Mask;
struct bGPDstroke;
struct bGPdata;
-#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
+#define GPENCIL_SIMPLIFY(scene) (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)
#define GPENCIL_SIMPLIFY_ONPLAY(playing) \
(((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \
((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
#define GPENCIL_SIMPLIFY_FILL(scene, playing) \
- ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
+ ((GPENCIL_SIMPLIFY_ONPLAY(playing) && GPENCIL_SIMPLIFY(scene) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
#define GPENCIL_SIMPLIFY_MODIF(scene) \
((GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
#define GPENCIL_SIMPLIFY_FX(scene, playing) \
- ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
+ ((GPENCIL_SIMPLIFY_ONPLAY(playing) && GPENCIL_SIMPLIFY(scene) && \
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
#define GPENCIL_SIMPLIFY_TINT(scene) \
- ((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT))
+ (GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT))
#define GPENCIL_SIMPLIFY_AA(scene) \
- ((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA))
+ (GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA))
/* Vertex Color macros. */
#define GPENCIL_USE_VERTEX_COLOR(toolsettings) \
@@ -154,17 +154,6 @@ bool BKE_gpencil_merge_materials(struct Object *ob,
/* statistics functions */
void BKE_gpencil_stats_update(struct bGPdata *gpd);
-/* Utilities for creating and populating GP strokes */
-/* - Number of values defining each point in the built-in data
- * buffers for primitives (e.g. 2D Monkey)
- */
-#define GP_PRIM_DATABUF_SIZE 5
-
-void BKE_gpencil_stroke_add_points(struct bGPDstroke *gps,
- const float *array,
- const int totpoints,
- const float mat[4][4]);
-
struct bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness);
struct bGPDstroke *BKE_gpencil_stroke_add(
struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head);
@@ -282,20 +271,25 @@ bool BKE_gpencil_from_image(struct SpaceImage *sima,
const float size,
const bool mask);
-/* Iterator */
+/* Iterators */
/* frame & stroke are NULL if it is a layer callback. */
typedef void (*gpIterCb)(struct bGPDlayer *layer,
struct bGPDframe *frame,
struct bGPDstroke *stroke,
void *thunk);
-void BKE_gpencil_visible_stroke_iter(struct ViewLayer *view_layer,
- struct Object *ob,
+void BKE_gpencil_visible_stroke_iter(struct bGPdata *gpd,
gpIterCb layer_cb,
gpIterCb stroke_cb,
- void *thunk,
- bool do_onion,
- int cfra);
+ void *thunk);
+
+void BKE_gpencil_visible_stroke_advanced_iter(struct ViewLayer *view_layer,
+ struct Object *ob,
+ gpIterCb layer_cb,
+ gpIterCb stroke_cb,
+ void *thunk,
+ bool do_onion,
+ int cfra);
extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd);
extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index 8fbc2112c77..33524e47473 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -325,6 +325,12 @@ struct bGPDframe *BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct bGPDlayer *gpl);
+int BKE_gpencil_time_modifier_cfra(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bGPDlayer *gpl,
+ const int cfra,
+ const bool is_render);
void BKE_gpencil_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase);
void BKE_gpencil_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 58b8d19abaa..70d65e02246 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -71,7 +71,7 @@ void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *
char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb);
/* conversion functions */
-/* Note: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */
+/* NOTE: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */
void BKE_keyblock_update_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb);
void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt);
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index 27076d908e7..c6658ff424a 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -42,8 +42,8 @@
extern "C" {
#endif
-struct Collection;
struct BlendFileReadReport;
+struct Collection;
struct ID;
struct IDOverrideLibrary;
struct IDOverrideLibraryProperty;
diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index e806dedc14c..c90a284c204 100644
--- a/source/blender/blenkernel/BKE_lib_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -91,7 +91,7 @@ enum {
ID_REMAP_FORCE_USER_REFCOUNT = 1 << 8,
};
-/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately,
+/* NOTE: Requiring new_id to be non-null, this *may* not be the case ultimately,
* but makes things simpler for now. */
void BKE_libblock_remap_locked(struct Main *bmain,
void *old_idv,
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 2c6e5ed3873..ed930fe539d 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -100,7 +100,7 @@ typedef struct MainIDRelations {
/* Mapping from an ID pointer to all of its parents (IDs using it) and children (IDs it uses).
* Values are `MainIDRelationsEntry` pointers. */
struct GHash *relations_from_pointers;
- /* Note: we could add more mappings when needed (e.g. from session uuid?). */
+ /* NOTE: we could add more mappings when needed (e.g. from session uuid?). */
short flag;
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 8d76a025e87..12560ebed7b 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -299,7 +299,7 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
struct MLoopTri *mlooptri,
const float (*poly_normals)[3]);
-/* *** mesh_normals.c *** */
+/* *** mesh_normals.cc *** */
void BKE_mesh_calc_normals_mapping_simple(struct Mesh *me);
void BKE_mesh_calc_normals_mapping(struct MVert *mverts,
@@ -494,7 +494,7 @@ void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loopnors)[3]);
void BKE_mesh_set_custom_normals_from_vertices(struct Mesh *mesh, float (*r_custom_vertnors)[3]);
-/* *** mesh_evaluate.c *** */
+/* *** mesh_evaluate.cc *** */
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
const struct MLoop *loopstart,
diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h
index 02f8af6443c..7f8f028c26b 100644
--- a/source/blender/blenkernel/BKE_mesh_remap.h
+++ b/source/blender/blenkernel/BKE_mesh_remap.h
@@ -115,7 +115,7 @@ enum {
MREMAP_USE_INTERP,
/* ***** Target's loops ***** */
- /* Note: when islands are given to loop mapping func,
+ /* NOTE: when islands are given to loop mapping func,
* all loops from the same destination face will always be mapped
* to loops of source faces within a same island, regardless of mapping mode. */
MREMAP_MODE_LOOP = 1 << 26,
diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h
index 67c87e96aff..3efbef94081 100644
--- a/source/blender/blenkernel/BKE_mesh_runtime.h
+++ b/source/blender/blenkernel/BKE_mesh_runtime.h
@@ -45,7 +45,7 @@ void BKE_mesh_runtime_reset(struct Mesh *mesh);
void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag);
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh);
-const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh);
+const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh);
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh);
bool BKE_mesh_runtime_clear_edit_data(struct Mesh *mesh);
bool BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);
diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h
index aed8c44a031..b223d3872ff 100644
--- a/source/blender/blenkernel/BKE_mesh_types.h
+++ b/source/blender/blenkernel/BKE_mesh_types.h
@@ -27,6 +27,7 @@ typedef enum eMeshBatchDirtyMode {
BKE_MESH_BATCH_DIRTY_SELECT,
BKE_MESH_BATCH_DIRTY_SELECT_PAINT,
BKE_MESH_BATCH_DIRTY_SHADING,
+ BKE_MESH_BATCH_DIRTY_DEFORM,
BKE_MESH_BATCH_DIRTY_UVEDIT_ALL,
BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT,
} eMeshBatchDirtyMode;
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index af238fda659..cf8848fe607 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -156,10 +156,10 @@ enum eNlaTime_ConvertModes {
/* convert from global time to strip time - for evaluation */
NLATIME_CONVERT_EVAL = 0,
/* convert from global time to strip time - for editing corrections */
- // XXX old 0 invert
+ /* XXX: old 0 invert. */
NLATIME_CONVERT_UNMAP,
/* convert from strip time to global time */
- // xxx old 1 invert
+ /* XXX: old 1 invert. */
NLATIME_CONVERT_MAP,
};
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index e390919c128..6d57106435b 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -144,7 +144,10 @@ typedef void *SocketGetCPPValueFunction;
* Defines the appearance and behavior of a socket in the UI.
*/
typedef struct bNodeSocketType {
- char idname[64]; /* identifier name */
+ /* Identifier name */
+ char idname[64];
+ /* Type label */
+ char label[64];
void (*draw)(struct bContext *C,
struct uiLayout *layout,
@@ -420,7 +423,7 @@ typedef struct bNodeTreeType {
void (*node_add_init)(struct bNodeTree *ntree, struct bNode *bnode);
/* Check if the socket type is valid for this tree type. */
- bool (*valid_socket_type)(enum eNodeSocketDatatype socket_type, struct bNodeTreeType *ntreetype);
+ bool (*valid_socket_type)(struct bNodeTreeType *ntreetype, struct bNodeSocketType *socket_type);
/* RNA integration */
ExtensionRNA rna_ext;
@@ -562,8 +565,12 @@ void nodeRegisterSocketType(struct bNodeSocketType *stype);
void nodeUnregisterSocketType(struct bNodeSocketType *stype);
bool nodeSocketIsRegistered(struct bNodeSocket *sock);
struct GHashIterator *nodeSocketTypeGetIterator(void);
+const char *nodeSocketTypeLabel(const bNodeSocketType *stype);
+
+bool nodeIsStaticSocketType(const struct bNodeSocketType *stype);
const char *nodeStaticSocketType(int type, int subtype);
const char *nodeStaticSocketInterfaceType(int type, int subtype);
+const char *nodeStaticSocketLabel(int type, int subtype);
/* helper macros for iterating over node types */
#define NODE_SOCKET_TYPES_BEGIN(stype) \
@@ -613,7 +620,11 @@ struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree,
const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
-void nodeModifySocketType(
+void nodeModifySocketType(struct bNodeTree *ntree,
+ struct bNode *node,
+ struct bNodeSocket *sock,
+ const char *idname);
+void nodeModifySocketTypeStatic(
struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, int type, int subtype);
struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
@@ -973,7 +984,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
/** \name Shader Nodes
* \{ */
-/* note: types are needed to restore callbacks, don't change values */
+/* NOTE: types are needed to restore callbacks, don't change values. */
/* range 1 - 100 is reserved for common nodes */
/* using toolbox, we add node groups by assuming the values below
* don't exceed NODE_GROUP_MENU for now. */
@@ -1140,7 +1151,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
// #define RRES_OUT_SUBSURFACE_COLOR 30
// #define RRES_OUT_DEBUG 31
-/* note: types are needed to restore callbacks, don't change values */
+/* NOTE: types are needed to restore callbacks, don't change values. */
#define CMP_NODE_VIEWER 201
#define CMP_NODE_RGB 202
#define CMP_NODE_VALUE 203
@@ -1271,6 +1282,11 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
#define CMP_CRYPTOMATTE_SRC_RENDER 0
#define CMP_CRYPTOMATTE_SRC_IMAGE 1
+/* Default SMAA configuration values. */
+#define CMP_DEFAULT_SMAA_THRESHOLD 1.0f
+#define CMP_DEFAULT_SMAA_CONTRAST_LIMIT 0.2f
+#define CMP_DEFAULT_SMAA_CORNER_ROUNDING 0.25f
+
/* API */
void ntreeCompositExecTree(struct Scene *scene,
struct bNodeTree *ntree,
@@ -1414,7 +1430,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_VOLUME_TO_MESH 1026
#define GEO_NODE_ATTRIBUTE_COMBINE_XYZ 1027
#define GEO_NODE_ATTRIBUTE_SEPARATE_XYZ 1028
-#define GEO_NODE_SUBDIVIDE 1029
+#define GEO_NODE_MESH_SUBDIVIDE 1029
#define GEO_NODE_ATTRIBUTE_REMOVE 1030
#define GEO_NODE_ATTRIBUTE_CONVERT 1031
#define GEO_NODE_MESH_PRIMITIVE_CUBE 1032
@@ -1452,8 +1468,12 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER 1064
#define GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT 1065
#define GEO_NODE_CURVE_PRIMITIVE_CIRCLE 1066
-#define GEO_NODE_ATTRIBUTE_GET 1067
-#define GEO_NODE_ATTRIBUTE_SET 1068
+#define GEO_NODE_VIEWER 1067
+#define GEO_NODE_CURVE_PRIMITIVE_LINE 1068
+#define GEO_NODE_CURVE_ENDPOINTS 1069
+#define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070
+#define GEO_NODE_ATTRIBUTE_GET 1071
+#define GEO_NODE_ATTRIBUTE_SET 1072
/** \} */
@@ -1466,6 +1486,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define FN_NODE_RANDOM_FLOAT 1206
#define FN_NODE_INPUT_VECTOR 1207
#define FN_NODE_INPUT_STRING 1208
+#define FN_NODE_FLOAT_TO_INT 1209
/** \} */
diff --git a/source/blender/blenkernel/BKE_node_ui_storage.hh b/source/blender/blenkernel/BKE_node_ui_storage.hh
deleted file mode 100644
index 4ec165aad8c..00000000000
--- a/source/blender/blenkernel/BKE_node_ui_storage.hh
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include <mutex>
-
-#include "BLI_hash.hh"
-#include "BLI_map.hh"
-#include "BLI_session_uuid.h"
-#include "BLI_set.hh"
-
-#include "DNA_ID.h"
-#include "DNA_customdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_session_uuid_types.h"
-
-#include "BKE_attribute.h"
-
-struct ModifierData;
-struct Object;
-struct bNode;
-struct bNodeTree;
-struct bContext;
-
-/**
- * Contains the context necessary to determine when to display settings for a certain node tree
- * that may be used for multiple modifiers and objects. The object name and modifier session UUID
- * are used instead of pointers because they are re-allocated between evaluations.
- *
- * \note This does not yet handle the context of nested node trees.
- */
-class NodeTreeEvaluationContext {
- private:
- std::string object_name_;
- SessionUUID modifier_session_uuid_;
-
- public:
- NodeTreeEvaluationContext(const Object &object, const ModifierData &modifier)
- {
- object_name_ = reinterpret_cast<const ID &>(object).name;
- modifier_session_uuid_ = modifier.session_uuid;
- }
-
- uint64_t hash() const
- {
- return blender::get_default_hash_2(object_name_, modifier_session_uuid_);
- }
-
- friend bool operator==(const NodeTreeEvaluationContext &a, const NodeTreeEvaluationContext &b)
- {
- return a.object_name_ == b.object_name_ &&
- BLI_session_uuid_is_equal(&a.modifier_session_uuid_, &b.modifier_session_uuid_);
- }
-};
-
-enum class NodeWarningType {
- Error,
- Warning,
- Info,
-};
-
-struct NodeWarning {
- NodeWarningType type;
- std::string message;
-};
-
-struct AvailableAttributeInfo {
- std::string name;
- AttributeDomain domain;
- CustomDataType data_type;
-
- uint64_t hash() const
- {
- return blender::get_default_hash(name);
- }
-
- friend bool operator==(const AvailableAttributeInfo &a, const AvailableAttributeInfo &b)
- {
- return a.name == b.name;
- }
-};
-
-struct NodeUIStorage {
- blender::Vector<NodeWarning> warnings;
- blender::Set<AvailableAttributeInfo> attribute_hints;
-};
-
-struct NodeTreeUIStorage {
- std::mutex mutex;
- blender::Map<NodeTreeEvaluationContext, blender::Map<std::string, NodeUIStorage>> context_map;
-
- /**
- * Attribute search uses this to store the fake info for the string typed into a node, in order
- * to pass the info to the execute callback that sets node socket values. This is mutable since
- * we can count on only one attribute search being open at a time, and there is no real data
- * stored here.
- */
- mutable AvailableAttributeInfo dummy_info_for_search;
-};
-
-const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C,
- const bNodeTree &ntree,
- const bNode &node);
-
-void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context);
-
-void BKE_nodetree_error_message_add(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context,
- const bNode &node,
- const NodeWarningType type,
- std::string message);
-
-void BKE_nodetree_attribute_hint_add(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context,
- const bNode &node,
- const blender::StringRef attribute_name,
- const AttributeDomain domain,
- const CustomDataType data_type);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index af9f5d7bf22..a16822fd7dd 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -70,10 +70,6 @@ void BKE_object_free_curve_cache(struct Object *ob);
void BKE_object_free_derived_caches(struct Object *ob);
void BKE_object_free_caches(struct Object *object);
-void BKE_object_preview_geometry_set_add(struct Object *ob,
- const uint64_t key,
- struct GeometrySet *geometry_set);
-
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
void BKE_object_modifier_gpencil_hook_reset(struct Object *ob,
struct HookGpencilModifierData *hmd);
@@ -243,7 +239,7 @@ void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis
void BKE_object_empty_draw_type_set(struct Object *ob, const int value);
void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set);
-void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval);
+void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval);
void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph,
struct Scene *scene,
@@ -378,6 +374,10 @@ void BKE_object_runtime_free_data(struct Object *object);
void BKE_object_batch_cache_dirty_tag(struct Object *ob);
void BKE_object_data_batch_cache_dirty_tag(struct ID *object_data);
+void BKE_object_data_eval_batch_cache_dirty_tag(struct Depsgraph *depsgraph,
+ struct ID *object_data);
+void BKE_object_data_eval_batch_cache_deform_tag(struct Depsgraph *depsgraph,
+ struct ID *object_data);
/* this function returns a superset of the scenes selection based on relationships */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 97e5698d6f9..056a7e2d897 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -329,7 +329,7 @@ bool BKE_pbvh_is_deformed(struct PBVH *pbvh);
* - allow the compiler to eliminate dead code and variables
* - spend most of the time in the relatively simple inner loop */
-/* note: PBVH_ITER_ALL does not skip hidden vertices,
+/* NOTE: PBVH_ITER_ALL does not skip hidden vertices,
* PBVH_ITER_UNIQUE does */
#define PBVH_ITER_ALL 0
#define PBVH_ITER_UNIQUE 1
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 8731162b720..3f99a0dc793 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -45,7 +45,7 @@ extern "C" {
#define PTCACHE_RESET_OUTDATED 2
/* #define PTCACHE_RESET_FREE 3 */ /*UNUSED*/
-/* Add the blendfile name after blendcache_ */
+/* Add the blend-file name after `blendcache_`. */
#define PTCACHE_EXT ".bphys"
#define PTCACHE_PATH "blendcache_"
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 9792f819bf9..6d58e165ea3 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -124,14 +124,16 @@ bool BKE_scene_camera_switch_update(struct Scene *scene);
const char *BKE_scene_find_marker_name(const struct Scene *scene, int frame);
const char *BKE_scene_find_last_marker_name(const struct Scene *scene, int frame);
-int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int cfra);
+int BKE_scene_frame_snap_by_seconds(struct Scene *scene, double interval_in_seconds, int frame);
/* checks for cycle, returns 1 if it's all OK */
bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce);
+float BKE_scene_ctime_get(const struct Scene *scene);
+float BKE_scene_frame_to_ctime(const struct Scene *scene, const int frame);
+
float BKE_scene_frame_get(const struct Scene *scene);
-float BKE_scene_frame_to_ctime(const struct Scene *scene, const float frame);
-void BKE_scene_frame_set(struct Scene *scene, double cfra);
+void BKE_scene_frame_set(struct Scene *scene, float frame);
struct TransformOrientationSlot *BKE_scene_orientation_slot_get_from_flag(struct Scene *scene,
int flag);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index fed155626ed..0b08bbfeff5 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -332,6 +332,9 @@ typedef void (*uiListFilterItemsFunc)(struct uiList *ui_list,
struct PointerRNA *,
const char *propname);
+/* Listen to notifiers. Only for lists defined in C. */
+typedef void (*uiListListener)(struct uiList *ui_list, wmRegionListenerParams *params);
+
typedef struct uiListType {
struct uiListType *next, *prev;
@@ -341,6 +344,9 @@ typedef struct uiListType {
uiListDrawFilterFunc draw_filter;
uiListFilterItemsFunc filter_items;
+ /* For lists defined in C only. */
+ uiListListener listener;
+
/* RNA integration */
ExtensionRNA rna_ext;
} uiListType;
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 1aac2e311e3..f85e62768f7 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -337,6 +337,18 @@ class BezierSpline final : public Spline {
blender::MutableSpan<blender::float3> positions) const;
bool segment_is_vector(const int start_index) const;
+ /** See comment and diagram for #calculate_segment_insertion. */
+ struct InsertResult {
+ blender::float3 handle_prev;
+ blender::float3 left_handle;
+ blender::float3 position;
+ blender::float3 right_handle;
+ blender::float3 handle_next;
+ };
+ InsertResult calculate_segment_insertion(const int index,
+ const int next_index,
+ const float parameter);
+
private:
void correct_end_tangents() const final;
void copy_settings(Spline &dst) const final;
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index 70b8743bcd2..59b1c2b28d9 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -145,7 +145,7 @@ typedef struct StudioLight {
void BKE_studiolight_init(void);
void BKE_studiolight_free(void);
-void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]);
+void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3]);
struct StudioLight *BKE_studiolight_find(const char *name, int flag);
struct StudioLight *BKE_studiolight_findindex(int index, int flag);
struct StudioLight *BKE_studiolight_find_default(int flag);
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index c2544c06514..47145a7d6bd 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -161,7 +161,7 @@ struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTr
struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track,
int framenr);
-/* Get marker position, possibly interpolating interpolating gap between keyframed/tracked markers.
+/* Get marker position, possibly interpolating gap between key-framed/tracked markers.
*
* The result marker frame number is set to the requested frame number. Its flags are 0 if the
* marker is interpolated, and is set to original marker flag if there were no interpolation
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index efac5d9097f..2973a432723 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -162,6 +162,13 @@ typedef enum UndoTypeFlags {
* \note Callback is still supposed to properly deal with a NULL context pointer.
*/
UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE = 1 << 0,
+
+ /**
+ * When the active undo step is of this type, it must be read before loading other undo steps.
+ *
+ * This is typically used for undo systems that store both before/after states.
+ */
+ UNDOTYPE_FLAG_DECODE_ACTIVE_STEP = 1 << 1,
} UndoTypeFlags;
/* Expose since we need to perform operations on specific undo types (rarely). */
diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h
index cf755827a6c..d9333996632 100644
--- a/source/blender/blenkernel/BKE_volume.h
+++ b/source/blender/blenkernel/BKE_volume.h
@@ -214,7 +214,7 @@ auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op)
}
/* Should never be called. */
- BLI_assert(!"should never be reached");
+ BLI_assert_msg(0, "should never be reached");
return op.template operator()<openvdb::FloatGrid>();
}
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index b66cb9e224d..527996ee46d 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -93,7 +93,7 @@ set(SRC
intern/boids.c
intern/bpath.c
intern/brush.c
- intern/bvhutils.c
+ intern/bvhutils.cc
intern/cachefile.c
intern/callbacks.c
intern/camera.c
@@ -143,7 +143,7 @@ set(SRC
intern/geometry_set_instances.cc
intern/gpencil.c
intern/gpencil_curve.c
- intern/gpencil_geom.c
+ intern/gpencil_geom.cc
intern/gpencil_modifier.c
intern/hair.c
intern/icons.cc
@@ -184,13 +184,13 @@ set(SRC
intern/mesh.c
intern/mesh_boolean_convert.cc
intern/mesh_convert.c
- intern/mesh_evaluate.c
+ intern/mesh_evaluate.cc
intern/mesh_fair.cc
intern/mesh_iterators.c
intern/mesh_mapping.c
intern/mesh_merge.c
intern/mesh_mirror.c
- intern/mesh_normals.c
+ intern/mesh_normals.cc
intern/mesh_remap.c
intern/mesh_remesh_voxel.c
intern/mesh_runtime.c
@@ -215,7 +215,6 @@ set(SRC
intern/multires_versioning.c
intern/nla.c
intern/node.cc
- intern/node_ui_storage.cc
intern/object.c
intern/object_deform.c
intern/object_dupli.cc
@@ -331,7 +330,6 @@ set(SRC
BKE_customdata_file.h
BKE_data_transfer.h
BKE_deform.h
- BKE_spline.hh
BKE_displist.h
BKE_displist_tangent.h
BKE_duplilist.h
@@ -399,7 +397,6 @@ set(SRC
BKE_multires.h
BKE_nla.h
BKE_node.h
- BKE_node_ui_storage.hh
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h
@@ -423,6 +420,7 @@ set(SRC
BKE_softbody.h
BKE_sound.h
BKE_speaker.h
+ BKE_spline.hh
BKE_studiolight.h
BKE_subdiv.h
BKE_subdiv_ccg.h
@@ -767,6 +765,7 @@ add_dependencies(bf_blenkernel bf_dna)
if(WITH_GTESTS)
set(TEST_SRC
+ intern/action_test.cc
intern/armature_test.cc
intern/cryptomatte_test.cc
intern/fcurve_test.cc
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 7063c670ee4..ba8cf8debe9 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -829,7 +829,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
}
if (do_loop_normals) {
- /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
+ /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). */
BKE_mesh_calc_normals_split(mesh_final);
BKE_mesh_tessface_clear(mesh_final);
}
@@ -900,7 +900,7 @@ static Mesh *prepare_geometry_set_for_mesh_modifier(Mesh *mesh, GeometrySet &r_g
{
/* Add the mesh to the geometry set. */
MeshComponent &mesh_component = r_geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace_mesh_but_keep_vertex_group_names(mesh, GeometryOwnershipType::Editable);
+ mesh_component.replace(mesh, GeometryOwnershipType::Editable);
}
{
/* Combine mesh and all instances into a single mesh that can be passed to the modifier. */
@@ -948,8 +948,7 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
/* Replace only the mesh rather than the whole component, because the entire #MeshComponent
* might have been replaced by data from a different object in the node tree, which means the
* component contains vertex group name data for that object that should not be removed. */
- mesh_component.replace_mesh_but_keep_vertex_group_names(input_mesh,
- GeometryOwnershipType::Editable);
+ mesh_component.replace(input_mesh, GeometryOwnershipType::Editable);
/* Let the modifier change the geometry set. */
mti->modifyGeometrySet(md, &mectx, &geometry_set);
@@ -993,12 +992,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
GeometrySet geometry_set_final;
- /* Add the initial mesh component, with a copy of the vertex group names from the object,
- * since they need to be stored in the geometry set for evaluation. */
- MeshComponent &initial_mesh_component =
- geometry_set_final.get_component_for_write<MeshComponent>();
- initial_mesh_component.copy_vertex_group_names_from_object(*ob);
-
BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
/* Deformed vertex locations array. Deform only modifier need this type of
@@ -1076,10 +1069,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
continue;
}
- if (mti->dependsOnTime && mti->dependsOnTime(md)) {
- continue;
- }
-
if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
if (!deformed_verts) {
deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
@@ -1173,10 +1162,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
continue;
}
- if (mti->dependsOnTime && mti->dependsOnTime(md)) {
- continue;
- }
-
/* Add orco mesh as layer if needed by this modifier. */
if (mesh_final && mesh_orco && mti->requiredDataMask) {
CustomData_MeshMasks mask = {0};
@@ -1412,7 +1397,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
* we need to apply these back onto the Mesh. If we have no
* Mesh then we need to build one. */
if (mesh_final == nullptr) {
- /* Note: this check on cdmask is a bit dodgy, it handles the issue at stake here (see T68211),
+ /* NOTE: this check on cdmask is a bit dodgy, it handles the issue at stake here (see T68211),
* but other cases might require similar handling?
* Could be a good idea to define a proper CustomData_MeshMask for that then. */
if (deformed_verts == nullptr && allow_shared_mesh &&
@@ -1610,12 +1595,6 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
GeometrySet geometry_set_final;
- /* Add the initial mesh component, with a copy of the vertex group names from the object,
- * since they need to be stored in the geometry set for evaluation. */
- MeshComponent &initial_mesh_component =
- geometry_set_final.get_component_for_write<MeshComponent>();
- initial_mesh_component.copy_vertex_group_names_from_object(*ob);
-
/* Deformed vertex locations array. Deform only modifier need this type of
* float array rather than MVert*. Tracked along with mesh_final as an
* optimization to avoid copying coordinates back and forth if there are
@@ -1959,8 +1938,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
/* Add the final mesh as read-only non-owning component to the geometry set. */
MeshComponent &mesh_component = geometry_set_eval->get_component_for_write<MeshComponent>();
- mesh_component.replace_mesh_but_keep_vertex_group_names(mesh_eval,
- GeometryOwnershipType::ReadOnly);
+ mesh_component.replace(mesh_eval, GeometryOwnershipType::ReadOnly);
ob->runtime.geometry_set_eval = geometry_set_eval;
ob->runtime.mesh_deform_eval = mesh_deform_eval;
@@ -1998,7 +1976,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
BKE_sculpt_update_object_before_eval(obedit);
}
- BKE_editmesh_free_derivedmesh(em);
+ BKE_editmesh_free_derived_caches(em);
Mesh *me_cage;
Mesh *me_final;
@@ -2426,7 +2404,7 @@ static void dm_debug_info_layers(DynStr *dynstr,
for (type = 0; type < CD_NUMTYPES; type++) {
if (CustomData_has_layer(cd, type)) {
- /* note: doesn't account for multiple layers */
+ /* NOTE: doesn't account for multiple layers. */
const char *name = CustomData_layertype_name(type);
const int size = CustomData_sizeof(type);
const void *pt = getElemDataArray(dm, type);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index fdf3558abed..d55f023d209 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -120,7 +120,7 @@ static void action_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src,
for (fcurve_src = action_src->curves.first; fcurve_src; fcurve_src = fcurve_src->next) {
/* Duplicate F-Curve. */
- /* XXX TODO pass subdata flag?
+ /* XXX TODO: pass subdata flag?
* But surprisingly does not seem to be doing any ID refcounting... */
fcurve_dst = BKE_fcurve_copy(fcurve_src);
@@ -497,9 +497,8 @@ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
}
/* Reconstruct group channel pointers.
- * Assumes that the channels are still in the proper order, i.e. that channels of the same group
- * are adjacent in the act->channels list. It also assumes that the groups
- * referred to by the FCurves are already in act->groups.
+ * Assumes that the groups referred to by the FCurves are already in act->groups.
+ * Reorders the main channel list to match group order.
*/
void BKE_action_groups_reconstruct(bAction *act)
{
@@ -514,23 +513,30 @@ void BKE_action_groups_reconstruct(bAction *act)
BLI_listbase_clear(&group->channels);
}
- bActionGroup *grp;
- bActionGroup *last_grp = NULL;
- LISTBASE_FOREACH (FCurve *, fcurve, &act->curves) {
- if (fcurve->grp == NULL) {
- continue;
- }
+ /* Sort the channels into the group lists, destroying the act->curves list. */
+ ListBase ungrouped = {NULL, NULL};
- grp = fcurve->grp;
- if (last_grp != grp) {
- /* If this is the first time we see this group, this must be the first channel. */
- grp->channels.first = fcurve;
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcurve, &act->curves) {
+ if (fcurve->grp) {
+ BLI_assert(BLI_findindex(&act->groups, fcurve->grp) >= 0);
+
+ BLI_addtail(&fcurve->grp->channels, fcurve);
+ }
+ else {
+ BLI_addtail(&ungrouped, fcurve);
}
+ }
+
+ /* Recombine into the main list. */
+ BLI_listbase_clear(&act->curves);
- /* This is the last channel, until it's overwritten by a later iteration. */
- grp->channels.last = fcurve;
- last_grp = grp;
+ LISTBASE_FOREACH (bActionGroup *, group, &act->groups) {
+ /* Copy the list header to preserve the pointers in the group. */
+ ListBase tmp = group->channels;
+ BLI_movelisttolist(&act->curves, &tmp);
}
+
+ BLI_movelisttolist(&act->curves, &ungrouped);
}
/* Remove the given channel from all groups */
diff --git a/source/blender/blenkernel/intern/action_mirror.c b/source/blender/blenkernel/intern/action_mirror.c
index 69e0091444b..48472dfc9b3 100644
--- a/source/blender/blenkernel/intern/action_mirror.c
+++ b/source/blender/blenkernel/intern/action_mirror.c
@@ -322,6 +322,25 @@ static void action_flip_pchan(Object *ob_arm,
/* Move back to bone-space space, using the flipped bone if it exists. */
mul_m4_m4m4(chan_mat, arm_mat_inv, chan_mat);
+ /* The rest pose having an X-axis that is not mapping to a left/right direction (so aligned
+ * with the Y or Z axis) creates issues when flipping the pose. Instead of a negative scale on
+ * the X-axis, it turns into a 180 degree rotation over the Y-axis.
+ * This has only been observed with bones that can't be flipped,
+ * hence the check for `pchan_flip`. */
+ const float unit_x[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+ const bool is_problematic = pchan_flip == NULL &&
+ fabsf(dot_v4v4(pchan->bone->arm_mat[0], unit_x)) <= 1e-6;
+ if (is_problematic) {
+ /* Matrix needs to flip both the X and Z axes to come out right. */
+ float extra_mat[4][4] = {
+ {-1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, -1.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f},
+ };
+ mul_m4_m4m4(chan_mat, extra_mat, chan_mat);
+ }
+
BKE_pchan_apply_mat4(&pchan_temp, chan_mat, false);
/* Write the values back to the F-curves. */
diff --git a/source/blender/blenkernel/intern/action_test.cc b/source/blender/blenkernel/intern/action_test.cc
new file mode 100644
index 00000000000..c02eca966ad
--- /dev/null
+++ b/source/blender/blenkernel/intern/action_test.cc
@@ -0,0 +1,144 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation
+ * All rights reserved.
+ */
+
+#include "BKE_action.h"
+
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
+
+#include "BLI_listbase.h"
+
+#include "testing/testing.h"
+
+namespace blender::bke::tests {
+
+TEST(action_groups, ReconstructGroupsWithReordering)
+{
+ /* Construct an Action with three groups. */
+ bAction action = {{nullptr}};
+ FCurve groupAcurve1 = {nullptr};
+ FCurve groupAcurve2 = {nullptr};
+ FCurve groupBcurve1 = {nullptr};
+ FCurve groupBcurve2 = {nullptr};
+ FCurve groupBcurve3 = {nullptr};
+ /* Group C has no curves intentionally. */
+ FCurve groupDcurve1 = {nullptr};
+ FCurve groupDcurve2 = {nullptr};
+
+ groupAcurve1.rna_path = (char *)"groupAcurve1";
+ groupAcurve2.rna_path = (char *)"groupAcurve2";
+ groupBcurve1.rna_path = (char *)"groupBcurve1";
+ groupBcurve2.rna_path = (char *)"groupBcurve2";
+ groupDcurve1.rna_path = (char *)"groupDcurve1";
+ groupBcurve3.rna_path = (char *)"groupBcurve3";
+ groupDcurve2.rna_path = (char *)"groupDcurve2";
+
+ BLI_addtail(&action.curves, &groupAcurve1);
+ BLI_addtail(&action.curves, &groupAcurve2);
+ BLI_addtail(&action.curves, &groupBcurve1);
+ BLI_addtail(&action.curves, &groupBcurve2);
+ BLI_addtail(&action.curves, &groupDcurve1);
+ BLI_addtail(&action.curves, &groupBcurve3); /* <-- The error that should be corrected. */
+ BLI_addtail(&action.curves, &groupDcurve2);
+
+ /* Introduce another error type, by changing some `prev` pointers. */
+ groupBcurve1.prev = nullptr;
+ groupBcurve3.prev = &groupBcurve2;
+ groupDcurve1.prev = &groupBcurve3;
+
+ bActionGroup groupA = {nullptr};
+ bActionGroup groupB = {nullptr};
+ bActionGroup groupC = {nullptr};
+ bActionGroup groupD = {nullptr};
+ strcpy(groupA.name, "groupA");
+ strcpy(groupB.name, "groupB");
+ strcpy(groupC.name, "groupC");
+ strcpy(groupD.name, "groupD");
+
+ BLI_addtail(&action.groups, &groupA);
+ BLI_addtail(&action.groups, &groupB);
+ BLI_addtail(&action.groups, &groupC);
+ BLI_addtail(&action.groups, &groupD);
+
+ groupAcurve1.grp = &groupA;
+ groupAcurve2.grp = &groupA;
+ groupBcurve1.grp = &groupB;
+ groupBcurve2.grp = &groupB;
+ groupBcurve3.grp = &groupB;
+ groupDcurve1.grp = &groupD;
+ groupDcurve2.grp = &groupD;
+
+ groupA.channels.first = &groupAcurve1;
+ groupA.channels.last = &groupAcurve2;
+ groupB.channels.first = &groupBcurve1;
+ groupB.channels.last = &groupBcurve3; /* The last channel in group B, after group C curve 1. */
+ groupD.channels.first = &groupDcurve1;
+ groupD.channels.last = &groupDcurve2;
+
+ EXPECT_EQ(groupA.channels.first, &groupAcurve1);
+ EXPECT_EQ(groupA.channels.last, &groupAcurve2);
+ EXPECT_EQ(groupB.channels.first, &groupBcurve1);
+ EXPECT_EQ(groupB.channels.last, &groupBcurve3);
+ EXPECT_EQ(groupC.channels.first, nullptr);
+ EXPECT_EQ(groupC.channels.last, nullptr);
+ EXPECT_EQ(groupD.channels.first, &groupDcurve1);
+ EXPECT_EQ(groupD.channels.last, &groupDcurve2);
+
+ BKE_action_groups_reconstruct(&action);
+
+ EXPECT_EQ(action.curves.first, &groupAcurve1);
+ EXPECT_EQ(action.curves.last, &groupDcurve2);
+
+ EXPECT_EQ(groupA.prev, nullptr);
+ EXPECT_EQ(groupB.prev, &groupA);
+ EXPECT_EQ(groupC.prev, &groupB);
+ EXPECT_EQ(groupD.prev, &groupC);
+
+ EXPECT_EQ(groupA.next, &groupB);
+ EXPECT_EQ(groupB.next, &groupC);
+ EXPECT_EQ(groupC.next, &groupD);
+ EXPECT_EQ(groupD.next, nullptr);
+
+ EXPECT_EQ(groupA.channels.first, &groupAcurve1);
+ EXPECT_EQ(groupA.channels.last, &groupAcurve2);
+ EXPECT_EQ(groupB.channels.first, &groupBcurve1);
+ EXPECT_EQ(groupB.channels.last, &groupBcurve3);
+ EXPECT_EQ(groupC.channels.first, nullptr);
+ EXPECT_EQ(groupC.channels.last, nullptr);
+ EXPECT_EQ(groupD.channels.first, &groupDcurve1);
+ EXPECT_EQ(groupD.channels.last, &groupDcurve2);
+
+ EXPECT_EQ(groupAcurve1.prev, nullptr);
+ EXPECT_EQ(groupAcurve2.prev, &groupAcurve1);
+ EXPECT_EQ(groupBcurve1.prev, &groupAcurve2);
+ EXPECT_EQ(groupBcurve2.prev, &groupBcurve1);
+ EXPECT_EQ(groupBcurve3.prev, &groupBcurve2);
+ EXPECT_EQ(groupDcurve1.prev, &groupBcurve3);
+ EXPECT_EQ(groupDcurve2.prev, &groupDcurve1);
+
+ EXPECT_EQ(groupAcurve1.next, &groupAcurve2);
+ EXPECT_EQ(groupAcurve2.next, &groupBcurve1);
+ EXPECT_EQ(groupBcurve1.next, &groupBcurve2);
+ EXPECT_EQ(groupBcurve2.next, &groupBcurve3);
+ EXPECT_EQ(groupBcurve3.next, &groupDcurve1);
+ EXPECT_EQ(groupDcurve1.next, &groupDcurve2);
+ EXPECT_EQ(groupDcurve2.next, nullptr);
+}
+
+} // namespace blender::bke::tests
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 2f71dda17f2..7e4ab754500 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -89,16 +89,16 @@ bool id_can_have_animdata(const ID *id)
return id_type_can_have_animdata(GS(id->name));
}
-/* Get AnimData from the given ID-block. In order for this to work, we assume that
- * the AnimData pointer is stored immediately after the given ID-block in the struct,
- * as per IdAdtTemplate.
+/**
+ * Get #AnimData from the given ID-block.
*/
AnimData *BKE_animdata_from_id(ID *id)
{
- /* only some ID-blocks have this info for now, so we cast the
- * types that do to be of type IdAdtTemplate, and extract the
- * AnimData that way
- */
+ /* In order for this to work, we assume that the #AnimData pointer is stored
+ * immediately after the given ID-block in the struct, as per IdAdtTemplate. */
+
+ /* Only some ID-blocks have this info for now, so we cast the types that do
+ * to be of type IdAdtTemplate, and add the AnimData to it using the template. */
if (id_can_have_animdata(id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
return iat->adt;
@@ -106,16 +106,16 @@ AnimData *BKE_animdata_from_id(ID *id)
return NULL;
}
-/* Add AnimData to the given ID-block. In order for this to work, we assume that
- * the AnimData pointer is stored immediately after the given ID-block in the struct,
- * as per IdAdtTemplate. Also note that
+/**
+ * Ensure #AnimData exists in the given ID-block (when supported).
*/
-AnimData *BKE_animdata_add_id(ID *id)
+AnimData *BKE_animdata_ensure_id(ID *id)
{
- /* Only some ID-blocks have this info for now, so we cast the
- * types that do to be of type IdAdtTemplate, and add the AnimData
- * to it using the template
- */
+ /* In order for this to work, we assume that the #AnimData pointer is stored
+ * immediately after the given ID-block in the struct, as per IdAdtTemplate. */
+
+ /* Only some ID-blocks have this info for now, so we cast the types that do
+ * to be of type IdAdtTemplate, and add the AnimData to it using the template. */
if (id_can_have_animdata(id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
@@ -336,7 +336,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
* BKE_id_copy_ex().
* So in case we do copy the ID and its sub-IDs in bmain, silence the 'no usercount' flag for
* the sub-IDs copying.
- * Note: This is a bit weak, as usually when it comes to recursive ID copy. Should work for
+ * NOTE: This is a bit weak, as usually when it comes to recursive ID copy. Should work for
* now, but we may have to revisit this at some point and add a proper extra flag to deal with
* that situation. Or refactor completely the way we handle such recursion, by flattening it
* e.g. */
@@ -444,7 +444,7 @@ void BKE_animdata_merge_copy(
return;
}
- // TODO: we must unset all "tweakmode" flags
+ /* TODO: we must unset all "tweak-mode" flags. */
if ((src->flag & ADT_NLA_EDIT_ON) || (dst->flag & ADT_NLA_EDIT_ON)) {
CLOG_ERROR(
&LOG,
@@ -667,7 +667,7 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
/* get animdata from src, and create for destination (if needed) */
srcAdt = BKE_animdata_from_id(srcID);
- dstAdt = BKE_animdata_add_id(dstID);
+ dstAdt = BKE_animdata_ensure_id(dstID);
if (ELEM(NULL, srcAdt, dstAdt)) {
if (G.debug & G_DEBUG) {
@@ -1563,7 +1563,7 @@ void BKE_animdata_blend_write(BlendWriter *writer, struct AnimData *adt)
BLO_write_string(writer, aor->rna_path);
}
- /* TODO write the remaps (if they are needed) */
+ /* TODO: write the remaps (if they are needed). */
/* write NLA data */
BKE_nla_blend_write(writer, &adt->nla_tracks);
@@ -1590,10 +1590,10 @@ void BKE_animdata_blend_read_data(BlendDataReader *reader, AnimData *adt)
/* relink active track/strip - even though strictly speaking this should only be used
* if we're in 'tweaking mode', we need to be able to have this loaded back for
- * undo, but also since users may not exit tweakmode before saving (T24535)
+ * undo, but also since users may not exit tweak-mode before saving (T24535).
*/
/* TODO: it's not really nice that anyone should be able to save the file in this
- * state, but it's going to be too hard to enforce this single case... */
+ * state, but it's going to be too hard to enforce this single case. */
BLO_read_data_address(reader, &adt->act_track);
BLO_read_data_address(reader, &adt->actstrip);
}
diff --git a/source/blender/blenkernel/intern/anim_path.c b/source/blender/blenkernel/intern/anim_path.c
index e2c2708101b..de470a15041 100644
--- a/source/blender/blenkernel/intern/anim_path.c
+++ b/source/blender/blenkernel/intern/anim_path.c
@@ -216,7 +216,7 @@ static bool binary_search_anim_path(const float *accum_len_arr,
if (UNLIKELY(cur_step == 0)) {
/* This should never happen unless there is something horribly wrong. */
CLOG_ERROR(&LOG, "Couldn't find any valid point on the animation path!");
- BLI_assert(!"Couldn't find any valid point on the animation path!");
+ BLI_assert_msg(0, "Couldn't find any valid point on the animation path!");
return false;
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 08a3f3fcf4f..2879a995ad6 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -621,6 +621,115 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
}
}
+/* This function assumes that the quaternion is fully keyed, and is stored in array index order. */
+static void animsys_quaternion_evaluate_fcurves(PathResolvedRNA quat_rna,
+ FCurve *first_fcurve,
+ const AnimationEvalContext *anim_eval_context,
+ float r_quaternion[4])
+{
+ FCurve *quat_curve_fcu = first_fcurve;
+ for (int prop_index = 0; prop_index < 4; ++prop_index, quat_curve_fcu = quat_curve_fcu->next) {
+ /* Big fat assumption that the quaternion is fully keyed, and stored in order. */
+ BLI_assert(STREQ(quat_curve_fcu->rna_path, first_fcurve->rna_path) &&
+ quat_curve_fcu->array_index == prop_index);
+
+ quat_rna.prop_index = prop_index;
+ r_quaternion[prop_index] = calculate_fcurve(&quat_rna, quat_curve_fcu, anim_eval_context);
+ }
+}
+
+/* This function assumes that the quaternion is fully keyed, and is stored in array index order. */
+static void animsys_blend_fcurves_quaternion(PathResolvedRNA *anim_rna,
+ FCurve *first_fcurve,
+ const AnimationEvalContext *anim_eval_context,
+ const float blend_factor)
+{
+ float current_quat[4];
+ RNA_property_float_get_array(&anim_rna->ptr, anim_rna->prop, current_quat);
+
+ float target_quat[4];
+ animsys_quaternion_evaluate_fcurves(*anim_rna, first_fcurve, anim_eval_context, target_quat);
+
+ float blended_quat[4];
+ interp_qt_qtqt(blended_quat, current_quat, target_quat, blend_factor);
+
+ RNA_property_float_set_array(&anim_rna->ptr, anim_rna->prop, blended_quat);
+}
+
+/* LERP between current value (blend_factor=0.0) and the value from the FCurve (blend_factor=1.0)
+ */
+static void animsys_blend_in_fcurves(PointerRNA *ptr,
+ ListBase *fcurves,
+ const AnimationEvalContext *anim_eval_context,
+ const float blend_factor)
+{
+ char *channel_to_skip = NULL;
+ int num_channels_to_skip = 0;
+ LISTBASE_FOREACH (FCurve *, fcu, fcurves) {
+
+ if (num_channels_to_skip) {
+ /* For skipping already-handled rotation channels. Rotation channels are handled per group,
+ * and not per individual channel. */
+ BLI_assert(channel_to_skip != NULL);
+ if (STREQ(channel_to_skip, fcu->rna_path)) {
+ /* This is indeed the channel we want to skip. */
+ num_channels_to_skip--;
+ continue;
+ }
+ }
+
+ if (!is_fcurve_evaluatable(fcu)) {
+ continue;
+ }
+
+ PathResolvedRNA anim_rna;
+ if (!BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ continue;
+ }
+
+ if (STREQ(RNA_property_identifier(anim_rna.prop), "rotation_quaternion")) {
+ animsys_blend_fcurves_quaternion(&anim_rna, fcu, anim_eval_context, blend_factor);
+
+ /* Skip the next three channels, because those have already been handled here. */
+ MEM_SAFE_FREE(channel_to_skip);
+ channel_to_skip = BLI_strdup(fcu->rna_path);
+ num_channels_to_skip = 3;
+ continue;
+ }
+ /* TODO(Sybren): do something similar as above for Euler and Axis/Angle representations. */
+
+ const float fcurve_value = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
+
+ float current_value;
+ float value_to_write;
+ if (BKE_animsys_read_from_rna_path(&anim_rna, &current_value)) {
+ value_to_write = (1 - blend_factor) * current_value + blend_factor * fcurve_value;
+
+ switch (RNA_property_type(anim_rna.prop)) {
+ case PROP_BOOLEAN:
+ /* Without this, anything less than 1.0 is converted to 'False' by
+ * ANIMSYS_FLOAT_AS_BOOL(). This is probably not desirable for blends, where anything
+ * above a 50% blend should act more like the FCurve than like the current value. */
+ case PROP_INT:
+ case PROP_ENUM:
+ value_to_write = roundf(value_to_write);
+ break;
+ default:
+ /* All other types are just handled as float, and value_to_write is already correct. */
+ break;
+ }
+ }
+ else {
+ /* Unable to read the current value for blending, so just apply the FCurve value instead. */
+ value_to_write = fcurve_value;
+ }
+
+ BKE_animsys_write_to_rna_path(&anim_rna, value_to_write);
+ }
+
+ MEM_SAFE_FREE(channel_to_skip);
+}
+
/* ***************************************** */
/* Driver Evaluation */
@@ -769,6 +878,16 @@ void animsys_evaluate_action(PointerRNA *ptr,
animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original);
}
+/* Evaluate Action and blend it into the current values of the animated properties. */
+void animsys_blend_in_action(PointerRNA *ptr,
+ bAction *act,
+ const AnimationEvalContext *anim_eval_context,
+ const float blend_factor)
+{
+ action_idcode_patch_check(ptr->owner_id, act);
+ animsys_blend_in_fcurves(ptr, &act->curves, anim_eval_context, blend_factor);
+}
+
/* ***************************************** */
/* NLA System - Evaluation */
@@ -1457,7 +1576,7 @@ static float nla_blend_value(const int blendmode,
return influence * (lower_value * strip_value) + (1 - influence) * lower_value;
case NLASTRIP_MODE_COMBINE:
- BLI_assert(!"combine mode");
+ BLI_assert_msg(0, "combine mode");
ATTR_FALLTHROUGH;
default:
@@ -1495,7 +1614,7 @@ static float nla_combine_value(const int mix_mode,
return lower_value * powf(strip_value / base_value, influence);
default:
- BLI_assert(!"invalid mix mode");
+ BLI_assert_msg(0, "invalid mix mode");
return lower_value;
}
}
@@ -1546,7 +1665,7 @@ static bool nla_blend_get_inverted_strip_value(const int blendmode,
return true;
case NLASTRIP_MODE_COMBINE:
- BLI_assert(!"combine mode");
+ BLI_assert_msg(0, "combine mode");
ATTR_FALLTHROUGH;
default:
@@ -1602,7 +1721,7 @@ static bool nla_combine_get_inverted_strip_value(const int mix_mode,
return true;
default:
- BLI_assert(!"invalid mix mode");
+ BLI_assert_msg(0, "invalid mix mode");
return false;
}
}
@@ -2746,7 +2865,7 @@ static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr,
}
}
- /** Note: Although we early out, we can still keyframe to the non-pushed action since the
+ /** NOTE: Although we early out, we can still keyframe to the non-pushed action since the
* keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without
* remapping.
*/
@@ -3033,7 +3152,7 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
NlaEvalChannel *nec = nlaevalchan_verify_key(eval_data, NULL, &key);
BLI_assert(nec);
if (nec->base_snapshot.length != count) {
- BLI_assert(!"invalid value count");
+ BLI_assert_msg(0, "invalid value count");
nlaeval_snapshot_free_data(&blended_snapshot);
return false;
}
@@ -3126,7 +3245,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
*
* 3) Drivers/expressions are evaluated on top of this, in an order where dependencies are
* resolved nicely.
- * Note: it may be necessary to have some tools to handle the cases where some higher-level
+ * NOTE: it may be necessary to have some tools to handle the cases where some higher-level
* drivers are added and cause some problematic dependencies that
* didn't exist in the local levels...
*
diff --git a/source/blender/blenkernel/intern/anim_visualization.c b/source/blender/blenkernel/intern/anim_visualization.c
index ecd71ec08fe..56bd8e769bc 100644
--- a/source/blender/blenkernel/intern/anim_visualization.c
+++ b/source/blender/blenkernel/intern/anim_visualization.c
@@ -50,8 +50,8 @@ void animviz_settings_init(bAnimVizSettings *avs)
/* path settings */
avs->path_bc = avs->path_ac = 10;
- avs->path_sf = 1; /* xxx - take from scene instead? */
- avs->path_ef = 250; /* xxx - take from scene instead? */
+ avs->path_sf = 1; /* XXX: Take from scene instead? */
+ avs->path_ef = 250; /* XXX: Take from scene instead? */
avs->path_viewflag = (MOTIONPATH_VIEW_KFRAS | MOTIONPATH_VIEW_KFNOS);
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 579f671e2b0..eae331fc7d1 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -191,8 +191,7 @@ bool BKE_appdir_folder_documents(char *dir)
{
dir[0] = '\0';
- const char *documents_path = (const char *)GHOST_getUserSpecialDir(
- GHOST_kUserSpecialDirDocuments);
+ const char *documents_path = GHOST_getUserSpecialDir(GHOST_kUserSpecialDirDocuments);
/* Usual case: Ghost gave us the documents path. We're done here. */
if (documents_path && BLI_is_dir(documents_path)) {
@@ -462,7 +461,7 @@ static bool get_path_user_ex(char *targetpath,
}
user_path[0] = '\0';
- user_base_path = (const char *)GHOST_getUserDir(version, blender_version_decimal(version));
+ user_base_path = GHOST_getUserDir(version, blender_version_decimal(version));
if (user_base_path) {
BLI_strncpy(user_path, user_base_path, FILE_MAX);
}
@@ -522,7 +521,7 @@ static bool get_path_system_ex(char *targetpath,
}
system_path[0] = '\0';
- system_base_path = (const char *)GHOST_getSystemDir(version, blender_version_decimal(version));
+ system_base_path = GHOST_getSystemDir(version, blender_version_decimal(version));
if (system_base_path) {
BLI_strncpy(system_path, system_base_path, FILE_MAX);
}
@@ -780,7 +779,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id,
default:
path[0] = '\0'; /* in case check_is_dir is false */
ok = false;
- BLI_assert(!"incorrect ID");
+ BLI_assert_msg(0, "incorrect ID");
break;
}
return ok ? path : NULL;
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index d0604f4bfda..b8ed519e8d1 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2405,9 +2405,9 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
BKE_pose_rest(frompose, false);
/* copy over all of the proxy's bone groups */
- /* TODO for later
+ /* TODO: for later
* - implement 'local' bone groups as for constraints
- * Note: this isn't trivial, as bones reference groups by index not by pointer,
+ * NOTE: this isn't trivial, as bones reference groups by index not by pointer,
* so syncing things correctly needs careful attention */
BLI_freelistN(&pose->agroups);
BLI_duplicatelist(&pose->agroups, &frompose->agroups);
@@ -2543,7 +2543,7 @@ static int rebuild_pose_bone(
* (grand-(grand-(...)))-child (as processed by the recursive, depth-first nature of this
* function) of the previous sibling.
*
- * Note: In most cases there is nothing to do here, but pose list may get out of order when some
+ * NOTE: In most cases there is nothing to do here, but pose list may get out of order when some
* bones are added, removed or moved in the armature data. */
bPoseChannel *pchan_prev = pchan->prev;
const Bone *last_visited_bone = *r_last_visited_bone_p;
@@ -2843,7 +2843,7 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
* hopefully this is OK. */
BKE_pose_ensure(NULL, ob, arm, true);
- ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ ctime = BKE_scene_ctime_get(scene); /* not accurate... */
/* In edit-mode or rest-position we read the data from the bones. */
if (arm->edbo || (arm->flag & ARM_RESTPOS)) {
diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c
index bca5503c8d2..5f721b49361 100644
--- a/source/blender/blenkernel/intern/armature_deform.c
+++ b/source/blender/blenkernel/intern/armature_deform.c
@@ -47,6 +47,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
@@ -485,7 +486,7 @@ static void armature_deform_coords_impl(const Object *ob_arm,
int defbase_len = 0; /* safety for vertexgroup index overflow */
int i, dverts_len = 0; /* safety for vertexgroup overflow */
bool use_dverts = false;
- int armature_def_nr;
+ int armature_def_nr = -1;
int cd_dvert_offset = -1;
/* in editmode, or not an armature */
@@ -500,11 +501,11 @@ static void armature_deform_coords_impl(const Object *ob_arm,
BLI_assert(0);
}
- /* get the def_nr for the overall armature vertex group if present */
- armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name);
+ if (BKE_object_supports_vertex_groups(ob_target)) {
+ /* get the def_nr for the overall armature vertex group if present */
+ armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name);
- if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- defbase_len = BLI_listbase_count(&ob_target->defbase);
+ defbase_len = BKE_object_defgroup_count(ob_target);
if (ob_target->type == OB_MESH) {
if (em_target == NULL) {
@@ -528,11 +529,9 @@ static void armature_deform_coords_impl(const Object *ob_arm,
dverts_len = gps_target->totpoints;
}
}
- }
- /* get a vertex-deform-index to posechannel array */
- if (deformflag & ARM_DEF_VGROUP) {
- if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
+ /* get a vertex-deform-index to posechannel array */
+ if (deformflag & ARM_DEF_VGROUP) {
/* if we have a Mesh, only use dverts if it has them */
if (em_target) {
cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
@@ -551,7 +550,8 @@ static void armature_deform_coords_impl(const Object *ob_arm,
*
* - Check whether keeping this consistent across frames gives speedup.
*/
- for (i = 0, dg = ob_target->defbase.first; dg; i++, dg = dg->next) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob_target);
+ for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) {
pchan_from_defbase[i] = BKE_pose_channel_find_name(ob_arm->pose, dg->name);
/* exclude non-deforming bones */
if (pchan_from_defbase[i]) {
diff --git a/source/blender/blenkernel/intern/armature_pose.cc b/source/blender/blenkernel/intern/armature_pose.cc
index ca11692372b..09e1c7d6615 100644
--- a/source/blender/blenkernel/intern/armature_pose.cc
+++ b/source/blender/blenkernel/intern/armature_pose.cc
@@ -26,6 +26,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
+#include "BLI_function_ref.hh"
#include "BLI_set.hh"
#include "DNA_action_types.h"
@@ -38,16 +39,62 @@
namespace {
using BoneNameSet = blender::Set<std::string>;
+using ActionApplier =
+ blender::FunctionRef<void(PointerRNA *, bAction *, const AnimationEvalContext *)>;
+
// Forward declarations.
BoneNameSet pose_apply_find_selected_bones(const bArmature *armature, const bPose *pose);
void pose_apply_disable_fcurves_for_unselected_bones(bAction *action,
const BoneNameSet &selected_bone_names);
void pose_apply_restore_fcurves(bAction *action);
+
+void pose_apply(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context,
+ ActionApplier applier);
+
} // namespace
-void BKE_pose_apply_action(struct Object *ob,
- struct bAction *action,
- struct AnimationEvalContext *anim_eval_context)
+void BKE_pose_apply_action_selected_bones(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context)
+{
+ auto evaluate_and_apply =
+ [](PointerRNA *ptr, bAction *act, const AnimationEvalContext *anim_eval_context) {
+ animsys_evaluate_action(ptr, act, anim_eval_context, false);
+ };
+
+ pose_apply(ob, action, anim_eval_context, evaluate_and_apply);
+}
+
+void BKE_pose_apply_action_all_bones(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context)
+{
+ PointerRNA pose_owner_ptr;
+ RNA_id_pointer_create(&ob->id, &pose_owner_ptr);
+ animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false);
+}
+
+void BKE_pose_apply_action_blend(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context,
+ const float blend_factor)
+{
+ auto evaluate_and_blend = [blend_factor](PointerRNA *ptr,
+ bAction *act,
+ const AnimationEvalContext *anim_eval_context) {
+ animsys_blend_in_action(ptr, act, anim_eval_context, blend_factor);
+ };
+
+ pose_apply(ob, action, anim_eval_context, evaluate_and_blend);
+}
+
+namespace {
+void pose_apply(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context,
+ ActionApplier applier)
{
bPose *pose = ob->pose;
if (pose == nullptr) {
@@ -67,14 +114,14 @@ void BKE_pose_apply_action(struct Object *ob,
/* Apply the Action. */
PointerRNA pose_owner_ptr;
RNA_id_pointer_create(&ob->id, &pose_owner_ptr);
- animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false);
+
+ applier(&pose_owner_ptr, action, anim_eval_context);
if (limit_to_selected_bones) {
pose_apply_restore_fcurves(action);
}
}
-namespace {
BoneNameSet pose_apply_find_selected_bones(const bArmature *armature, const bPose *pose)
{
BoneNameSet selected_bone_names;
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 0f8956a1a91..35ae2d2dbef 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -562,7 +562,7 @@ static void splineik_evaluate_bone(
* spline dictates, while still maintaining roll control from the existing bone animation. */
mul_m3_m3m3(pose_mat, dmat, rmat);
- /* Attempt to reduce shearing, though I doubt this'll really help too much now... */
+ /* Attempt to reduce shearing, though I doubt this will really help too much now. */
normalize_m3(pose_mat);
mul_m3_m3m3(base_pose_mat, dmat, base_pose_mat);
@@ -828,7 +828,7 @@ void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *ob
{
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
BLI_assert(object->type == OB_ARMATURE);
- const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
bArmature *armature = (bArmature *)object->data;
if (armature->flag & ARM_RESTPOS) {
return;
@@ -869,7 +869,7 @@ void BKE_pose_eval_bone(struct Depsgraph *depsgraph, Scene *scene, Object *objec
else {
if ((pchan->flag & POSE_DONE) == 0) {
/* TODO(sergey): Use time source node for time. */
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
BKE_pose_where_is_bone(depsgraph, scene, object, pchan, ctime, 1);
}
}
@@ -897,7 +897,7 @@ void BKE_pose_constraints_evaluate(struct Depsgraph *depsgraph,
}
else {
if ((pchan->flag & POSE_DONE) == 0) {
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
BKE_pose_where_is_bone(depsgraph, scene, object, pchan, ctime, 1);
}
}
@@ -981,7 +981,7 @@ void BKE_pose_iktree_evaluate(struct Depsgraph *depsgraph,
DEG_debug_print_eval_subdata(
depsgraph, __func__, object->id.name, object, "rootchan", rootchan->name, rootchan);
BLI_assert(object->type == OB_ARMATURE);
- const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
if (armature->flag & ARM_RESTPOS) {
return;
}
@@ -1002,7 +1002,7 @@ void BKE_pose_splineik_evaluate(struct Depsgraph *depsgraph,
DEG_debug_print_eval_subdata(
depsgraph, __func__, object->id.name, object, "rootchan", rootchan->name, rootchan);
BLI_assert(object->type == OB_ARMATURE);
- const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
if (armature->flag & ARM_RESTPOS) {
return;
}
@@ -1031,7 +1031,7 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph, Scene *scene, Object *ob
bPose *pose = object->pose;
BLI_assert(pose != NULL);
UNUSED_VARS_NDEBUG(pose);
- const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
BLI_assert(object->type == OB_ARMATURE);
/* Release the IK tree. */
diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc
index b5a7f5e37a6..f74018b20c5 100644
--- a/source/blender/blenkernel/intern/asset.cc
+++ b/source/blender/blenkernel/intern/asset.cc
@@ -110,6 +110,11 @@ void BKE_asset_metadata_tag_remove(AssetMetaData *asset_data, AssetTag *tag)
BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags);
}
+void BKE_asset_library_reference_init_default(AssetLibraryReference *library_ref)
+{
+ memcpy(library_ref, DNA_struct_default_get(AssetLibraryReference), sizeof(*library_ref));
+}
+
/* Queries -------------------------------------------- */
PreviewImage *BKE_asset_metadata_preview_get_from_id(const AssetMetaData *UNUSED(asset_data),
diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c
index 5db45471f0a..ad2be4ffe30 100644
--- a/source/blender/blenkernel/intern/attribute.c
+++ b/source/blender/blenkernel/intern/attribute.c
@@ -119,7 +119,7 @@ bool BKE_id_attribute_rename(ID *id,
ReportList *reports)
{
if (BKE_id_attribute_required(id, layer)) {
- BLI_assert(!"Required attribute name is not editable");
+ BLI_assert_msg(0, "Required attribute name is not editable");
return false;
}
@@ -202,7 +202,7 @@ AttributeDomain BKE_id_attribute_domain(ID *id, CustomDataLayer *layer)
}
}
- BLI_assert(!"Custom data layer not found in geometry");
+ BLI_assert_msg(0, "Custom data layer not found in geometry");
return ATTR_DOMAIN_NUM;
}
@@ -218,7 +218,7 @@ int BKE_id_attribute_data_length(ID *id, CustomDataLayer *layer)
}
}
- BLI_assert(!"Custom data layer not found in geometry");
+ BLI_assert_msg(0, "Custom data layer not found in geometry");
return 0;
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index e84b485c466..97a54f289ee 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -127,7 +127,7 @@ static void blender_version_init(void)
version_cycle = "";
}
else {
- BLI_assert(!"Invalid Blender version cycle");
+ BLI_assert_msg(0, "Invalid Blender version cycle");
}
BLI_snprintf(blender_version_string,
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index f31d8f5ade7..19721b4313d 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -128,7 +128,7 @@ static void setup_app_userdef(BlendFileData *bfd)
}
/**
- * Context matching, handle no-ui case
+ * Context matching, handle no-UI case.
*
* \note this is called on Undo so any slow conversion functions here
* should be avoided or check (mode != LOAD_UNDO).
@@ -622,6 +622,7 @@ UserDef *BKE_blendfile_userdef_from_defaults(void)
"io_scene_obj",
"io_scene_x3d",
"cycles",
+ "pose_library",
};
for (int i = 0; i < ARRAY_SIZE(addons); i++) {
bAddon *addon = BKE_addon_new();
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index f26a9f06697..70274de8bff 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -18,7 +18,7 @@
* \ingroup bli
*/
-/* TODO,
+/* TODO:
* currently there are some cases we don't support.
* - passing output paths to the visitor?, like render out.
* - passing sequence strips with many images.
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index fdf9cf21b85..abf7bab7612 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -379,10 +379,10 @@ static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
BKE_lib_id_swap(NULL, id_new, id_old);
/* `id_new` now has content from `id_old`, we need to ensure those old ID pointers are valid.
- * Note: Since we want to re-use all old pointers here, code is much simpler than for Scene. */
+ * NOTE: Since we want to re-use all old pointers here, code is much simpler than for Scene. */
BKE_library_foreach_ID_link(NULL, id_new, brush_undo_preserve_cb, reader, IDWALK_NOP);
- /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be
+ /* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
SWAP(IDProperty *, id_new->properties, id_old->properties);
}
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.cc
index 4659c464099..164f921c7ac 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.cc
@@ -21,9 +21,9 @@
* \ingroup bke
*/
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -46,15 +46,15 @@
/** \name BVHCache
* \{ */
-typedef struct BVHCacheItem {
+struct BVHCacheItem {
bool is_filled;
BVHTree *tree;
-} BVHCacheItem;
+};
-typedef struct BVHCache {
+struct BVHCache {
BVHCacheItem items[BVHTREE_MAX_ITEM];
ThreadMutex mutex;
-} BVHCache;
+};
/**
* Queries a bvhcache for the cache bvhtree of the request type
@@ -74,14 +74,14 @@ static bool bvhcache_find(BVHCache **bvh_cache_p,
if (r_locked) {
*r_locked = false;
}
- if (*bvh_cache_p == NULL) {
+ if (*bvh_cache_p == nullptr) {
if (!do_lock) {
/* Cache does not exist and no lock is requested. */
return false;
}
/* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */
BLI_mutex_lock(mesh_eval_mutex);
- if (*bvh_cache_p == NULL) {
+ if (*bvh_cache_p == nullptr) {
*bvh_cache_p = bvhcache_init();
}
BLI_mutex_unlock(mesh_eval_mutex);
@@ -94,7 +94,7 @@ static bool bvhcache_find(BVHCache **bvh_cache_p,
}
if (do_lock) {
BLI_mutex_lock(&bvh_cache->mutex);
- bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL);
+ bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, nullptr, nullptr);
if (in_cache) {
BLI_mutex_unlock(&bvh_cache->mutex);
return in_cache;
@@ -113,11 +113,11 @@ static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
{
- if (bvh_cache == NULL) {
+ if (bvh_cache == nullptr) {
return false;
}
- for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) {
+ for (int i = 0; i < BVHTREE_MAX_ITEM; i++) {
if (bvh_cache->items[i].tree == tree) {
return true;
}
@@ -127,7 +127,7 @@ bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
BVHCache *bvhcache_init(void)
{
- BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__);
+ BVHCache *cache = (BVHCache *)MEM_callocN(sizeof(BVHCache), __func__);
BLI_mutex_init(&cache->mutex);
return cache;
}
@@ -137,7 +137,7 @@ BVHCache *bvhcache_init(void)
* as that will be done when the cache is freed.
*
* A call to this assumes that there was no previous cached tree of the given type
- * \warning The #BVHTree can be NULL.
+ * \warning The #BVHTree can be nullptr.
*/
static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type)
{
@@ -152,10 +152,10 @@ static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType typ
*/
void bvhcache_free(BVHCache *bvh_cache)
{
- for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) {
+ for (int index = 0; index < BVHTREE_MAX_ITEM; index++) {
BVHCacheItem *item = &bvh_cache->items[index];
BLI_bvhtree_free(item->tree);
- item->tree = NULL;
+ item->tree = nullptr;
}
BLI_mutex_end(&bvh_cache->mutex);
MEM_freeN(bvh_cache);
@@ -197,9 +197,10 @@ float bvhtree_ray_tri_intersection(const BVHTreeRay *ray,
float dist;
#ifdef USE_KDOPBVH_WATERTIGHT
- if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, NULL))
+ if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, nullptr))
#else
- if (isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON))
+ if (isect_ray_tri_epsilon_v3(
+ ray->origin, ray->direction, v0, v1, v2, &dist, nullptr, FLT_EPSILON))
#endif
{
return dist;
@@ -247,7 +248,7 @@ static void mesh_faces_nearest_point(void *userdata,
t0 = vert[face->v1].co;
t1 = vert[face->v2].co;
t2 = vert[face->v3].co;
- t3 = face->v4 ? vert[face->v4].co : NULL;
+ t3 = face->v4 ? vert[face->v4].co : nullptr;
do {
float nearest_tmp[3], dist_sq;
@@ -264,7 +265,7 @@ static void mesh_faces_nearest_point(void *userdata,
t1 = t2;
t2 = t3;
- t3 = NULL;
+ t3 = nullptr;
} while (t2);
}
@@ -300,7 +301,7 @@ static void editmesh_looptri_nearest_point(void *userdata,
const float co[3],
BVHTreeNearest *nearest)
{
- const BVHTreeFromEditMesh *data = userdata;
+ const BVHTreeFromEditMesh *data = (const BVHTreeFromEditMesh *)userdata;
BMEditMesh *em = data->em;
const BMLoop **ltri = (const BMLoop **)em->looptris[index];
@@ -339,7 +340,7 @@ static void mesh_faces_spherecast(void *userdata,
t0 = vert[face->v1].co;
t1 = vert[face->v2].co;
t2 = vert[face->v3].co;
- t3 = face->v4 ? vert[face->v4].co : NULL;
+ t3 = face->v4 ? vert[face->v4].co : nullptr;
do {
float dist;
@@ -360,7 +361,7 @@ static void mesh_faces_spherecast(void *userdata,
t1 = t2;
t2 = t3;
- t3 = NULL;
+ t3 = nullptr;
} while (t2);
}
@@ -457,7 +458,7 @@ static void mesh_edges_nearest_point(void *userdata,
}
}
-/* Helper, does all the point-spherecast work actually. */
+/* Helper, does all the point-sphere-cast work actually. */
static void mesh_verts_spherecast_do(int index,
const float v[3],
const BVHTreeRay *ray,
@@ -484,7 +485,7 @@ static void editmesh_verts_spherecast(void *userdata,
const BVHTreeRay *ray,
BVHTreeRayHit *hit)
{
- const BVHTreeFromEditMesh *data = userdata;
+ const BVHTreeFromEditMesh *data = (const BVHTreeFromEditMesh *)userdata;
BMVert *eve = BM_vert_at_index(data->em->bm, index);
mesh_verts_spherecast_do(index, eve->co, ray, hit);
@@ -600,7 +601,7 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon,
const BLI_bitmap *verts_mask,
int verts_num_active)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (verts_mask) {
BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
@@ -637,9 +638,9 @@ static void bvhtree_from_mesh_verts_setup_data(BVHTreeFromMesh *data,
data->tree = tree;
data->cached = is_cached;
- /* a NULL nearest callback works fine
+ /* a nullptr nearest callback works fine
* remember the min distance to point is the same as the min distance to BV of point */
- data->nearest_callback = NULL;
+ data->nearest_callback = nullptr;
data->raycast_callback = mesh_verts_spherecast;
data->vert = vert;
@@ -658,7 +659,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
bool lock_started = false;
@@ -671,7 +672,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
bvhtree_balance(tree, true);
/* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
+ // printf("BVHTree built and saved on cache\n");
bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type);
data->cached = true;
}
@@ -687,9 +688,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
memset(data, 0, sizeof(*data));
data->tree = tree;
data->em = em;
- data->nearest_callback = NULL;
+ data->nearest_callback = nullptr;
data->raycast_callback = editmesh_verts_spherecast;
- data->cached = bvh_cache_p != NULL;
+ data->cached = bvh_cache_p != nullptr;
}
return tree;
@@ -699,11 +700,11 @@ BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
return bvhtree_from_editmesh_verts_ex(
- data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
+ data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr);
}
/**
- * Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!).
+ * Builds a bvh tree where nodes are the given vertices (NOTE: does not copy given `vert`!).
* \param vert_allocated: if true, vert freeing will be done when freeing data.
* \param verts_mask: if not null, true elements give which vert to add to BVH tree.
* \param verts_num_active: if >= 0, number of active verts to add to BVH tree
@@ -724,7 +725,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
{
bool in_cache = false;
bool lock_started = false;
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
@@ -732,11 +733,11 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
if (in_cache == false) {
tree = bvhtree_from_mesh_verts_create_tree(
epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
- bvhtree_balance(tree, bvh_cache_p != NULL);
+ bvhtree_balance(tree, bvh_cache_p != nullptr);
if (bvh_cache_p) {
/* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
+ // printf("BVHTree built and saved on cache\n");
BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
in_cache = true;
@@ -807,7 +808,7 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert,
int tree_type,
int axis)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (edges_mask) {
BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num));
@@ -817,7 +818,7 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert,
}
if (edges_num_active) {
- /* Create a bvh-tree of the given target */
+ /* Create a BVH-tree of the given target */
tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
if (tree) {
for (int i = 0; i < edge_num; i++) {
@@ -871,7 +872,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
bool lock_started = false;
@@ -883,7 +884,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
epsilon, tree_type, axis, em, edges_mask, edges_num_active);
bvhtree_balance(tree, true);
/* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
+ // printf("BVHTree built and saved on cache\n");
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
data->cached = true;
}
@@ -899,9 +900,9 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
memset(data, 0, sizeof(*data));
data->tree = tree;
data->em = em;
- data->nearest_callback = NULL; /* TODO */
- data->raycast_callback = NULL; /* TODO */
- data->cached = bvh_cache_p != NULL;
+ data->nearest_callback = nullptr; /* TODO */
+ data->raycast_callback = nullptr; /* TODO */
+ data->cached = bvh_cache_p != nullptr;
}
return tree;
@@ -911,7 +912,7 @@ BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
return bvhtree_from_editmesh_edges_ex(
- data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
+ data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr);
}
/**
@@ -939,7 +940,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
{
bool in_cache = false;
bool lock_started = false;
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
@@ -953,7 +954,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
BVHCache *bvh_cache = *bvh_cache_p;
/* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
+ // printf("BVHTree built and saved on cache\n");
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
in_cache = true;
}
@@ -988,7 +989,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
const BLI_bitmap *faces_mask,
int faces_num_active)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (faces_num) {
if (faces_mask) {
@@ -998,8 +999,8 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
faces_num_active = faces_num;
}
- /* Create a bvh-tree of the given target */
- /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ /* Create a BVH-tree of the given target. */
+ // printf("%s: building BVH, total=%d\n", __func__, numFaces);
tree = BLI_bvhtree_new(faces_num_active, epsilon, tree_type, axis);
if (tree) {
if (vert && face) {
@@ -1050,7 +1051,7 @@ static void bvhtree_from_mesh_faces_setup_data(BVHTreeFromMesh *data,
/**
* Builds a bvh tree where nodes are the given tessellated faces
- * (note: does not copy given mfaces!).
+ * (NOTE: does not copy given mfaces!).
* \param vert_allocated: if true, vert freeing will be done when freeing data.
* \param face_allocated: if true, face freeing will be done when freeing data.
* \param faces_mask: if not null, true elements give which faces to add to BVH tree.
@@ -1074,7 +1075,7 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data,
{
bool in_cache = false;
bool lock_started = false;
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
@@ -1082,11 +1083,11 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data,
if (in_cache == false) {
tree = bvhtree_from_mesh_faces_create_tree(
epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active);
- bvhtree_balance(tree, bvh_cache_p != NULL);
+ bvhtree_balance(tree, bvh_cache_p != nullptr);
if (bvh_cache_p) {
/* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
+ // printf("BVHTree built and saved on cache\n");
BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
in_cache = true;
@@ -1117,7 +1118,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
const BLI_bitmap *looptri_mask,
int looptri_num_active)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
const int looptri_num = em->tottri;
if (looptri_num) {
@@ -1128,11 +1129,11 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
looptri_num_active = looptri_num;
}
- /* Create a bvh-tree of the given target */
- /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ /* Create a BVH-tree of the given target */
+ // printf("%s: building BVH, total=%d\n", __func__, numFaces);
tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
if (tree) {
- const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
+ const BMLoop *(*looptris)[3] = (const BMLoop *(*)[3])em->looptris;
/* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
* and/or selected. Even if the faces themselves are not selected for the snapped
@@ -1169,7 +1170,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
const BLI_bitmap *looptri_mask,
int looptri_num_active)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (looptri_mask) {
BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num));
@@ -1179,8 +1180,8 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
}
if (looptri_num_active) {
- /* Create a bvh-tree of the given target */
- /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ /* Create a BVH-tree of the given target */
+ // printf("%s: building BVH, total=%d\n", __func__, numFaces);
tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
if (tree) {
if (vert && looptri) {
@@ -1247,7 +1248,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
/* BMESH specific check that we have tessfaces,
* we _could_ tessellate here but rather not - campbell */
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
bool lock_started = false;
bool in_cache = bvhcache_find(
@@ -1260,7 +1261,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
/* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
+ // printf("BVHTree built and saved on cache\n");
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
}
bvhcache_unlock(bvh_cache, lock_started);
@@ -1276,7 +1277,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
data->nearest_callback = editmesh_looptri_nearest_point;
data->raycast_callback = editmesh_looptri_spherecast;
data->em = em;
- data->cached = bvh_cache_p != NULL;
+ data->cached = bvh_cache_p != nullptr;
}
return tree;
}
@@ -1285,13 +1286,13 @@ BVHTree *bvhtree_from_editmesh_looptri(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
return bvhtree_from_editmesh_looptri_ex(
- data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
+ data, em, nullptr, -1, epsilon, tree_type, axis, BVHTREE_FROM_VERTS, nullptr, nullptr);
}
/**
- * Builds a bvh tree where nodes are the looptri faces of the given dm
+ * Builds a BVH-tree where nodes are the looptri faces of the given mesh.
*
- * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces_ex
+ * \note for edit-mesh this is currently a duplicate of #bvhtree_from_mesh_faces_ex
*/
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -1312,7 +1313,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
{
bool in_cache = false;
bool lock_started = false;
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
if (bvh_cache_p) {
in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
@@ -1329,7 +1330,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
looptri_mask,
looptri_num_active);
- bvhtree_balance(tree, bvh_cache_p != NULL);
+ bvhtree_balance(tree, bvh_cache_p != nullptr);
if (bvh_cache_p) {
BVHCache *bvh_cache = *bvh_cache_p;
@@ -1437,19 +1438,22 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly,
/**
* Builds or queries a bvhcache for the cache bvhtree of the request type.
+ *
+ * \note This function only fills a cache, and therefore the mesh argument can
+ * be considered logically const. Concurrent access is protected by a mutex.
*/
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
- struct Mesh *mesh,
+ const struct Mesh *mesh,
const BVHCacheType bvh_cache_type,
const int tree_type)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache;
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
- bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
+ const bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, nullptr, nullptr);
- if (is_cached && tree == NULL) {
+ if (is_cached && tree == nullptr) {
memset(data, 0, sizeof(*data));
return tree;
}
@@ -1458,7 +1462,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
case BVHTREE_FROM_VERTS:
case BVHTREE_FROM_LOOSEVERTS:
if (is_cached == false) {
- BLI_bitmap *loose_verts_mask = NULL;
+ BLI_bitmap *loose_verts_mask = nullptr;
int loose_vert_len = -1;
int verts_len = mesh->totvert;
@@ -1480,7 +1484,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
bvh_cache_p,
mesh_eval_mutex);
- if (loose_verts_mask != NULL) {
+ if (loose_verts_mask != nullptr) {
MEM_freeN(loose_verts_mask);
}
}
@@ -1493,7 +1497,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
case BVHTREE_FROM_EDGES:
case BVHTREE_FROM_LOOSEEDGES:
if (is_cached == false) {
- BLI_bitmap *loose_edges_mask = NULL;
+ BLI_bitmap *loose_edges_mask = nullptr;
int loose_edges_len = -1;
int edges_len = mesh->totedge;
@@ -1516,7 +1520,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
bvh_cache_p,
mesh_eval_mutex);
- if (loose_edges_mask != NULL) {
+ if (loose_edges_mask != nullptr) {
MEM_freeN(loose_edges_mask);
}
}
@@ -1538,7 +1542,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
mesh->mface,
num_faces,
false,
- NULL,
+ nullptr,
-1,
0.0,
tree_type,
@@ -1561,7 +1565,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
int looptri_len = BKE_mesh_runtime_looptri_len(mesh);
int looptri_mask_active_len = -1;
- BLI_bitmap *looptri_mask = NULL;
+ BLI_bitmap *looptri_mask = nullptr;
if (bvh_cache_type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) {
looptri_mask = looptri_no_hidden_map_get(
mesh->mpoly, looptri_len, &looptri_mask_active_len);
@@ -1584,7 +1588,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
bvh_cache_p,
mesh_eval_mutex);
- if (looptri_mask != NULL) {
+ if (looptri_mask != nullptr) {
MEM_freeN(looptri_mask);
}
}
@@ -1603,7 +1607,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
break;
}
- if (data->tree != NULL) {
+ if (data->tree != nullptr) {
#ifdef DEBUG
if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
printf("tree_type %d obtained instead of %d\n",
@@ -1631,15 +1635,15 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
BVHCache **bvh_cache_p,
ThreadMutex *mesh_eval_mutex)
{
- BVHTree *tree = NULL;
+ BVHTree *tree = nullptr;
bool is_cached = false;
memset(data, 0, sizeof(*data));
if (bvh_cache_p) {
- is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
+ is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, nullptr, nullptr);
- if (is_cached && tree == NULL) {
+ if (is_cached && tree == nullptr) {
return tree;
}
}
@@ -1650,31 +1654,55 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
switch (bvh_cache_type) {
case BVHTREE_FROM_EM_VERTS:
if (is_cached == false) {
- tree = bvhtree_from_editmesh_verts_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
+ tree = bvhtree_from_editmesh_verts_ex(data,
+ em,
+ nullptr,
+ -1,
+ 0.0f,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
- data->nearest_callback = NULL;
+ data->nearest_callback = nullptr;
data->raycast_callback = editmesh_verts_spherecast;
}
break;
case BVHTREE_FROM_EM_EDGES:
if (is_cached == false) {
- tree = bvhtree_from_editmesh_edges_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
+ tree = bvhtree_from_editmesh_edges_ex(data,
+ em,
+ nullptr,
+ -1,
+ 0.0f,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
- data->nearest_callback = NULL; /* TODO */
- data->raycast_callback = NULL; /* TODO */
+ data->nearest_callback = nullptr; /* TODO */
+ data->raycast_callback = nullptr; /* TODO */
}
break;
case BVHTREE_FROM_EM_LOOPTRI:
if (is_cached == false) {
- tree = bvhtree_from_editmesh_looptri_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
+ tree = bvhtree_from_editmesh_looptri_ex(data,
+ em,
+ nullptr,
+ -1,
+ 0.0f,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1694,7 +1722,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
break;
}
- if (data->tree != NULL) {
+ if (data->tree != nullptr) {
#ifdef DEBUG
if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
printf("tree_type %d obtained instead of %d\n",
@@ -1763,7 +1791,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data,
{
BVHTree *tree = BLI_bvhtree_new(pointcloud->totpoint, 0.0f, tree_type, 6);
if (!tree) {
- return NULL;
+ return nullptr;
}
for (int i = 0; i < pointcloud->totpoint; i++) {
@@ -1774,7 +1802,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data,
data->coords = pointcloud->co;
data->tree = tree;
- data->nearest_callback = NULL;
+ data->nearest_callback = nullptr;
return tree;
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 30e9ae39b67..eaba5d33a20 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -314,7 +314,7 @@ bool BKE_cachefile_filepath_get(const Main *bmain,
if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) {
Scene *scene = DEG_get_evaluated_scene(depsgraph);
- const float ctime = BKE_scene_frame_get(scene);
+ const float ctime = BKE_scene_ctime_get(scene);
const float fps = (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base);
const float frame = BKE_cachefile_time_offset(cache_file, ctime, fps);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 879313783d9..039a971fe2c 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -289,7 +289,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
dm->dirty |= DM_DIRTY_NORMALS;
}
- /* TODO DM_DIRTY_TESS_CDLAYERS ? Maybe not though,
+ /* TODO: DM_DIRTY_TESS_CDLAYERS ? Maybe not though,
* since we probably want to switch to looptris? */
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 09bd397cc78..0fa58a74f2b 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -96,7 +96,7 @@ static BVHTree *bvhtree_build_from_cloth(ClothModifierData *clmd, float epsilon)
return NULL;
}
- /* create quadtree with k=26 */
+ /* Create quad-tree with k=26. */
BVHTree *bvhtree = BLI_bvhtree_new(cloth->primitive_num, epsilon, 4, 26);
/* fill tree */
@@ -262,17 +262,19 @@ static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int
static int do_step_cloth(
Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr)
{
+ /* simulate 1 frame forward */
ClothVertex *verts = NULL;
Cloth *cloth;
ListBase *effectors = NULL;
MVert *mvert;
unsigned int i = 0;
int ret = 0;
+ bool vert_mass_changed = false;
- /* simulate 1 frame forward */
cloth = clmd->clothObject;
verts = cloth->verts;
mvert = result->mvert;
+ vert_mass_changed = verts->mass != clmd->sim_parms->mass;
/* force any pinned verts to their constrained location. */
for (i = 0; i < clmd->clothObject->mvert_num; i++, verts++) {
@@ -283,6 +285,11 @@ static int do_step_cloth(
/* Get the current position. */
copy_v3_v3(verts->xconst, mvert[i].co);
mul_m4_v3(ob->obmat, verts->xconst);
+
+ if (vert_mass_changed) {
+ verts->mass = clmd->sim_parms->mass;
+ SIM_mass_spring_set_implicit_vertex_mass(cloth->implicit, i, verts->mass);
+ }
}
effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights, false);
@@ -597,7 +604,7 @@ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexC
Cloth *cloth = clmd->clothObject;
if (clmd->clothObject) {
- /* inverse matrix is not uptodate... */
+ /* Inverse matrix is not up to date. */
invert_m4_m4(ob->imat, ob->obmat);
for (i = 0; i < cloth->mvert_num; i++) {
@@ -991,7 +998,7 @@ static void cloth_hair_update_bending_targets(ClothModifierData *clmd)
return;
}
- /* XXX Note: we need to propagate frames from the root up,
+ /* XXX NOTE: we need to propagate frames from the root up,
* but structural hair springs are stored in reverse order.
* The bending springs however are then inserted in the same
* order as vertices again ...
@@ -1049,7 +1056,7 @@ static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd)
return;
}
- /* XXX Note: we need to propagate frames from the root up,
+ /* XXX NOTE: we need to propagate frames from the root up,
* but structural hair springs are stored in reverse order.
* The bending springs however are then inserted in the same
* order as vertices again ...
@@ -1883,7 +1890,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
cloth_hair_update_bending_rest_targets(clmd);
}
- /* note: the edges may already exist so run reinsert */
+ /* NOTE: the edges may already exist so run reinsert. */
/* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */
for (int i = 0; i < numedges; i++) { /* struct springs */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 24266dc6bea..c354115e030 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -115,7 +115,7 @@ static void collection_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons
((collection_src->id.flag & LIB_EMBEDDED_DATA) != 0));
/* Do not copy collection's preview (same behavior as for objects). */
- if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO: temp hack. */
BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id);
}
else {
@@ -191,7 +191,7 @@ static ID *collection_owner_get(Main *bmain, ID *id)
}
}
- BLI_assert(!"Embedded collection with no owner. Critical Main inconsistency.");
+ BLI_assert_msg(0, "Embedded collection with no owner. Critical Main inconsistency.");
return NULL;
}
@@ -522,7 +522,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
{
/* Master collection is not real datablock, can't be removed. */
if (collection->flag & COLLECTION_IS_MASTER) {
- BLI_assert(!"Scene master collection can't be deleted");
+ BLI_assert_msg(0, "Scene master collection can't be deleted");
return false;
}
@@ -888,7 +888,7 @@ Collection *BKE_collection_master_add()
{
/* Not an actual datablock, but owned by scene. */
Collection *master_collection = BKE_libblock_alloc(
- NULL, ID_GR, "Master Collection", LIB_ID_CREATE_NO_MAIN);
+ NULL, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN);
master_collection->id.flag |= LIB_EMBEDDED_DATA;
master_collection->flag |= COLLECTION_IS_MASTER;
master_collection->color_tag = COLLECTION_COLOR_NONE;
@@ -1706,7 +1706,7 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain)
for (Collection *collection = bmain->collections.first; collection != NULL;
collection = collection->id.next) {
if (collection->tag & COLLECTION_TAG_RELATION_REBUILD) {
- /* Note: we do not have easy access to 'which collections is root' info in that case, which
+ /* NOTE: we do not have easy access to 'which collections is root' info in that case, which
* means test for cycles in collection relationships may fail here. I don't think that is an
* issue in practice here, but worth keeping in mind... */
collection_parents_rebuild_recursive(collection);
@@ -1896,7 +1896,7 @@ static void layer_collection_flags_restore_recursive(LayerCollection *layer_coll
* and now we moved a new collection to be part of the background this collection should
* probably be disabled.
*
- * Note: If we were to also keep the exclude flag we would need to re-sync the collections.
+ * NOTE: If we were to also keep the exclude flag we would need to re-sync the collections.
*/
layer_collection->flag = flag->flag | (layer_collection->flag & LAYER_COLLECTION_EXCLUDE);
}
@@ -2203,8 +2203,8 @@ void BKE_scene_objects_iterator_end(BLI_Iterator *iter)
* Generate a new GSet (or extend given `objects_gset` if not NULL) with all objects referenced by
* all collections of given `scene`.
*
- * \note: This will include objects without a base currently (because they would belong to excluded
- * collections only e.g.).
+ * \note This will include objects without a base currently
+ * (because they would belong to excluded collections only e.g.).
*/
GSet *BKE_scene_objects_as_gset(Scene *scene, GSet *objects_gset)
{
diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c
index d6b318caa5e..52a599a0361 100644
--- a/source/blender/blenkernel/intern/colorband.c
+++ b/source/blender/blenkernel/intern/colorband.c
@@ -295,7 +295,7 @@ void BKE_colorband_init_from_table_rgba(ColorBand *coba,
const int array_len,
bool filter_samples)
{
- /* Note, we could use MAXCOLORBAND here, but results of re-sampling are nicer,
+ /* NOTE: we could use MAXCOLORBAND here, but results of re-sampling are nicer,
* avoid different behavior when limit is hit. */
if (array_len < 2) {
/* No Re-sample, just de-duplicate. */
@@ -420,7 +420,7 @@ bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
cbd1 = coba->data;
- /* Note: when ipotype >= COLBAND_INTERP_B_SPLINE,
+ /* NOTE: when ipotype >= COLBAND_INTERP_B_SPLINE,
* we cannot do early-out with a constant color before first color stop and after last one,
* because interpolation starts before and ends after those... */
ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 1484021cb9d..a9f0f69b855 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -873,7 +873,7 @@ static int sort_curvepoints(const void *a1, const void *a2)
/* ************************ more CurveMapping calls *************** */
-/* note; only does current curvemap! */
+/* NOTE: only does current curvemap! */
void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
{
CurveMap *cuma = cumap->cm + cumap->cur;
@@ -1267,9 +1267,9 @@ void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
BLI_INLINE int get_bin_float(float f)
{
- int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */
+ int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantization differences */
- /* note: clamp integer instead of float to avoid problems with NaN */
+ /* NOTE: clamp integer instead of float to avoid problems with NaN. */
CLAMP(bin, 0, 255);
return bin;
@@ -1497,7 +1497,7 @@ static void scopes_update_cb(void *__restrict userdata,
mul_v3_fl(ycc, INV_255);
minmax_v3v3_v3(min, max, ycc);
}
- /* Increment count for histo. */
+ /* Increment count for histogram. */
bin_lum[get_bin_float(luma)]++;
bin_r[get_bin_float(rgba[0])]++;
bin_g[get_bin_float(rgba[1])]++;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index ca03c9c3de4..47df31e3a2c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -299,7 +299,10 @@ void BKE_constraint_mat_convertspace(Object *ob,
mul_m4_m4m4(mat, imat, mat);
/* Use pose-space as stepping stone for other spaces. */
- if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
+ if (ELEM(to,
+ CONSTRAINT_SPACE_LOCAL,
+ CONSTRAINT_SPACE_PARLOCAL,
+ CONSTRAINT_SPACE_OWNLOCAL)) {
/* Call self with slightly different values. */
BKE_constraint_mat_convertspace(
ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
@@ -315,6 +318,17 @@ void BKE_constraint_mat_convertspace(Object *ob,
BKE_armature_mat_pose_to_bone(pchan, mat, mat);
}
}
+ /* pose to owner local */
+ else if (to == CONSTRAINT_SPACE_OWNLOCAL) {
+ /* pose to local */
+ if (pchan->bone) {
+ BKE_armature_mat_pose_to_bone(pchan, mat, mat);
+ }
+
+ /* local to owner local (recursive) */
+ BKE_constraint_mat_convertspace(
+ ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale);
+ }
/* pose to local with parent */
else if (to == CONSTRAINT_SPACE_PARLOCAL) {
if (pchan->bone) {
@@ -336,17 +350,59 @@ void BKE_constraint_mat_convertspace(Object *ob,
}
case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */
{
+ /* local to owner local */
+ if (to == CONSTRAINT_SPACE_OWNLOCAL) {
+ if (pchan->bone) {
+ copy_m4_m4(diff_mat, pchan->bone->arm_mat);
+
+ if (cob && cob->pchan && cob->pchan->bone) {
+ invert_m4_m4(imat, cob->pchan->bone->arm_mat);
+ mul_m4_m4m4(diff_mat, imat, diff_mat);
+ }
+
+ zero_v3(diff_mat[3]);
+ invert_m4_m4(imat, diff_mat);
+ mul_m4_series(mat, diff_mat, mat, imat);
+ }
+ }
/* local to pose - do inverse procedure that was done for pose to local */
+ else {
+ if (pchan->bone) {
+ /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
+ BKE_armature_mat_bone_to_pose(pchan, mat, mat);
+ }
+
+ /* use pose-space as stepping stone for other spaces */
+ if (ELEM(to,
+ CONSTRAINT_SPACE_WORLD,
+ CONSTRAINT_SPACE_PARLOCAL,
+ CONSTRAINT_SPACE_CUSTOM)) {
+ /* call self with slightly different values */
+ BKE_constraint_mat_convertspace(
+ ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
+ }
+ }
+ break;
+ }
+ case CONSTRAINT_SPACE_OWNLOCAL: { /* -------------- FROM OWNER LOCAL ---------- */
+ /* owner local to local */
if (pchan->bone) {
- /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
- BKE_armature_mat_bone_to_pose(pchan, mat, mat);
+ copy_m4_m4(diff_mat, pchan->bone->arm_mat);
+
+ if (cob && cob->pchan && cob->pchan->bone) {
+ invert_m4_m4(imat, cob->pchan->bone->arm_mat);
+ mul_m4_m4m4(diff_mat, imat, diff_mat);
+ }
+
+ zero_v3(diff_mat[3]);
+ invert_m4_m4(imat, diff_mat);
+ mul_m4_series(mat, imat, mat, diff_mat);
}
- /* use pose-space as stepping stone for other spaces */
- if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_CUSTOM)) {
+ if (to != CONSTRAINT_SPACE_LOCAL) {
/* call self with slightly different values */
BKE_constraint_mat_convertspace(
- ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
+ ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale);
}
break;
}
@@ -358,7 +414,11 @@ void BKE_constraint_mat_convertspace(Object *ob,
}
/* use pose-space as stepping stone for other spaces */
- if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_CUSTOM)) {
+ if (ELEM(to,
+ CONSTRAINT_SPACE_WORLD,
+ CONSTRAINT_SPACE_LOCAL,
+ CONSTRAINT_SPACE_OWNLOCAL,
+ CONSTRAINT_SPACE_CUSTOM)) {
/* call self with slightly different values */
BKE_constraint_mat_convertspace(
ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
@@ -470,7 +530,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
/* when not in EditMode, use the 'final' evaluated mesh, depsgraph
* ensures we build with CD_MDEFORMVERT layer
*/
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
BMEditMesh *em = BKE_editmesh_from_object(ob);
float plane[3];
float imat[3][3], tmat[3][3];
@@ -488,17 +548,17 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
float normal[3] = {0.0f, 0.0f, 0.0f};
float weightsum = 0.0f;
if (me_eval) {
- MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
+ const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
int numVerts = me_eval->totvert;
/* check that dvert is a valid pointers (just in case) */
if (dvert) {
- MDeformVert *dv = dvert;
- MVert *mv = me_eval->mvert;
/* get the average of all verts with that are in the vertex-group */
- for (int i = 0; i < numVerts; i++, dv++, mv++) {
- MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
+ for (int i = 0; i < numVerts; i++) {
+ const MDeformVert *dv = &dvert[i];
+ const MVert *mv = &me_eval->mvert[i];
+ const MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
if (dw && dw->weight > 0.0f) {
float nor[3];
@@ -867,7 +927,7 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph),
/* This following macro should be used for all standard single-target *_flush_tars functions
* to save typing and reduce maintenance woes.
- * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed)
+ * NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed)
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
* really just to help this code easier to read)
*/
@@ -889,7 +949,7 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph),
/* This following macro should be used for all standard single-target *_flush_tars functions
* to save typing and reduce maintenance woes. It does not do the subtarget related operations.
- * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed)
+ * NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed)
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
* really just to help this code easier to read)
*/
@@ -1088,7 +1148,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
}
-/* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */
+/* XXX NOTE: con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in `readfile.c`. */
static bConstraintTypeInfo CTI_CHILDOF = {
CONSTRAINT_TYPE_CHILDOF, /* type */
sizeof(bChildOfConstraint), /* size */
@@ -1205,7 +1265,7 @@ static void vectomat(const float vec[3],
u[2] = 1;
}
- /* note: even though 'n' is normalized, don't use 'project_v3_v3v3_normalized' below
+ /* NOTE: even though 'n' is normalized, don't use 'project_v3_v3v3_normalized' below
* because precision issues cause a problem in near degenerate states, see: T53455. */
/* project the up vector onto the plane specified by n */
@@ -1459,7 +1519,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
unit_m4(ct->matrix);
- /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
+ /* NOTE: when creating constraints that follow path, the curve gets the CU_PATH set now,
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
@@ -1543,8 +1603,8 @@ static void followpath_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
/* un-apply scaling caused by path */
if ((data->followflag & FOLLOWPATH_RADIUS) == 0) {
- /* XXX: Assume that scale correction means that radius
- * will have some scale error in it - Campbell. */
+ /* XXX(campbell): Assume that scale correction means that radius
+ * will have some scale error in it. */
float obsize[3];
mat4_to_size(obsize, cob->matrix);
@@ -2235,21 +2295,51 @@ static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
+ float target_mat[4][4];
+
+ copy_m4_m4(target_mat, ct->matrix);
+
+ /* Remove the shear of the target matrix if enabled.
+ * Use Y as the axis since it's the natural default for bones. */
+ if (data->flag & TRANSLIKE_REMOVE_TARGET_SHEAR) {
+ orthogonalize_m4_stable(target_mat, 1, false);
+ }
+
+ /* Finally, combine the matrices. */
switch (data->mix_mode) {
case TRANSLIKE_MIX_REPLACE:
- copy_m4_m4(cob->matrix, ct->matrix);
+ copy_m4_m4(cob->matrix, target_mat);
break;
+ /* Simple matrix multiplication. */
+ case TRANSLIKE_MIX_BEFORE_FULL:
+ mul_m4_m4m4(cob->matrix, target_mat, cob->matrix);
+ break;
+
+ case TRANSLIKE_MIX_AFTER_FULL:
+ mul_m4_m4m4(cob->matrix, cob->matrix, target_mat);
+ break;
+
+ /* Aligned Inherit Scale emulation. */
case TRANSLIKE_MIX_BEFORE:
- mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
+ mul_m4_m4m4_aligned_scale(cob->matrix, target_mat, cob->matrix);
break;
case TRANSLIKE_MIX_AFTER:
- mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
+ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, target_mat);
+ break;
+
+ /* Fully separate handling of channels. */
+ case TRANSLIKE_MIX_BEFORE_SPLIT:
+ mul_m4_m4m4_split_channels(cob->matrix, target_mat, cob->matrix);
+ break;
+
+ case TRANSLIKE_MIX_AFTER_SPLIT:
+ mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, target_mat);
break;
default:
- BLI_assert(!"Unknown Copy Transforms mix mode");
+ BLI_assert_msg(0, "Unknown Copy Transforms mix mode");
}
}
}
@@ -2901,7 +2991,7 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
break;
default:
- BLI_assert(!"Unknown Action mix mode");
+ BLI_assert_msg(0, "Unknown Action mix mode");
}
}
}
@@ -3791,7 +3881,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
unit_m4(targetMatrix);
INIT_MINMAX(curveMin, curveMax);
- /* XXX - don't think this is good calling this here - campbell */
+ /* XXX(campbell): don't think this is good calling this here. */
BKE_object_minmax(ct->tar, curveMin, curveMax, true);
/* get targetmatrix */
@@ -4242,7 +4332,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
float mat[4][4];
float no[3] = {0.0f, 0.0f, 0.0f};
- /* TODO should use FLT_MAX.. but normal projection doenst yet supports it */
+ /* TODO: should use FLT_MAX.. but normal projection doesn't yet supports it. */
hit.index = -1;
hit.dist = (scon->projLimit == 0.0f) ? BVH_RAYCAST_DIST_MAX : scon->projLimit;
@@ -5009,7 +5099,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co
}
Object *depth_object = context->depth_object;
- Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object);
+ const Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object);
if (depth_mesh == NULL) {
return;
}
@@ -6269,7 +6359,7 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph,
* (T26014 and T25725), since some constraints may not convert the solution back to the input
* space before blending but all are guaranteed to end up in good "world-space" result.
*/
- /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate,
+ /* NOTE: all kind of stuff here before (caused trouble), much easier to just interpolate,
* or did I miss something? -jahka (r.32105) */
if (enf < 1.0f) {
float solution[4][4];
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 1028790856c..dced945bea0 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1448,6 +1448,36 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
+const AssetLibraryReference *CTX_wm_asset_library(const bContext *C)
+{
+ return ctx_data_pointer_get(C, "asset_library");
+}
+
+AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
+{
+ AssetHandle *asset_handle_p =
+ (AssetHandle *)CTX_data_pointer_get_type(C, "asset_handle", &RNA_AssetHandle).data;
+ if (asset_handle_p) {
+ *r_is_valid = true;
+ return *asset_handle_p;
+ }
+
+ /* If the asset handle was not found in context directly, try if there's an active file with
+ * asset data there instead. Not nice to have this here, would be better to have this in
+ * `ED_asset.h`, but we can't include that in BKE. Even better would be not needing this at all
+ * and being able to have editors return this in the usual `context` callback. But that would
+ * require returning a non-owning pointer, which we don't have in the Asset Browser (yet). */
+ FileDirEntry *file =
+ (FileDirEntry *)CTX_data_pointer_get_type(C, "active_file", &RNA_FileSelectEntry).data;
+ if (file && file->asset_data) {
+ *r_is_valid = true;
+ return (AssetHandle){.file_data = file};
+ }
+
+ *r_is_valid = false;
+ return (AssetHandle){0};
+}
+
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)
{
Main *bmain = CTX_data_main(C);
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 4e1ec9ba35e..26894495777 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -398,8 +398,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
if (crazyspace_modifier_supports_deform_matrices(md)) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
if (defmats == NULL) {
- /* NOTE: Evaluated object si re-set to its original undeformed
- * state. */
+ /* NOTE: Evaluated object is re-set to its original un-deformed state. */
Mesh *me = object_eval.data;
me_eval = BKE_mesh_copy_for_eval(me, true);
crazyspace_init_verts_and_matrices(me_eval, &defmats, &deformedVerts);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index a5538453248..24615dd8c2b 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -2123,8 +2123,8 @@ static void tilt_bezpart(const BezTriple *prevbezt,
if (radius_array) {
if (nu->radius_interp == KEY_CU_EASE) {
/* Support 2.47 ease interp
- * Note! - this only takes the 2 points into account,
- * giving much more localized results to changes in radius, sometimes you want that */
+ * NOTE: this only takes the 2 points into account,
+ * giving much more localized results to changes in radius, sometimes you want that. */
*radius_array = prevbezt->radius + (bezt->radius - prevbezt->radius) *
(3.0f * fac * fac - 2.0f * fac * fac * fac);
}
@@ -2490,7 +2490,7 @@ static void make_bevel_list_3D_tangent(BevList *bl)
cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir);
normalize_v3(cross_tmp);
- tri_to_quat(bevp1->quat, zero, cross_tmp, bevp1->tan); /* XXX - could be faster */
+ tri_to_quat(bevp1->quat, zero, cross_tmp, bevp1->tan); /* XXX: could be faster. */
/* bevp0 = bevp1; */ /* UNUSED */
bevp1 = bevp2;
@@ -2559,8 +2559,8 @@ static void make_bevel_list_segment_2D(BevList *bl)
static void make_bevel_list_2D(BevList *bl)
{
- /* note: bevp->dir and bevp->quat are not needed for beveling but are
- * used when making a path from a 2D curve, therefore they need to be set - Campbell */
+ /* NOTE(campbell): `bevp->dir` and `bevp->quat` are not needed for beveling but are
+ * used when making a path from a 2D curve, therefore they need to be set. */
BevPoint *bevp0, *bevp1, *bevp2;
int nr;
@@ -3658,7 +3658,7 @@ static bool tridiagonal_solve_with_limits(float *a,
* is affected by all other points of the curve segment, in practice the influence
* decreases exponentially with distance.
*
- * Note: this algorithm assumes that the handle horizontal size is always 1/3 of the
+ * NOTE: this algorithm assumes that the handle horizontal size is always 1/3 of the
* of the interval to the next point. This rule ensures linear interpolation of time.
*
* ^ height (co 1)
diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c
index 7deac4e4f19..28b7c2dfba0 100644
--- a/source/blender/blenkernel/intern/curve_deform.c
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -168,7 +168,7 @@ static bool calc_curve_deform(
*
* Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
*
- * note: moved functions into quat_apply_track/vec_apply_track
+ * NOTE: moved functions into quat_apply_track/vec_apply_track
*/
copy_qt_qt(quat, new_quat);
copy_v3_v3(cent, co);
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index 72ee2587c8a..8e1577ab072 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -335,4 +335,4 @@ void CurveEval::assert_valid_point_attributes() const
ATTR_DOMAIN_POINT);
}
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 08d0af45e92..7aa9d1958eb 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -105,8 +105,10 @@ typedef struct LayerTypeInfo {
/**
* default layer name.
- * note! when NULL this is a way to ensure there is only ever one item
- * see: CustomData_layertype_is_singleton() */
+ *
+ * \note when NULL this is a way to ensure there is only ever one item
+ * see: CustomData_layertype_is_singleton().
+ */
const char *defaultname;
/**
@@ -329,7 +331,7 @@ static void layerInterp_normal(const void **sources,
int count,
void *dest)
{
- /* Note: This is linear interpolation, which is not optimal for vectors.
+ /* NOTE: This is linear interpolation, which is not optimal for vectors.
* Unfortunately, spherical interpolation of more than two values is hairy,
* so for now it will do... */
float no[3] = {0.0f};
@@ -1594,7 +1596,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 14: CD_ORCO */
{sizeof(float[3]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 15: CD_MTEXPOLY */ /* DEPRECATED */
- /* note, when we expose the UV Map / TexFace split to the user,
+ /* NOTE: when we expose the UV Map / TexFace split to the user,
* change this back to face Texture. */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 16: CD_MLOOPUV */
@@ -3555,7 +3557,7 @@ bool CustomData_bmesh_merge(const CustomData *source,
totelem = bm->totface;
break;
default: /* should never happen */
- BLI_assert(!"invalid type given");
+ BLI_assert_msg(0, "invalid type given");
iter_type = BM_VERTS_OF_MESH;
totelem = bm->totvert;
break;
@@ -3805,7 +3807,7 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
}
-/* Gets from the layer at physical index n, note: doesn't check type. */
+/* Gets from the layer at physical index n, NOTE: doesn't check type. */
void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
{
if (n < 0 || n >= data->totlayer) {
@@ -4974,7 +4976,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
size_t tmp_buff_size = 32;
const void **tmp_data_src = NULL;
- /* Note: NULL data_src may happen and be valid (see vgroups...). */
+ /* NOTE: NULL data_src may happen and be valid (see vgroups...). */
if (!data_dst) {
return;
}
@@ -4991,7 +4993,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
else {
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
- /* Note: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/ */
+ /* NOTE: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/. */
data_size = (size_t)type_info->size;
data_step = laymap->elem_size ? laymap->elem_size : data_size;
data_offset = laymap->data_offset;
diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c
index 314d5f4ff82..ef86a65f47d 100644
--- a/source/blender/blenkernel/intern/customdata_file.c
+++ b/source/blender/blenkernel/intern/customdata_file.c
@@ -361,9 +361,9 @@ bool cdf_write_open(CDataFile *cdf, const char *filename)
cdf->writef = f;
- /* fill header */
+ /* Fill header. */
header = &cdf->header;
- /* strcpy(, "BCDF"); // terminator out of range */
+ /* Copy "BCDF" (string terminator out of range). */
header->ID[0] = 'B';
header->ID[1] = 'C';
header->ID[2] = 'D';
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 12269cf0d51..605061570b8 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -691,7 +691,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
}
if (data_dst_to_delete) {
- /* Note:
+ /* NOTE:
* This won't affect newly created layers, if any, since tot_dst has not been updated!
* Also, looping backward ensures us we do not suffer
* from index shifting when deleting a layer. */
@@ -764,7 +764,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
}
}
else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
- /* Note: use_delete has not much meaning in this case, ignored. */
+ /* NOTE: use_delete has not much meaning in this case, ignored. */
if (fromlayers >= 0) { /* Real-layer index */
idx_src = fromlayers;
@@ -1437,7 +1437,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (vgroup_name) {
mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT);
if (mdef) {
- vg_idx = BKE_object_defgroup_name_index(ob_dst, vgroup_name);
+ vg_idx = BKE_id_defgroup_name_index(&me_dst->id, vgroup_name);
}
}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index e6ef569d4b9..f7ef84728b6 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -29,6 +29,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -64,7 +66,9 @@ bDeformGroup *BKE_object_defgroup_new(Object *ob, const char *name)
BLI_strncpy(defgroup->name, name, sizeof(defgroup->name));
- BLI_addtail(&ob->defbase, defgroup);
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
+ BLI_addtail(defbase, defgroup);
BKE_object_defgroup_unique_name(defgroup, ob);
BKE_object_batch_cache_dirty_tag(ob);
@@ -484,18 +488,120 @@ void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int
}
}
+bool BKE_object_supports_vertex_groups(const Object *ob)
+{
+ const ID *id = (const ID *)ob->data;
+ if (id == NULL) {
+ return false;
+ }
+
+ return ELEM(GS(id->name), ID_ME, ID_LT, ID_GD);
+}
+
+const ListBase *BKE_id_defgroup_list_get(const ID *id)
+{
+ switch (GS(id->name)) {
+ case ID_ME: {
+ const Mesh *me = (const Mesh *)id;
+ return &me->vertex_group_names;
+ }
+ case ID_LT: {
+ const Lattice *lt = (const Lattice *)id;
+ return &lt->vertex_group_names;
+ }
+ case ID_GD: {
+ const bGPdata *gpd = (const bGPdata *)id;
+ return &gpd->vertex_group_names;
+ }
+ default: {
+ BLI_assert_unreachable();
+ }
+ }
+ return NULL;
+}
+
+static const int *object_defgroup_active_index_get_p(const Object *ob)
+{
+ BLI_assert(BKE_object_supports_vertex_groups(ob));
+ switch (ob->type) {
+ case OB_MESH: {
+ const Mesh *mesh = (const Mesh *)ob->data;
+ return &mesh->vertex_group_active_index;
+ }
+ case OB_LATTICE: {
+ const Lattice *lattice = (const Lattice *)ob->data;
+ return &lattice->vertex_group_active_index;
+ }
+ case OB_GPENCIL: {
+ const bGPdata *gpd = (const bGPdata *)ob->data;
+ return &gpd->vertex_group_active_index;
+ }
+ }
+ return NULL;
+}
+
+ListBase *BKE_id_defgroup_list_get_mutable(ID *id)
+{
+ /* Cast away const just for the accessor. */
+ return (ListBase *)BKE_id_defgroup_list_get(id);
+}
+
bDeformGroup *BKE_object_defgroup_find_name(const Object *ob, const char *name)
{
- return (name && name[0] != '\0') ?
- BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name)) :
- NULL;
+ if (name == NULL || name[0] == '\0') {
+ return NULL;
+ }
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ return BLI_findstring(defbase, name, offsetof(bDeformGroup, name));
+}
+
+int BKE_id_defgroup_name_index(const ID *id, const char *name)
+{
+ if (name == NULL || name[0] == '\0') {
+ return -1;
+ }
+ const ListBase *defbase = BKE_id_defgroup_list_get(id);
+ return BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name));
+}
+
+const ListBase *BKE_object_defgroup_list(const Object *ob)
+{
+ BLI_assert(BKE_object_supports_vertex_groups(ob));
+ return BKE_id_defgroup_list_get((const ID *)ob->data);
}
int BKE_object_defgroup_name_index(const Object *ob, const char *name)
{
- return (name && name[0] != '\0') ?
- BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) :
- -1;
+ return BKE_id_defgroup_name_index((ID *)ob->data, name);
+}
+
+ListBase *BKE_object_defgroup_list_mutable(Object *ob)
+{
+ BLI_assert(BKE_object_supports_vertex_groups(ob));
+ return BKE_id_defgroup_list_get_mutable((ID *)ob->data);
+}
+
+int BKE_object_defgroup_count(const Object *ob)
+{
+ return BLI_listbase_count(BKE_object_defgroup_list(ob));
+}
+
+/**
+ * \note For historical reasons, the index starts at 1 rather than 0.
+ */
+int BKE_object_defgroup_active_index_get(const Object *ob)
+{
+ return *object_defgroup_active_index_get_p(ob);
+}
+
+/**
+ * \note For historical reasons, the index starts at 1 rather than 0.
+ */
+void BKE_object_defgroup_active_index_set(Object *ob, const int new_index)
+{
+ /* Cast away const just for the accessor. */
+ int *index = (int *)object_defgroup_active_index_get_p(ob);
+ *index = new_index;
}
/**
@@ -503,7 +609,8 @@ int BKE_object_defgroup_name_index(const Object *ob, const char *name)
*/
int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default)
{
- int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ int defbase_tot = *flip_map_len = BLI_listbase_count(defbase);
if (defbase_tot == 0) {
return NULL;
@@ -517,7 +624,7 @@ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const boo
map[i] = -1;
}
- for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
+ for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) {
if (map[i] == -1) { /* may be calculated previously */
/* in case no valid value is found, use this */
@@ -547,7 +654,8 @@ int *BKE_object_defgroup_flip_map_single(const Object *ob,
const bool use_default,
int defgroup)
{
- int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ int defbase_tot = *flip_map_len = BLI_listbase_count(defbase);
if (defbase_tot == 0) {
return NULL;
@@ -561,7 +669,7 @@ int *BKE_object_defgroup_flip_map_single(const Object *ob,
map[i] = use_default ? i : -1;
}
- dg = BLI_findlink(&ob->defbase, defgroup);
+ dg = BLI_findlink(defbase, defgroup);
BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
if (!STREQ(name_flip, dg->name)) {
@@ -578,7 +686,8 @@ int *BKE_object_defgroup_flip_map_single(const Object *ob,
int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_default)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, index);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *dg = BLI_findlink(defbase, index);
int flip_index = -1;
if (dg) {
@@ -595,9 +704,10 @@ int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_d
static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
{
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
bDeformGroup *curdef;
- for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
+ for (curdef = defbase->first; curdef; curdef = curdef->next) {
if (dg != curdef) {
if (STREQ(curdef->name, name)) {
return true;
@@ -716,7 +826,7 @@ MDeformWeight *BKE_defvert_ensure_index(MDeformVert *dvert, const int defgroup)
return dw_new;
}
-/* TODO. merge with code above! */
+/* TODO: merge with code above! */
/**
* Adds the given vertex to the specified vertex group, with given weight.
@@ -1189,7 +1299,10 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
{
int idx_src;
int idx_dst;
- int tot_dst = BLI_listbase_count(&ob_dst->defbase);
+ const ListBase *src_list = BKE_object_defgroup_list(ob_src);
+ ListBase *dst_defbase = BKE_object_defgroup_list_mutable(ob_dst);
+
+ int tot_dst = BLI_listbase_count(dst_defbase);
const size_t elem_size = sizeof(*((MDeformVert *)NULL));
@@ -1218,7 +1331,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
}
else if (use_delete && idx_dst > idx_src) {
while (idx_dst-- > idx_src) {
- BKE_object_defgroup_remove(ob_dst, ob_dst->defbase.last);
+ BKE_object_defgroup_remove(ob_dst, dst_defbase->last);
}
}
if (r_map) {
@@ -1255,7 +1368,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
if (use_delete) {
/* Remove all unused dst vgroups first, simpler in this case. */
- for (dg_dst = ob_dst->defbase.first; dg_dst;) {
+ for (dg_dst = dst_defbase->first; dg_dst;) {
bDeformGroup *dg_dst_next = dg_dst->next;
if (BKE_object_defgroup_name_index(ob_src, dg_dst->name) == -1) {
@@ -1265,7 +1378,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
}
}
- for (idx_src = 0, dg_src = ob_src->defbase.first; idx_src < num_layers_src;
+ for (idx_src = 0, dg_src = src_list->first; idx_src < num_layers_src;
idx_src++, dg_src = dg_src->next) {
if (!use_layers_src[idx_src]) {
continue;
@@ -1274,7 +1387,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
if ((idx_dst = BKE_object_defgroup_name_index(ob_dst, dg_src->name)) == -1) {
if (use_create) {
BKE_object_defgroup_add_name(ob_dst, dg_src->name);
- idx_dst = ob_dst->actdef - 1;
+ idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1;
}
else {
/* If we are not allowed to create missing dst vgroups, just skip matching src one. */
@@ -1334,14 +1447,18 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
const size_t elem_size = sizeof(*((MDeformVert *)NULL));
- /* Note:
+ /* NOTE:
* VGroups are a bit hairy, since their layout is defined on object level (ob->defbase),
* while their actual data is a (mesh) CD layer.
* This implies we may have to handle data layout itself while having NULL data itself,
* and even have to support NULL data_src in transfer data code
* (we always create a data_dst, though).
+ *
+ * Note: Above comment is outdated, but this function was written when that was true.
*/
- if (BLI_listbase_is_empty(&ob_src->defbase)) {
+
+ const ListBase *src_defbase = BKE_object_defgroup_list(ob_src);
+ if (BLI_listbase_is_empty(src_defbase)) {
if (use_delete) {
BKE_object_defgroup_remove_all(ob_dst);
}
@@ -1357,39 +1474,41 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
}
if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
- /* Note: use_delete has not much meaning in this case, ignored. */
+ /* NOTE: use_delete has not much meaning in this case, ignored. */
if (fromlayers >= 0) {
idx_src = fromlayers;
- if (idx_src >= BLI_listbase_count(&ob_src->defbase)) {
+ if (idx_src >= BLI_listbase_count(src_defbase)) {
/* This can happen when vgroups are removed from source object...
* Remapping would be really tricky here, we'd need to go over all objects in
* Main every time we delete a vgroup... for now, simpler and safer to abort. */
return false;
}
}
- else if ((idx_src = ob_src->actdef - 1) == -1) {
+ else if ((idx_src = BKE_object_defgroup_active_index_get(ob_src) - 1) == -1) {
return false;
}
if (tolayers >= 0) {
- /* Note: in this case we assume layer exists! */
+ /* NOTE: in this case we assume layer exists! */
idx_dst = tolayers;
- BLI_assert(idx_dst < BLI_listbase_count(&ob_dst->defbase));
+ const ListBase *dst_defbase = BKE_object_defgroup_list(ob_dst);
+ BLI_assert(idx_dst < BLI_listbase_count(dst_defbase));
+ UNUSED_VARS_NDEBUG(dst_defbase);
}
else if (tolayers == DT_LAYERS_ACTIVE_DST) {
- if ((idx_dst = ob_dst->actdef - 1) == -1) {
+ if ((idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1) == -1) {
bDeformGroup *dg_src;
if (!use_create) {
return true;
}
- dg_src = BLI_findlink(&ob_src->defbase, idx_src);
+ dg_src = BLI_findlink(src_defbase, idx_src);
BKE_object_defgroup_add_name(ob_dst, dg_src->name);
- idx_dst = ob_dst->actdef - 1;
+ idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1;
}
}
else if (tolayers == DT_LAYERS_INDEX_DST) {
- int num = BLI_listbase_count(&ob_src->defbase);
+ int num = BLI_listbase_count(src_defbase);
idx_dst = idx_src;
if (num <= idx_dst) {
if (!use_create) {
@@ -1402,13 +1521,13 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
}
}
else if (tolayers == DT_LAYERS_NAME_DST) {
- bDeformGroup *dg_src = BLI_findlink(&ob_src->defbase, idx_src);
+ bDeformGroup *dg_src = BLI_findlink(src_defbase, idx_src);
if ((idx_dst = BKE_object_defgroup_name_index(ob_dst, dg_src->name)) == -1) {
if (!use_create) {
return true;
}
BKE_object_defgroup_add_name(ob_dst, dg_src->name);
- idx_dst = ob_dst->actdef - 1;
+ idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1;
}
}
else {
@@ -1531,6 +1650,13 @@ void BKE_defvert_weight_to_rgb(float r_rgb[3], const float weight)
/** \name .blend file I/O
* \{ */
+void BKE_defbase_blend_write(BlendWriter *writer, const ListBase *defbase)
+{
+ LISTBASE_FOREACH (bDeformGroup *, defgroup, defbase) {
+ BLO_write_struct(writer, bDeformGroup, defgroup);
+ }
+}
+
void BKE_defvert_blend_write(BlendWriter *writer, int count, MDeformVert *dvlist)
{
if (dvlist == NULL) {
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index cfe4701fb69..a4ffaa8b10b 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -1694,7 +1694,7 @@ static void boundbox_displist_object(Object *ob)
ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), __func__);
}
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
if (mesh_eval) {
BKE_object_boundbox_calc_from_mesh(ob, mesh_eval);
}
diff --git a/source/blender/blenkernel/intern/displist_tangent.c b/source/blender/blenkernel/intern/displist_tangent.c
index 88fef1a4cfd..5c969d52aea 100644
--- a/source/blender/blenkernel/intern/displist_tangent.c
+++ b/source/blender/blenkernel/intern/displist_tangent.c
@@ -171,7 +171,7 @@ static void dlsurf_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
int idx = face_to_vert_index(dlt, face_num, vert_index);
- /* Note: For some reason the shading U and V are swapped compared to the
+ /* NOTE: For some reason the shading U and V are swapped compared to the
* one described in the surface format. */
r_uv[0] = (idx / dlt->dl->nr) / (float)(dlt->v_len);
r_uv[1] = (idx % dlt->dl->nr) / (float)(dlt->u_len);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 2eb18a06799..52996e3bcc7 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -248,7 +248,7 @@ typedef struct PaintAdjData {
int *n_target;
/** Index to start reading n_target for each point. */
int *n_index;
- /** Num of neighs for each point. */
+ /** Number of neighbors for each point. */
int *n_num;
/** Vertex adjacency flags. */
int *flags;
@@ -2288,7 +2288,8 @@ static void dynamic_paint_create_uv_surface_direct_cb(
/* Loop through samples, starting from middle point */
for (int sample = 0; sample < 5; sample++) {
/* Loop through every face in the mesh */
- /* XXX TODO This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here! */
+ /* XXX TODO: This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here!
+ */
for (int i = 0; i < tottri; i++) {
/* Check uv bb */
if ((faceBB[i].min[0] > point[sample][0]) || (faceBB[i].min[1] > point[sample][1]) ||
@@ -2476,7 +2477,7 @@ static int dynamic_paint_find_neighbor_pixel(const DynamicPaintCreateUVSurfaceDa
const int py,
const int n_index)
{
- /* Note: Current method only uses polygon edges to detect neighboring pixels.
+ /* NOTE: Current method only uses polygon edges to detect neighboring pixels.
* -> It doesn't always lead to the optimum pixel but is accurate enough
* and faster/simpler than including possible face tip point links)
*/
@@ -3817,7 +3818,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
ob,
true,
SUBFRAME_RECURSION,
- BKE_scene_frame_get(scene),
+ BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
mesh_p = BKE_mesh_copy_for_eval(dynamicPaint_brush_mesh_get(brush), false);
numOfVerts_p = mesh_p->totvert;
@@ -3833,7 +3834,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
ob,
true,
SUBFRAME_RECURSION,
- BKE_scene_frame_get(scene),
+ BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
mesh_c = dynamicPaint_brush_mesh_get(brush);
numOfVerts_c = mesh_c->totvert;
@@ -3893,7 +3894,7 @@ static void dynamicPaint_brushObjectCalculateVelocity(
ob,
false,
SUBFRAME_RECURSION,
- BKE_scene_frame_get(scene),
+ BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
copy_m4_m4(prev_obmat, ob->obmat);
@@ -3905,7 +3906,7 @@ static void dynamicPaint_brushObjectCalculateVelocity(
ob,
false,
SUBFRAME_RECURSION,
- BKE_scene_frame_get(scene),
+ BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
/* calculate speed */
@@ -4190,8 +4191,8 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
/* calculate barycentric weights for hit point */
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, hitCoord);
- /* simple check based on brush surface velocity,
- * todo: perhaps implement something that handles volume movement as well. */
+ /* Simple check based on brush surface velocity,
+ * TODO: perhaps implement something that handles volume movement as well. */
/* interpolate vertex speed vectors to get hit point velocity */
interp_v3_v3v3v3(brushPointVelocity,
@@ -4881,7 +4882,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, cons
0, sData->total_points, sData, dynamic_paint_prepare_adjacency_cb, &settings);
/* calculate average values (single thread).
- * Note: tried to put this in threaded callback (using _reduce feature),
+ * NOTE: tried to put this in threaded callback (using _reduce feature),
* but gave ~30% slower result! */
bData->average_dist = 0.0;
for (index = 0; index < sData->total_points; index++) {
@@ -5521,7 +5522,7 @@ static void dynamicPaint_doEffectStep(
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) {
const float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * timescale / 2.0f;
- /* Same as BLI_bitmask, but handled atomicaly as 'ePoint' locks. */
+ /* Same as #BLI_bitmask, but handled atomically as 'ePoint' locks. */
const size_t point_locks_size = (sData->total_points / 8) + 1;
uint8_t *point_locks = MEM_callocN(sizeof(*point_locks) * point_locks_size, __func__);
@@ -6069,7 +6070,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
if (bData) {
const bool surface_moved = dynamicPaint_surfaceHasMoved(surface, ob);
- /* get previous speed for accelertaion */
+ /* Get previous speed for acceleration. */
if (do_accel_data && bData->prev_velocity && bData->velocity) {
memcpy(bData->prev_velocity, bData->velocity, sData->total_points * sizeof(Vec3f));
}
@@ -6270,7 +6271,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph,
brushObj,
true,
SUBFRAME_RECURSION,
- BKE_scene_frame_get(scene),
+ BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
}
@@ -6311,7 +6312,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph,
brushObj,
true,
SUBFRAME_RECURSION,
- BKE_scene_frame_get(scene),
+ BKE_scene_ctime_get(scene),
eModifierType_DynamicPaint);
}
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 49c2a2cbd89..9cae74e4e9a 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -39,15 +39,14 @@
#include "BKE_mesh_wrapper.h"
#include "BKE_object.h"
-BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
+/**
+ * \note The caller is responsible for ensuring triangulation data,
+ * typically by calling #BKE_editmesh_looptri_calc.
+ */
+BMEditMesh *BKE_editmesh_create(BMesh *bm)
{
BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
-
em->bm = bm;
- if (do_tessellate) {
- BKE_editmesh_looptri_calc(em);
- }
-
return em;
}
@@ -209,7 +208,7 @@ void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em,
});
}
-void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
+void BKE_editmesh_free_derived_caches(BMEditMesh *em)
{
if (em->mesh_eval_cage) {
BKE_id_free(NULL, em->mesh_eval_cage);
@@ -223,9 +222,9 @@ void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
}
/* Does not free the #BMEditMesh struct itself. */
-void BKE_editmesh_free(BMEditMesh *em)
+void BKE_editmesh_free_data(BMEditMesh *em)
{
- BKE_editmesh_free_derivedmesh(em);
+ BKE_editmesh_free_derived_caches(em);
if (em->looptris) {
MEM_freeN(em->looptris);
@@ -330,7 +329,7 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me)
* otherwise there is no way to edit them.
* Similar code to #MESH_OT_customdata_custom_splitnormals_add operator,
* we want to keep same shading in case we were using auto-smooth so far.
- * Note: there is a problem here, which is that if someone starts a normal editing operation on
+ * NOTE: there is a problem here, which is that if someone starts a normal editing operation on
* previously auto-smooth-ed mesh, and cancel that operation, generated CLNORS data remain,
* with related sharp edges (and hence auto-smooth is 'lost').
* Not sure how critical this is, and how to fix that issue? */
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 9e0e1933a00..087481b1b5d 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -117,7 +117,7 @@ BMBVHTree *BKE_bmbvh_new_ex(BMesh *bm,
for (int i = 0; i < looptris_tot; i++) {
if (test_fn) {
- /* Note: the arrays won't align now! Take care. */
+ /* NOTE: the arrays won't align now! Take care. */
f_test = looptris[i][0]->f;
if (f_test != f_test_prev) {
test_fn_ret = test_fn(f_test, user_data);
diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c
index d849f4ab37d..da4ea742656 100644
--- a/source/blender/blenkernel/intern/editmesh_tangent.c
+++ b/source/blender/blenkernel/intern/editmesh_tangent.c
@@ -25,6 +25,7 @@
#include "DNA_defs.h"
#include "DNA_meshdata_types.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_tangent.h"
#include "BKE_mesh.h"
@@ -381,7 +382,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
#endif
mesh2tangent->precomputedFaceNormals = poly_normals;
- /* Note, we assume we do have tessellated loop normals at this point
+ /* NOTE: we assume we do have tessellated loop normals at this point
* (in case it is object-enabled), have to check this is valid. */
mesh2tangent->precomputedLoopNormals = loop_normals;
mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 97aba5e787d..1b628b16802 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -716,7 +716,7 @@ int get_effector_data(EffectorCache *eff,
}
else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) {
/* TODO: hair and points object support */
- Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
if (me_eval != NULL) {
copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co);
normal_short_to_float_v3(efd->nor, me_eval->mvert[*efd->index].no);
@@ -830,7 +830,7 @@ static void get_effector_tot(
if (eff->pd->shape == PFIELD_SHAPE_POINTS) {
/* TODO: hair and points object support */
- Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
*tot = me_eval != NULL ? me_eval->totvert : 1;
if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 7fe7b38e120..8f47a7e75d4 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -2147,7 +2147,7 @@ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime)
* \{ */
/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
- * Note: this is also used for drivers.
+ * NOTE: this is also used for drivers.
*/
static float evaluate_fcurve_ex(FCurve *fcu, float evaltime, float cvalue)
{
@@ -2194,9 +2194,9 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
float evaluate_fcurve_only_curve(FCurve *fcu, float evaltime)
{
- /* Can be used to evaluate the (keyframed) fcurve only.
- * Also works for driver-fcurves when the driver itself is not relevant.
- * E.g. when inserting a keyframe in a driver fcurve. */
+ /* Can be used to evaluate the (key-framed) f-curve only.
+ * Also works for driver-f-curves when the driver itself is not relevant.
+ * E.g. when inserting a keyframe in a driver f-curve. */
return evaluate_fcurve_ex(fcu, evaltime, 0.0);
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 947417af55d..2b48683a3a8 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -1283,10 +1283,10 @@ static void compute_obstaclesemission(Scene *scene,
# endif
/* Update frame time, this is considering current subframe fraction
* BLI_mutex_lock() called in manta_step(), so safe to update subframe here
- * TODO(sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph)
+ * TODO(sebbas): Using BKE_scene_ctime_get(scene) instead of new DEG_get_ctime(depsgraph)
* as subframes don't work with the latter yet. */
BKE_object_modifier_update_subframe(
- depsgraph, scene, effecobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
+ depsgraph, scene, effecobj, true, 5, BKE_scene_ctime_get(scene), eModifierType_Fluid);
if (subframes) {
obstacles_from_mesh(effecobj, fds, fes, &bb_temp, subframe_dt);
@@ -1616,7 +1616,7 @@ static void emit_from_particles(Object *flow_ob,
}
/* `DEG_get_ctime(depsgraph)` does not give sub-frame time. */
- state.time = BKE_scene_frame_get(scene);
+ state.time = BKE_scene_ctime_get(scene);
if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
continue;
@@ -2820,10 +2820,10 @@ static void compute_flowsemission(Scene *scene,
# endif
/* Update frame time, this is considering current subframe fraction
* BLI_mutex_lock() called in manta_step(), so safe to update subframe here
- * TODO(sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph)
+ * TODO(sebbas): Using BKE_scene_ctime_get(scene) instead of new DEG_get_ctime(depsgraph)
* as subframes don't work with the latter yet. */
BKE_object_modifier_update_subframe(
- depsgraph, scene, flowobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
+ depsgraph, scene, flowobj, true, 5, BKE_scene_ctime_get(scene), eModifierType_Fluid);
/* Emission from particles. */
if (ffs->source == FLUID_FLOW_SOURCE_PARTICLES) {
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index b9f0b97ab46..641c003d456 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -604,7 +604,7 @@ int BKE_fcm_envelope_find_index(FCM_EnvelopeData array[],
* NOTE: this needs to be at the start of the stack to be of use,
* as it needs to know the extents of the keyframes/sample-data.
*
- * Possible TODO - store length of cycle information that can be initialized from the extents of
+ * Possible TODO: store length of cycle information that can be initialized from the extents of
* the keyframes/sample-data, and adjusted as appropriate.
*/
@@ -688,7 +688,7 @@ static float fcm_cycles_time(
ofs = lastkey[0];
}
}
- if ((ELEM(0, side, mode))) {
+ if (ELEM(0, side, mode)) {
return evaltime;
}
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 8bb2c401b03..d0b9aeefa55 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -984,7 +984,7 @@ static bool vfont_to_curve(Object *ob,
}
if (dobreak) {
if (tb_scale.h == 0.0f) {
- /* Note: If underlined text is truncated away, the extra space is also truncated. */
+ /* NOTE: If underlined text is truncated away, the extra space is also truncated. */
custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
}
goto makebreak;
@@ -1032,7 +1032,7 @@ static bool vfont_to_curve(Object *ob,
current_line_length = 0.0f;
}
- /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
+ /* XXX(campbell): has been unused for years, need to check if this is useful, r4613 r5282. */
#if 0
if (ascii == '\n') {
xof = xof_scale;
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 28e46aab732..ef93a3f9b3f 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -53,7 +53,6 @@ GeometryComponent *MeshComponent::copy() const
if (mesh_ != nullptr) {
new_component->mesh_ = BKE_mesh_copy_for_eval(mesh_, false);
new_component->ownership_ = GeometryOwnershipType::Owned;
- new_component->vertex_group_names_ = blender::Map(vertex_group_names_);
}
return new_component;
}
@@ -67,7 +66,6 @@ void MeshComponent::clear()
}
mesh_ = nullptr;
}
- vertex_group_names_.clear();
}
bool MeshComponent::has_mesh() const
@@ -84,23 +82,6 @@ void MeshComponent::replace(Mesh *mesh, GeometryOwnershipType ownership)
ownership_ = ownership;
}
-/* This function exists for the same reason as #vertex_group_names_. Non-nodes modifiers need to
- * be able to replace the mesh data without losing the vertex group names, which may have come
- * from another object. */
-void MeshComponent::replace_mesh_but_keep_vertex_group_names(Mesh *mesh,
- GeometryOwnershipType ownership)
-{
- BLI_assert(this->is_mutable());
- if (mesh_ != nullptr) {
- if (ownership_ == GeometryOwnershipType::Owned) {
- BKE_id_free(nullptr, mesh_);
- }
- mesh_ = nullptr;
- }
- mesh_ = mesh;
- ownership_ = ownership;
-}
-
/* Return the mesh and clear the component. The caller takes over responsibility for freeing the
* mesh (if the component was responsible before). */
Mesh *MeshComponent::release()
@@ -111,28 +92,6 @@ Mesh *MeshComponent::release()
return mesh;
}
-void MeshComponent::copy_vertex_group_names_from_object(const Object &object)
-{
- BLI_assert(this->is_mutable());
- vertex_group_names_.clear();
- int index = 0;
- LISTBASE_FOREACH (const bDeformGroup *, group, &object.defbase) {
- vertex_group_names_.add(group->name, index);
- index++;
- }
-}
-
-const blender::Map<std::string, int> &MeshComponent::vertex_group_names() const
-{
- return vertex_group_names_;
-}
-
-/* This is only exposed for the internal attribute API. */
-blender::Map<std::string, int> &MeshComponent::vertex_group_names()
-{
- return vertex_group_names_;
-}
-
/* Get the mesh from this component. This method can be used by multiple threads at the same
* time. Therefore, the returned mesh should not be modified. No ownership is transferred. */
const Mesh *MeshComponent::get_for_read() const
@@ -864,12 +823,15 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
- const int vertex_group_index = mesh_component.vertex_group_names().lookup_default_as(
- attribute_name, -1);
+ if (mesh == nullptr) {
+ return {};
+ }
+ const int vertex_group_index = BLI_findstringindex(
+ &mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name));
if (vertex_group_index < 0) {
return {};
}
- if (mesh == nullptr || mesh->dvert == nullptr) {
+ if (mesh->dvert == nullptr) {
static const float default_value = 0.0f;
return {std::make_unique<fn::GVArray_For_SingleValueRef>(
CPPType::get<float>(), mesh->totvert, &default_value),
@@ -889,8 +851,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
if (mesh == nullptr) {
return {};
}
- const int vertex_group_index = mesh_component.vertex_group_names().lookup_default_as(
- attribute_name, -1);
+
+ const int vertex_group_index = BLI_findstringindex(
+ &mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name));
if (vertex_group_index < 0) {
return {};
}
@@ -913,16 +876,16 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
MeshComponent &mesh_component = static_cast<MeshComponent &>(component);
-
- const int vertex_group_index = mesh_component.vertex_group_names().pop_default_as(
- attribute_name, -1);
- if (vertex_group_index < 0) {
- return false;
- }
Mesh *mesh = mesh_component.get_for_write();
if (mesh == nullptr) {
return true;
}
+
+ const int vertex_group_index = BLI_findstringindex(
+ &mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name));
+ if (vertex_group_index < 0) {
+ return false;
+ }
if (mesh->dvert == nullptr) {
return true;
}
@@ -938,14 +901,14 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
- for (const auto item : mesh_component.vertex_group_names().items()) {
- const StringRefNull name = item.key;
- const int vertex_group_index = item.value;
- if (vertex_group_index >= 0) {
- AttributeMetaData meta_data{ATTR_DOMAIN_POINT, CD_PROP_FLOAT};
- if (!callback(name, meta_data)) {
- return false;
- }
+ const Mesh *mesh = mesh_component.get_for_read();
+ if (mesh == nullptr) {
+ return true;
+ }
+
+ LISTBASE_FOREACH (const bDeformGroup *, group, &mesh->vertex_group_names) {
+ if (!callback(group->name, {ATTR_DOMAIN_POINT, CD_PROP_FLOAT})) {
+ return false;
}
}
return true;
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 01b51d552a9..90a97264c8f 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -48,7 +48,6 @@ static void add_final_mesh_as_geometry_component(const Object &object, GeometryS
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
- mesh_component.copy_vertex_group_names_from_object(object);
}
}
@@ -566,6 +565,7 @@ static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup
}
PointCloud *new_pointcloud = BKE_pointcloud_new_nomain(totpoint);
+ MutableSpan new_positions{(float3 *)new_pointcloud->co, new_pointcloud->totpoint};
/* Transform each instance's point locations into the new point cloud. */
int offset = 0;
@@ -577,9 +577,7 @@ static PointCloud *join_pointcloud_position_attribute(Span<GeometryInstanceGroup
}
for (const float4x4 &transform : set_group.transforms) {
for (const int i : IndexRange(pointcloud->totpoint)) {
- const float3 old_position = pointcloud->co[i];
- const float3 new_position = transform * old_position;
- copy_v3_v3(new_pointcloud->co[offset + i], new_position);
+ new_positions[offset + i] = transform * float3(pointcloud->co[i]);
}
offset += pointcloud->totpoint;
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 459fc5e4c68..38397f8f307 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -87,12 +87,14 @@ static void greasepencil_copy_data(Main *UNUSED(bmain),
gpd_dst->mat = MEM_dupallocN(gpd_src->mat);
}
+ BKE_defgroup_copy_list(&gpd_dst->vertex_group_names, &gpd_src->vertex_group_names);
+
/* copy layers */
BLI_listbase_clear(&gpd_dst->layers);
LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
/* make a copy of source layer and its data */
- /* TODO here too could add unused flags... */
+ /* TODO: here too could add unused flags... */
bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src, true, true);
/* Apply local layer transform to all frames. Calc the active frame is not enough
@@ -165,6 +167,8 @@ static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id
BKE_animdata_blend_write(writer, gpd->adt);
}
+ BKE_defbase_blend_write(writer, &gpd->vertex_group_names);
+
BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
/* write grease-pencil layers to file */
@@ -227,6 +231,8 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
}
}
+ BLO_read_list(reader, &gpd->vertex_group_names);
+
/* Materials. */
BLO_read_pointer_array(reader, (void **)&gpd->mat);
@@ -498,6 +504,8 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_all)
/* materials */
MEM_SAFE_FREE(gpd->mat);
+ BLI_freelistN(&gpd->vertex_group_names);
+
/* free all data */
if (free_all) {
/* clear cache */
@@ -798,32 +806,6 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
/* Utilities for easier bulk-creation of geometry */
/**
- * Populate stroke with point data from data buffers.
- * \param gps: Grease pencil stroke
- * \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values.
- * \param totpoints: Total of points
- * \param mat: 4x4 transform matrix to transform points into the right coordinate space.
- */
-void BKE_gpencil_stroke_add_points(bGPDstroke *gps,
- const float *array,
- const int totpoints,
- const float mat[4][4])
-{
- for (int i = 0; i < totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- const int x = GP_PRIM_DATABUF_SIZE * i;
-
- pt->x = array[x];
- pt->y = array[x + 1];
- pt->z = array[x + 2];
- mul_m4_v3(mat, &pt->x);
-
- pt->pressure = array[x + 3];
- pt->strength = array[x + 4];
- }
-}
-
-/**
* Create a new stroke, with pre-allocated data buffers.
* \param mat_idx: Index of the material
* \param totpoints: Total points
@@ -2087,8 +2069,9 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
{
bGPdata *gpd = ob->data;
MDeformVert *dvert = NULL;
- const int def_nr = BLI_findindex(&ob->defbase, defgroup);
- const int totgrp = BLI_listbase_count(&ob->defbase);
+
+ const int def_nr = BLI_findindex(&gpd->vertex_group_names, defgroup);
+ const int totgrp = BLI_listbase_count(&gpd->vertex_group_names);
/* Remove points data */
if (gpd) {
@@ -2117,7 +2100,7 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
}
/* Remove the group */
- BLI_freelinkN(&ob->defbase, defgroup);
+ BLI_freelinkN(&gpd->vertex_group_names, defgroup);
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
@@ -2694,22 +2677,60 @@ static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer
}
/* -------------------------------------------------------------------- */
-/** \name Iterators
+/** \name Iterator
*
- * Iterate over all visible stroke of all visible layers inside a gpObject.
- * Also take into account onion-skinning.
+ * Iterate over all visible stroke of all visible layers inside a grease pencil datablock.
* \{ */
-void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
- Object *ob,
+void BKE_gpencil_visible_stroke_iter(bGPdata *gpd,
gpIterCb layer_cb,
gpIterCb stroke_cb,
- void *thunk,
- bool do_onion,
- int cfra)
+ void *thunk)
+{
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+
+ /* If scale to 0 the layer must be invisible. */
+ if (is_zero_v3(gpl->scale)) {
+ continue;
+ }
+
+ bGPDframe *act_gpf = gpl->actframe;
+ if (layer_cb) {
+ layer_cb(gpl, act_gpf, NULL, thunk);
+ }
+
+ if (act_gpf) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ stroke_cb(gpl, act_gpf, gps, thunk);
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Advanced Iterator
+ *
+ * Iterate over all visible stroke of all visible layers inside a gpObject.
+ * Also take into account onion-skinning.
+ * \{ */
+
+void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer,
+ Object *ob,
+ gpIterCb layer_cb,
+ gpIterCb stroke_cb,
+ void *thunk,
+ bool do_onion,
+ int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd)));
+ const bool is_multiedit = (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && (!GPENCIL_PLAY_ON(gpd)));
const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.cc
index 53939da08e2..785f63a7ba2 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -21,22 +21,24 @@
* \ingroup bke
*/
-#include <math.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_float3.hh"
#include "BLI_ghash.h"
#include "BLI_hash.h"
#include "BLI_heap.h"
#include "BLI_math_vector.h"
#include "BLI_polyfill_2d.h"
+#include "BLI_span.hh"
#include "BLT_translation.h"
@@ -61,6 +63,9 @@
#include "DEG_depsgraph_query.h"
+using blender::float3;
+using blender::Span;
+
/* GP Object - Boundbox Support */
/**
*Get min/max coordinate bounds for single stroke.
@@ -75,20 +80,26 @@ bool BKE_gpencil_stroke_minmax(const bGPDstroke *gps,
float r_min[3],
float r_max[3])
{
- const bGPDspoint *pt;
- int i;
- bool changed = false;
-
- if (ELEM(NULL, gps, r_min, r_max)) {
+ if (gps == nullptr) {
return false;
}
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {
- minmax_v3v3_v3(r_min, r_max, &pt->x);
+ bool changed = false;
+ if (use_select) {
+ for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) {
+ if (pt.flag & GP_SPOINT_SELECT) {
+ minmax_v3v3_v3(r_min, r_max, &pt.x);
+ changed = true;
+ }
+ }
+ }
+ else {
+ for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) {
+ minmax_v3v3_v3(r_min, r_max, &pt.x);
changed = true;
}
}
+
return changed;
}
@@ -105,14 +116,14 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
INIT_MINMAX(r_min, r_max);
- if (gpd == NULL) {
+ if (gpd == nullptr) {
return changed;
}
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
- if (gpf != NULL) {
+ if (gpf != nullptr) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
changed |= BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
}
@@ -129,11 +140,11 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
*/
void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
{
- float min[3], max[3], tot[3];
-
+ float3 min;
+ float3 max;
BKE_gpencil_data_minmax(gpd, min, max);
- add_v3_v3v3(tot, min, max);
+ const float3 tot = min + max;
mul_v3_v3fl(r_centroid, tot, 0.5f);
}
@@ -153,20 +164,18 @@ void BKE_gpencil_stroke_boundingbox_calc(bGPDstroke *gps)
*/
static void boundbox_gpencil(Object *ob)
{
- BoundBox *bb;
- bGPdata *gpd;
- float min[3], max[3];
-
- if (ob->runtime.bb == NULL) {
- ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
+ if (ob->runtime.bb == nullptr) {
+ ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
}
- bb = ob->runtime.bb;
- gpd = ob->data;
+ BoundBox *bb = ob->runtime.bb;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ float3 min;
+ float3 max;
if (!BKE_gpencil_data_minmax(gpd, min, max)) {
- min[0] = min[1] = min[2] = -1.0f;
- max[0] = max[1] = max[2] = 1.0f;
+ min = float3(-1);
+ max = float3(1);
}
BKE_boundbox_init_from_minmax(bb, min, max);
@@ -181,8 +190,8 @@ static void boundbox_gpencil(Object *ob)
*/
BoundBox *BKE_gpencil_boundbox_get(Object *ob)
{
- if (ELEM(NULL, ob, ob->data)) {
- return NULL;
+ if (ELEM(nullptr, ob, ob->data)) {
+ return nullptr;
}
bGPdata *gpd = (bGPdata *)ob->data;
@@ -196,9 +205,9 @@ BoundBox *BKE_gpencil_boundbox_get(Object *ob)
/* Update orig object's boundbox with re-computed evaluated values. This function can be
* called with the evaluated object and need update the original object bound box data
* to keep both values synchronized. */
- if (!ELEM(ob_orig, NULL, ob)) {
- if (ob_orig->runtime.bb == NULL) {
- ob_orig->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
+ if (!ELEM(ob_orig, nullptr, ob)) {
+ if (ob_orig->runtime.bb == nullptr) {
+ ob_orig->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
}
for (int i = 0; i < 8; i++) {
copy_v3_v3(ob_orig->runtime.bb->vec[i], ob->runtime.bb->vec[i]);
@@ -227,7 +236,7 @@ static int stroke_march_next_point(const bGPDstroke *gps,
float step_start[3];
float point[3];
int next_point_index = index_next_pt;
- bGPDspoint *pt = NULL;
+ bGPDspoint *pt = nullptr;
if (!(next_point_index < gps->totpoints)) {
return -1;
@@ -295,7 +304,7 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
float step_start[3];
float point[3];
int next_point_index = index_next_pt;
- bGPDspoint *pt = NULL;
+ bGPDspoint *pt = nullptr;
if (!(next_point_index < gps->totpoints)) {
return -1;
@@ -336,7 +345,7 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist)
int point_count = 0;
float point[3];
int next_point_index = 1;
- bGPDspoint *pt = NULL;
+ bGPDspoint *pt = nullptr;
pt = &gps->points[0];
copy_v3_v3(point, &pt->x);
@@ -369,14 +378,14 @@ static void stroke_defvert_create_nr_list(MDeformVert *dv_list,
for (j = 0; j < dv->totweight; j++) {
bool found = false;
dw = &dv->dw[j];
- for (ld = result->first; ld; ld = ld->next) {
+ for (ld = (LinkData *)result->first; ld; ld = ld->next) {
if (ld->data == POINTER_FROM_INT(dw->def_nr)) {
found = true;
break;
}
}
if (!found) {
- ld = MEM_callocN(sizeof(LinkData), "def_nr_item");
+ ld = (LinkData *)MEM_callocN(sizeof(LinkData), "def_nr_item");
ld->data = POINTER_FROM_INT(dw->def_nr);
BLI_addtail(result, ld);
tw++;
@@ -391,14 +400,15 @@ static MDeformVert *stroke_defvert_new_count(int count, int totweight, ListBase
{
int i, j;
LinkData *ld;
- MDeformVert *dst = MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert");
+ MDeformVert *dst = (MDeformVert *)MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert");
for (i = 0; i < count; i++) {
- dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * totweight, "new_deformWeight");
+ dst[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * totweight,
+ "new_deformWeight");
dst[i].totweight = totweight;
j = 0;
/* re-assign deform groups */
- for (ld = def_nr_list->first; ld; ld = ld->next) {
+ for (ld = (LinkData *)def_nr_list->first; ld; ld = ld->next) {
dst[i].dw[j].def_nr = POINTER_AS_INT(ld->data);
j++;
}
@@ -429,10 +439,10 @@ static void stroke_interpolate_deform_weights(
bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select)
{
bGPDspoint *pt = gps->points;
- bGPDspoint *pt1 = NULL;
- bGPDspoint *pt2 = NULL;
+ bGPDspoint *pt1 = nullptr;
+ bGPDspoint *pt2 = nullptr;
LinkData *ld;
- ListBase def_nr_list = {0};
+ ListBase def_nr_list = {nullptr};
if (gps->totpoints < 2 || dist < FLT_EPSILON) {
return false;
@@ -440,12 +450,13 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
/* TODO: Implement feature point preservation. */
int count = stroke_march_count(gps, dist);
- bGPDspoint *new_pt = MEM_callocN(sizeof(bGPDspoint) * count, "gp_stroke_points_sampled");
- MDeformVert *new_dv = NULL;
+ bGPDspoint *new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * count,
+ "gp_stroke_points_sampled");
+ MDeformVert *new_dv = nullptr;
int result_totweight;
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
stroke_defvert_create_nr_list(gps->dvert, gps->totpoints, &def_nr_list, &result_totweight);
new_dv = stroke_defvert_new_count(count, result_totweight, &def_nr_list);
}
@@ -513,7 +524,7 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
/* Free original weight data. */
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->dvert);
- while ((ld = BLI_pophead(&def_nr_list))) {
+ while ((ld = (LinkData *)BLI_pophead(&def_nr_list))) {
MEM_freeN(ld);
}
@@ -610,30 +621,32 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
if (new_count == 1) {
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->points);
- gps->points = NULL;
- gps->dvert = NULL;
+ gps->points = nullptr;
+ gps->dvert = nullptr;
gps->totpoints = 0;
return false;
}
- new_pt = MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
+ new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
for (int i = 0; i < new_count; i++) {
memcpy(&new_pt[i], &pt[i + index_from], sizeof(bGPDspoint));
}
if (gps->dvert) {
- new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, "gp_stroke_dverts_trimmed");
+ new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count,
+ "gp_stroke_dverts_trimmed");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + index_from];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
- new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
- "gp_stroke_dverts_dw_trimmed");
+ new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ "gp_stroke_dverts_dw_trimmed");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
}
+ BKE_defvert_clear(dv);
}
MEM_freeN(gps->dvert);
gps->dvert = new_dv;
@@ -684,18 +697,19 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
}
if (gps->dvert) {
- new_dv = MEM_callocN(sizeof(MDeformVert) * new_count,
- "gp_stroke_dverts_remaining(MDeformVert)");
+ new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count,
+ "gp_stroke_dverts_remaining(MDeformVert)");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + before_index];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
- new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
- "gp_stroke_dverts_dw_remaining(MDeformWeight)");
+ new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ "gp_stroke_dverts_dw_remaining(MDeformWeight)");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
}
+ BKE_defvert_clear(dv);
}
new_gps->dvert = new_dv;
}
@@ -1299,11 +1313,12 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
/* allocate memory for temporary areas */
gps->tot_triangles = gps->totpoints - 2;
- uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles,
- "GP Stroke temp triangulation");
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
- "GP Stroke temp 2d points");
- float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
+ uint(*tmp_triangles)[3] = (uint(*)[3])MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles,
+ "GP Stroke temp triangulation");
+ float(*points2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*points2d) * gps->totpoints,
+ "GP Stroke temp 2d points");
+ float(*uv)[2] = (float(*)[2])MEM_mallocN(sizeof(*uv) * gps->totpoints,
+ "GP Stroke temp 2d uv data");
int direction = 0;
@@ -1324,8 +1339,8 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
/* Save triangulation data. */
if (gps->tot_triangles > 0) {
MEM_SAFE_FREE(gps->triangles);
- gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
- "GP Stroke triangulation");
+ gps->triangles = (bGPDtriangle *)MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
+ "GP Stroke triangulation");
for (int i = 0; i < gps->tot_triangles; i++) {
memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
@@ -1342,7 +1357,7 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
MEM_freeN(gps->triangles);
}
- gps->triangles = NULL;
+ gps->triangles = nullptr;
}
/* clear memory */
@@ -1357,7 +1372,7 @@ void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
*/
void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
{
- if (gps == NULL || gps->totpoints == 0) {
+ if (gps == nullptr || gps->totpoints == 0) {
return;
}
@@ -1377,11 +1392,11 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
*/
void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps)
{
- if (gps == NULL) {
+ if (gps == nullptr) {
return;
}
- if (gps->editcurve != NULL) {
+ if (gps->editcurve != nullptr) {
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
/* curve geometry was updated: stroke needs recalculation */
if (gps->flag & GP_STROKE_NEEDS_CURVE_UPDATE) {
@@ -1517,20 +1532,20 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
if (intersect) {
/* save points */
- bGPDspoint *old_points = MEM_dupallocN(gps->points);
- MDeformVert *old_dvert = NULL;
- MDeformVert *dvert_src = NULL;
+ bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points);
+ MDeformVert *old_dvert = nullptr;
+ MDeformVert *dvert_src = nullptr;
- if (gps->dvert != NULL) {
- old_dvert = MEM_dupallocN(gps->dvert);
+ if (gps->dvert != nullptr) {
+ old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert);
}
/* resize gps */
int newtot = end - start + 1;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
+ gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
+ if (gps->dvert != nullptr) {
+ gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
}
for (int i = 0; i < newtot; i++) {
@@ -1538,7 +1553,7 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
bGPDspoint *pt_src = &old_points[idx];
bGPDspoint *pt_new = &gps->points[i];
memcpy(pt_new, pt_src, sizeof(bGPDspoint));
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert_src = &old_dvert[idx];
MDeformVert *dvert = &gps->dvert[i];
memcpy(dvert, dvert_src, sizeof(MDeformVert));
@@ -1568,8 +1583,8 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
*/
bool BKE_gpencil_stroke_close(bGPDstroke *gps)
{
- bGPDspoint *pt1 = NULL;
- bGPDspoint *pt2 = NULL;
+ bGPDspoint *pt1 = nullptr;
+ bGPDspoint *pt2 = nullptr;
/* Only can close a stroke with 3 points or more. */
if (gps->totpoints < 3) {
@@ -1603,9 +1618,9 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
/* Resize stroke array. */
int old_tot = gps->totpoints;
gps->totpoints += tot_newpoints;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != nullptr) {
+ gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
/* Generate new points */
@@ -1627,7 +1642,7 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step);
/* Set weights. */
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
MDeformVert *dvert1 = &gps->dvert[old_tot - 1];
MDeformWeight *dw1 = BKE_defvert_ensure_index(dvert1, 0);
float weight_1 = dw1 ? dw1->weight : 0.0f;
@@ -1661,7 +1676,7 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, const short tag)
{
bGPDspoint *pt;
- MDeformVert *dvert = NULL;
+ MDeformVert *dvert = nullptr;
int i;
int tot = gps->totpoints; /* number of points in new buffer */
@@ -1691,30 +1706,32 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps,
}
else {
/* just copy all points to keep into a smaller buffer */
- bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
+ bGPDspoint *new_points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * tot,
+ "new gp stroke points copy");
bGPDspoint *npt = new_points;
- MDeformVert *new_dvert = NULL;
- MDeformVert *ndvert = NULL;
+ MDeformVert *new_dvert = nullptr;
+ MDeformVert *ndvert = nullptr;
- if (gps->dvert != NULL) {
- new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
+ if (gps->dvert != nullptr) {
+ new_dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * tot,
+ "new gp stroke weights copy");
ndvert = new_dvert;
}
- (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
+ (gps->dvert != nullptr) ? dvert = gps->dvert : nullptr;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if ((pt->flag & tag) == 0) {
*npt = *pt;
npt++;
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
*ndvert = *dvert;
- ndvert->dw = MEM_dupallocN(dvert->dw);
+ ndvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw);
ndvert++;
}
}
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert++;
}
}
@@ -1787,15 +1804,15 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
*/
void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float epsilon)
{
- bGPDspoint *old_points = MEM_dupallocN(gps->points);
+ bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points);
int totpoints = gps->totpoints;
- char *marked = NULL;
+ char *marked = nullptr;
char work;
int start = 0;
int end = gps->totpoints - 1;
- marked = MEM_callocN(totpoints, "GP marked array");
+ marked = (char *)MEM_callocN(totpoints, "GP marked array");
marked[start] = 1;
marked[end] = 1;
@@ -1847,11 +1864,11 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
}
/* adding points marked */
- MDeformVert *old_dvert = NULL;
- MDeformVert *dvert_src = NULL;
+ MDeformVert *old_dvert = nullptr;
+ MDeformVert *dvert_src = nullptr;
- if (gps->dvert != NULL) {
- old_dvert = MEM_dupallocN(gps->dvert);
+ if (gps->dvert != nullptr) {
+ old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert);
}
/* resize gps */
int j = 0;
@@ -1861,7 +1878,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
if ((marked[i]) || (i == 0) || (i == totpoints - 1)) {
memcpy(pt, pt_src, sizeof(bGPDspoint));
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert_src = &old_dvert[i];
MDeformVert *dvert = &gps->dvert[j];
memcpy(dvert, dvert_src, sizeof(MDeformVert));
@@ -1872,7 +1889,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
j++;
}
else {
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert_src = &old_dvert[i];
BKE_gpencil_free_point_weights(dvert_src);
}
@@ -1901,12 +1918,12 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
}
/* save points */
- bGPDspoint *old_points = MEM_dupallocN(gps->points);
- MDeformVert *old_dvert = NULL;
- MDeformVert *dvert_src = NULL;
+ bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points);
+ MDeformVert *old_dvert = nullptr;
+ MDeformVert *dvert_src = nullptr;
- if (gps->dvert != NULL) {
- old_dvert = MEM_dupallocN(gps->dvert);
+ if (gps->dvert != nullptr) {
+ old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert);
}
/* resize gps */
@@ -1916,9 +1933,9 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
}
newtot += 2;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
- if (gps->dvert != NULL) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
+ gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
+ if (gps->dvert != nullptr) {
+ gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
}
int j = 0;
@@ -1928,7 +1945,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) {
memcpy(pt, pt_src, sizeof(bGPDspoint));
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert_src = &old_dvert[i];
MDeformVert *dvert = &gps->dvert[j];
memcpy(dvert, dvert_src, sizeof(MDeformVert));
@@ -1939,7 +1956,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
j++;
}
else {
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert_src = &old_dvert[i];
BKE_gpencil_free_point_weights(dvert_src);
}
@@ -1964,25 +1981,25 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int type)
{
bGPDspoint *temp_points;
- MDeformVert *temp_dverts = NULL;
- MDeformVert *dvert = NULL;
- MDeformVert *dvert_final = NULL;
- MDeformVert *dvert_next = NULL;
+ MDeformVert *temp_dverts = nullptr;
+ MDeformVert *dvert = nullptr;
+ MDeformVert *dvert_final = nullptr;
+ MDeformVert *dvert_next = nullptr;
int totnewpoints, oldtotpoints;
int i2;
for (int s = 0; s < level; s++) {
totnewpoints = gps->totpoints - 1;
/* duplicate points in a temp area */
- temp_points = MEM_dupallocN(gps->points);
+ temp_points = (bGPDspoint *)MEM_dupallocN(gps->points);
oldtotpoints = gps->totpoints;
/* resize the points arrays */
gps->totpoints += totnewpoints;
- gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
- if (gps->dvert != NULL) {
- temp_dverts = MEM_dupallocN(gps->dvert);
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != nullptr) {
+ temp_dverts = (MDeformVert *)MEM_dupallocN(gps->dvert);
+ gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
/* move points from last to first to new place */
@@ -2000,7 +2017,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
pt_final->runtime.idx_orig = pt->runtime.idx_orig;
copy_v4_v4(pt_final->vert_color, pt->vert_color);
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert = &temp_dverts[i];
dvert_final = &gps->dvert[i2];
dvert_final->totweight = dvert->totweight;
@@ -2021,17 +2038,17 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
- pt_final->runtime.pt_orig = NULL;
+ pt_final->runtime.pt_orig = nullptr;
pt_final->flag = 0;
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
dvert = &temp_dverts[i];
dvert_next = &temp_dverts[i + 1];
dvert_final = &gps->dvert[i2];
dvert_final->totweight = dvert->totweight;
- dvert_final->dw = MEM_dupallocN(dvert->dw);
+ dvert_final->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw);
/* interpolate weight values */
for (int d = 0; d < dvert->totweight; d++) {
@@ -2053,7 +2070,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
/* Move points to smooth stroke (not simple type). */
if (type != GP_SUBDIV_SIMPLE) {
/* duplicate points in a temp area with the new subdivide data */
- temp_points = MEM_dupallocN(gps->points);
+ temp_points = (bGPDspoint *)MEM_dupallocN(gps->points);
/* extreme points are not changed */
for (int i = 0; i < gps->totpoints - 2; i++) {
@@ -2091,8 +2108,8 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd,
const float threshold,
const bool use_unselected)
{
- bGPDspoint *pt = NULL;
- bGPDspoint *pt_next = NULL;
+ bGPDspoint *pt = nullptr;
+ bGPDspoint *pt_next = nullptr;
float tagged = false;
/* Use square distance to speed up loop */
const float th_square = threshold * threshold;
@@ -2158,7 +2175,7 @@ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd,
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
-typedef struct GpEdge {
+struct GpEdge {
uint v1, v2;
/* Coordinates. */
float v1_co[3], v2_co[3];
@@ -2167,7 +2184,7 @@ typedef struct GpEdge {
/* Direction of the segment. */
float vec[3];
int flag;
-} GpEdge;
+};
static int gpencil_next_edge(
GpEdge *gp_edges, int totedges, GpEdge *gped_init, const float threshold, const bool reverse)
@@ -2260,13 +2277,13 @@ static void gpencil_generate_edgeloops(Object *ob,
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
* This is reused for each edgeloop to create gpencil stroke. */
- uint *stroke = MEM_callocN(sizeof(uint) * me->totedge * 2, __func__);
- uint *stroke_fw = MEM_callocN(sizeof(uint) * me->totedge, __func__);
- uint *stroke_bw = MEM_callocN(sizeof(uint) * me->totedge, __func__);
+ uint *stroke = (uint *)MEM_callocN(sizeof(uint) * me->totedge * 2, __func__);
+ uint *stroke_fw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__);
+ uint *stroke_bw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__);
/* Create array with all edges. */
- GpEdge *gp_edges = MEM_callocN(sizeof(GpEdge) * me->totedge, __func__);
- GpEdge *gped = NULL;
+ GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * me->totedge, __func__);
+ GpEdge *gped = nullptr;
for (int i = 0; i < me->totedge; i++) {
MEdge *ed = &me->medge[i];
gped = &gp_edges[i];
@@ -2319,7 +2336,7 @@ static void gpencil_generate_edgeloops(Object *ob,
/* Look backward edges. */
int totbw = gpencil_walk_edge(v_table, gp_edges, me->totedge, stroke_bw, e, angle, true);
- BLI_ghash_free(v_table, NULL, NULL);
+ BLI_ghash_free(v_table, nullptr, nullptr);
/* Join both arrays. */
int array_len = 0;
@@ -2421,7 +2438,7 @@ static int gpencil_material_find_index_by_name(Object *ob, const char *name)
{
for (int i = 0; i < ob->totcol; i++) {
Material *ma = BKE_object_material_get(ob, i + 1);
- if ((ma != NULL) && (ma->gp_style != NULL) && (STREQ(ma->id.name + 2, name))) {
+ if ((ma != nullptr) && (ma->gp_style != nullptr) && (STREQ(ma->id.name + 2, name))) {
return i;
}
}
@@ -2472,7 +2489,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
const bool use_seams,
const bool use_faces)
{
- if (ELEM(NULL, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
+ if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) {
return false;
}
@@ -2480,9 +2497,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
/* Use evaluated data to get mesh with all modifiers on top. */
Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh);
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
- MPoly *mp, *mpoly = me_eval->mpoly;
- MLoop *mloop = me_eval->mloop;
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ const MPoly *mpoly = me_eval->mpoly;
+ const MLoop *mloop = me_eval->mloop;
int mpoly_len = me_eval->totpoly;
char element_name[200];
@@ -2509,23 +2526,24 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name);
/* Create Layer and Frame. */
bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name);
- if (gpl_fill == NULL) {
+ if (gpl_fill == nullptr) {
gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
}
bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
int i;
- for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) {
- MLoop *ml = &mloop[mp->loopstart];
+ for (i = 0; i < mpoly_len; i++) {
+ const MPoly *mp = &mpoly[i];
+
/* Find material. */
int mat_idx = 0;
Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
make_element_name(
- ob_mesh->id.name + 2, (ma != NULL) ? ma->id.name + 2 : "Fill", 64, element_name);
+ ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
if (mat_idx == -1) {
float color[4];
- if (ma != NULL) {
+ if (ma != nullptr) {
copy_v3_v3(color, &ma->r);
color[3] = 1.0f;
}
@@ -2539,8 +2557,10 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
gps_fill->flag |= GP_STROKE_CYCLIC;
/* Add points to strokes. */
- for (int j = 0; j < mp->totloop; j++, ml++) {
- MVert *mv = &me_eval->mvert[ml->v];
+ for (int j = 0; j < mp->totloop; j++) {
+ const MLoop *ml = &mloop[mp->loopstart + j];
+ const MVert *mv = &me_eval->mvert[ml->v];
+
bGPDspoint *pt = &gps_fill->points[j];
copy_v3_v3(&pt->x, mv->co);
mul_m4_v3(matrix, &pt->x);
@@ -2562,7 +2582,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
/* Create Layer and Frame. */
bGPDlayer *gpl_stroke = BKE_gpencil_layer_named_get(gpd, element_name);
- if (gpl_stroke == NULL) {
+ if (gpl_stroke == nullptr) {
gpl_stroke = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
}
bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get(
@@ -2584,7 +2604,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
*/
void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4])
{
- if (gpd == NULL) {
+ if (gpd == nullptr) {
return;
}
@@ -2620,7 +2640,7 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd)
{
int total_points = 0;
- if (gpd == NULL) {
+ if (gpd == nullptr) {
return 0;
}
@@ -2645,7 +2665,7 @@ int BKE_gpencil_stroke_point_count(const bGPdata *gpd)
/* Used for "move only origins" in object_data_transform.c */
void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_data)
{
- if (gpd == NULL) {
+ if (gpd == nullptr) {
return;
}
@@ -2676,7 +2696,7 @@ void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_da
/* Used for "move only origins" in object_data_transform.c */
void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates *elem_data)
{
- if (gpd == NULL) {
+ if (gpd == nullptr) {
return;
}
@@ -2712,7 +2732,7 @@ void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd,
const GPencilPointCoordinates *elem_data,
const float mat[4][4])
{
- if (gpd == NULL) {
+ if (gpd == nullptr) {
return;
}
@@ -2813,24 +2833,24 @@ void BKE_gpencil_stroke_flip(bGPDstroke *gps)
* that should be kept when splitting up a stroke. Used in:
* gpencil_stroke_delete_tagged_points()
*/
-typedef struct tGPDeleteIsland {
+struct tGPDeleteIsland {
int start_idx;
int end_idx;
-} tGPDeleteIsland;
+};
static void gpencil_stroke_join_islands(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps_first,
bGPDstroke *gps_last)
{
- bGPDspoint *pt = NULL;
- bGPDspoint *pt_final = NULL;
+ bGPDspoint *pt = nullptr;
+ bGPDspoint *pt_final = nullptr;
const int totpoints = gps_first->totpoints + gps_last->totpoints;
/* create new stroke */
bGPDstroke *join_stroke = BKE_gpencil_stroke_duplicate(gps_first, false, true);
- join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
+ join_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
join_stroke->totpoints = totpoints;
join_stroke->flag &= ~GP_STROKE_CYCLIC;
@@ -2863,17 +2883,17 @@ static void gpencil_stroke_join_islands(bGPdata *gpd,
}
/* Copy over vertex weight data (if available) */
- if ((gps_first->dvert != NULL) || (gps_last->dvert != NULL)) {
- join_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * totpoints, __func__);
- MDeformVert *dvert_src = NULL;
- MDeformVert *dvert_dst = NULL;
+ if ((gps_first->dvert != nullptr) || (gps_last->dvert != nullptr)) {
+ join_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * totpoints, __func__);
+ MDeformVert *dvert_src = nullptr;
+ MDeformVert *dvert_dst = nullptr;
/* Copy weights (last before). */
e1 = 0;
e2 = 0;
for (int i = 0; i < totpoints; i++) {
dvert_dst = &join_stroke->dvert[i];
- dvert_src = NULL;
+ dvert_src = nullptr;
if (i < gps_last->totpoints) {
if (gps_last->dvert) {
dvert_src = &gps_last->dvert[e1];
@@ -2888,7 +2908,7 @@ static void gpencil_stroke_join_islands(bGPdata *gpd,
}
if ((dvert_src) && (dvert_src->dw)) {
- dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ dvert_dst->dw = (MDeformWeight *)MEM_dupallocN(dvert_src->dw);
}
}
}
@@ -2929,13 +2949,13 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
bool select,
int limit)
{
- tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2,
- "gp_point_islands");
+ tGPDeleteIsland *islands = (tGPDeleteIsland *)MEM_callocN(
+ sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands");
bool in_island = false;
int num_islands = 0;
- bGPDstroke *new_stroke = NULL;
- bGPDstroke *gps_first = NULL;
+ bGPDstroke *new_stroke = nullptr;
+ bGPDstroke *gps_first = nullptr;
const bool is_cyclic = (bool)(gps->flag & GP_STROKE_CYCLIC);
/* First Pass: Identify start/end of islands */
@@ -2977,7 +2997,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
new_stroke = BKE_gpencil_stroke_duplicate(gps, false, true);
/* if cyclic and first stroke, save to join later */
- if ((is_cyclic) && (gps_first == NULL)) {
+ if ((is_cyclic) && (gps_first == nullptr)) {
gps_first = new_stroke;
}
@@ -2987,17 +3007,17 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
new_stroke->totpoints = island->end_idx - island->start_idx + 1;
/* Copy over the relevant point data */
- new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints,
- "gp delete stroke fragment");
+ new_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints,
+ "gp delete stroke fragment");
memcpy(new_stroke->points,
gps->points + island->start_idx,
sizeof(bGPDspoint) * new_stroke->totpoints);
/* Copy over vertex weight data (if available) */
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
/* Copy over the relevant vertex-weight points */
- new_stroke->dvert = MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints,
- "gp delete stroke fragment weight");
+ new_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_stroke->totpoints,
+ "gp delete stroke fragment weight");
memcpy(new_stroke->dvert,
gps->dvert + island->start_idx,
sizeof(MDeformVert) * new_stroke->totpoints);
@@ -3008,7 +3028,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
MDeformVert *dvert_src = &gps->dvert[e];
MDeformVert *dvert_dst = &new_stroke->dvert[i];
if (dvert_src->dw) {
- dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
+ dvert_dst->dw = (MDeformWeight *)MEM_dupallocN(dvert_src->dw);
}
e++;
}
@@ -3042,7 +3062,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
/* Add new stroke to the frame or delete if below limit */
if ((limit > 0) && (new_stroke->totpoints <= limit)) {
if (gps_first == new_stroke) {
- gps_first = NULL;
+ gps_first = nullptr;
}
BKE_gpencil_free_stroke(new_stroke);
}
@@ -3059,7 +3079,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
}
}
/* if cyclic, need to join last stroke with first stroke */
- if ((is_cyclic) && (gps_first != NULL) && (gps_first != new_stroke)) {
+ if ((is_cyclic) && (gps_first != nullptr) && (gps_first != new_stroke)) {
gpencil_stroke_join_islands(gpd, gpf, gps_first, new_stroke);
}
}
@@ -3081,13 +3101,13 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd,
bGPDcurve *gpc,
int tag_flags)
{
- if (gpc == NULL) {
+ if (gpc == nullptr) {
return;
}
const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
const int idx_last = gpc->tot_curve_points - 1;
- bGPDstroke *gps_first = NULL;
- bGPDstroke *gps_last = NULL;
+ bGPDstroke *gps_first = nullptr;
+ bGPDstroke *gps_last = nullptr;
int idx_start = 0;
int idx_end = 0;
@@ -3118,11 +3138,11 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd,
}
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false, false);
- new_stroke->points = NULL;
+ new_stroke->points = nullptr;
new_stroke->flag &= ~GP_STROKE_CYCLIC;
new_stroke->editcurve = BKE_gpencil_stroke_editcurve_new(island_length);
- if (gps_first == NULL) {
+ if (gps_first == nullptr) {
gps_first = new_stroke;
}
@@ -3150,15 +3170,15 @@ void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd,
}
/* join first and last stroke if cyclic */
- if (is_cyclic && gps_first != NULL && gps_last != NULL && gps_first != gps_last) {
+ if (is_cyclic && gps_first != nullptr && gps_last != nullptr && gps_first != gps_last) {
bGPDcurve *gpc_first = gps_first->editcurve;
bGPDcurve *gpc_last = gps_last->editcurve;
int first_tot_points = gpc_first->tot_curve_points;
int old_tot_points = gpc_last->tot_curve_points;
gpc_last->tot_curve_points = first_tot_points + old_tot_points;
- gpc_last->curve_points = MEM_recallocN(gpc_last->curve_points,
- sizeof(bGPDcurve_point) * gpc_last->tot_curve_points);
+ gpc_last->curve_points = (bGPDcurve_point *)MEM_recallocN(
+ gpc_last->curve_points, sizeof(bGPDcurve_point) * gpc_last->tot_curve_points);
/* copy data from first to last */
memcpy(gpc_last->curve_points + old_tot_points,
gpc_first->curve_points,
@@ -3191,14 +3211,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps,
{
bGPDspoint *newpoint;
- gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
- if (gps->dvert != NULL) {
- gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1));
+ gps->points = (bGPDspoint *)MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
+ if (gps->dvert != nullptr) {
+ gps->dvert = (MDeformVert *)MEM_reallocN(gps->dvert,
+ sizeof(MDeformVert) * (gps->totpoints + 1));
}
else {
/* If destination has weight add weight to origin. */
- if (dvert != NULL) {
- gps->dvert = MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), __func__);
+ if (dvert != nullptr) {
+ gps->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1),
+ __func__);
}
}
@@ -3214,16 +3236,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps,
newpoint->time = point->time + deltatime;
copy_v4_v4(newpoint->vert_color, point->vert_color);
- if (gps->dvert != NULL) {
+ if (gps->dvert != nullptr) {
MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1];
- if (dvert != NULL) {
+ if (dvert != nullptr) {
newdvert->totweight = dvert->totweight;
- newdvert->dw = MEM_dupallocN(dvert->dw);
+ newdvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw);
}
else {
newdvert->totweight = 0;
- newdvert->dw = NULL;
+ newdvert->dw = nullptr;
}
}
}
@@ -3241,7 +3263,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
float deltatime = 0.0f;
/* sanity checks */
- if (ELEM(NULL, gps_a, gps_b)) {
+ if (ELEM(nullptr, gps_a, gps_b)) {
return;
}
@@ -3303,11 +3325,11 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
point = gps_a->points[gps_a->totpoints - 1];
deltatime = point.time;
- gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f);
+ gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, 0.0f);
/* 2nd: add one head point to finish invisible area */
point = gps_b->points[0];
- gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime);
+ gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, deltatime);
}
const float ratio = (fit_thickness && gps_a->thickness > 0.0f) ?
@@ -3316,7 +3338,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
/* 3rd: add all points */
for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
- MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL;
+ MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : nullptr;
gpencil_stroke_copy_point(
gps_a, dvert, pt, delta, pt->pressure * ratio, pt->strength, deltatime);
}
@@ -3335,16 +3357,16 @@ void BKE_gpencil_stroke_copy_to_keyframes(
if (gpf->framenum != cfra) {
bGPDframe *gpf_new = BKE_gpencil_layer_frame_find(gpl, cfra);
- if (gpf_new == NULL) {
+ if (gpf_new == nullptr) {
gpf_new = BKE_gpencil_frame_addnew(gpl, cfra);
}
- if (gpf_new == NULL) {
+ if (gpf_new == nullptr) {
continue;
}
bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true);
- if (gps_new == NULL) {
+ if (gps_new == nullptr) {
continue;
}
@@ -3358,38 +3380,38 @@ void BKE_gpencil_stroke_copy_to_keyframes(
}
/* Free hash table. */
- BLI_ghash_free(frame_list, NULL, NULL);
+ BLI_ghash_free(frame_list, nullptr, nullptr);
}
/* Stroke Uniform Subdivide ------------------------------------- */
-typedef struct tSamplePoint {
+struct tSamplePoint {
struct tSamplePoint *next, *prev;
float x, y, z;
float pressure, strength, time;
float vertex_color[4];
struct MDeformWeight *dw;
int totweight;
-} tSamplePoint;
+};
-typedef struct tSampleEdge {
+struct tSampleEdge {
float length_sq;
tSamplePoint *from;
tSamplePoint *to;
-} tSampleEdge;
+};
/* Helper: creates a tSamplePoint from a bGPDspoint and (optionally) a MDeformVert. */
static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const MDeformVert *dvert)
{
- tSamplePoint *new_pt = MEM_callocN(sizeof(tSamplePoint), __func__);
+ tSamplePoint *new_pt = (tSamplePoint *)MEM_callocN(sizeof(tSamplePoint), __func__);
copy_v3_v3(&new_pt->x, &pt->x);
new_pt->pressure = pt->pressure;
new_pt->strength = pt->strength;
new_pt->time = pt->time;
copy_v4_v4((float *)&new_pt->vertex_color, (float *)&pt->vert_color);
- if (dvert != NULL) {
+ if (dvert != nullptr) {
new_pt->totweight = dvert->totweight;
- new_pt->dw = MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__);
+ new_pt->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__);
for (uint i = 0; i < new_pt->totweight; ++i) {
MDeformWeight *dw = &new_pt->dw[i];
MDeformWeight *dw_from = &dvert->dw[i];
@@ -3404,7 +3426,7 @@ static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const
* the edge. */
static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamplePoint *to)
{
- tSampleEdge *new_edge = MEM_callocN(sizeof(tSampleEdge), __func__);
+ tSampleEdge *new_edge = (tSampleEdge *)MEM_callocN(sizeof(tSampleEdge), __func__);
new_edge->from = from;
new_edge->to = to;
new_edge->length_sq = len_squared_v3v3(&from->x, &to->x);
@@ -3426,27 +3448,27 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
const bool select)
{
/* Stroke needs at least two points and strictly less points than the target number. */
- if (gps == NULL || gps->totpoints < 2 || gps->totpoints >= target_number) {
+ if (gps == nullptr || gps->totpoints < 2 || gps->totpoints >= target_number) {
return;
}
const int totpoints = gps->totpoints;
- const bool has_dverts = (gps->dvert != NULL);
+ const bool has_dverts = (gps->dvert != nullptr);
const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC);
- ListBase points = {NULL, NULL};
+ ListBase points = {nullptr, nullptr};
Heap *edges = BLI_heap_new();
/* Add all points into list. */
for (uint32_t i = 0; i < totpoints; ++i) {
bGPDspoint *pt = &gps->points[i];
- MDeformVert *dvert = has_dverts ? &gps->dvert[i] : NULL;
+ MDeformVert *dvert = has_dverts ? &gps->dvert[i] : nullptr;
tSamplePoint *sp = new_sample_point_from_gp_point(pt, dvert);
BLI_addtail(&points, sp);
}
/* Iterate over edges and insert them into the heap. */
- for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != NULL; pt = pt->next) {
+ for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != nullptr; pt = pt->next) {
tSampleEdge *se = new_sample_edge_from_sample_points(pt->prev, pt);
/* BLI_heap is a min-heap, but we need the largest key to be at the top, so we take the
* negative of the squared length. */
@@ -3454,8 +3476,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
}
if (is_cyclic) {
- tSamplePoint *sp_first = points.first;
- tSamplePoint *sp_last = points.last;
+ tSamplePoint *sp_first = (tSamplePoint *)points.first;
+ tSamplePoint *sp_last = (tSamplePoint *)points.last;
tSampleEdge *se = new_sample_edge_from_sample_points(sp_last, sp_first);
BLI_heap_insert(edges, -(se->length_sq), se);
}
@@ -3464,12 +3486,12 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
BLI_assert(num_points_needed > 0);
while (num_points_needed > 0) {
- tSampleEdge *se = BLI_heap_pop_min(edges);
+ tSampleEdge *se = (tSampleEdge *)BLI_heap_pop_min(edges);
tSamplePoint *sp = se->from;
tSamplePoint *sp_next = se->to;
/* Subdivide the edge. */
- tSamplePoint *new_sp = MEM_callocN(sizeof(tSamplePoint), __func__);
+ tSamplePoint *new_sp = (tSamplePoint *)MEM_callocN(sizeof(tSamplePoint), __func__);
interp_v3_v3v3(&new_sp->x, &sp->x, &sp_next->x, 0.5f);
new_sp->pressure = interpf(sp->pressure, sp_next->pressure, 0.5f);
new_sp->strength = interpf(sp->strength, sp_next->strength, 0.5f);
@@ -3480,7 +3502,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
0.5f);
if (sp->dw && sp_next->dw) {
new_sp->totweight = MIN2(sp->totweight, sp_next->totweight);
- new_sp->dw = MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, __func__);
+ new_sp->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight,
+ __func__);
for (uint32_t i = 0; i < new_sp->totweight; ++i) {
MDeformWeight *dw = &new_sp->dw[i];
MDeformWeight *dw_from = &sp->dw[i];
@@ -3504,13 +3527,13 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
BLI_heap_free(edges, (HeapFreeFP)MEM_freeN);
gps->totpoints = target_number;
- gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints);
+ gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints);
if (has_dverts) {
- gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints);
+ gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints);
}
/* Convert list back to stroke point array. */
- tSamplePoint *sp = points.first;
+ tSamplePoint *sp = (tSamplePoint *)points.first;
for (uint32_t i = 0; i < gps->totpoints && sp; ++i, sp = sp->next) {
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = &gps->dvert[i];
@@ -3523,7 +3546,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
if (sp->dw) {
dvert->totweight = sp->totweight;
- dvert->dw = MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__);
+ dvert->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__);
for (uint32_t j = 0; j < dvert->totweight; ++j) {
MDeformWeight *dw = &dvert->dw[j];
MDeformWeight *dw_from = &sp->dw[j];
@@ -3544,7 +3567,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
/* Free the sample points. Important to use the mutable loop here because we are erasing the list
* elements. */
LISTBASE_FOREACH_MUTABLE (tSamplePoint *, temp, &points) {
- if (temp->dw != NULL) {
+ if (temp->dw != nullptr) {
MEM_freeN(temp->dw);
}
MEM_SAFE_FREE(temp);
@@ -3558,7 +3581,7 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
* Stroke to view space
* Transforms a stroke to view space. This allows for manipulations in 2D but also easy conversion
* back to 3D.
- * Note: also takes care of parent space transform
+ * NOTE: also takes care of parent space transform
*/
void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
bGPDstroke *gps,
@@ -3577,7 +3600,7 @@ void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
* Stroke from view space
* Transforms a stroke from view space back to world space. Inverse of
* BKE_gpencil_stroke_to_view_space
- * Note: also takes care of parent space transform
+ * NOTE: also takes care of parent space transform
*/
void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
bGPDstroke *gps,
@@ -3596,14 +3619,14 @@ void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
/* ----------------------------------------------------------------------------- */
/* Stroke to perimeter */
-typedef struct tPerimeterPoint {
+struct tPerimeterPoint {
struct tPerimeterPoint *next, *prev;
float x, y, z;
-} tPerimeterPoint;
+};
static tPerimeterPoint *new_perimeter_point(const float pt[3])
{
- tPerimeterPoint *new_pt = MEM_callocN(sizeof(tPerimeterPoint), __func__);
+ tPerimeterPoint *new_pt = (tPerimeterPoint *)MEM_callocN(sizeof(tPerimeterPoint), __func__);
copy_v3_v3(&new_pt->x, pt);
return new_pt;
}
@@ -3766,14 +3789,14 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
{
/* sanity check */
if (gps->totpoints < 1) {
- return NULL;
+ return nullptr;
}
float defaultpixsize = 1000.0f / gpd->pixfactor;
float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f;
- ListBase *perimeter_right_side = MEM_callocN(sizeof(ListBase), __func__);
- ListBase *perimeter_left_side = MEM_callocN(sizeof(ListBase), __func__);
+ ListBase *perimeter_right_side = (ListBase *)MEM_callocN(sizeof(ListBase), __func__);
+ ListBase *perimeter_left_side = (ListBase *)MEM_callocN(sizeof(ListBase), __func__);
int num_perimeter_points = 0;
bGPDspoint *first = &gps->points[0];
@@ -4013,7 +4036,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
const float diff_mat[4][4])
{
if (gps->totpoints == 0) {
- return NULL;
+ return nullptr;
}
bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, true, false);
const bool cyclic = ((gps_temp->flag & GP_STROKE_CYCLIC) != 0);
@@ -4021,8 +4044,8 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
/* If Cyclic, add a new point. */
if (cyclic && (gps_temp->totpoints > 1)) {
gps_temp->totpoints++;
- gps_temp->points = MEM_recallocN(gps_temp->points,
- sizeof(*gps_temp->points) * gps_temp->totpoints);
+ gps_temp->points = (bGPDspoint *)MEM_recallocN(
+ gps_temp->points, sizeof(*gps_temp->points) * gps_temp->totpoints);
bGPDspoint *pt_src = &gps_temp->points[0];
bGPDspoint *pt_dst = &gps_temp->points[gps_temp->totpoints - 1];
copy_v3_v3(&pt_dst->x, &pt_src->x);
@@ -4038,7 +4061,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
gpd, gpl, gps_temp, subdivisions, &num_perimeter_points);
if (num_perimeter_points == 0) {
- return NULL;
+ return nullptr;
}
/* Create new stroke. */
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 9f5f70ab2ba..4db527e5b42 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -257,9 +257,13 @@ bool BKE_gpencil_is_first_lineart_in_stack(const Object *ob, const GpencilModifi
return false;
}
-/* apply time modifiers */
-static int gpencil_time_modifier(
- Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl, int cfra, bool is_render)
+/* Get Time modifier frame number. */
+int BKE_gpencil_time_modifier_cfra(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ bGPDlayer *gpl,
+ const int cfra,
+ const bool is_render)
{
bGPdata *gpd = ob->data;
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
@@ -269,7 +273,7 @@ static int gpencil_time_modifier(
if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
- if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
+ if (GPENCIL_MODIFIER_EDIT(md, is_edit) && (!is_render)) {
continue;
}
@@ -350,7 +354,7 @@ GpencilModifierData *BKE_gpencil_modifier_new(int type)
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type);
GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name);
- /* note, this name must be made unique later */
+ /* NOTE: this name must be made unique later. */
BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
md->type = type;
@@ -665,7 +669,7 @@ static int gpencil_remap_time_get(Depsgraph *depsgraph, Scene *scene, Object *ob
int remap_cfra = cfra_eval;
if (time_remap) {
- remap_cfra = gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
+ remap_cfra = BKE_gpencil_time_modifier_cfra(depsgraph, scene, ob, gpl, cfra_eval, is_render);
}
return remap_cfra;
@@ -834,7 +838,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
- if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
+ if (GPENCIL_MODIFIER_EDIT(md, is_edit) && (!is_render)) {
continue;
}
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index a67e78ceea0..7a88a00c44f 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -186,7 +186,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
}
}
- /* - Note: This code comes from python, here's the corresponding comment. - */
+ /* NOTE: This code comes from python, here's the corresponding comment. */
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
@@ -240,7 +240,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
return;
}
- /* - Note: This code comes from python, here's the corresponding comment. - */
+ /* NOTE: This code comes from python, here's the corresponding comment. */
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
@@ -942,7 +942,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
if (val->string.subtype == IDP_STRING_SUB_BYTE) {
- /* note, intentionally not null terminated */
+ /* NOTE: Intentionally not null terminated. */
if (st == NULL) {
prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
*IDP_String(prop) = '\0';
@@ -1183,7 +1183,7 @@ static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader)
IDProperty *array = (IDProperty *)prop->data.pointer;
- /* note!, idp-arrays didn't exist in 2.4x, so the pointer will be cleared
+ /* NOTE:, idp-arrays didn't exist in 2.4x, so the pointer will be cleared
* there's not really anything we can do to correct this, at least don't crash */
if (array == NULL) {
prop->len = 0;
@@ -1274,7 +1274,7 @@ static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader)
* IDP are way too polymorphic to do it safely. */
printf(
"%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type);
- /* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */
+ /* NOTE: we do not attempt to free unknown prop, we have no way to know how to do that! */
prop->type = IDP_INT;
prop->subtype = 0;
IDP_Int(prop) = 0;
diff --git a/source/blender/blenkernel/intern/idprop_utils.c b/source/blender/blenkernel/intern/idprop_utils.c
index 433f0e97844..0cc212e1880 100644
--- a/source/blender/blenkernel/intern/idprop_utils.c
+++ b/source/blender/blenkernel/intern/idprop_utils.c
@@ -96,7 +96,7 @@ static void idp_str_append_escape(struct ReprState *state,
static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop)
{
- /* Note: 'strlen' will be calculated at compile time for literals. */
+ /* NOTE: 'strlen' will be calculated at compile time for literals. */
#define STR_APPEND_STR(str) state->str_append_fn(state->user_data, str, (uint)strlen(str))
#define STR_APPEND_STR_QUOTE(str) idp_str_append_escape(state, str, (uint)strlen(str), true)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 740c9b3864c..f4ba1ff8b92 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -640,7 +640,7 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
}
}
-/* note, we could be clever and scale all imbuf's but since some are mipmaps its not so simple */
+/* NOTE: We could be clever and scale all imbuf's but since some are mipmaps its not so simple. */
bool BKE_image_scale(Image *image, int width, int height)
{
ImBuf *ibuf;
@@ -1778,7 +1778,7 @@ static bool do_add_image_extension(char *string,
}
}
else {
- BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
+ BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec");
}
}
else {
@@ -1949,7 +1949,7 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
im_format->jp2_codec = R_IMF_JP2_CODEC_J2K;
}
else {
- BLI_assert(!"Unsupported jp2 codec was specified in file type");
+ BLI_assert_msg(0, "Unsupported jp2 codec was specified in file type");
}
}
#endif
@@ -2323,7 +2323,7 @@ void BKE_image_stamp_buf(Scene *scene,
stampdata_from_template(&stamp_data, scene, stamp_data_template, do_prefix);
}
- /* TODO, do_versions */
+ /* TODO: do_versions. */
if (scene->r.stamp_font_id < 8) {
scene->r.stamp_font_id = 12;
}
@@ -2867,7 +2867,7 @@ bool BKE_imbuf_alpha_test(ImBuf *ibuf)
return false;
}
-/* note: imf->planes is ignored here, its assumed the image channels
+/* NOTE: imf->planes is ignored here, its assumed the image channels
* are already set */
void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
{
@@ -3017,7 +3017,7 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
ibuf->foptions.flag |= JP2_J2K;
}
else {
- BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
+ BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec");
}
}
#endif
@@ -4540,7 +4540,7 @@ static ImBuf *load_image_single(Image *ima,
}
/* warning, 'iuser' can be NULL
- * note: Image->views was already populated (in image_update_views_format)
+ * NOTE: Image->views was already populated (in image_update_views_format)
*/
static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
{
@@ -5391,7 +5391,7 @@ void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
}
if (ima && ima->gpuframenr != iuser->framenr) {
- /* Note: a single texture and refresh doesn't really work when
+ /* NOTE: a single texture and refresh doesn't really work when
* multiple image users may use different frames, this is to
* be improved with perhaps a GPU texture cache. */
ima->gpuflag |= IMA_GPU_REFRESH;
diff --git a/source/blender/blenkernel/intern/image_save.c b/source/blender/blenkernel/intern/image_save.c
index b68cd9e4d2d..9e3d5a162ae 100644
--- a/source/blender/blenkernel/intern/image_save.c
+++ b/source/blender/blenkernel/intern/image_save.c
@@ -169,7 +169,7 @@ static bool image_save_single(ReportList *reports,
}
}
else {
- /* TODO, better solution, if a 24bit image is painted onto it may contain alpha */
+ /* TODO: better solution, if a 24bit image is painted onto it may contain alpha. */
if ((opts->im_format.planes == R_IMF_PLANES_RGBA) &&
/* it has been painted onto */
(ibuf->userflags & IB_BITMAPDIRTY)) {
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index f365e759221..8a70f065e40 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1135,7 +1135,7 @@ static char *get_rna_access(ID *id,
/* special case for rotdiff drivers... we don't need a property for this... */
break;
- /* TODO... add other blocktypes... */
+ /* TODO: add other block-types. */
default:
CLOG_WARN(&LOG, "No path for blocktype %d, adrcode %d yet", blocktype, adrcode);
break;
@@ -1162,7 +1162,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 escapted and they should be! */
if ((actname && actname[0]) && (constname && constname[0])) {
/* Constraint in Pose-Channel */
char actname_esc[sizeof(((bActionChannel *)NULL)->name) * 2];
@@ -1305,7 +1305,7 @@ static ChannelDriver *idriver_to_cdriver(IpoDriver *idriver)
dtar = &dvar->targets[1];
dtar->id = (ID *)idriver->ob;
dtar->idtype = ID_OB;
- if (idriver->name[0]) { /* xxx... for safety */
+ if (idriver->name[0]) { /* XXX: for safety. */
BLI_strncpy(
dtar->pchan_name, idriver->name + DRIVER_NAME_OFFS, sizeof(dtar->pchan_name));
}
@@ -1358,12 +1358,12 @@ static void fcurve_add_to_list(
bActionGroup *agrp = NULL;
/* init the temp action */
- memset(&tmp_act, 0, sizeof(bAction)); /* XXX only enable this line if we get errors */
+ memset(&tmp_act, 0, sizeof(bAction)); /* XXX: Only enable this line if we get errors. */
tmp_act.groups.first = groups->first;
tmp_act.groups.last = groups->last;
tmp_act.curves.first = list->first;
tmp_act.curves.last = list->last;
- /* ... xxx, the other vars don't need to be filled in */
+ /* XXX: The other vars don't need to be filled in. */
/* get the group to use */
agrp = BKE_action_group_find_name(&tmp_act, grpname);
@@ -2087,7 +2087,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* check if object has any animation data */
if (ob->nlastrips.first) {
/* Add AnimData block */
- BKE_animdata_add_id(id);
+ BKE_animdata_ensure_id(id);
/* IPO first to take into any non-NLA'd Object Animation */
if (ob->ipo) {
@@ -2109,7 +2109,7 @@ void do_versions_ipos_to_animato(Main *bmain)
}
else if ((ob->ipo) || (ob->action)) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Action first - so that Action name get conserved */
if (ob->action) {
@@ -2133,7 +2133,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* check PoseChannels for constraints with local data */
if (ob->pose) {
/* Verify if there's AnimData block */
- BKE_animdata_add_id(id);
+ BKE_animdata_ensure_id(id);
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
@@ -2159,7 +2159,7 @@ void do_versions_ipos_to_animato(Main *bmain)
*/
if (con->ipo) {
/* Verify if there's AnimData block, just in case */
- BKE_animdata_add_id(id);
+ BKE_animdata_ensure_id(id);
/* although this was the constraint's local IPO, we still need to provide con
* so that drivers can be added properly...
@@ -2176,7 +2176,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* check constraint channels - we need to remove them anyway... */
if (ob->constraintChannels.first) {
/* Verify if there's AnimData block */
- BKE_animdata_add_id(id);
+ BKE_animdata_ensure_id(id);
for (conchan = ob->constraintChannels.first; conchan; conchan = conchann) {
/* get pointer to next Constraint Channel */
@@ -2217,7 +2217,7 @@ void do_versions_ipos_to_animato(Main *bmain)
*/
if (key->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert Shapekey data... */
ipo_to_animdata(bmain, id, key->ipo, NULL, NULL, NULL);
@@ -2242,7 +2242,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* we're only interested in the IPO */
if (ma->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert Material data... */
ipo_to_animdata(bmain, id, ma->ipo, NULL, NULL, NULL);
@@ -2267,7 +2267,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* we're only interested in the IPO */
if (wo->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert World data... */
ipo_to_animdata(bmain, id, wo->ipo, NULL, NULL, NULL);
@@ -2288,7 +2288,7 @@ void do_versions_ipos_to_animato(Main *bmain)
if (ed && ed->seqbasep) {
Sequence *seq;
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
SEQ_ALL_BEGIN (ed, seq) {
IpoCurve *icu = (seq->ipo) ? seq->ipo->curve.first : NULL;
@@ -2346,7 +2346,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* we're only interested in the IPO */
if (te->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert Texture data... */
ipo_to_animdata(bmain, id, te->ipo, NULL, NULL, NULL);
@@ -2371,7 +2371,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* we're only interested in the IPO */
if (ca->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert Camera data... */
ipo_to_animdata(bmain, id, ca->ipo, NULL, NULL, NULL);
@@ -2396,7 +2396,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* we're only interested in the IPO */
if (la->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert Light data... */
ipo_to_animdata(bmain, id, la->ipo, NULL, NULL, NULL);
@@ -2421,7 +2421,7 @@ void do_versions_ipos_to_animato(Main *bmain)
/* we're only interested in the IPO */
if (cu->ipo) {
/* Add AnimData block */
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
/* Convert Curve data... */
ipo_to_animdata(bmain, id, cu->ipo, NULL, NULL, NULL);
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 6cc90f86b4a..0f8c9bad798 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -694,7 +694,7 @@ static bool key_pointer_size(const Key *key, const int mode, int *poinsize, int
*poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
break;
default:
- BLI_assert(!"invalid 'key->from' ID type");
+ BLI_assert_msg(0, "invalid 'key->from' ID type");
return false;
}
@@ -806,7 +806,7 @@ static void cp_key(const int start,
if (freekref) {
MEM_freeN(freekref);
}
- BLI_assert(!"invalid 'cp[1]'");
+ BLI_assert_msg(0, "invalid 'cp[1]'");
return;
}
@@ -984,7 +984,7 @@ static void key_evaluate_relative(const int start,
if (freefrom) {
MEM_freeN(freefrom);
}
- BLI_assert(!"invalid 'cp[1]'");
+ BLI_assert_msg(0, "invalid 'cp[1]'");
return;
}
@@ -1204,7 +1204,7 @@ static void do_key(const int start,
if (freek4) {
MEM_freeN(freek4);
}
- BLI_assert(!"invalid 'cp[1]'");
+ BLI_assert_msg(0, "invalid 'cp[1]'");
return;
}
@@ -1317,7 +1317,7 @@ static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cac
if (cache) {
if (cache->defgroup_weights == NULL) {
- int num_defgroup = BLI_listbase_count(&ob->defbase);
+ int num_defgroup = BKE_object_defgroup_count(ob);
cache->defgroup_weights = MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup,
"cached defgroup weights");
cache->num_defgroup_weights = num_defgroup;
@@ -1695,7 +1695,7 @@ void BKE_keyblock_data_set_with_mat4(Key *key,
const float mat[4][4])
{
if (key->elemsize != sizeof(float[3])) {
- BLI_assert(!"Invalid elemsize");
+ BLI_assert_msg(0, "Invalid elemsize");
return;
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 1357424d5ff..9875d776d33 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -87,6 +87,8 @@ static void lattice_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i
lattice_dst->key->from = &lattice_dst->id;
}
+ BKE_defgroup_copy_list(&lattice_dst->vertex_group_names, &lattice_src->vertex_group_names);
+
if (lattice_src->dvert) {
int tot = lattice_src->pntsu * lattice_src->pntsv * lattice_src->pntsw;
lattice_dst->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
@@ -103,6 +105,8 @@ static void lattice_free_data(ID *id)
BKE_lattice_batch_cache_free(lattice);
+ BLI_freelistN(&lattice->vertex_group_names);
+
MEM_SAFE_FREE(lattice->def);
if (lattice->dvert) {
BKE_defvert_array_free(lattice->dvert, lattice->pntsu * lattice->pntsv * lattice->pntsw);
@@ -150,6 +154,7 @@ static void lattice_blend_write(BlendWriter *writer, ID *id, const void *id_addr
/* direct data */
BLO_write_struct_array(writer, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+ BKE_defbase_blend_write(writer, &lt->vertex_group_names);
BKE_defvert_blend_write(writer, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
}
}
@@ -161,6 +166,7 @@ static void lattice_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &lt->dvert);
BKE_defvert_blend_read(reader, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ BLO_read_list(reader, &lt->vertex_group_names);
lt->editlatt = NULL;
lt->batch_cache = NULL;
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
index a3133b58a0a..f9437eeaffa 100644
--- a/source/blender/blenkernel/intern/lattice_deform.c
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -108,11 +108,11 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob
invert_m4_m4(imat, latmat);
}
- /* Prefetch latice deform group weights. */
+ /* Prefetch lattice deform group weights. */
int defgrp_index = -1;
const MDeformVert *dvert = BKE_lattice_deform_verts_get(oblatt);
if (lt->vgroup[0] && dvert) {
- defgrp_index = BKE_object_defgroup_name_index(oblatt, lt->vgroup);
+ defgrp_index = BKE_id_defgroup_name_index(&lt->id, lt->vgroup);
if (defgrp_index != -1) {
lattice_weights = MEM_malloc_arrayN(sizeof(float), num_points, "lattice_weights");
@@ -364,7 +364,7 @@ static void lattice_deform_coords_impl(const Object *ob_lattice,
* We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
*/
if (defgrp_name && defgrp_name[0] && ob_target && ELEM(ob_target->type, OB_MESH, OB_LATTICE)) {
- defgrp_index = BKE_object_defgroup_name_index(ob_target, defgrp_name);
+ defgrp_index = BKE_id_defgroup_name_index((ID *)ob_target->data, defgrp_name);
if (defgrp_index != -1) {
/* if there's derived data without deformverts, don't use vgroups */
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index d49eb0d4da8..730c989abc9 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -737,172 +737,193 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection
* in at least one layer collection. That list is also synchronized here, and
* stores state like selection. */
+static void layer_collection_objects_sync(ViewLayer *view_layer,
+ LayerCollection *layer,
+ ListBase *r_lb_new_object_bases,
+ const short collection_restrict,
+ const short layer_restrict,
+ const ushort local_collections_bits)
+{
+ /* No need to sync objects if the collection is excluded. */
+ if ((layer->flag & LAYER_COLLECTION_EXCLUDE) != 0) {
+ return;
+ }
+
+ LISTBASE_FOREACH (CollectionObject *, cob, &layer->collection->gobject) {
+ if (cob->ob == NULL) {
+ continue;
+ }
+
+ /* Tag linked object as a weak reference so we keep the object
+ * base pointer on file load and remember hidden state. */
+ id_lib_indirect_weak_link(&cob->ob->id);
+
+ void **base_p;
+ Base *base;
+ if (BLI_ghash_ensure_p(view_layer->object_bases_hash, cob->ob, &base_p)) {
+ /* Move from old base list to new base list. Base might have already
+ * been moved to the new base list and the first/last test ensure that
+ * case also works. */
+ base = *base_p;
+ if (!ELEM(base, r_lb_new_object_bases->first, r_lb_new_object_bases->last)) {
+ BLI_remlink(&view_layer->object_bases, base);
+ BLI_addtail(r_lb_new_object_bases, base);
+ }
+ }
+ else {
+ /* Create new base. */
+ base = object_base_new(cob->ob);
+ base->local_collections_bits = local_collections_bits;
+ *base_p = base;
+ BLI_addtail(r_lb_new_object_bases, base);
+ }
+
+ if ((collection_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) {
+ base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH);
+ if ((layer_restrict & LAYER_COLLECTION_HIDE) == 0) {
+ base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER;
+ }
+ if (((collection_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
+ base->flag_from_collection |= BASE_SELECTABLE;
+ }
+ }
+
+ if ((collection_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
+ base->flag_from_collection |= BASE_ENABLED_RENDER;
+ }
+
+ /* Holdout and indirect only */
+ if (layer->flag & LAYER_COLLECTION_HOLDOUT) {
+ base->flag_from_collection |= BASE_HOLDOUT;
+ }
+ if (layer->flag & LAYER_COLLECTION_INDIRECT_ONLY) {
+ base->flag_from_collection |= BASE_INDIRECT_ONLY;
+ }
+
+ layer->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;
+ }
+}
+
static void layer_collection_sync(ViewLayer *view_layer,
- const ListBase *lb_collections,
- ListBase *lb_layer_collections,
- ListBase *new_object_bases,
- short parent_exclude,
- short parent_restrict,
- short parent_layer_restrict,
- unsigned short parent_local_collections_bits)
+ const ListBase *lb_children_collections,
+ ListBase *r_lb_children_layers,
+ ListBase *r_lb_new_object_bases,
+ const short parent_layer_flag,
+ const short parent_collection_restrict,
+ const short parent_layer_restrict,
+ const ushort parent_local_collections_bits)
{
/* TODO: support recovery after removal of intermediate collections, reordering, ..
* For local edits we can make editing operating do the appropriate thing, but for
* linking we can only sync after the fact. */
/* Remove layer collections that no longer have a corresponding scene collection. */
- LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, lb_layer_collections) {
- /* Note that ID remap can set lc->collection to NULL when deleting collections. */
- Collection *collection = (lc->collection) ?
- BLI_findptr(lb_collections,
- lc->collection,
- offsetof(CollectionChild, collection)) :
- NULL;
-
- if (!collection) {
- if (lc == view_layer->active_collection) {
+ LISTBASE_FOREACH_MUTABLE (LayerCollection *, child_layer, r_lb_children_layers) {
+ /* Note that ID remap can set child_layer->collection to NULL when deleting collections. */
+ Collection *child_collection = (child_layer->collection != NULL) ?
+ BLI_findptr(lb_children_collections,
+ child_layer->collection,
+ offsetof(CollectionChild, collection)) :
+ NULL;
+
+ if (child_collection == NULL) {
+ if (child_layer == view_layer->active_collection) {
view_layer->active_collection = NULL;
}
/* Free recursively. */
- layer_collection_free(view_layer, lc);
- BLI_freelinkN(lb_layer_collections, lc);
+ layer_collection_free(view_layer, child_layer);
+ BLI_freelinkN(r_lb_children_layers, child_layer);
}
}
/* Add layer collections for any new scene collections, and ensure order is the same. */
- ListBase new_lb_layer = {NULL, NULL};
+ ListBase lb_new_children_layers = {NULL, NULL};
- LISTBASE_FOREACH (const CollectionChild *, child, lb_collections) {
- Collection *collection = child->collection;
- LayerCollection *lc = BLI_findptr(
- lb_layer_collections, collection, offsetof(LayerCollection, collection));
+ LISTBASE_FOREACH (const CollectionChild *, child, lb_children_collections) {
+ Collection *child_collection = child->collection;
+ LayerCollection *child_layer = BLI_findptr(
+ r_lb_children_layers, child_collection, offsetof(LayerCollection, collection));
- if (lc) {
- BLI_remlink(lb_layer_collections, lc);
- BLI_addtail(&new_lb_layer, lc);
+ if (child_layer) {
+ BLI_remlink(r_lb_children_layers, child_layer);
+ BLI_addtail(&lb_new_children_layers, child_layer);
}
else {
- lc = layer_collection_add(&new_lb_layer, collection);
- lc->flag = parent_exclude;
+ child_layer = layer_collection_add(&lb_new_children_layers, child_collection);
+ child_layer->flag = parent_layer_flag;
}
- unsigned short local_collections_bits = parent_local_collections_bits &
- lc->local_collections_bits;
+ const ushort child_local_collections_bits = parent_local_collections_bits &
+ child_layer->local_collections_bits;
/* Tag linked collection as a weak reference so we keep the layer
* collection pointer on file load and remember exclude state. */
- id_lib_indirect_weak_link(&collection->id);
+ id_lib_indirect_weak_link(&child_collection->id);
/* Collection restrict is inherited. */
- short child_restrict = parent_restrict;
+ short child_collection_restrict = parent_collection_restrict;
short child_layer_restrict = parent_layer_restrict;
- if (!(collection->flag & COLLECTION_IS_MASTER)) {
- child_restrict |= collection->flag;
- child_layer_restrict |= lc->flag;
+ if (!(child_collection->flag & COLLECTION_IS_MASTER)) {
+ child_collection_restrict |= child_collection->flag;
+ child_layer_restrict |= child_layer->flag;
}
/* Sync child collections. */
layer_collection_sync(view_layer,
- &collection->children,
- &lc->layer_collections,
- new_object_bases,
- lc->flag,
- child_restrict,
+ &child_collection->children,
+ &child_layer->layer_collections,
+ r_lb_new_object_bases,
+ child_layer->flag,
+ child_collection_restrict,
child_layer_restrict,
- local_collections_bits);
+ child_local_collections_bits);
- /* Layer collection exclude is not inherited. */
- lc->runtime_flag = 0;
- if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ /* Layer collection exclude is not inherited, we can skip the remaining process, including
+ * object bases synchronization. */
+ child_layer->runtime_flag = 0;
+ if (child_layer->flag & LAYER_COLLECTION_EXCLUDE) {
continue;
}
/* We separate restrict viewport and visible view layer because a layer collection can be
* hidden in the view layer yet (locally) visible in a viewport (if it is not restricted). */
- if (child_restrict & COLLECTION_RESTRICT_VIEWPORT) {
- lc->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT;
+ if (child_collection_restrict & COLLECTION_RESTRICT_VIEWPORT) {
+ child_layer->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT;
}
- if (((lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) &&
+ if (((child_layer->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) &&
((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) {
- lc->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER;
+ child_layer->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER;
}
- /* Sync objects, except if collection was excluded. */
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- if (cob->ob == NULL) {
- continue;
- }
-
- /* Tag linked object as a weak reference so we keep the object
- * base pointer on file load and remember hidden state. */
- id_lib_indirect_weak_link(&cob->ob->id);
-
- void **base_p;
- Base *base;
- if (BLI_ghash_ensure_p(view_layer->object_bases_hash, cob->ob, &base_p)) {
- /* Move from old base list to new base list. Base might have already
- * been moved to the new base list and the first/last test ensure that
- * case also works. */
- base = *base_p;
- if (!ELEM(base, new_object_bases->first, new_object_bases->last)) {
- BLI_remlink(&view_layer->object_bases, base);
- BLI_addtail(new_object_bases, base);
- }
- }
- else {
- /* Create new base. */
- base = object_base_new(cob->ob);
- base->local_collections_bits = local_collections_bits;
- *base_p = base;
- BLI_addtail(new_object_bases, base);
- }
-
- if ((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) {
- base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH);
- if ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0) {
- base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER;
- }
- if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
- base->flag_from_collection |= BASE_SELECTABLE;
- }
- }
-
- if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
- base->flag_from_collection |= BASE_ENABLED_RENDER;
- }
-
- /* Holdout and indirect only */
- if (lc->flag & LAYER_COLLECTION_HOLDOUT) {
- base->flag_from_collection |= BASE_HOLDOUT;
- }
- if (lc->flag & LAYER_COLLECTION_INDIRECT_ONLY) {
- base->flag_from_collection |= BASE_INDIRECT_ONLY;
- }
-
- lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;
- }
+ layer_collection_objects_sync(view_layer,
+ child_layer,
+ r_lb_new_object_bases,
+ child_collection_restrict,
+ child_layer_restrict,
+ child_local_collections_bits);
}
/* Free potentially remaining unused layer collections in old list.
* NOTE: While this does not happen in typical situations, some corner cases (like remapping
* several different collections to a single one) can lead to this list having extra unused
* items. */
- LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, lb_layer_collections) {
+ LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, r_lb_children_layers) {
if (lc == view_layer->active_collection) {
view_layer->active_collection = NULL;
}
/* Free recursively. */
layer_collection_free(view_layer, lc);
- BLI_freelinkN(lb_layer_collections, lc);
+ BLI_freelinkN(r_lb_children_layers, lc);
}
- BLI_assert(BLI_listbase_is_empty(lb_layer_collections));
+ BLI_assert(BLI_listbase_is_empty(r_lb_children_layers));
/* Replace layer collection list with new one. */
- *lb_layer_collections = new_lb_layer;
- BLI_assert(BLI_listbase_count(lb_collections) == BLI_listbase_count(lb_layer_collections));
+ *r_lb_children_layers = lb_new_children_layers;
+ BLI_assert(BLI_listbase_count(lb_children_collections) ==
+ BLI_listbase_count(r_lb_children_layers));
}
/**
diff --git a/source/blender/blenkernel/intern/layer_utils.c b/source/blender/blenkernel/intern/layer_utils.c
index 10ab0a06dd0..48179e0c3bf 100644
--- a/source/blender/blenkernel/intern/layer_utils.c
+++ b/source/blender/blenkernel/intern/layer_utils.c
@@ -23,6 +23,7 @@
#include "BLI_array.h"
#include "BKE_collection.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 297ee565257..62d29188c5a 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -499,7 +499,7 @@ bool BKE_lib_id_make_local(Main *bmain, ID *id, const bool test, const int flags
return false;
}
- BLI_assert(!"IDType Missing IDTypeInfo");
+ BLI_assert_msg(0, "IDType Missing IDTypeInfo");
return false;
}
@@ -603,7 +603,7 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
}
}
else {
- BLI_assert(!"IDType Missing IDTypeInfo");
+ BLI_assert_msg(0, "IDType Missing IDTypeInfo");
}
/* Update ID refcount, remap pointers to self in new ID. */
@@ -667,7 +667,7 @@ ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplica
ID_NEW_SET(key, key_new);
}
- /* Note: embedded data (root nodetrees and master collections) should never be referenced by
+ /* NOTE: embedded data (root nodetrees and master collections) should never be referenced by
* anything else, so we do not need to set their newid pointer and flag. */
BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags);
@@ -1053,7 +1053,7 @@ void *BKE_libblock_alloc_notest(short type)
if (size != 0) {
return MEM_callocN(size, name);
}
- BLI_assert(!"Request to allocate unknown data type");
+ BLI_assert_msg(0, "Request to allocate unknown data type");
return NULL;
}
@@ -1099,7 +1099,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
/* alphabetic insertion: is in new_id */
BKE_main_unlock(bmain);
- /* TODO to be removed from here! */
+ /* TODO: to be removed from here! */
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
DEG_id_type_tag(bmain, type);
}
@@ -1134,7 +1134,7 @@ void BKE_libblock_init_empty(ID *id)
return;
}
- BLI_assert(!"IDType Missing IDTypeInfo");
+ BLI_assert_msg(0, "IDType Missing IDTypeInfo");
}
/* ********** ID session-wise UUID management. ********** */
@@ -1234,11 +1234,11 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
/* r_newid already contains pointer to allocated memory. */
- /* TODO do we want to memset(0) whole mem before filling it? */
+ /* TODO: do we want to memset(0) whole mem before filling it? */
BLI_strncpy(new_id->name, id->name, sizeof(new_id->name));
new_id->us = 0;
new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT;
- /* TODO Do we want/need to copy more from ID struct itself? */
+ /* TODO: Do we want/need to copy more from ID struct itself? */
}
else {
new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag);
@@ -1380,7 +1380,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
/* Step one: We go backward over a whole chunk of items at once, until we find a limit item
* that is lower than, or equal (should never happen!) to the one we want to insert. */
- /* Note: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at
+ /* NOTE: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at
* once using the same base name), newly inserted items will generally be towards the end
* (higher extension numbers). */
bool is_in_library = false;
@@ -1450,7 +1450,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
#undef ID_SORT_STEP_SIZE
}
-/* Note: this code assumes and ensures that the suffix number can never go beyond 1 billion. */
+/* NOTE: this code assumes and ensures that the suffix number can never go beyond 1 billion. */
#define MAX_NUMBER 1000000000
/* We do not want to get "name.000", so minimal number is 1. */
#define MIN_NUMBER 1
@@ -1605,7 +1605,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
}
/* In case we get an insane initial number suffix in given name. */
- /* Note: BLI_split_name_num() cannot return negative numbers, so we do not have to check for
+ /* NOTE: BLI_split_name_num() cannot return negative numbers, so we do not have to check for
* that here. */
if (number >= MAX_NUMBER || number < MIN_NUMBER) {
number = MIN_NUMBER;
@@ -1642,9 +1642,8 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
* already.
*/
if (!is_orig_name_used) {
- /* Don't bother updating prev_ static variables here, this case is not supposed to happen
- * that often, and is not straight-forward here, so just ignore and reset them to default.
- */
+ /* Don't bother updating `prev_*` static variables here, this case is not supposed to happen
+ * that often, and is not straight-forward here, so just ignore and reset them to default. */
prev_id_type = ID_LINK_PLACEHOLDER;
prev_final_base_name[0] = '\0';
prev_number = MIN_NUMBER - 1;
@@ -1684,7 +1683,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
continue;
}
- /* Update prev_ static variables, in case next call is for the same type of IDs and with the
+ /* Update `prev_*` static variables, in case next call is for the same type of IDs and with the
* same initial base name, we can skip a lot of above process. */
prev_id_type = id_type;
strcpy(prev_final_base_name, base_name);
@@ -1892,7 +1891,7 @@ static void library_make_local_copying_check(ID *id,
* \param set_fake: If true, set fake user on all localized data-blocks
* (except group and objects ones).
*/
-/* Note: Old (2.77) version was simply making (tagging) data-blocks as local,
+/* NOTE: Old (2.77) version was simply making (tagging) data-blocks as local,
* without actually making any check whether they were also indirectly used or not...
*
* Current version uses regular id_make_local callback, with advanced pre-processing step to
@@ -2070,7 +2069,7 @@ void BKE_library_make_local(Main *bmain,
* ID in a separated loop,
* as lbarray ordering is not enough to ensure us we did catch all dependencies
* (e.g. if making local a parent object before its child...). See T48907. */
- /* TODO This is now the biggest step by far (in term of processing time).
+ /* TODO: This is now the biggest step by far (in term of processing time).
* We may be able to gain here by using again main->relations mapping, but...
* this implies BKE_libblock_remap & co to be able to update main->relations on the fly.
* Have to think about it a bit more, and see whether new code is OK first, anyway. */
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index 67b2e4429d6..a9407860c06 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -83,7 +83,7 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
return;
}
- BLI_assert(!"IDType Missing IDTypeInfo");
+ BLI_assert_msg(0, "IDType Missing IDTypeInfo");
}
/**
@@ -277,7 +277,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
for (id = lb->first; id; id = id_next) {
id_next = id->next;
- /* Note: in case we delete a library, we also delete all its datablocks! */
+ /* NOTE: in case we delete a library, we also delete all its datablocks! */
if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
BLI_remlink(lb, id);
BLI_addtail(&tagged_deleted_ids, id);
@@ -331,7 +331,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
for (id = lb->first; id; id = id_next) {
id_next = id->next;
- /* Note: in case we delete a library, we also delete all its datablocks! */
+ /* NOTE: in case we delete a library, we also delete all its datablocks! */
if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
id->tag |= tag;
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 595e470876d..9871bf5dc83 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -94,7 +94,7 @@ BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id)
if (id_type->owner_get != NULL) {
return id_type->owner_get(bmain, id)->override_library;
}
- BLI_assert(!"IDTypeInfo of liboverride-embedded ID with no owner getter");
+ BLI_assert_msg(0, "IDTypeInfo of liboverride-embedded ID with no owner getter");
}
return id->override_library;
}
@@ -130,7 +130,7 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id)
local_id->override_library->reference = reference_id;
id_us_plus(local_id->override_library->reference);
local_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK;
- /* TODO do we want to add tag or flag to referee to mark it as such? */
+ /* TODO: do we want to add tag or flag to referee to mark it as such? */
return local_id->override_library;
}
@@ -217,7 +217,7 @@ static ID *lib_override_library_create_from(Main *bmain,
ID *reference_id,
const int lib_id_copy_flags)
{
- /* Note: We do not want to copy possible override data from reference here (whether it is an
+ /* NOTE: We do not want to copy possible override data from reference here (whether it is an
* override template, or already an override of some other ref data). */
ID *local_id = BKE_id_copy_ex(bmain,
reference_id,
@@ -232,7 +232,7 @@ static ID *lib_override_library_create_from(Main *bmain,
BKE_lib_override_library_init(local_id, reference_id);
- /* Note: From liboverride perspective (and RNA one), shape keys are considered as local embedded
+ /* NOTE: From liboverride perspective (and RNA one), shape keys are considered as local embedded
* data-blocks, just like root node trees or master collections. Therefore, we never need to
* create overrides for them. We need a way to mark them as overrides though. */
Key *reference_key;
@@ -369,7 +369,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
/* If `newid` is already set, assume it has been handled by calling code.
* Only current use case: re-using proxy ID when converting to liboverride. */
if (reference_id->newid == NULL) {
- /* Note: `no main` case is used during resync procedure, to support recursive resync.
+ /* NOTE: `no main` case is used during resync procedure, to support recursive resync.
* This requires extra care further down the resync process,
* see: #BKE_lib_override_library_resync. */
reference_id->newid = lib_override_library_create_from(
@@ -569,7 +569,7 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat
/* We tag all collections and objects for override. And we also tag all other data-blocks which
* would use one of those.
- * Note: missing IDs (aka placeholders) are never overridden. */
+ * NOTE: missing IDs (aka placeholders) are never overridden. */
if (ELEM(GS(to_id->name), ID_OB, ID_GR)) {
if ((to_id->tag & LIB_TAG_MISSING)) {
to_id->tag |= missing_tag;
@@ -1347,7 +1347,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
if (do_post_process) {
/* Essentially ensures that potentially new overrides of new objects will be instantiated. */
- /* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine
+ /* NOTE: Here 'reference' collection and 'newly added' collection are the same, which is fine
* since we already relinked old root override collection to new resync'ed one above. So this
* call is not expected to instantiate this new resync'ed collection anywhere, just to ensure
* that we do not have any stray objects. */
@@ -2126,7 +2126,7 @@ bool BKE_lib_override_library_property_operation_operands_validate(
ATTR_FALLTHROUGH;
case IDOVERRIDE_LIBRARY_OP_MULTIPLY:
if (ptr_storage == NULL || ptr_storage->data == NULL || prop_storage == NULL) {
- BLI_assert(!"Missing data to apply differential override operation.");
+ BLI_assert_msg(0, "Missing data to apply differential override operation.");
return false;
}
ATTR_FALLTHROUGH;
@@ -2137,7 +2137,7 @@ bool BKE_lib_override_library_property_operation_operands_validate(
case IDOVERRIDE_LIBRARY_OP_REPLACE:
if ((ptr_dst == NULL || ptr_dst->data == NULL || prop_dst == NULL) ||
(ptr_src == NULL || ptr_src->data == NULL || prop_src == NULL)) {
- BLI_assert(!"Missing data to apply override operation.");
+ BLI_assert_msg(0, "Missing data to apply override operation.");
return false;
}
}
@@ -2820,7 +2820,7 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
local->tag |= LIB_TAG_OVERRIDE_LIBRARY_REFOK;
- /* Note: Since we reload full content from linked ID here, potentially from edited local
+ /* NOTE: Since we reload full content from linked ID here, potentially from edited local
* override, we do not really have a way to know *what* is changed, so we need to rely on the
* massive destruction weapon of `ID_RECALC_ALL` here. */
DEG_id_tag_update_ex(bmain, local, ID_RECALC_ALL);
@@ -2907,7 +2907,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
* other-ID-reference creation/update in that case (since no differential operation is expected
* to involve those anyway). */
#if 0
- /* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy
+ /* XXX TODO: We may also want a specialized handling of things here too, to avoid copying heavy
* never-overridable data (like Mesh geometry etc.)? And also maybe avoid lib
* reference-counting completely (shallow copy). */
/* This would imply change in handling of user-count all over RNA
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 9d2552777bf..977e53c8474 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -273,7 +273,7 @@ static void library_foreach_ID_link(Main *bmain,
continue;
}
- /* Note: ID.lib pointer is purposefully fully ignored here...
+ /* NOTE: ID.lib pointer is purposefully fully ignored here...
* We may want to add it at some point? */
if (flag & IDWALK_DO_INTERNAL_RUNTIME_POINTERS) {
diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index 2641208897e..bba15a3bcdf 100644
--- a/source/blender/blenkernel/intern/lib_remap.c
+++ b/source/blender/blenkernel/intern/lib_remap.c
@@ -126,7 +126,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
const bool is_reference = (cb_flag & IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE) != 0;
const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
- /* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
+ /* NOTE: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
* on the other hand since they get reset to lib data on file open/reload it is indirect too.
* Edit Mode is also a 'skip direct' case. */
const bool is_obj = (GS(id_owner->name) == ID_OB);
@@ -312,7 +312,7 @@ static void libblock_remap_data_postprocess_collection_update(Main *bmain,
/* XXX Complex cases can lead to NULL pointers in other collections than old_collection,
* and BKE_main_collection_sync_remap() does not tolerate any of those, so for now always check
* whole existing collections for NULL pointers.
- * I'd consider optimizing that whole collection remapping process a TODO for later. */
+ * I'd consider optimizing that whole collection remapping process a TODO: for later. */
BKE_collections_child_remove_nulls(bmain, owner_collection, NULL /*old_collection*/);
}
else {
@@ -630,7 +630,7 @@ void BKE_libblock_relink_ex(
switch (GS(id->name)) {
case ID_SCE:
case ID_GR: {
- /* Note: here we know which collection we have affected, so at lest for NULL children
+ /* NOTE: here we know which collection we have affected, so at lest for NULL children
* detection we can only process that one.
* This is also a required fix in case `id` would not be in Main anymore, which can happen
* e.g. when called from `id_delete`. */
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 677b9497c98..07a3396ad5f 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -102,10 +102,10 @@ void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
/* Not essential but set `filepath_abs` is an absolute copy of value which
* is more useful if its kept in sync. */
if (BLI_path_is_rel(lib->filepath_abs)) {
- /* note that the file may be unsaved, in this case, setting the
+ /* NOTE(campbell): the file may be unsaved, in this case, setting the
* `filepath_abs` on an indirectly linked path is not allowed from the
* outliner, and its not really supported but allow from here for now
- * since making local could cause this to be directly linked - campbell
+ * since making local could cause this to be directly linked.
*/
/* Never make paths relative to parent lib - reading code (blenloader) always set *all*
* `lib->filepath` relative to current main, not to their parent for indirectly linked ones. */
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index d872ecf7578..b09aed82921 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -131,7 +131,7 @@ void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type)
probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
break;
default:
- BLI_assert(!"LightProbe type not configured.");
+ BLI_assert_msg(0, "LightProbe type not configured.");
break;
}
}
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index 39cc5737ca2..655b6d3732c 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -400,7 +400,7 @@ ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
}
if (data) {
- /* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer,
+ /* NOTE: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer,
* which will fail here (we do not want to pass the first two ints!). */
img = IMB_allocImBuf(
(unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata);
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 371af2a95ed..34dd38164c2 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -69,7 +69,7 @@ static void mask_copy_data(Main *UNUSED(bmain),
BLI_listbase_clear(&mask_dst->masklayers);
- /* TODO add unused flag to those as well. */
+ /* TODO: add unused flag to those as well. */
BKE_mask_layer_copy_list(&mask_dst->masklayers, &mask_src->masklayers);
/* enable fake user by default */
@@ -342,7 +342,7 @@ MaskSplinePoint *BKE_mask_spline_point_array_from_point(MaskSpline *spline,
return spline->points_deform;
}
- BLI_assert(!"wrong array");
+ BLI_assert_msg(0, "wrong array");
return NULL;
}
@@ -372,7 +372,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name)
return masklay;
}
-/* note: may still be hidden, caller needs to check */
+/* NOTE: may still be hidden, caller needs to check. */
MaskLayer *BKE_mask_layer_active(Mask *mask)
{
return BLI_findlink(&mask->masklayers, mask->masklay_act);
@@ -707,7 +707,7 @@ void BKE_mask_point_handle(const MaskSplinePoint *point,
copy_v2_v2(r_handle, bezt->vec[2]);
}
else {
- BLI_assert(!"Unknown handle passed to BKE_mask_point_handle");
+ BLI_assert_msg(0, "Unknown handle passed to BKE_mask_point_handle");
}
}
@@ -760,7 +760,7 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point,
copy_v2_v2(bezt->vec[2], loc);
}
else {
- BLI_assert(!"unknown handle passed to BKE_mask_point_set_handle");
+ BLI_assert_msg(0, "unknown handle passed to BKE_mask_point_set_handle");
}
}
@@ -1003,7 +1003,7 @@ void BKE_mask_point_select_set_handle(MaskSplinePoint *point,
point->bezt.f3 |= SELECT;
}
else {
- BLI_assert(!"Wrong which_handle passed to BKE_mask_point_select_set_handle");
+ BLI_assert_msg(0, "Wrong which_handle passed to BKE_mask_point_select_set_handle");
}
}
else {
@@ -1018,7 +1018,7 @@ void BKE_mask_point_select_set_handle(MaskSplinePoint *point,
point->bezt.f3 &= ~SELECT;
}
else {
- BLI_assert(!"Wrong which_handle passed to BKE_mask_point_select_set_handle");
+ BLI_assert_msg(0, "Wrong which_handle passed to BKE_mask_point_select_set_handle");
}
}
}
@@ -1133,7 +1133,7 @@ MaskSpline *BKE_mask_spline_copy(const MaskSpline *spline)
return nspline;
}
-/* note: does NOT add to the list */
+/* NOTE: Does NOT add to the list. */
MaskLayerShape *BKE_mask_layer_shape_alloc(MaskLayer *masklay, const int frame)
{
MaskLayerShape *masklay_shape;
@@ -1422,7 +1422,7 @@ void BKE_mask_get_handle_point_adjacent(MaskSpline *spline,
MaskSplinePoint **r_point_prev,
MaskSplinePoint **r_point_next)
{
- /* TODO, could avoid calling this at such low level */
+ /* TODO: could avoid calling this at such low level. */
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
*r_point_prev = mask_spline_point_prev(spline, points_array, point);
@@ -1472,7 +1472,7 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline,
MaskSplinePoint *point,
const float u)
{
- /* TODO! - make this interpolate between siblings - not always midpoint! */
+ /* TODO: make this interpolate between siblings - not always midpoint! */
int length_tot = 0;
float length_average = 0.0f;
float weight_average = 0.0f;
@@ -1942,7 +1942,7 @@ void BKE_mask_layer_shape_changed_add(MaskLayer *masklay,
int tot = BKE_mask_layer_shape_totvert(masklay) - 1;
/* for interpolation */
- /* TODO - assumes closed curve for now */
+ /* TODO: assumes closed curve for now. */
float uv[3][2]; /* 3x 2D handles */
const int pi_curr = spline_point_index;
const int pi_prev = ((spline_point_index - 1) + spline->tot_point) % spline->tot_point;
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 69f60ca0384..4584d9e527e 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -545,7 +545,7 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__even(
float u = (float)j / resol, weight;
float co[2], n[2];
- /* TODO - these calls all calculate similar things
+ /* TODO: these calls all calculate similar things
* could be unified for some speed */
BKE_mask_point_segment_co(spline, point_prev, u, co);
BKE_mask_point_normal(spline, point_prev, u, n);
@@ -691,7 +691,7 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double
float weight_uw, weight_scalar;
float co[2];
- /* TODO - these calls all calculate similar things
+ /* TODO: these calls all calculate similar things
* could be unified for some speed */
BKE_mask_point_segment_co(spline, point_prev, u, co);
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index d29a6e75954..81c161a4a7d 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -514,7 +514,7 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size)
BLI_assert(bucket_index < bucket_tot);
/* Check if the bucket intersects with the face. */
- /* Note: there is a trade off here since checking box/tri intersections isn't as
+ /* NOTE: there is a trade off here since checking box/tri intersections isn't as
* optimal as it could be, but checking pixels against faces they will never
* intersect with is likely the greater slowdown here -
* so check if the cell intersects the face. */
@@ -729,7 +729,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
sf_vert_tot++;
- /* TODO, an alternate functions so we can avoid double vector copy! */
+ /* TODO: an alternate functions so we can avoid double vector copy! */
for (j = 1; j < tot_diff_point; j++) {
copy_v2_v2(co, diff_points[j]);
sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
@@ -762,7 +762,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
BLI_assert(tot_diff_feather_points == tot_diff_point);
- /* Note: only added for convenience, we don't in fact use these to scan-fill,
+ /* NOTE: only added for convenience, we don't in fact use these to scan-fill,
* only to create feather faces after scan-fill. */
for (j = 0; j < tot_diff_feather_points; j++) {
copy_v2_v2(co_feather, diff_feather_points[j]);
@@ -804,7 +804,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
open_spline_ranges[open_spline_index].vertex_offset = sf_vert_tot;
open_spline_ranges[open_spline_index].vertex_total = tot_diff_point;
- /* TODO, an alternate functions so we can avoid double vector copy! */
+ /* TODO: an alternate functions so we can avoid double vector copy! */
for (j = 0; j < tot_diff_point; j++) {
/* center vert */
@@ -937,7 +937,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
ListBase isect_remedgebase = {NULL, NULL};
/* now we have all the splines */
- face_coords = MEM_mallocN((sizeof(float[3])) * sf_vert_tot, "maskrast_face_coords");
+ face_coords = MEM_mallocN(sizeof(float[3]) * sf_vert_tot, "maskrast_face_coords");
/* init bounds */
BLI_rctf_init_minmax(&bounds);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index c5060e16e4d..4f0b2a718ed 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -135,7 +135,7 @@ static void material_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const
BLI_listbase_clear(&material_dst->gpumaterial);
- /* TODO Duplicate Engine Settings and set runtime to NULL */
+ /* TODO: Duplicate Engine Settings and set runtime to NULL. */
}
static void material_free_data(ID *id)
@@ -864,7 +864,7 @@ void BKE_object_material_resize(Main *bmain, Object *ob, const short totcol, boo
ob->mat = newmatar;
ob->matbits = newmatbits;
}
- /* XXX, why not realloc on shrink? - campbell */
+ /* XXX(campbell): why not realloc on shrink? */
ob->totcol = totcol;
if (ob->totcol && ob->actcol == 0) {
@@ -1168,7 +1168,7 @@ void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, ID *data_e
BKE_object_materials_test(bmain, ob_orig, data_orig);
}
-/* XXX - this calls many more update calls per object then are needed, could be optimized */
+/* XXX: this calls many more update calls per object then are needed, could be optimized. */
void BKE_object_material_array_assign(Main *bmain,
struct Object *ob,
struct Material ***matar,
@@ -1823,7 +1823,7 @@ void BKE_material_copybuf_copy(Main *bmain, Material *ma)
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
- /* TODO Duplicate Engine Settings and set runtime to NULL */
+ /* TODO: Duplicate Engine Settings and set runtime to NULL. */
matcopied = 1;
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index f5d898e801b..6a2b56306d6 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -559,7 +559,7 @@ bool BKE_mball_minmax_ex(
copy_v3_v3(centroid, &ml->x);
}
- /* TODO, non circle shapes cubes etc, probably nobody notices - campbell */
+ /* TODO(campbell): non circle shapes cubes etc, probably nobody notices. */
for (int i = -1; i != 3; i += 2) {
copy_v3_v3(vec, centroid);
add_v3_fl(vec, scale_mb * i);
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 413cefd2271..760febaca91 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -1336,7 +1336,7 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
}
/* untransformed Bounding Box of MetaElem */
- /* TODO, its possible the elem type has been changed and the exp*
+ /* TODO: its possible the elem type has been changed and the exp*
* values can use a fallback. */
copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */
copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */
@@ -1438,7 +1438,7 @@ void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBa
build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb);
/* Don't polygonize meta-balls with too high resolution (base mball too small)
- * note: Eps was 0.0001f but this was giving problems for blood animation for
+ * NOTE: Eps was 0.0001f but this was giving problems for blood animation for
* the open movie "Sintel", using 0.00001f. */
if (ob->scale[0] > 0.00001f * (process.allbb.max[0] - process.allbb.min[0]) ||
ob->scale[1] > 0.00001f * (process.allbb.max[1] - process.allbb.min[1]) ||
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index b518f35fac7..b463d903303 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -39,6 +39,7 @@
#include "BLI_ghash.h"
#include "BLI_hash.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_string.h"
@@ -125,6 +126,8 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->mat = MEM_dupallocN(mesh_src->mat);
+ BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names);
+
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, alloc_type, mesh_dst->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, alloc_type, mesh_dst->totedge);
@@ -143,7 +146,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->mselect = MEM_dupallocN(mesh_dst->mselect);
- /* TODO Do we want to add flag to prevent this? */
+ /* TODO: Do we want to add flag to prevent this? */
if (mesh_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &mesh_src->key->id, (ID **)&mesh_dst->key, flag);
/* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */
@@ -155,6 +158,8 @@ static void mesh_free_data(ID *id)
{
Mesh *mesh = (Mesh *)id;
+ BLI_freelistN(&mesh->vertex_group_names);
+
BKE_mesh_runtime_clear_cache(mesh);
mesh_clear_geometry(mesh);
MEM_SAFE_FREE(mesh->mat);
@@ -229,6 +234,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
BKE_animdata_blend_write(writer, mesh->adt);
}
+ BKE_defbase_blend_write(writer, &mesh->vertex_group_names);
+
BLO_write_pointer_array(writer, mesh->totcol, mesh->mat);
BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect);
@@ -288,6 +295,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
/* Normally BKE_defvert_blend_read should be called in CustomData_blend_read,
* but for backwards compatibility in do_versions to work we do it here. */
BKE_defvert_blend_read(reader, mesh->totvert, mesh->dvert);
+ BLO_read_list(reader, &mesh->vertex_group_names);
CustomData_blend_read(reader, &mesh->vdata, mesh->totvert);
CustomData_blend_read(reader, &mesh->edata, mesh->totedge);
@@ -304,7 +312,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
mesh->totselect = 0;
}
- if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) {
+ if (BLO_read_requires_endian_switch(reader) && mesh->tface) {
TFace *tf = mesh->tface;
for (int i = 0; i < mesh->totface; i++, tf++) {
BLI_endian_switch_uint32_array(tf->col, 4);
@@ -657,12 +665,12 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface);
- /* TODO - add some --debug-mesh option */
+ /* TODO: add some `--debug-mesh` option. */
if (G.debug & G_DEBUG) {
- /* note: this warning may be un-called for if we are initializing the mesh for the
- * first time from bmesh, rather than giving a warning about this we could be smarter
+ /* NOTE(campbell): this warning may be un-called for if we are initializing the mesh for
+ * the first time from #BMesh, rather than giving a warning about this we could be smarter
* and check if there was any data to begin with, for now just print the warning with
- * some info to help troubleshoot what's going on - campbell */
+ * some info to help troubleshoot what's going on. */
printf(
"%s: warning! Tessellation uvs or vcol data got out of sync, "
"had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: "
@@ -923,6 +931,8 @@ void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src)
me_dst->texflag = me_src->texflag;
copy_v3_v3(me_dst->loc, me_src->loc);
copy_v3_v3(me_dst->size, me_src->size);
+
+ me_dst->vertex_group_active_index = me_src->vertex_group_active_index;
}
/**
@@ -938,6 +948,10 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
BKE_mesh_copy_parameters(me_dst, me_src);
+ /* Copy vertex group names. */
+ BLI_assert(BLI_listbase_is_empty(&me_dst->vertex_group_names));
+ BKE_defgroup_copy_list(&me_dst->vertex_group_names, &me_src->vertex_group_names);
+
/* Copy materials. */
if (me_dst->mat != NULL) {
MEM_freeN(me_dst->mat);
@@ -2126,7 +2140,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
}
}
- /* Note: after this point mesh is expected to be valid again. */
+ /* NOTE: after this point mesh is expected to be valid again. */
/* CD_NORMAL is expected to be temporary only. */
if (free_loop_normals) {
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index c162458ffb9..798d9562150 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -38,6 +38,7 @@
#include "BLI_mesh_boolean.hh"
#include "BLI_mesh_intersect.hh"
#include "BLI_span.hh"
+#include "BLI_task.hh"
namespace blender::meshintersect {
@@ -309,22 +310,38 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
clean_obmat(*obmats[mi]);
r_info->to_target_transform[mi] = inv_target_mat * objn_mat;
- /* Skip the matrix multiplication for each point when there is no transform for a mesh,
- * for example when the first mesh is already in the target space. (Note the logic directly
- * above, which uses an identity matrix with a null input transform). */
+ Vector<Vert *> verts(me->totvert);
+ Span<MVert> mverts = Span(me->mvert, me->totvert);
+
+ /* Allocate verts
+ * Skip the matrix multiplication for each point when there is no transform for a mesh,
+ * for example when the first mesh is already in the target space. (Note the logic
+ * directly above, which uses an identity matrix with a null input transform). */
if (obmats[mi] == nullptr) {
- for (const MVert &vert : Span(me->mvert, me->totvert)) {
- const float3 co = float3(vert.co);
- r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co.x, co.y, co.z), v);
- ++v;
- }
+ threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) {
+ float3 co;
+ for (int i : range) {
+ co = float3(mverts[i].co);
+ mpq3 mco = mpq3(co.x, co.y, co.z);
+ double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d());
+ verts[i] = new Vert(mco, dco, NO_INDEX, i);
+ }
+ });
}
else {
- for (const MVert &vert : Span(me->mvert, me->totvert)) {
- const float3 co = r_info->to_target_transform[mi] * float3(vert.co);
- r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co.x, co.y, co.z), v);
- ++v;
- }
+ threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) {
+ float3 co;
+ for (int i : range) {
+ co = r_info->to_target_transform[mi] * float3(mverts[i].co);
+ mpq3 mco = mpq3(co.x, co.y, co.z);
+ double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d());
+ verts[i] = new Vert(mco, dco, NO_INDEX, i);
+ }
+ });
+ }
+ for (int i : mverts.index_range()) {
+ r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(verts[i]);
+ ++v;
}
for (const MPoly &poly : Span(me->mpoly, me->totpoly)) {
@@ -611,7 +628,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
source_cd, target_cd, source_layer_i, target_layer_i, orig_loop_index, loop_index, 1);
}
else {
- /* Note: although CustomData_bmesh_interp_n function has bmesh in its name, nothing about
+ /* NOTE: although CustomData_bmesh_interp_n function has bmesh in its name, nothing about
* it is BMesh-specific. We can't use CustomData_interp because it assumes that
* all source layers exist in the dest.
* A non bmesh version could have the benefit of not copying data into src_blocks_ofs -
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index cfad5e1100d..e777eb7ffe9 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1117,7 +1117,7 @@ static void curve_to_mesh_eval_ensure(Object *object)
BKE_displist_make_curveTypes_forRender(
NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, &mesh_eval);
- /* Note: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a
+ /* NOTE: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a
* real issue currently, code here is broken in more than one way, fix(es) will be done
* separately. */
if (mesh_eval != NULL) {
@@ -1327,7 +1327,7 @@ static int foreach_libblock_make_usercounts_callback(LibraryIDLinkCallbackData *
id_us_plus(*id_p);
}
else if (cb_flag & IDWALK_CB_USER_ONE) {
- /* Note: in that context, that one should not be needed (since there should be at least already
+ /* NOTE: in that context, that one should not be needed (since there should be at least already
* one USER_ONE user of that ID), but better be consistent. */
id_us_ensure_real(*id_p);
}
@@ -1668,7 +1668,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
}
/* object had got displacement layer, should copy this layer to save sculpted data */
- /* NOTE: maybe some other layers should be copied? nazgul */
+ /* NOTE(nazgul): maybe some other layers should be copied? */
if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) {
if (totloop == mesh_dst->totloop) {
MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS);
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.cc
index 6eac96ba85b..91fd022a316 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.cc
@@ -23,7 +23,7 @@
* Functions to evaluate mesh data.
*/
-#include <limits.h>
+#include <climits>
#include "MEM_guardedalloc.h"
@@ -191,7 +191,7 @@ void BKE_mesh_calc_poly_center(const MPoly *mpoly,
}
}
-/* note, passing polynormal is only a speedup so we can skip calculating it */
+/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */
float BKE_mesh_calc_poly_area(const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray)
{
if (mpoly->totloop == 3) {
@@ -200,7 +200,7 @@ float BKE_mesh_calc_poly_area(const MPoly *mpoly, const MLoop *loopstart, const
}
const MLoop *l_iter = loopstart;
- float(*vertexcos)[3] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
+ float(*vertexcos)[3] = (float(*)[3])BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
/* pack vertex cos into an array for area_poly_v3 */
for (int i = 0; i < mpoly->totloop; i++, l_iter++) {
@@ -236,7 +236,7 @@ float BKE_mesh_calc_poly_uv_area(const MPoly *mpoly, const MLoopUV *uv_array)
int i, l_iter = mpoly->loopstart;
float area;
- float(*vertexcos)[2] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
+ float(*vertexcos)[2] = (float(*)[2])BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
/* pack vertex cos into an array for area_poly_v2 */
for (i = 0; i < mpoly->totloop; i++, l_iter++) {
@@ -404,7 +404,7 @@ void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *mp, const MLoop
ml = &ml_next[i - 1]; /* last loop */
while (i-- != 0) {
- BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, NULL);
+ BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, nullptr);
ml = ml_next;
ml_next++;
@@ -656,7 +656,7 @@ void BKE_mesh_calc_volume(const MVert *mverts,
}
}
- /* Note: Depending on arbitrary centroid position,
+ /* NOTE: Depending on arbitrary centroid position,
* totvol can become negative even for a valid mesh.
* The true value is always the positive value.
*/
@@ -664,7 +664,7 @@ void BKE_mesh_calc_volume(const MVert *mverts,
*r_volume = fabsf(totvol);
}
if (r_center) {
- /* Note: Factor 1/3 is applied once for all vertices here.
+ /* NOTE: Factor 1/3 is applied once for all vertices here.
* This also automatically negates the vector if totvol is negative.
*/
if (totvol != 0.0f) {
@@ -676,7 +676,7 @@ void BKE_mesh_calc_volume(const MVert *mverts,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name NGon Tessellation (NGon/Tessface Conversion)
+/** \name NGon Tessellation (NGon to MFace Conversion)
* \{ */
static void bm_corners_to_loops_ex(ID *id,
@@ -692,9 +692,9 @@ static void bm_corners_to_loops_ex(ID *id,
MFace *mf = mface + findex;
for (int i = 0; i < numTex; i++) {
- MTFace *texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ MTFace *texface = (MTFace *)CustomData_get_n(fdata, CD_MTFACE, findex, i);
- MLoopUV *mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
+ MLoopUV *mloopuv = (MLoopUV *)CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
copy_v2_v2(mloopuv->uv, texface->uv[0]);
mloopuv++;
copy_v2_v2(mloopuv->uv, texface->uv[1]);
@@ -709,8 +709,8 @@ static void bm_corners_to_loops_ex(ID *id,
}
for (int i = 0; i < numCol; i++) {
- MLoopCol *mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
- MCol *mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+ MLoopCol *mloopcol = (MLoopCol *)CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
+ MCol *mcol = (MCol *)CustomData_get_n(fdata, CD_MCOL, findex, i);
MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]);
mloopcol++;
@@ -725,8 +725,8 @@ static void bm_corners_to_loops_ex(ID *id,
}
if (CustomData_has_layer(fdata, CD_TESSLOOPNORMAL)) {
- float(*lnors)[3] = CustomData_get(ldata, loopstart, CD_NORMAL);
- short(*tlnors)[3] = CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
+ float(*lnors)[3] = (float(*)[3])CustomData_get(ldata, loopstart, CD_NORMAL);
+ short(*tlnors)[3] = (short(*)[3])CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
const int max = mf->v4 ? 4 : 3;
for (int i = 0; i < max; i++, lnors++, tlnors++) {
@@ -735,8 +735,8 @@ static void bm_corners_to_loops_ex(ID *id,
}
if (CustomData_has_layer(fdata, CD_MDISPS)) {
- MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS);
- MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS);
+ MDisps *ld = (MDisps *)CustomData_get(ldata, loopstart, CD_MDISPS);
+ MDisps *fd = (MDisps *)CustomData_get(fdata, findex, CD_MDISPS);
float(*disps)[3] = fd->disps;
int tot = mf->v4 ? 4 : 3;
int corners;
@@ -750,9 +750,9 @@ static void bm_corners_to_loops_ex(ID *id,
corners = multires_mdisp_corners(fd);
if (corners == 0) {
- /* Empty MDisp layers appear in at least one of the sintel.blend files.
+ /* Empty #MDisp layers appear in at least one of the `sintel.blend` files.
* Not sure why this happens, but it seems fine to just ignore them here.
- * If (corners == 0) for a non-empty layer though, something went wrong. */
+ * If `corners == 0` for a non-empty layer though, something went wrong. */
BLI_assert(fd->totdisp == 0);
}
else {
@@ -767,7 +767,8 @@ static void bm_corners_to_loops_ex(ID *id,
MEM_freeN(ld->disps);
}
- ld->disps = MEM_malloc_arrayN((size_t)side_sq, sizeof(float[3]), "converted loop mdisps");
+ ld->disps = (float(*)[3])MEM_malloc_arrayN(
+ (size_t)side_sq, sizeof(float[3]), "converted loop mdisps");
if (fd->disps) {
memcpy(ld->disps, disps, (size_t)side_sq * sizeof(float[3]));
}
@@ -801,15 +802,16 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
/**
* The same as #BKE_mesh_convert_mfaces_to_mpolys
- * but oriented to be used in #do_versions from readfile.c
- * the difference is how active/render/clone/stencil indices are handled here
+ * but oriented to be used in #do_versions from `readfile.c`
+ * the difference is how active/render/clone/stencil indices are handled here.
*
- * normally thay're being set from pdata which totally makes sense for meshes which are already
- * converted to bmesh structures, but when loading older files indices shall be updated in other
- * way around, so newly added pdata and ldata would have this indices set based on fdata layer
+ * normally they're being set from `pdata` which totally makes sense for meshes which are already
+ * converted to #BMesh structures, but when loading older files indices shall be updated in other
+ * way around, so newly added `pdata` and `ldata` would have this indices set
+ * based on `fdata` layer.
*
* this is normally only needed when reading older files,
- * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used
+ * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used.
*/
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
{
@@ -864,7 +866,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
CustomData_free(pdata, totpoly_i);
totpoly = totface_i;
- mpoly = MEM_calloc_arrayN((size_t)totpoly, sizeof(MPoly), "mpoly converted");
+ mpoly = (MPoly *)MEM_calloc_arrayN((size_t)totpoly, sizeof(MPoly), "mpoly converted");
CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly);
numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
@@ -876,7 +878,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
totloop += mf->v4 ? 4 : 3;
}
- mloop = MEM_calloc_arrayN((size_t)totloop, sizeof(MLoop), "mloop converted");
+ mloop = (MLoop *)MEM_calloc_arrayN((size_t)totloop, sizeof(MLoop), "mloop converted");
CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
@@ -900,7 +902,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
me->flag &= ~ME_FGON;
}
- polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
+ polyindex = (int *)CustomData_get_layer(fdata, CD_ORIGINDEX);
j = 0; /* current loop index */
ml = mloop;
@@ -943,10 +945,10 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
}
}
- /* note, we don't convert NGons at all, these are not even real ngons,
+ /* NOTE: we don't convert NGons at all, these are not even real ngons,
* they have their own UV's, colors etc - its more an editing feature. */
- BLI_edgehash_free(eh, NULL);
+ BLI_edgehash_free(eh, nullptr);
*r_totpoly = totpoly;
*r_totloop = totloop;
@@ -1050,8 +1052,8 @@ void BKE_mesh_polygon_flip_ex(MPoly *mpoly,
void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata)
{
- MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS);
- BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, NULL, mdisp, true);
+ MDisps *mdisp = (MDisps *)CustomData_get_layer(ldata, CD_MDISPS);
+ BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, nullptr, mdisp, true);
}
/**
@@ -1061,12 +1063,12 @@ void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata)
*/
void BKE_mesh_polygons_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata, int totpoly)
{
- MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS);
+ MDisps *mdisp = (MDisps *)CustomData_get_layer(ldata, CD_MDISPS);
MPoly *mp;
int i;
for (mp = mpoly, i = 0; i < totpoly; mp++, i++) {
- BKE_mesh_polygon_flip_ex(mp, mloop, ldata, NULL, mdisp, true);
+ BKE_mesh_polygon_flip_ex(mp, mloop, ldata, nullptr, mdisp, true);
}
}
@@ -1277,7 +1279,7 @@ void BKE_mesh_calc_relative_deform(const MPoly *mpoly,
const MPoly *mp;
int i;
- int *vert_accum = MEM_calloc_arrayN((size_t)totvert, sizeof(*vert_accum), __func__);
+ int *vert_accum = (int *)MEM_calloc_arrayN((size_t)totvert, sizeof(*vert_accum), __func__);
memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * (size_t)totvert);
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index c469a65449d..ca6c60557a6 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -776,7 +776,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
}
if (UNLIKELY(gid_bit > 31)) {
/* All bits used in contiguous smooth groups, we can't do much!
- * Note: this is *very* unlikely - theoretically, four groups are enough,
+ * NOTE: this is *very* unlikely - theoretically, four groups are enough,
* I don't think we can reach this goal with such a simple algorithm,
* but I don't think either we'll never need all 32 groups!
*/
@@ -998,7 +998,7 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store,
}
/* TODO: I'm not sure edge seam flag is enough to define UV islands?
- * Maybe we should also consider UVmaps values
+ * Maybe we should also consider UV-maps values
* themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
* Would make things much more complex though,
* and each UVMap would then need its own mesh mapping, not sure we want that at all!
@@ -1140,7 +1140,7 @@ static bool mesh_calc_islands_loop_poly_uv(MVert *UNUSED(verts),
poly_indices = MEM_mallocN(sizeof(*poly_indices) * (size_t)totpoly, __func__);
loop_indices = MEM_mallocN(sizeof(*loop_indices) * (size_t)totloop, __func__);
- /* Note: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
+ /* NOTE: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) {
num_pidx = num_lidx = 0;
if (num_edge_borders) {
diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c
index 1e51ee73c7c..d3d835378ca 100644
--- a/source/blender/blenkernel/intern/mesh_merge.c
+++ b/source/blender/blenkernel/intern/mesh_merge.c
@@ -259,7 +259,7 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
STACK_DECLARE(mvert);
STACK_DECLARE(oldv);
- /* Note: create (totedge + totloop) elements because partially invalid polys due to merge may
+ /* NOTE: create (totedge + totloop) elements because partially invalid polys due to merge may
* require generating new edges, and while in 99% cases we'll still end with less final edges
* than totedge, cases can be forged that would end requiring more. */
MEdge *med, *medge = MEM_malloc_arrayN((totedge + totloop), sizeof(*medge), __func__);
diff --git a/source/blender/blenkernel/intern/mesh_normals.c b/source/blender/blenkernel/intern/mesh_normals.cc
index 9f09ce46e11..2fe132fc684 100644
--- a/source/blender/blenkernel/intern/mesh_normals.c
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -25,7 +25,7 @@
* \see bmesh_mesh_normals.c for the equivalent #BMesh functionality.
*/
-#include <limits.h>
+#include <climits>
#include "CLG_log.h"
@@ -90,15 +90,15 @@ void BKE_mesh_calc_normals_mapping_simple(struct Mesh *mesh)
mesh->mpoly,
mesh->totloop,
mesh->totpoly,
- NULL,
+ nullptr,
mesh->mface,
mesh->totface,
- NULL,
- NULL,
+ nullptr,
+ nullptr,
only_face_normals);
}
-/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-NULL
+/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-nullptr
* and vertex normals are stored in actual mverts.
*/
void BKE_mesh_calc_normals_mapping(MVert *mverts,
@@ -150,13 +150,13 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
}
/* if we are not calculating verts and no verts were passes then we have nothing to do */
- if ((only_face_normals == true) && (r_polyNors == NULL) && (r_faceNors == NULL)) {
+ if ((only_face_normals == true) && (r_polyNors == nullptr) && (r_faceNors == nullptr)) {
CLOG_WARN(&LOG, "called with nothing to do");
return;
}
if (!pnors) {
- pnors = MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__);
+ pnors = (float(*)[3])MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__);
}
/* NO NEED TO ALLOC YET */
/* if (!fnors) fnors = MEM_calloc_arrayN(numFaces, sizeof(float[3]), "face nors mesh.c"); */
@@ -165,7 +165,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
/* vertex normals are optional, they require some extra calculations,
* so make them optional */
BKE_mesh_calc_normals_poly(
- mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
+ mverts, nullptr, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
}
else {
/* only calc poly normals */
@@ -177,7 +177,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
if (origIndexFace &&
/* fnors == r_faceNors */ /* NO NEED TO ALLOC YET */
- fnors != NULL &&
+ fnors != nullptr &&
numFaces) {
const MFace *mf = mfaces;
for (int i = 0; i < numFaces; i++, mf++, origIndexFace++) {
@@ -196,23 +196,23 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
}
/* if (fnors != r_faceNors) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */
- fnors = pnors = NULL;
+ fnors = pnors = nullptr;
}
-typedef struct MeshCalcNormalsData {
+struct MeshCalcNormalsData {
const MPoly *mpolys;
const MLoop *mloop;
MVert *mverts;
float (*pnors)[3];
float (*lnors_weighted)[3];
float (*vnors)[3];
-} MeshCalcNormalsData;
+};
static void mesh_calc_normals_poly_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = userdata;
+ MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
const MPoly *mp = &data->mpolys[pidx];
BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]);
@@ -222,7 +222,7 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = userdata;
+ MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
const MPoly *mp = &data->mpolys[pidx];
const MLoop *ml = &data->mloop[mp->loopstart];
const MVert *mverts = data->mverts;
@@ -232,7 +232,7 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
float(*lnors_weighted)[3] = data->lnors_weighted;
const int nverts = mp->totloop;
- float(*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts);
+ float(*edgevecbuf)[3] = (float(*)[3])BLI_array_alloca(edgevecbuf, (size_t)nverts);
/* Polygon Normal and edge-vector */
/* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
@@ -285,7 +285,7 @@ static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata,
const int vidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = userdata;
+ MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
MVert *mv = &data->mverts[vidx];
float *no = data->vnors[vidx];
@@ -315,42 +315,40 @@ void BKE_mesh_calc_normals_poly(MVert *mverts,
settings.min_iter_per_thread = 1024;
if (only_face_normals) {
- BLI_assert((pnors != NULL) || (numPolys == 0));
- BLI_assert(r_vertnors == NULL);
-
- MeshCalcNormalsData data = {
- .mpolys = mpolys,
- .mloop = mloop,
- .mverts = mverts,
- .pnors = pnors,
- };
+ BLI_assert((pnors != nullptr) || (numPolys == 0));
+ BLI_assert(r_vertnors == nullptr);
+
+ MeshCalcNormalsData data;
+ data.mpolys = mpolys;
+ data.mloop = mloop;
+ data.mverts = mverts;
+ data.pnors = pnors;
BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_cb, &settings);
return;
}
float(*vnors)[3] = r_vertnors;
- float(*lnors_weighted)[3] = MEM_malloc_arrayN(
+ float(*lnors_weighted)[3] = (float(*)[3])MEM_malloc_arrayN(
(size_t)numLoops, sizeof(*lnors_weighted), __func__);
bool free_vnors = false;
/* first go through and calculate normals for all the polys */
- if (vnors == NULL) {
- vnors = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__);
+ if (vnors == nullptr) {
+ vnors = (float(*)[3])MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__);
free_vnors = true;
}
else {
memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts);
}
- MeshCalcNormalsData data = {
- .mpolys = mpolys,
- .mloop = mloop,
- .mverts = mverts,
- .pnors = pnors,
- .lnors_weighted = lnors_weighted,
- .vnors = vnors,
- };
+ MeshCalcNormalsData data;
+ data.mpolys = mpolys;
+ data.mloop = mloop;
+ data.mverts = mverts;
+ data.pnors = pnors;
+ data.lnors_weighted = lnors_weighted;
+ data.vnors = vnors;
/* Compute poly normals, and prepare weighted loop normals. */
BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings);
@@ -400,19 +398,21 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
}
}
- float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ float(*poly_nors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0;
- const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL);
+ const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL ||
+ poly_nors == nullptr);
if (do_vert_normals || do_poly_normals) {
- const bool do_add_poly_nors_cddata = (poly_nors == NULL);
+ const bool do_add_poly_nors_cddata = (poly_nors == nullptr);
if (do_add_poly_nors_cddata) {
- poly_nors = MEM_malloc_arrayN((size_t)mesh->totpoly, sizeof(*poly_nors), __func__);
+ poly_nors = (float(*)[3])MEM_malloc_arrayN(
+ (size_t)mesh->totpoly, sizeof(*poly_nors), __func__);
}
/* calculate poly/vert normals */
BKE_mesh_calc_normals_poly(mesh->mvert,
- NULL,
+ nullptr,
mesh->totvert,
mesh->mloop,
mesh->mpoly,
@@ -438,13 +438,13 @@ void BKE_mesh_calc_normals(Mesh *mesh)
TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
#endif
BKE_mesh_calc_normals_poly(mesh->mvert,
- NULL,
+ nullptr,
mesh->totvert,
mesh->mloop,
mesh->mpoly,
mesh->totloop,
mesh->totpoly,
- NULL,
+ nullptr,
false);
#ifdef DEBUG_TIME
TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
@@ -459,10 +459,10 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts,
int looptri_num,
float (*r_tri_nors)[3])
{
- float(*tnorms)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms");
- float(*fnors)[3] = (r_tri_nors) ?
- r_tri_nors :
- MEM_calloc_arrayN((size_t)looptri_num, sizeof(*fnors), "meshnormals");
+ float(*tnorms)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms");
+ float(*fnors)[3] = (r_tri_nors) ? r_tri_nors :
+ (float(*)[3])MEM_calloc_arrayN(
+ (size_t)looptri_num, sizeof(*fnors), "meshnormals");
if (!tnorms || !fnors) {
goto cleanup;
@@ -519,9 +519,10 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
lnors_spacearr->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
mem = lnors_spacearr->mem;
- lnors_spacearr->lspacearr = BLI_memarena_calloc(mem,
- sizeof(MLoopNorSpace *) * (size_t)numLoops);
- lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops);
+ lnors_spacearr->lspacearr = (MLoopNorSpace **)BLI_memarena_calloc(
+ mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
+ lnors_spacearr->loops_pool = (LinkNode *)BLI_memarena_alloc(
+ mem, sizeof(LinkNode) * (size_t)numLoops);
lnors_spacearr->num_spaces = 0;
}
@@ -532,9 +533,9 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
{
lnors_spacearr->num_spaces = 0;
- lnors_spacearr->lspacearr = NULL;
- lnors_spacearr->loops_pool = NULL;
- if (lnors_spacearr->mem != NULL) {
+ lnors_spacearr->lspacearr = nullptr;
+ lnors_spacearr->loops_pool = nullptr;
+ if (lnors_spacearr->mem != nullptr) {
BLI_memarena_clear(lnors_spacearr->mem);
}
}
@@ -542,16 +543,16 @@ void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
{
lnors_spacearr->num_spaces = 0;
- lnors_spacearr->lspacearr = NULL;
- lnors_spacearr->loops_pool = NULL;
+ lnors_spacearr->lspacearr = nullptr;
+ lnors_spacearr->loops_pool = nullptr;
BLI_memarena_free(lnors_spacearr->mem);
- lnors_spacearr->mem = NULL;
+ lnors_spacearr->mem = nullptr;
}
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
{
lnors_spacearr->num_spaces++;
- return BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace));
+ return (MLoopNorSpace *)BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace));
}
/* This threshold is a bit touchy (usual float precision issue), this value seems OK. */
@@ -592,12 +593,12 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
float alpha = 0.0f;
int nbr = 0;
while (!BLI_stack_is_empty(edge_vectors)) {
- const float *vec = BLI_stack_peek(edge_vectors);
+ const float *vec = (const float *)BLI_stack_peek(edge_vectors);
alpha += saacosf(dot_v3v3(vec, lnor));
BLI_stack_discard(edge_vectors);
nbr++;
}
- /* Note: In theory, this could be 'nbr > 2',
+ /* NOTE: In theory, this could be 'nbr > 2',
* but there is one case where we only have two edges for two loops:
* a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.).
*/
@@ -637,10 +638,10 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
/**
* Add a new given loop to given lnor_space.
* Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct
- * (in case of BMLOOP_PTR), or NULL (in case of LOOP_INDEX), loop index is then stored in pointer.
- * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops
- * pointer (since there is only one loop in this fan),
- * else it is added to the linked list of loops in the fan.
+ * (in case of BMLOOP_PTR), or nullptr (in case of LOOP_INDEX), loop index is then stored in
+ * pointer. If \a is_single is set, the BMLoop or loop index is directly stored in \a
+ * lnor_space->loops pointer (since there is only one loop in this fan), else it is added to the
+ * linked list of loops in the fan.
*/
void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpace *lnor_space,
@@ -648,17 +649,17 @@ void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr,
void *bm_loop,
const bool is_single)
{
- BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) ||
- (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL));
+ BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == nullptr) ||
+ (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != nullptr));
lnors_spacearr->lspacearr[ml_index] = lnor_space;
- if (bm_loop == NULL) {
+ if (bm_loop == nullptr) {
bm_loop = POINTER_FROM_INT(ml_index);
}
if (is_single) {
- BLI_assert(lnor_space->loops == NULL);
+ BLI_assert(lnor_space->loops == nullptr);
lnor_space->flags |= MLNOR_SPACE_IS_SINGLE;
- lnor_space->loops = bm_loop;
+ lnor_space->loops = (LinkNode *)bm_loop;
}
else {
BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0);
@@ -688,8 +689,8 @@ void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space,
}
{
- /* TODO Check whether using sincosf() gives any noticeable benefit
- * (could not even get it working under linux though)! */
+ /* TODO: Check whether using #sincosf() gives any noticeable benefit
+ * (could not even get it working under linux though)! */
const float pi2 = (float)(M_PI * 2.0);
const float alphafac = unit_short_to_float(clnor_data[0]);
const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) *
@@ -715,7 +716,8 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space,
const float custom_lnor[3],
short r_clnor_data[2])
{
- /* We use null vector as NOP custom normal (can be simpler than giving auto-computed `lnor`). */
+ /* We use nullptr vector as NOP custom normal (can be simpler than giving auto-computed `lnor`).
+ */
if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) {
r_clnor_data[0] = r_clnor_data[1] = 0;
return;
@@ -765,7 +767,7 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space,
#define LOOP_SPLIT_TASK_BLOCK_SIZE 1024
-typedef struct LoopSplitTaskData {
+struct LoopSplitTaskData {
/* Specific to each instance (each task). */
/** We have to create those outside of tasks, since #MemArena is not thread-safe. */
@@ -784,9 +786,9 @@ typedef struct LoopSplitTaskData {
BLI_Stack *edge_vectors;
char pad_c;
-} LoopSplitTaskData;
+};
-typedef struct LoopSplitTaskDataCommon {
+struct LoopSplitTaskDataCommon {
/* Read/write.
* Note we do not need to protect it, though, since two different tasks will *always* affect
* different elements in the arrays. */
@@ -806,7 +808,7 @@ typedef struct LoopSplitTaskDataCommon {
int numEdges;
int numLoops;
int numPolys;
-} LoopSplitTaskDataCommon;
+};
#define INDEX_UNSET INT_MIN
#define INDEX_INVALID -1
@@ -827,13 +829,13 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
const int numEdges = data->numEdges;
const int numPolys = data->numPolys;
- float(*loopnors)[3] = data->loopnors; /* Note: loopnors may be NULL here. */
+ float(*loopnors)[3] = data->loopnors; /* NOTE: loopnors may be nullptr here. */
const float(*polynors)[3] = data->polynors;
int(*edge_to_loops)[2] = data->edge_to_loops;
int *loop_to_poly = data->loop_to_poly;
- BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : NULL;
+ BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : nullptr;
const MPoly *mp;
int mp_index;
@@ -879,7 +881,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
*/
if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
ml_curr->v == mloops[e2l[0]].v || is_angle_sharp) {
- /* Note: we are sure that loop != 0 here ;) */
+ /* NOTE: we are sure that loop != 0 here ;). */
e2l[1] = INDEX_INVALID;
/* We want to avoid tagging edges as sharp when it is already defined as such by
@@ -943,22 +945,22 @@ void BKE_edges_sharp_from_angle_set(const struct MVert *mverts,
}
/* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */
- int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__);
+ int(*edge_to_loops)[2] = (int(*)[2])MEM_calloc_arrayN(
+ (size_t)numEdges, sizeof(*edge_to_loops), __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
-
- LoopSplitTaskDataCommon common_data = {
- .mverts = mverts,
- .medges = medges,
- .mloops = mloops,
- .mpolys = mpolys,
- .edge_to_loops = edge_to_loops,
- .loop_to_poly = loop_to_poly,
- .polynors = polynors,
- .numEdges = numEdges,
- .numPolys = numPolys,
- };
+ int *loop_to_poly = (int *)MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+
+ LoopSplitTaskDataCommon common_data;
+ common_data.mverts = mverts;
+ common_data.medges = medges;
+ common_data.mloops = mloops;
+ common_data.mpolys = mpolys;
+ common_data.edge_to_loops = edge_to_loops;
+ common_data.loop_to_poly = loop_to_poly;
+ common_data.polynors = polynors;
+ common_data.numEdges = numEdges;
+ common_data.numPolys = numPolys;
mesh_edges_sharp_tag(&common_data, true, split_angle, true);
@@ -1065,10 +1067,10 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
sub_v3_v3v3(vec_prev, mv_3->co, mv_pivot->co);
normalize_v3(vec_prev);
- BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL);
+ BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, nullptr);
/* We know there is only one loop in this space,
* no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, nullptr, true);
if (clnors_data) {
BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor);
@@ -1125,7 +1127,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* We validate clnors data on the fly - cheapest way to do! */
int clnors_avg[2] = {0, 0};
- short(*clnor_ref)[2] = NULL;
+ short(*clnor_ref)[2] = nullptr;
int clnors_nbr = 0;
bool clnors_invalid = false;
@@ -1205,7 +1207,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (lnors_spacearr) {
/* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, nullptr, false);
if (me_curr != me_org) {
/* We store here all edges-normalized vectors processed. */
BLI_stack_push(edge_vectors, vec_curr);
@@ -1261,7 +1263,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (G.debug & G_DEBUG) {
printf("Invalid clnors in this fan!\n");
}
- while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
+ while ((clnor = (short *)BLI_SMALLSTACK_POP(clnors))) {
// print_v2("org clnor", clnor);
clnor[0] = (short)clnors_avg[0];
clnor[1] = (short)clnors_avg[1];
@@ -1280,7 +1282,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Copy back the final computed normal into all related loop-normals. */
float *nor;
- while ((nor = BLI_SMALLSTACK_POP(normal))) {
+ while ((nor = (float *)BLI_SMALLSTACK_POP(normal))) {
copy_v3_v3(nor, lnor);
}
}
@@ -1295,7 +1297,7 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data,
{
BLI_assert(data->ml_curr);
if (data->e2l_prev) {
- BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors));
+ BLI_assert((edge_vectors == nullptr) || BLI_stack_is_empty(edge_vectors));
data->edge_vectors = edge_vectors;
split_loop_nor_fan_do(common_data, data);
}
@@ -1307,21 +1309,21 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data,
static void loop_split_worker(TaskPool *__restrict pool, void *taskdata)
{
- LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool);
- LoopSplitTaskData *data = taskdata;
+ LoopSplitTaskDataCommon *common_data = (LoopSplitTaskDataCommon *)BLI_task_pool_user_data(pool);
+ LoopSplitTaskData *data = (LoopSplitTaskData *)taskdata;
/* Temp edge vectors stack, only used when computing lnor spacearr. */
BLI_Stack *edge_vectors = common_data->lnors_spacearr ?
BLI_stack_new(sizeof(float[3]), __func__) :
- NULL;
+ nullptr;
#ifdef DEBUG_TIME
TIMEIT_START_AVERAGED(loop_split_worker);
#endif
for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
- /* A NULL ml_curr is used to tag ended data! */
- if (data->ml_curr == NULL) {
+ /* A nullptr ml_curr is used to tag ended data! */
+ if (data->ml_curr == nullptr) {
break;
}
@@ -1434,12 +1436,12 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__);
- LoopSplitTaskData *data_buff = NULL;
+ LoopSplitTaskData *data_buff = nullptr;
int data_idx = 0;
/* Temp edge vectors stack, only used when computing lnor spacearr
* (and we are not multi-threading). */
- BLI_Stack *edge_vectors = NULL;
+ BLI_Stack *edge_vectors = nullptr;
#ifdef DEBUG_TIME
TIMEIT_START_AVERAGED(loop_split_generator);
@@ -1481,7 +1483,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
* If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge
* as 'entry point', otherwise we can skip it. */
- /* Note: In theory, we could make #loop_split_generator_check_cyclic_smooth_fan() store
+ /* NOTE: In theory, we could make #loop_split_generator_check_cyclic_smooth_fan() store
* mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around
* the vert during actual computation of `clnor` & `clnorspace`.
* However, this would complicate the code, add more memory usage, and despite its logical
@@ -1508,7 +1510,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
if (pool) {
if (data_idx == 0) {
- data_buff = MEM_calloc_arrayN(
+ data_buff = (LoopSplitTaskData *)MEM_calloc_arrayN(
LOOP_SPLIT_TASK_BLOCK_SIZE, sizeof(*data_buff), __func__);
}
data = &data_buff[data_idx];
@@ -1525,7 +1527,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
data->ml_curr_index = ml_curr_index;
#if 0 /* Not needed for 'single' loop. */
data->ml_prev_index = ml_prev_index;
- data->e2l_prev = NULL; /* Tag as 'single' task. */
+ data->e2l_prev = nullptr; /* Tag as 'single' task. */
#endif
data->mp_index = mp_index;
if (lnors_spacearr) {
@@ -1559,7 +1561,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
if (pool) {
data_idx++;
if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) {
- BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL);
+ BLI_task_pool_push(pool, loop_split_worker, data_buff, true, nullptr);
data_idx = 0;
}
}
@@ -1573,10 +1575,10 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
}
}
- /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper,
+ /* Last block of data... Since it is calloc'ed and we use first nullptr item as stopper,
* everything is fine. */
if (pool && data_idx) {
- BLI_task_pool_push(pool, loop_split_worker, data_buff, true, NULL);
+ BLI_task_pool_push(pool, loop_split_worker, data_buff, true, nullptr);
}
if (edge_vectors) {
@@ -1659,17 +1661,18 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
* However, if needed, we can store the negated value of loop index instead of INDEX_INVALID
* to retrieve the real value later in code).
* Note also that loose edges always have both values set to 0! */
- int(*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__);
+ int(*edge_to_loops)[2] = (int(*)[2])MEM_calloc_arrayN(
+ (size_t)numEdges, sizeof(*edge_to_loops), __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = r_loop_to_poly ?
- r_loop_to_poly :
- MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+ int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly :
+ (int *)MEM_malloc_arrayN(
+ (size_t)numLoops, sizeof(*loop_to_poly), __func__);
/* When using custom loop normals, disable the angle feature! */
- const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL);
+ const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == nullptr);
- MLoopNorSpaceArray _lnors_spacearr = {NULL};
+ MLoopNorSpaceArray _lnors_spacearr = {nullptr};
#ifdef DEBUG_TIME
TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split);
@@ -1684,28 +1687,27 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
}
/* Init data common to all tasks. */
- LoopSplitTaskDataCommon common_data = {
- .lnors_spacearr = r_lnors_spacearr,
- .loopnors = r_loopnors,
- .clnors_data = clnors_data,
- .mverts = mverts,
- .medges = medges,
- .mloops = mloops,
- .mpolys = mpolys,
- .edge_to_loops = edge_to_loops,
- .loop_to_poly = loop_to_poly,
- .polynors = polynors,
- .numEdges = numEdges,
- .numLoops = numLoops,
- .numPolys = numPolys,
- };
+ LoopSplitTaskDataCommon common_data;
+ common_data.lnors_spacearr = r_lnors_spacearr;
+ common_data.loopnors = r_loopnors;
+ common_data.clnors_data = clnors_data;
+ common_data.mverts = mverts;
+ common_data.medges = medges;
+ common_data.mloops = mloops;
+ common_data.mpolys = mpolys;
+ common_data.edge_to_loops = edge_to_loops;
+ common_data.loop_to_poly = loop_to_poly;
+ common_data.polynors = polynors;
+ common_data.numEdges = numEdges;
+ common_data.numLoops = numLoops;
+ common_data.numPolys = numPolys;
/* This first loop check which edges are actually smooth, and compute edge vectors. */
mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false);
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead... */
- loop_split_generator(NULL, &common_data);
+ loop_split_generator(nullptr, &common_data);
}
else {
TaskPool *task_pool = BLI_task_pool_create(&common_data, TASK_PRIORITY_HIGH);
@@ -1766,10 +1768,10 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
* (and perhaps from some editing tools later?).
* So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice!
*/
- MLoopNorSpaceArray lnors_spacearr = {NULL};
+ MLoopNorSpaceArray lnors_spacearr = {nullptr};
BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
- float(*lnors)[3] = MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__);
- int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(int), __func__);
+ float(*lnors)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__);
+ int *loop_to_poly = (int *)MEM_malloc_arrayN((size_t)numLoops, sizeof(int), __func__);
/* In this case we always consider split nors as ON,
* and do not want to use angle to define smooth fans! */
const bool use_split_normals = true;
@@ -1791,7 +1793,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
use_split_normals,
split_angle,
&lnors_spacearr,
- NULL,
+ nullptr,
loop_to_poly);
/* Set all given zero vectors to their default value. */
@@ -1823,12 +1825,12 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
for (int i = 0; i < numLoops; i++) {
if (!lnors_spacearr.lspacearr[i]) {
/* This should not happen in theory, but in some rare case (probably ugly geometry)
- * we can get some NULL loopspacearr at this point. :/
+ * we can get some nullptr loopspacearr at this point. :/
* Maybe we should set those loops' edges as sharp?
*/
BLI_BITMAP_ENABLE(done_loops, i);
if (G.debug & G_DEBUG) {
- printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i);
+ printf("WARNING! Getting invalid nullptr loop space for loop %d!\n", i);
}
continue;
}
@@ -1849,8 +1851,8 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
}
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
- MLoop *prev_ml = NULL;
- const float *org_nor = NULL;
+ MLoop *prev_ml = nullptr;
+ const float *org_nor = nullptr;
while (loops) {
const int lidx = POINTER_AS_INT(loops->link);
@@ -1916,7 +1918,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
use_split_normals,
split_angle,
&lnors_spacearr,
- NULL,
+ nullptr,
loop_to_poly);
}
else {
@@ -1929,7 +1931,8 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
if (!lnors_spacearr.lspacearr[i]) {
BLI_BITMAP_DISABLE(done_loops, i);
if (G.debug & G_DEBUG) {
- printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i);
+ printf("WARNING! Still getting invalid nullptr loop space in second loop for loop %d!\n",
+ i);
}
continue;
}
@@ -1970,7 +1973,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors);
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp);
- while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) {
+ while ((clnor_data = (short *)BLI_SMALLSTACK_POP(clnors_data))) {
clnor_data[0] = clnor_data_tmp[0];
clnor_data[1] = clnor_data_tmp[1];
}
@@ -2041,20 +2044,21 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
short(*clnors)[2];
const int numloops = mesh->totloop;
- clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
- if (clnors != NULL) {
+ clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+ if (clnors != nullptr) {
memset(clnors, 0, sizeof(*clnors) * (size_t)numloops);
}
else {
- clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numloops);
+ clnors = (short(*)[2])CustomData_add_layer(
+ &mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, nullptr, numloops);
}
- float(*polynors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ float(*polynors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
bool free_polynors = false;
- if (polynors == NULL) {
- polynors = MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__);
+ if (polynors == nullptr) {
+ polynors = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__);
BKE_mesh_calc_normals_poly(mesh->mvert,
- NULL,
+ nullptr,
mesh->totvert,
mesh->mloop,
mesh->mpoly,
@@ -2119,7 +2123,8 @@ void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const float (*clnors)[3],
float (*r_vert_clnors)[3])
{
- int *vert_loops_nbr = MEM_calloc_arrayN((size_t)numVerts, sizeof(*vert_loops_nbr), __func__);
+ int *vert_loops_nbr = (int *)MEM_calloc_arrayN(
+ (size_t)numVerts, sizeof(*vert_loops_nbr), __func__);
copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f);
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index b7cff624a04..c5e8858ea12 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -216,7 +216,7 @@ static void mesh_calc_eigen_matrix(const MVert *verts,
}
unit_m4(r_mat);
- /* Note: here we apply sample correction to covariance matrix, since we consider the vertices
+ /* NOTE: here we apply sample correction to covariance matrix, since we consider the vertices
* as a sample of the whole 'surface' population of our mesh. */
BLI_covariance_m3_v3n(vcos, numverts, true, covmat, center);
@@ -256,7 +256,7 @@ static void mesh_calc_eigen_matrix(const MVert *verts,
float evi = eigen_val[i];
/* Protect against 1D/2D degenerated cases! */
- /* Note: not sure why we need square root of eigen values here
+ /* NOTE: not sure why we need square root of eigen values here
* (which are equivalent to singular values, as far as I have understood),
* but it seems to heavily reduce (if not completely nullify)
* the error due to non-uniform scalings... */
@@ -470,7 +470,7 @@ typedef struct IslandResult {
} IslandResult;
/**
- * \note About all bvh/raycasting stuff below:
+ * \note About all BVH/ray-casting stuff below:
*
* * We must use our ray radius as BVH epsilon too, else rays not hitting anything but
* 'passing near' an item would be missed (since BVH handling would not detect them,
@@ -478,8 +478,8 @@ typedef struct IslandResult {
* * However, in 'islands' case where each hit gets a weight, 'precise' hits should have a better
* weight than 'approximate' hits.
* To address that, we simplify things with:
- * * A first raycast with default, given rayradius;
- * * If first one fails, we do more raycasting with bigger radius, but if hit is found
+ * * A first ray-cast with default, given ray-radius;
+ * * If first one fails, we do more ray-casting with bigger radius, but if hit is found
* it will get smaller weight.
*
* This only concerns loops, currently (because of islands), and 'sampled' edges/polys norproj.
@@ -1035,7 +1035,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
if (!weights[j]) {
continue;
}
- /* Note: sources_num is always <= j! */
+ /* NOTE: sources_num is always <= j! */
weights[sources_num] = weights[j] / totweights;
indices[sources_num] = j;
sources_num++;
@@ -2332,7 +2332,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
for (i = 0; i < numpolys_dst; i++) {
/* For each dst poly, we sample some rays from it (2D grid in pnor space)
* and use their hits to interpolate from source polys. */
- /* Note: dst poly is early-converted into src space! */
+ /* NOTE: dst poly is early-converted into src space! */
MPoly *mp = &polys_dst[i];
int tot_rays, done_rays = 0;
@@ -2465,7 +2465,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
if (!weights[j]) {
continue;
}
- /* Note: sources_num is always <= j! */
+ /* NOTE: sources_num is always <= j! */
weights[sources_num] = weights[j] / totweights;
indices[sources_num] = j;
sources_num++;
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index 011dd7e25ee..7ac4c29f0ee 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -158,8 +158,12 @@ static void mesh_runtime_looptri_recalc_isolated(void *userdata)
BKE_mesh_runtime_looptri_recalc(mesh);
}
-/* This is a ported copy of dm_getLoopTriArray(dm). */
-const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh)
+/**
+ * \note This function only fills a cache, and therefore the mesh argument can
+ * be considered logically const. Concurrent access is protected by a mutex.
+ * \note This is a ported copy of dm_getLoopTriArray(dm).
+ */
+const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
{
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
BLI_mutex_lock(mesh_eval_mutex);
@@ -171,7 +175,7 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh)
}
else {
/* Must isolate multithreaded tasks while holding a mutex lock. */
- BLI_task_isolate(mesh_runtime_looptri_recalc_isolated, mesh);
+ BLI_task_isolate(mesh_runtime_looptri_recalc_isolated, (void *)mesh);
looptri = mesh->runtime.looptris.array;
}
@@ -286,7 +290,7 @@ static void mesh_runtime_debug_info_layers(DynStr *dynstr, CustomData *cd)
for (type = 0; type < CD_NUMTYPES; type++) {
if (CustomData_has_layer(cd, type)) {
- /* note: doesn't account for multiple layers */
+ /* NOTE: doesn't account for multiple layers. */
const char *name = CustomData_layertype_name(type);
const int size = CustomData_sizeof(type);
const void *pt = CustomData_get_layer(cd, type);
diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c
index 2e22e521a13..e5e971fd574 100644
--- a/source/blender/blenkernel/intern/mesh_tangent.c
+++ b/source/blender/blenkernel/intern/mesh_tangent.c
@@ -119,7 +119,7 @@ static void set_tspace(const SMikkTSpaceContext *pContext,
* Compute simplified tangent space normals, i.e.
* tangent vector + sign of bi-tangent one, which combined with
* split normals can be used to recreate the full tangent space.
- * Note: * The mesh should be made of only tris and quads!
+ * NOTE: * The mesh should be made of only tris and quads!
*/
void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts,
const int UNUSED(numVerts),
@@ -675,7 +675,7 @@ void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert,
mesh2tangent->mpoly = mpoly;
mesh2tangent->mloop = mloop;
mesh2tangent->looptri = looptri;
- /* Note, we assume we do have tessellated loop normals at this point
+ /* NOTE: we assume we do have tessellated loop normals at this point
* (in case it is object-enabled), have to check this is valid. */
mesh2tangent->precomputedLoopNormals = loop_normals;
mesh2tangent->precomputedFaceNormals = poly_normals;
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index bfdbf844a26..08668d55cf4 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -154,7 +154,7 @@ static int search_face_cmp(const void *v1, const void *v2)
return 0;
}
-/* TODO check there is not some standard define of this somewhere! */
+/* TODO: check there is not some standard define of this somewhere! */
static int int_cmp(const void *v1, const void *v2)
{
return *(int *)v1 > *(int *)v2 ? 1 : *(int *)v1 < *(int *)v2 ? -1 : 0;
@@ -819,7 +819,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
MDeformWeight *dw;
for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
- /* note, greater than max defgroups is accounted for in our code, but not < 0 */
+ /* NOTE: greater than max defgroups is accounted for in our code, but not < 0. */
if (!isfinite(dw->weight)) {
PRINT_ERR("\tVertex deform %u, group %u has weight: %f", i, dw->def_nr, dw->weight);
if (do_fixes) {
@@ -1287,7 +1287,7 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me)
}
/* And now, update polys' start loop index. */
- /* Note: At this point, there should never be any poly using a striped loop! */
+ /* NOTE: At this point, there should never be any poly using a striped loop! */
for (a = 0, p = me->mpoly; a < me->totpoly; a++, p++) {
p->loopstart = new_idx[p->loopstart];
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index e60f0102b9a..2088c4268e6 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -156,7 +156,7 @@ ModifierData *BKE_modifier_new(int type)
const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
- /* note, this name must be made unique later */
+ /* NOTE: this name must be made unique later. */
BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
md->type = type;
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 3a7910d1a9f..f32b0c434c1 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -287,7 +287,7 @@ static void movieclip_blend_read_data(BlendDataReader *reader, ID *id)
clip->tracking_context = NULL;
clip->tracking.stats = NULL;
- /* TODO we could store those in undo cache storage as well, and preserve them instead of
+ /* TODO: we could store those in undo cache storage as well, and preserve them instead of
* re-creating them... */
BLI_listbase_clear(&clip->runtime.gputextures);
@@ -1849,7 +1849,7 @@ static void movieclip_build_proxy_ibuf(
IMB_freeImBuf(scaleibuf);
}
-/* note: currently used by proxy job for movies, threading happens within single frame
+/* NOTE: currently used by proxy job for movies, threading happens within single frame
* (meaning scaling shall be threaded)
*/
void BKE_movieclip_build_proxy_frame(MovieClip *clip,
@@ -1893,7 +1893,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip,
}
}
-/* note: currently used by proxy job for sequences, threading happens within sequence
+/* NOTE: currently used by proxy job for sequences, threading happens within sequence
* (different threads handles different frames, no threading within frame is needed)
*/
void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip,
diff --git a/source/blender/blenkernel/intern/multires_inline.h b/source/blender/blenkernel/intern/multires_inline.h
index e85aa12781e..f88b5dd3143 100644
--- a/source/blender/blenkernel/intern/multires_inline.h
+++ b/source/blender/blenkernel/intern/multires_inline.h
@@ -53,7 +53,7 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3]
mul_v3_fl(tangent_matrix[0], -1.0f);
}
else {
- BLI_assert(!"Unhandled corner index");
+ BLI_assert_msg(0, "Unhandled corner index");
}
cross_v3_v3v3(tangent_matrix[2], dPdu, dPdv);
normalize_v3(tangent_matrix[0]);
diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c
index aed8c3122a2..9fb158d2f84 100644
--- a/source/blender/blenkernel/intern/multires_reshape_smooth.c
+++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c
@@ -1354,7 +1354,7 @@ static void evaluate_higher_grid_positions_with_details_callback(
{
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
- /* Position of the original veretx at top level. */
+ /* Position of the original vertex at top level. */
float orig_final_P[3];
evaluate_final_original_point(reshape_smooth_context, grid_coord, orig_final_P);
diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c
index 4210f26a694..501e3f27389 100644
--- a/source/blender/blenkernel/intern/multires_unsubdivide.c
+++ b/source/blender/blenkernel/intern/multires_unsubdivide.c
@@ -603,7 +603,7 @@ static void write_loop_in_face_grid(
step_y[1] = 0;
break;
default:
- BLI_assert(!"Should never happen");
+ BLI_assert_msg(0, "Should never happen");
break;
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index bf18765aa94..7e524da0f53 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -631,10 +631,10 @@ float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
{
NlaStrip *strip;
- /* sanity checks
- * - obviously we've got to have some starting data
- * - when not in tweakmode, the active Action does not have any scaling applied :)
- * - when in tweakmode, if the no-mapping flag is set, do not map
+ /* Sanity checks:
+ * - Obviously we've got to have some starting data.
+ * - When not in tweak-mode, the active Action does not have any scaling applied :)
+ * - When in tweak-mode, if the no-mapping flag is set, do not map.
*/
if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON) == 0 || (adt->flag & ADT_NLA_EDIT_NOMAP)) {
return cframe;
@@ -2089,9 +2089,8 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
return false;
}
- /* if block is already in tweakmode, just leave, but we should report
- * that this block is in tweakmode (as our returncode)
- */
+ /* If block is already in tweak-mode, just leave, but we should report
+ * that this block is in tweak-mode (as our returncode). */
if (adt->flag & ADT_NLA_EDIT_ON) {
return true;
}
@@ -2111,8 +2110,8 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
}
- /* There are situations where we may have multiple strips selected and we want to enter tweakmode
- * on all of those at once. Usually in those cases,
+ /* There are situations where we may have multiple strips selected and we want to enter
+ * tweak-mode on all of those at once. Usually in those cases,
* it will usually just be a single strip per AnimData.
* In such cases, compromise and take the last selected track and/or last selected strip, T28468.
*/
@@ -2142,7 +2141,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) {
if (G.debug & G_DEBUG) {
- printf("NLA tweakmode enter - neither active requirement found\n");
+ printf("NLA tweak-mode enter - neither active requirement found\n");
printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
}
return false;
@@ -2192,7 +2191,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
return true;
}
-/* Exit tweakmode for this AnimData block */
+/* Exit tweak-mode for this AnimData block. */
void BKE_nla_tweakmode_exit(AnimData *adt)
{
NlaStrip *strip;
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 1b68c38e4ba..79caeaf7617 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -69,7 +69,6 @@
#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_node.h"
-#include "BKE_node_ui_storage.hh"
#include "BLI_ghash.h"
#include "BLI_threads.h"
@@ -220,10 +219,6 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
/* node tree will generate its own interface type */
ntree_dst->interface_type = nullptr;
-
- /* Don't copy error messages in the runtime struct.
- * They should be filled during execution anyway. */
- ntree_dst->ui_storage = nullptr;
}
static void ntree_free_data(ID *id)
@@ -277,8 +272,6 @@ static void ntree_free_data(ID *id)
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
BKE_libblock_free_data(&ntree->id, true);
}
-
- delete ntree->ui_storage;
}
static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
@@ -365,7 +358,7 @@ static void node_foreach_cache(ID *id,
key.offset_in_ID = offsetof(bNodeTree, previews);
key.cache_v = nodetree->previews;
- /* TODO, see also `direct_link_nodetree()` in readfile.c. */
+ /* TODO: see also `direct_link_nodetree()` in readfile.c. */
#if 0
function_callback(id, &key, (void **)&nodetree->previews, 0, user_data);
#endif
@@ -407,7 +400,7 @@ static ID *node_owner_get(Main *bmain, ID *id)
}
}
- BLI_assert(!"Embedded node tree with no owner. Critical Main inconsistency.");
+ BLI_assert_msg(0, "Embedded node tree with no owner. Critical Main inconsistency.");
return nullptr;
}
@@ -517,7 +510,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
if (node->storage) {
/* could be handlerized at some point, now only 1 exception still */
- if ((ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY)) &&
+ if (ELEM(ntree->type, NTREE_SHADER, NTREE_GEOMETRY) &&
ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) {
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
}
@@ -625,7 +618,6 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres
ntree->interface_type = nullptr;
ntree->progress = nullptr;
ntree->execdata = nullptr;
- ntree->ui_storage = nullptr;
BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
@@ -649,7 +641,7 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
/* ntree itself has been read! */
void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
{
- /* note: writing and reading goes in sync, for speed */
+ /* NOTE: writing and reading goes in sync, for speed. */
ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
@@ -657,7 +649,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
ntree->progress = nullptr;
ntree->execdata = nullptr;
- ntree->ui_storage = nullptr;
BLO_read_data_address(reader, &ntree->adt);
BKE_animdata_blend_read_data(reader, ntree->adt);
@@ -800,7 +791,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
BLO_read_data_address(reader, &link->tosock);
}
- /* TODO, should be dealt by new generic cache handling of IDs... */
+ /* TODO: should be dealt by new generic cache handling of IDs... */
ntree->previews = nullptr;
/* type verification is in lib-link */
@@ -1048,7 +1039,7 @@ static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType
}
}
-/* Note: This function is called to initialize node data based on the type.
+/* NOTE: This function is called to initialize node data based on the type.
* The bNodeType may not be registered at creation time of the node,
* so this can be delayed until the node type gets registered.
*/
@@ -1070,7 +1061,7 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
node->height = ntype->height;
node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
/* initialize the node name with the node label.
- * note: do this after the initfunc so nodes get their data set which may be used in naming
+ * NOTE: do this after the initfunc so nodes get their data set which may be used in naming
* (node groups for example) */
/* XXX Do not use nodeLabel() here, it returns translated content for UI,
* which should *only* be used in UI, *never* in data...
@@ -1431,6 +1422,12 @@ GHashIterator *nodeSocketTypeGetIterator(void)
return BLI_ghashIterator_new(nodesockettypes_hash);
}
+const char *nodeSocketTypeLabel(const bNodeSocketType *stype)
+{
+ /* Use socket type name as a fallback if label is undefined. */
+ return stype->label[0] != '\0' ? stype->label : RNA_struct_ui_name(stype->ext_socket.srna);
+}
+
struct bNodeSocket *nodeFindSocket(const bNode *node,
eNodeSocketInOut in_out,
const char *identifier)
@@ -1593,13 +1590,15 @@ static void socket_id_user_decrement(bNodeSocket *sock)
}
}
-void nodeModifySocketType(
- bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, int type, int subtype)
+void nodeModifySocketType(bNodeTree *ntree,
+ bNode *UNUSED(node),
+ bNodeSocket *sock,
+ const char *idname)
{
- const char *idname = nodeStaticSocketType(type, subtype);
+ bNodeSocketType *socktype = nodeSocketTypeFind(idname);
- if (!idname) {
- CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
+ if (!socktype) {
+ CLOG_ERROR(&LOG, "node socket type %s undefined", idname);
return;
}
@@ -1609,9 +1608,21 @@ void nodeModifySocketType(
sock->default_value = nullptr;
}
- sock->type = type;
BLI_strncpy(sock->idname, idname, sizeof(sock->idname));
- node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname));
+ node_socket_set_typeinfo(ntree, sock, socktype);
+}
+
+void nodeModifySocketTypeStatic(
+ bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype)
+{
+ const char *idname = nodeStaticSocketType(type, subtype);
+
+ if (!idname) {
+ CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
+ return;
+ }
+
+ nodeModifySocketType(ntree, node, sock, idname);
}
bNodeSocket *nodeAddSocket(bNodeTree *ntree,
@@ -1655,6 +1666,15 @@ bNodeSocket *nodeInsertSocket(bNodeTree *ntree,
return sock;
}
+bool nodeIsStaticSocketType(const struct bNodeSocketType *stype)
+{
+ /*
+ * Cannot rely on type==SOCK_CUSTOM here, because type is 0 by default
+ * and can be changed on custom sockets.
+ */
+ return RNA_struct_is_a(stype->ext_socket.srna, &RNA_NodeSocketStandard);
+}
+
const char *nodeStaticSocketType(int type, int subtype)
{
switch (type) {
@@ -1813,6 +1833,39 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
return nullptr;
}
+const char *nodeStaticSocketLabel(int type, int UNUSED(subtype))
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ return "Float";
+ case SOCK_INT:
+ return "Integer";
+ case SOCK_BOOLEAN:
+ return "Boolean";
+ case SOCK_VECTOR:
+ return "Vector";
+ case SOCK_RGBA:
+ return "Color";
+ case SOCK_STRING:
+ return "String";
+ case SOCK_SHADER:
+ return "Shader";
+ case SOCK_OBJECT:
+ return "Object";
+ case SOCK_IMAGE:
+ return "Image";
+ case SOCK_GEOMETRY:
+ return "Geometry";
+ case SOCK_COLLECTION:
+ return "Collection";
+ case SOCK_TEXTURE:
+ return "Texture";
+ case SOCK_MATERIAL:
+ return "Material";
+ }
+ return nullptr;
+}
+
bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
bNode *node,
eNodeSocketInOut in_out,
@@ -2895,7 +2948,7 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo
BKE_node_instance_hash_insert(to_ntree->previews, key, preview);
}
- /* Note: null free function here,
+ /* NOTE: null free function here,
* because pointers have already been moved over to to_ntree->previews! */
BKE_node_instance_hash_free(from_ntree->previews, nullptr);
from_ntree->previews = nullptr;
@@ -3102,7 +3155,7 @@ static void free_localized_node_groups(bNodeTree *ntree)
}
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) {
+ if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
bNodeTree *ngroup = (bNodeTree *)node->id;
ntreeFreeTree(ngroup);
MEM_freeN(ngroup);
@@ -3163,8 +3216,8 @@ void ntreeSetOutput(bNodeTree *ntree)
if (ntree->type == NTREE_COMPOSIT) {
/* same type, exception for viewer */
if (tnode->type == node->type ||
- (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
- ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
+ (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER) &&
+ ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER))) {
if (tnode->flag & NODE_DO_OUTPUT) {
output++;
if (output > 1) {
@@ -3286,7 +3339,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
{
if (ntree) {
/* Make full copy outside of Main database.
- * Note: previews are not copied here.
+ * NOTE: previews are not copied here.
*/
bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex(
nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA));
@@ -3294,7 +3347,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
ltree->id.tag |= LIB_TAG_LOCALIZED;
LISTBASE_FOREACH (bNode *, node, &ltree->nodes) {
- if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) {
+ if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
}
}
@@ -4763,7 +4816,7 @@ static bool node_undefined_poll(bNodeType *UNUSED(ntype),
/* register fallback types used for undefined tree, nodes, sockets */
static void register_undefined_types()
{
- /* Note: these types are not registered in the type hashes,
+ /* NOTE: these types are not registered in the type hashes,
* they are just used as placeholders in case the actual types are not registered.
*/
@@ -5057,27 +5110,30 @@ static void registerGeometryNodes()
register_node_type_geo_attribute_mix();
register_node_type_geo_attribute_proximity();
register_node_type_geo_attribute_randomize();
+ register_node_type_geo_attribute_remove();
register_node_type_geo_attribute_separate_xyz();
register_node_type_geo_attribute_set();
register_node_type_geo_attribute_transfer();
register_node_type_geo_attribute_vector_math();
register_node_type_geo_attribute_vector_rotate();
- register_node_type_geo_attribute_remove();
register_node_type_geo_boolean();
register_node_type_geo_bounding_box();
register_node_type_geo_collection_info();
register_node_type_geo_convex_hull();
+ register_node_type_geo_curve_endpoints();
register_node_type_geo_curve_length();
register_node_type_geo_curve_primitive_bezier_segment();
register_node_type_geo_curve_primitive_circle();
+ register_node_type_geo_curve_primitive_line();
register_node_type_geo_curve_primitive_quadratic_bezier();
+ register_node_type_geo_curve_primitive_quadrilateral();
register_node_type_geo_curve_primitive_spiral();
register_node_type_geo_curve_primitive_star();
- register_node_type_geo_curve_to_mesh();
- register_node_type_geo_curve_to_points();
register_node_type_geo_curve_resample();
register_node_type_geo_curve_reverse();
register_node_type_geo_curve_subdivide();
+ register_node_type_geo_curve_to_mesh();
+ register_node_type_geo_curve_to_points();
register_node_type_geo_delete_geometry();
register_node_type_geo_edge_split();
register_node_type_geo_input_material();
@@ -5093,6 +5149,7 @@ static void registerGeometryNodes()
register_node_type_geo_mesh_primitive_ico_sphere();
register_node_type_geo_mesh_primitive_line();
register_node_type_geo_mesh_primitive_uv_sphere();
+ register_node_type_geo_mesh_subdivide();
register_node_type_geo_mesh_to_curve();
register_node_type_geo_object_info();
register_node_type_geo_point_distribute();
@@ -5106,11 +5163,11 @@ static void registerGeometryNodes()
register_node_type_geo_sample_texture();
register_node_type_geo_select_by_material();
register_node_type_geo_separate_components();
- register_node_type_geo_subdivide();
register_node_type_geo_subdivision_surface();
register_node_type_geo_switch();
register_node_type_geo_transform();
register_node_type_geo_triangulate();
+ register_node_type_geo_viewer();
register_node_type_geo_volume_to_mesh();
}
@@ -5118,6 +5175,7 @@ static void registerFunctionNodes()
{
register_node_type_fn_boolean_math();
register_node_type_fn_float_compare();
+ register_node_type_fn_float_to_int();
register_node_type_fn_input_string();
register_node_type_fn_input_vector();
register_node_type_fn_random_float();
diff --git a/source/blender/blenkernel/intern/node_ui_storage.cc b/source/blender/blenkernel/intern/node_ui_storage.cc
deleted file mode 100644
index e5e9f00c7c3..00000000000
--- a/source/blender/blenkernel/intern/node_ui_storage.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "CLG_log.h"
-
-#include <mutex>
-
-#include "BLI_map.hh"
-#include "BLI_string_ref.hh"
-#include "BLI_vector.hh"
-
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_context.h"
-#include "BKE_node_ui_storage.hh"
-#include "BKE_object.h"
-
-static CLG_LogRef LOG = {"bke.node_ui_storage"};
-
-using blender::Map;
-using blender::StringRef;
-using blender::Vector;
-
-/* Use a global mutex because otherwise it would have to be stored directly in the
- * bNodeTree struct in DNA. This could change if the node tree had a runtime struct. */
-static std::mutex global_ui_storage_mutex;
-
-static NodeTreeUIStorage &ui_storage_ensure(bNodeTree &ntree)
-{
- /* As an optimization, only acquire a lock if the UI storage doesn't exist,
- * because it only needs to be allocated once for every node tree. */
- if (ntree.ui_storage == nullptr) {
- std::lock_guard<std::mutex> lock(global_ui_storage_mutex);
- /* Check again-- another thread may have allocated the storage while this one waited. */
- if (ntree.ui_storage == nullptr) {
- ntree.ui_storage = new NodeTreeUIStorage();
- }
- }
- return *ntree.ui_storage;
-}
-
-const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C,
- const bNodeTree &ntree,
- const bNode &node)
-{
- const NodeTreeUIStorage *ui_storage = ntree.ui_storage;
- if (ui_storage == nullptr) {
- return nullptr;
- }
-
- const Object *active_object = CTX_data_active_object(C);
- if (active_object == nullptr) {
- return nullptr;
- }
-
- const ModifierData *active_modifier = BKE_object_active_modifier(active_object);
- if (active_modifier == nullptr) {
- return nullptr;
- }
-
- const NodeTreeEvaluationContext context(*active_object, *active_modifier);
- const Map<std::string, NodeUIStorage> *storage = ui_storage->context_map.lookup_ptr(context);
- if (storage == nullptr) {
- return nullptr;
- }
-
- return storage->lookup_ptr_as(StringRef(node.name));
-}
-
-/**
- * Removes only the UI data associated with a particular evaluation context. The same node tree
- * can be used for execution in multiple places, but the entire UI storage can't be removed when
- * one execution starts, or all of the data associated with the node tree would be lost.
- */
-void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context)
-{
- NodeTreeUIStorage *ui_storage = ntree.ui_storage;
- if (ui_storage != nullptr) {
- std::lock_guard<std::mutex> lock(ui_storage->mutex);
- ui_storage->context_map.remove(context);
- }
-}
-
-static void node_error_message_log(bNodeTree &ntree,
- const bNode &node,
- const StringRef message,
- const NodeWarningType type)
-{
- switch (type) {
- case NodeWarningType::Error:
- CLOG_ERROR(&LOG,
- "Node Tree: \"%s\", Node: \"%s\", %s",
- ntree.id.name + 2,
- node.name,
- message.data());
- break;
- case NodeWarningType::Warning:
- CLOG_WARN(&LOG,
- "Node Tree: \"%s\", Node: \"%s\", %s",
- ntree.id.name + 2,
- node.name,
- message.data());
- break;
- case NodeWarningType::Info:
- CLOG_INFO(&LOG,
- 2,
- "Node Tree: \"%s\", Node: \"%s\", %s",
- ntree.id.name + 2,
- node.name,
- message.data());
- break;
- }
-}
-
-static NodeUIStorage &node_ui_storage_ensure(NodeTreeUIStorage &locked_ui_storage,
- const NodeTreeEvaluationContext &context,
- const bNode &node)
-{
- Map<std::string, NodeUIStorage> &node_tree_ui_storage =
- locked_ui_storage.context_map.lookup_or_add_default(context);
- NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as(
- StringRef(node.name));
- return node_ui_storage;
-}
-
-void BKE_nodetree_error_message_add(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context,
- const bNode &node,
- const NodeWarningType type,
- std::string message)
-{
- NodeTreeUIStorage &ui_storage = ui_storage_ensure(ntree);
- std::lock_guard lock{ui_storage.mutex};
-
- node_error_message_log(ntree, node, message, type);
-
- NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ui_storage, context, node);
- node_ui_storage.warnings.append({type, std::move(message)});
-}
-
-void BKE_nodetree_attribute_hint_add(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context,
- const bNode &node,
- const StringRef attribute_name,
- const AttributeDomain domain,
- const CustomDataType data_type)
-{
- NodeTreeUIStorage &ui_storage = ui_storage_ensure(ntree);
- std::lock_guard lock{ui_storage.mutex};
-
- NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ui_storage, context, node);
- node_ui_storage.attribute_hints.add_as(
- AvailableAttributeInfo{attribute_name, domain, data_type});
-}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index a5e16172e75..941db80b76c 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -205,7 +205,8 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
}
else if (ob_dst->mat != NULL || ob_dst->matbits != NULL) {
/* This shall not be needed, but better be safe than sorry. */
- BLI_assert(!"Object copy: non-NULL material pointers with zero counter, should not happen.");
+ BLI_assert_msg(
+ 0, "Object copy: non-NULL material pointers with zero counter, should not happen.");
ob_dst->mat = NULL;
ob_dst->matbits = NULL;
}
@@ -234,7 +235,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
BKE_pose_rebuild(bmain, ob_dst, ob_dst->data, do_pose_id_user);
}
}
- BKE_defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase);
+
BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
@@ -251,7 +252,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
BLI_listbase_clear(&ob_dst->modifiers);
BLI_listbase_clear(&ob_dst->greasepencil_modifiers);
- /* Note: Also takes care of softbody and particle systems copying. */
+ /* NOTE: Also takes care of softbody and particle systems copying. */
BKE_object_modifier_stack_copy(ob_dst, ob_src, true, flag_subdata);
BLI_listbase_clear((ListBase *)&ob_dst->drawdata);
@@ -262,7 +263,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
/* Do not copy object's preview
* (mostly due to the fact renderers create temp copy of objects). */
- if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO: temp hack. */
BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id);
}
else {
@@ -285,7 +286,6 @@ static void object_free_data(ID *id)
MEM_SAFE_FREE(ob->iuser);
MEM_SAFE_FREE(ob->runtime.bb);
- BLI_freelistN(&ob->defbase);
BLI_freelistN(&ob->fmaps);
if (ob->pose) {
BKE_pose_free_ex(ob->pose, false);
@@ -510,13 +510,6 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
-static void write_defgroups(BlendWriter *writer, ListBase *defbase)
-{
- LISTBASE_FOREACH (bDeformGroup *, defgroup, defbase) {
- BLO_write_struct(writer, bDeformGroup, defgroup);
- }
-}
-
static void write_fmaps(BlendWriter *writer, ListBase *fbase)
{
LISTBASE_FOREACH (bFaceMap *, fmap, fbase) {
@@ -561,7 +554,6 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
}
BKE_pose_blend_write(writer, ob->pose, arm);
- write_defgroups(writer, &ob->defbase);
write_fmaps(writer, &ob->fmaps);
BKE_constraint_blend_write(writer, &ob->constraints);
animviz_motionpath_blend_write(writer, ob->mpath);
@@ -644,7 +636,9 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
animviz_motionpath_blend_read_data(reader, ob->mpath);
}
+ /* Only for versioning, vertex group names are now stored on object data. */
BLO_read_list(reader, &ob->defbase);
+
BLO_read_list(reader, &ob->fmaps);
/* XXX deprecated - old animation system <<< */
direct_link_nlastrips(reader, &ob->nlastrips);
@@ -1041,6 +1035,8 @@ static void object_blend_read_expand(BlendExpander *expander, ID *id)
BLO_expand(expander, ob->data);
+ BLO_expand(expander, ob->parent);
+
/* expand_object_expandModifier() */
if (ob->modifiers.first) {
BKE_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, expander);
@@ -1537,7 +1533,8 @@ bool BKE_object_modifier_stack_copy(Object *ob_dst,
const int flag_subdata)
{
if ((ob_dst->type == OB_GPENCIL) != (ob_src->type == OB_GPENCIL)) {
- BLI_assert(!"Trying to copy a modifier stack between a GPencil object and another type.");
+ BLI_assert_msg(0,
+ "Trying to copy a modifier stack between a GPencil object and another type.");
return false;
}
@@ -1758,10 +1755,6 @@ void BKE_object_free_derived_caches(Object *ob)
BKE_geometry_set_free(ob->runtime.geometry_set_eval);
ob->runtime.geometry_set_eval = NULL;
}
- if (ob->runtime.geometry_set_previews != NULL) {
- BLI_ghash_free(ob->runtime.geometry_set_previews, NULL, (GHashValFreeFP)BKE_geometry_set_free);
- ob->runtime.geometry_set_previews = NULL;
- }
}
void BKE_object_free_caches(Object *object)
@@ -1812,24 +1805,6 @@ void BKE_object_free_caches(Object *object)
}
}
-/* Can be called from multiple threads. */
-void BKE_object_preview_geometry_set_add(Object *ob,
- const uint64_t key,
- struct GeometrySet *geometry_set)
-{
- static ThreadMutex mutex = BLI_MUTEX_INITIALIZER;
- BLI_mutex_lock(&mutex);
- if (ob->runtime.geometry_set_previews == NULL) {
- ob->runtime.geometry_set_previews = BLI_ghash_int_new(__func__);
- }
- BLI_ghash_reinsert(ob->runtime.geometry_set_previews,
- POINTER_FROM_UINT(key),
- geometry_set,
- NULL,
- (GHashValFreeFP)BKE_geometry_set_free);
- BLI_mutex_unlock(&mutex);
-}
-
/**
* Actual check for internal data, not context or flags.
*/
@@ -2380,8 +2355,8 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f
psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag);
}
- /* XXX - from reading existing code this seems correct but intended usage of
- * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
+ /* XXX(campbell): from reading existing code this seems correct but intended usage of
+ * pointcache should /w cloth should be added in 'ParticleSystem'. */
if (psysn->clmd) {
psysn->clmd->point_cache = psysn->pointcache;
}
@@ -2439,7 +2414,7 @@ void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const
static void copy_object_pose(Object *obn, const Object *ob, const int flag)
{
- /* note: need to clear obn->pose pointer first,
+ /* NOTE: need to clear obn->pose pointer first,
* so that BKE_pose_copy_data works (otherwise there's a crash) */
obn->pose = NULL;
BKE_pose_copy_data_ex(&obn->pose, ob->pose, flag, true); /* true = copy constraints */
@@ -2833,7 +2808,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
/* add new animdata block */
if (!ob->adt) {
- ob->adt = BKE_animdata_add_id(&ob->id);
+ ob->adt = BKE_animdata_ensure_id(&ob->id);
}
/* make a copy of all the drivers (for now), then correct any links that need fixing */
@@ -2921,9 +2896,6 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
ob->data = target->data;
id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_TAG_EXTERN */
- /* copy vertex groups */
- BKE_defgroup_copy_list(&ob->defbase, &target->defbase);
-
/* copy material and index information */
ob->actcol = ob->totcol = 0;
if (ob->mat) {
@@ -3365,7 +3337,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
BLI_mutex_unlock(&vparent_lock);
#else
- BLI_assert(!"Not safe for threading");
+ BLI_assert_msg(0, "Not safe for threading");
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
#endif
}
@@ -3860,7 +3832,7 @@ void BKE_object_boundbox_flag(Object *ob, int flag, const bool set)
}
}
-void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval)
+void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval)
{
float min[3], max[3];
@@ -4089,7 +4061,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
if ((visibility_flag & (OB_EMPTY_IMAGE_HIDE_BACK | OB_EMPTY_IMAGE_HIDE_FRONT)) != 0) {
float eps, dot;
if (rv3d->is_persp) {
- /* Note, we could normalize the 'view_dir' then use 'eps'
+ /* NOTE: we could normalize the 'view_dir' then use 'eps'
* however the issue with empty objects being visible when viewed from the side
* is only noticeable in orthographic views. */
float view_dir[3];
@@ -4163,13 +4135,37 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
return ok;
}
+struct GPencilStrokePointIterData {
+ const float (*obmat)[4];
+
+ void (*point_func_cb)(const float co[3], void *user_data);
+ void *user_data;
+};
+
+static void foreach_display_point_gpencil_stroke_fn(bGPDlayer *UNUSED(layer),
+ bGPDframe *UNUSED(frame),
+ bGPDstroke *stroke,
+ void *thunk)
+{
+ struct GPencilStrokePointIterData *iter_data = thunk;
+ {
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = stroke->points; i < stroke->totpoints; i++, pt++) {
+ float co[3];
+ mul_v3_m4v3(co, iter_data->obmat, &pt->x);
+ iter_data->point_func_cb(co, iter_data->user_data);
+ }
+ }
+}
+
void BKE_object_foreach_display_point(Object *ob,
const float obmat[4][4],
void (*func_cb)(const float[3], void *),
void *user_data)
{
/* TODO: pointcloud and hair objects support */
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
float co[3];
if (mesh_eval != NULL) {
@@ -4180,6 +4176,13 @@ void BKE_object_foreach_display_point(Object *ob,
func_cb(co, user_data);
}
}
+ else if (ob->type == OB_GPENCIL) {
+ struct GPencilStrokePointIterData iter_data = {
+ .obmat = obmat, .point_func_cb = func_cb, .user_data = user_data};
+
+ BKE_gpencil_visible_stroke_iter(
+ ob->data, NULL, foreach_display_point_gpencil_stroke_fn, &iter_data);
+ }
else if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
DispList *dl;
@@ -5616,7 +5619,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
}
}
- /* was originally ID_RECALC_ALL - TODO - which flags are really needed??? */
+ /* was originally ID_RECALC_ALL - TODO: which flags are really needed??? */
/* TODO(sergey): What about animation? */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
frame);
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 1e7624d0d7d..c69326a23c6 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -33,6 +33,7 @@
#include "DNA_armature_types.h"
#include "DNA_cloth_types.h"
#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -123,8 +124,7 @@ bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
}
defgroup = BKE_object_defgroup_new(ob, name);
-
- ob->actdef = BLI_listbase_count(&ob->defbase);
+ BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_count(ob));
return defgroup;
}
@@ -171,7 +171,8 @@ MDeformVert *BKE_object_defgroup_data_create(ID *id)
bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
{
MDeformVert *dv;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const int def_nr = BLI_findindex(defbase, dg);
bool changed = false;
if (ob->type == OB_MESH) {
@@ -249,7 +250,9 @@ bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
bDeformGroup *dg;
bool changed = false;
- for (dg = ob->defbase.first; dg; dg = dg->next) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
+ for (dg = defbase->first; dg; dg = dg->next) {
if (BKE_object_defgroup_clear(ob, dg, use_selection)) {
changed = true;
}
@@ -265,7 +268,7 @@ bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
static void object_defgroup_remove_update_users(Object *ob, const int idx)
{
- int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
+ int i, defbase_tot = BKE_object_defgroup_count(ob) + 1;
int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
map[idx] = map[0] = 0;
@@ -285,15 +288,18 @@ static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const in
object_defgroup_remove_update_users(ob, def_nr + 1);
/* Remove the group */
- BLI_freelinkN(&ob->defbase, dg);
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
+ BLI_freelinkN(defbase, dg);
/* Update the active deform index if necessary */
- if (ob->actdef > def_nr) {
- ob->actdef--;
+ const int active_index = BKE_object_defgroup_active_index_get(ob);
+ if (active_index > def_nr) {
+ BKE_object_defgroup_active_index_set(ob, active_index - 1);
}
/* remove all dverts */
- if (BLI_listbase_is_empty(&ob->defbase)) {
+ if (BLI_listbase_is_empty(defbase)) {
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
@@ -307,8 +313,9 @@ static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const in
}
}
}
- else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */
- ob->actdef = 1;
+ else if (BKE_object_defgroup_active_index_get(ob) < 1) {
+ /* Keep a valid active index if we still have some vgroups. */
+ BKE_object_defgroup_active_index_set(ob, 1);
}
}
@@ -316,7 +323,9 @@ static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
{
MDeformVert *dvert_array = NULL;
int dvert_tot = 0;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
+ const int def_nr = BLI_findindex(defbase, dg);
BLI_assert(def_nr != -1);
@@ -347,7 +356,8 @@ static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
{
int i;
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const int def_nr = BLI_findindex(defbase, dg);
BLI_assert(def_nr != -1);
@@ -425,7 +435,9 @@ void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
*/
void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
{
- bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
+ bDeformGroup *dg = (bDeformGroup *)defbase->first;
const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
if (dg) {
@@ -444,7 +456,7 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
dg = next_dg;
}
}
- else { /* ob->defbase is empty... */
+ else { /* defbase is empty... */
/* remove all dverts */
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
@@ -459,7 +471,7 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
}
}
/* Fix counters/indices */
- ob->actdef = 0;
+ BKE_object_defgroup_active_index_set(ob, 0);
}
}
@@ -478,20 +490,23 @@ void BKE_object_defgroup_remove_all(struct Object *ob)
*/
int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
{
+ const ListBase *src_defbase = BKE_object_defgroup_list(ob_src);
+ const ListBase *dst_defbase = BKE_object_defgroup_list(ob_dst);
+
/* Build src to merged mapping of vgroup indices. */
- if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
+ if (BLI_listbase_is_empty(src_defbase) || BLI_listbase_is_empty(dst_defbase)) {
*r_map_len = 0;
return NULL;
}
bDeformGroup *dg_src;
- *r_map_len = BLI_listbase_count(&ob_src->defbase);
+ *r_map_len = BLI_listbase_count(src_defbase);
int *vgroup_index_map = MEM_malloc_arrayN(
*r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
bool is_vgroup_remap_needed = false;
int i;
- for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
+ for (dg_src = src_defbase->first, i = 0; dg_src; dg_src = dg_src->next, i++) {
vgroup_index_map[i] = BKE_object_defgroup_name_index(ob_dst, dg_src->name);
is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
}
@@ -576,17 +591,17 @@ bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_t
/**
* gets the status of "flag" for each bDeformGroup
- * in ob->defbase and returns an array containing them
+ * in the object data's vertex group list and returns an array containing them
*/
bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
{
bool is_locked = false;
int i;
- // int defbase_tot = BLI_listbase_count(&ob->defbase);
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
bDeformGroup *defgroup;
- for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
+ for (i = 0, defgroup = defbase->first; i < defbase_tot && defgroup;
defgroup = defgroup->next, i++) {
lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
is_locked |= lock_flags[i];
@@ -606,17 +621,17 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
bool *defgroup_validmap;
GHash *gh;
int i, step1 = 1;
- // int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
VirtualModifierData virtualModifierData;
- if (BLI_listbase_is_empty(&ob->defbase)) {
+ if (BLI_listbase_is_empty(defbase)) {
return NULL;
}
gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
/* add all names to a hash table */
- for (dg = ob->defbase.first; dg; dg = dg->next) {
+ for (dg = defbase->first; dg; dg = dg->next) {
BLI_ghash_insert(gh, dg->name, NULL);
}
@@ -655,7 +670,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
/* add all names to a hash table */
- for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
+ for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) {
defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
}
@@ -676,9 +691,11 @@ bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_fl
Object *armob = BKE_object_pose_armature_get(ob);
(*r_dg_flags_sel_tot) = 0;
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
if (armob) {
bPose *pose = armob->pose;
- for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
+ for (i = 0, defgroup = defbase->first; i < defbase_tot && defgroup;
defgroup = defgroup->next, i++) {
bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
@@ -774,11 +791,13 @@ void BKE_object_defgroup_mirror_selection(struct Object *ob,
bool *dg_flags_sel,
int *r_dg_flags_sel_tot)
{
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
bDeformGroup *defgroup;
unsigned int i;
int i_mirr;
- for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
+ for (i = 0, defgroup = defbase->first; i < defbase_tot && defgroup;
defgroup = defgroup->next, i++) {
if (dg_selection[i]) {
char name_flip[MAXBONENAME];
@@ -804,11 +823,12 @@ bool *BKE_object_defgroup_subset_from_select_type(Object *ob,
int *r_subset_count)
{
bool *defgroup_validmap = NULL;
- *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
+
+ *r_defgroup_tot = BKE_object_defgroup_count(ob);
switch (subset_type) {
case WT_VGROUP_ACTIVE: {
- const int def_nr_active = ob->actdef - 1;
+ const int def_nr_active = BKE_object_defgroup_active_index_get(ob) - 1;
defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index 768fa9373c1..77969328365 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -335,14 +335,14 @@ static void make_child_duplis(const DupliContext *ctx,
/** \name Internal Data Access Utilities
* \{ */
-static Mesh *mesh_data_from_duplicator_object(Object *ob,
- BMEditMesh **r_em,
- const float (**r_vert_coords)[3],
- const float (**r_vert_normals)[3])
+static const Mesh *mesh_data_from_duplicator_object(Object *ob,
+ BMEditMesh **r_em,
+ const float (**r_vert_coords)[3],
+ const float (**r_vert_normals)[3])
{
/* Gather mesh info. */
BMEditMesh *em = BKE_editmesh_from_object(ob);
- Mesh *me_eval;
+ const Mesh *me_eval;
*r_em = nullptr;
*r_vert_coords = nullptr;
@@ -603,7 +603,7 @@ static void make_duplis_verts(const DupliContext *ctx)
BMEditMesh *em = nullptr;
const float(*vert_coords)[3] = nullptr;
const float(*vert_normals)[3] = nullptr;
- Mesh *me_eval = mesh_data_from_duplicator_object(
+ const Mesh *me_eval = mesh_data_from_duplicator_object(
parent, &em, &vert_coords, use_rotation ? &vert_normals : nullptr);
if (em == nullptr && me_eval == nullptr) {
return;
@@ -1151,7 +1151,7 @@ static void make_duplis_faces(const DupliContext *ctx)
/* Gather mesh info. */
BMEditMesh *em = nullptr;
const float(*vert_coords)[3] = nullptr;
- Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, nullptr);
+ const Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, nullptr);
if (em == nullptr && me_eval == nullptr) {
return;
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index ab247ef5507..7cdea14e9bd 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -123,7 +123,7 @@ void BKE_object_eval_parent(Depsgraph *depsgraph, Object *ob)
void BKE_object_eval_constraints(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
bConstraintOb *cob;
- float ctime = BKE_scene_frame_get(scene);
+ float ctime = BKE_scene_ctime_get(scene);
DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
@@ -388,12 +388,31 @@ void BKE_object_batch_cache_dirty_tag(Object *ob)
BKE_object_data_batch_cache_dirty_tag(ob->data);
}
+void BKE_object_data_eval_batch_cache_dirty_tag(Depsgraph *depsgraph, ID *object_data)
+{
+ DEG_debug_print_eval(depsgraph, __func__, object_data->name, object_data);
+ BKE_object_data_batch_cache_dirty_tag(object_data);
+}
+
+void BKE_object_data_eval_batch_cache_deform_tag(Depsgraph *depsgraph, ID *object_data)
+{
+ DEG_debug_print_eval(depsgraph, __func__, object_data->name, object_data);
+ switch (GS(object_data->name)) {
+ case ID_ME:
+ BKE_mesh_batch_cache_dirty_tag((Mesh *)object_data, BKE_MESH_BATCH_DIRTY_DEFORM);
+ break;
+ default:
+ /* Only mesh is currently supported. Fallback to dirty all for other datablocks types. */
+ BKE_object_data_batch_cache_dirty_tag(object_data);
+ break;
+ }
+}
+
void BKE_object_eval_uber_data(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
BLI_assert(ob->type != OB_ARMATURE);
BKE_object_handle_data_update(depsgraph, scene, ob);
- BKE_object_batch_cache_dirty_tag(ob);
}
void BKE_object_eval_ptcache_reset(Depsgraph *depsgraph, Scene *scene, Object *object)
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 2e7152302c7..3aee5cd639d 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -62,7 +62,7 @@ static float nextfr(RNG *rng, float min, float max)
static float gaussRand(RNG *rng)
{
- /* Note: to avoid numerical problems with very small numbers, we make these variables
+ /* NOTE: to avoid numerical problems with very small numbers, we make these variables
* singe-precision floats, but later we call the double-precision log() and sqrt() functions
* instead of logf() and sqrtf(). */
float x;
@@ -1381,9 +1381,9 @@ void BKE_ocean_bake(struct Ocean *o,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
- /* note: some of these values remain uninitialized unless certain options
+ /* NOTE(campbell): some of these values remain uninitialized unless certain options
* are enabled, take care that BKE_ocean_eval_ij() initializes a member
- * before use - campbell */
+ * before use. */
OceanResult ocr;
ImageFormatData imf = {0};
@@ -1437,7 +1437,7 @@ void BKE_ocean_bake(struct Ocean *o,
rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp);
if (o->_do_jacobian) {
- /* TODO: cleanup unused code - campbell */
+ /* TODO(campbell): cleanup unused code. */
float /* r, */ /* UNUSED */ pr = 0.0f, foam_result;
float neg_disp, neg_eplus;
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 87239d160b4..78e7e11c248 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -527,7 +527,7 @@ static void unpack_generate_paths(const char *name,
BLI_split_dirfile(name, tempdir, tempname, sizeof(tempdir), sizeof(tempname));
if (tempname[0] == '\0') {
- /* Note: we generally do not have any real way to re-create extension out of data. */
+ /* NOTE: we generally do not have any real way to re-create extension out of data. */
BLI_strncpy(tempname, id->name + 2, sizeof(tempname));
printf("%s\n", tempname);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index a7c6dc2deb9..1af66fa090b 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -128,8 +128,8 @@ static void palette_blend_read_data(BlendDataReader *reader, ID *id)
static void palette_undo_preserve(BlendLibReader *UNUSED(reader), ID *id_new, ID *id_old)
{
/* Whole Palette is preserved across undo-steps, and it has no extra pointer, simple. */
- /* Note: We do not care about potential internal references to self here, Palette has none. */
- /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be
+ /* NOTE: We do not care about potential internal references to self here, Palette has none. */
+ /* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
BKE_lib_id_swap(NULL, id_new, id_old);
SWAP(IDProperty *, id_new->properties, id_old->properties);
@@ -2067,7 +2067,7 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
/* If a sculpt session is active, ensure we have its faceset data porperly up-to-date. */
object->sculpt->face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
- /* Note: In theory we could add that on the fly when required by sculpt code.
+ /* NOTE: In theory we could add that on the fly when required by sculpt code.
* But this then requires proper update of depsgraph etc. For now we play safe, optimization is
* always possible later if it's worth it. */
BKE_sculpt_mask_layers_ensure(object, mmd);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index d386967bf8b..db1fbb56125 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -2811,7 +2811,7 @@ static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
task->rng_path = BLI_rng_new(seed);
}
-/* note: this function must be thread safe, except for branching! */
+/* NOTE: this function must be thread safe, except for branching! */
static void psys_thread_create_path(ParticleTask *task,
struct ChildParticle *cpa,
ParticleCacheKey *child_keys,
@@ -3961,7 +3961,7 @@ static ModifierData *object_add_or_copy_particle_system(
psys->totpart = 0;
psys->flag = PSYS_CURRENT;
if (scene != NULL) {
- psys->cfra = BKE_scene_frame_to_ctime(scene, CFRA + 1);
+ psys->cfra = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1);
}
DEG_relations_tag_update(bmain);
@@ -5400,8 +5400,8 @@ void BKE_particle_system_blend_read_lib(BlendLibReader *reader,
BLO_read_id_address(reader, id->lib, &psys->target_ob);
if (psys->clmd) {
- /* XXX - from reading existing code this seems correct but intended usage of
- * pointcache /w cloth should be added in 'ParticleSystem' - campbell */
+ /* XXX(campbell): from reading existing code this seems correct but intended usage of
+ * pointcache /w cloth should be added in 'ParticleSystem'. */
psys->clmd->point_cache = psys->pointcache;
psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = NULL;
BLO_read_id_address(reader, id->lib, &psys->clmd->coll_parms->group);
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index 2231731287d..415147fb36a 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -331,7 +331,7 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx,
int totkeys, k;
float max_length;
- /* TODO for the future: use true particle modifiers that work on the whole curve */
+ /* TODO: for the future: use true particle modifiers that work on the whole curve. */
(void)modifiers;
(void)mod;
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 1fd99bb2cbd..863476c6638 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -472,7 +472,7 @@ static int distribute_binary_search(const float *sum, int n, float value)
* be sure to keep up to date if this changes */
#define PSYS_RND_DIST_SKIP 3
-/* note: this function must be thread safe, for from == PART_FROM_CHILD */
+/* NOTE: this function must be thread safe, for `from == PART_FROM_CHILD`. */
#define ONLY_WORKING_WITH_PA_VERTS 0
static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
{
@@ -1214,7 +1214,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
* It allows us to consider pos as 'midpoint between v and v+1'
* (or 'p and p+1', depending whether we have more vertices than particles or not),
* and avoid stumbling over float impression in element_sum.
- * Note: moved face and volume distribution to this as well (instead of starting at zero),
+ * NOTE: moved face and volume distribution to this as well (instead of starting at zero),
* for the same reasons, see T52682. */
pos = (totpart < totmapped) ? 0.5 / (double)totmapped :
step * 0.5; /* We choose the smaller step. */
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index c35f703b072..06d3daaf4d6 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -447,9 +447,9 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic
MEM_freeN(nodedmelem);
}
else {
- /* TODO PARTICLE, make the following line unnecessary, each function
+ /* TODO_PARTICLE: make the following line unnecessary, each function
* should know to use the num or num_dmcache, set the num_dmcache to
- * an invalid value, just in case */
+ * an invalid value, just in case. */
LOOP_PARTICLES
{
@@ -992,9 +992,9 @@ void psys_get_birth_coords(
/* (part->rotmode == PART_ROT_NOR_TAN) */
float tmat[3][3];
- /* note: utan_local is not taken from 'utan', we calculate from rot_vec/vtan */
- /* note: it looks like rotation phase may be applied twice (once with vtan, again below)
- * however this isn't the case - campbell */
+ /* NOTE: utan_local is not taken from 'utan', we calculate from rot_vec/vtan. */
+ /* NOTE(campbell): it looks like rotation phase may be applied twice
+ * (once with vtan, again below) however this isn't the case. */
float *rot_vec_local = tmat[0];
float *vtan_local = tmat[1];
float *utan_local = tmat[2];
@@ -1014,7 +1014,7 @@ void psys_get_birth_coords(
cross_v3_v3v3(utan_local, vtan_local, rot_vec_local);
cross_v3_v3v3(vtan_local, utan_local, rot_vec_local);
- /* note: no need to normalize */
+ /* NOTE: no need to normalize. */
mat3_to_quat(q2, tmat);
}
@@ -2617,7 +2617,7 @@ static float collision_newton_rhapson(ParticleCollision *col,
* here. */
if (d1 == d0) {
/* If first iteration, try from other end where the gradient may be
- * greater. Note: code duplicated below. */
+ * greater. NOTE: code duplicated below. */
if (iter == 0) {
t0 = 1.0f;
collision_interpolate_element(pce, t0, col->f, col);
@@ -2638,7 +2638,7 @@ static float collision_newton_rhapson(ParticleCollision *col,
t1 -= d1 * dd;
/* Particle moving away from plane could also mean a strangely rotating
- * face, so check from end. Note: code duplicated above. */
+ * face, so check from end. NOTE: code duplicated above. */
if (iter == 0 && t1 < 0.0f) {
t0 = 1.0f;
collision_interpolate_element(pce, t0, col->f, col);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 0d84022da77..461ffa7765e 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1053,7 +1053,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
const int v = vtri[j];
if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
- /* Note: This avoids `lock, add_v3_v3, unlock`
+ /* NOTE: This avoids `lock, add_v3_v3, unlock`
* and is five to ten times quicker than a spin-lock.
* Not exact equivalent though, since atomicity is only ensured for one component
* of the vector at a time, but here it shall not make any sensible difference. */
@@ -2157,7 +2157,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
const float *co[3];
if (origco) {
- /* intersect with backuped original coordinates */
+ /* Intersect with backed up original coordinates. */
co[0] = origco[face_verts[0]];
co[1] = origco[face_verts[1]];
co[2] = origco[face_verts[2]];
@@ -2798,7 +2798,7 @@ float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3]
void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int totvert)
{
if (totvert != pbvh->totvert) {
- BLI_assert(!"PBVH: Given deforming vcos number does not natch PBVH vertex number!");
+ BLI_assert_msg(0, "PBVH: Given deforming vcos number does not natch PBVH vertex number!");
return;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index c2483b265a5..d3d7f02ecad 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1324,7 +1324,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
/* For all remaining faces of v_del, create a new face that is the
* same except it uses v_conn instead of v_del */
- /* Note: this could be done with BM_vert_splice(), but that
+ /* NOTE: this could be done with BM_vert_splice(), but that
* requires handling other issues like duplicate edges, so doesn't
* really buy anything. */
BLI_buffer_clear(deleted_faces);
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 948b57578dc..84c4ae4dead 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -30,7 +30,7 @@ typedef struct {
float bmin[3], bmax[3], bcentroid[3];
} BBC;
-/* Note: this structure is getting large, might want to split it into
+/* NOTE: this structure is getting large, might want to split it into
* union'd structs */
struct PBVHNode {
/* Opaque handle for drawing code */
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index a05eb6962ce..9ed5b0230e6 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -849,7 +849,7 @@ static void ptcache_rigidbody_interpolate(int index,
dfra = cfra2 - cfra1;
- /* note: keys[0] and keys[3] unused for type < 1 (crappy) */
+ /* NOTE: keys[0] and keys[3] unused for type < 1 (crappy). */
psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true);
interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
@@ -1837,7 +1837,7 @@ static void ptcache_data_copy(void *from[], void *to[])
{
int i;
for (i = 0; i < BPHYS_TOT_DATA; i++) {
- /* note, durian file 03.4b_comp crashes if to[i] is not tested
+ /* NOTE: durian file 03.4b_comp crashes if to[i] is not tested
* its NULL, not sure if this should be fixed elsewhere but for now its needed */
if (from[i] && to[i]) {
memcpy(to[i], from[i], ptcache_data_size[i]);
@@ -2807,8 +2807,8 @@ void BKE_ptcache_id_time(
cache = pid->cache;
if (timescale) {
- time = BKE_scene_frame_get(scene);
- nexttime = BKE_scene_frame_to_ctime(scene, CFRA + 1.0f);
+ time = BKE_scene_ctime_get(scene);
+ nexttime = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1);
*timescale = MAX2(nexttime - time, 0.0f);
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 2d4cce4b953..328c54fc21b 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -367,7 +367,7 @@ static Mesh *rigidbody_get_mesh(Object *ob)
}
/* Just return something sensible so that at least Blender won't crash. */
- BLI_assert(!"Unknown mesh source");
+ BLI_assert_msg(0, "Unknown mesh source");
return BKE_object_get_evaluated_mesh(ob);
}
@@ -1787,7 +1787,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
rigidbody_update_sim_world(scene, rbw);
- /* XXX TODO For rebuild: remove all constraints first.
+ /* XXX TODO: For rebuild: remove all constraints first.
* Otherwise we can end up deleting objects that are still
* referenced by constraints, corrupting bullet's internal list.
*
@@ -1811,11 +1811,12 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
/* validate that we've got valid object set up here... */
RigidBodyOb *rbo = ob->rigidbody_object;
- /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */
+ /* TODO: remove this whole block once we are sure we never get NULL rbo here anymore. */
/* This cannot be done in CoW evaluation context anymore... */
if (rbo == NULL) {
- BLI_assert(!"CoW object part of RBW object collection without RB object data, "
- "should not happen.\n");
+ BLI_assert_msg(0,
+ "CoW object part of RBW object collection without RB object data, "
+ "should not happen.\n");
/* Since this object is included in the sim group but doesn't have
* rigid body settings (perhaps it was added manually), add!
* - assume object to be active? That is the default for newly added settings...
@@ -1868,11 +1869,12 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
/* validate that we've got valid object set up here... */
RigidBodyCon *rbc = ob->rigidbody_constraint;
- /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */
+ /* TODO: remove this whole block once we are sure we never get NULL rbo here anymore. */
/* This cannot be done in CoW evaluation context anymore... */
if (rbc == NULL) {
- BLI_assert(!"CoW object part of RBW constraints collection without RB constraint data, "
- "should not happen.\n");
+ BLI_assert_msg(0,
+ "CoW object part of RBW constraints collection without RB constraint data, "
+ "should not happen.\n");
/* Since this object is included in the group but doesn't have
* constraint settings (perhaps it was added manually), add!
*/
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 84741038164..cc5a8536a5a 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -192,7 +192,7 @@ static void scene_init_data(ID *id)
BLI_strncpy(scene->r.pic, U.renderdir, sizeof(scene->r.pic));
- /* Note; in header_info.c the scene copy happens...,
+ /* NOTE: in header_info.c the scene copy happens...,
* if you add more to renderdata it has to be checked there. */
/* multiview - stereo */
@@ -1045,7 +1045,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
static void direct_link_paint_helper(BlendDataReader *reader, const Scene *scene, Paint **paint)
{
- /* TODO. is this needed */
+ /* TODO: is this needed. */
BLO_read_data_address(reader, paint);
if (*paint) {
@@ -1899,14 +1899,14 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src)
sce_dst->eevee = sce_src->eevee;
sce_dst->eevee.light_cache_data = NULL;
sce_dst->eevee.light_cache_info[0] = '\0';
- /* TODO Copy the cache. */
+ /* TODO: Copy the cache. */
}
Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
{
Scene *sce_copy;
- /* TODO this should/could most likely be replaced by call to more generic code at some point...
+ /* TODO: this should/could most likely be replaced by call to more generic code at some point...
* But for now, let's keep it well isolated here. */
if (type == SCE_COPY_EMPTY) {
ListBase rv;
@@ -2299,10 +2299,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene)
return NULL;
}
- const int cfra = ((scene->r.images == scene->r.framapto) ?
- scene->r.cfra :
- (int)(scene->r.cfra *
- ((float)scene->r.framapto / (float)scene->r.images)));
+ const int ctime = (int)BKE_scene_ctime_get(scene);
int frame = -(MAXFRAME + 1);
int min_frame = MAXFRAME + 1;
Object *camera = NULL;
@@ -2310,11 +2307,11 @@ Object *BKE_scene_camera_switch_find(Scene *scene)
LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) {
if (m->camera && (m->camera->restrictflag & OB_RESTRICT_RENDER) == 0) {
- if ((m->frame <= cfra) && (m->frame > frame)) {
+ if ((m->frame <= ctime) && (m->frame > frame)) {
camera = m->camera;
frame = m->frame;
- if (frame == cfra) {
+ if (frame == ctime) {
break;
}
}
@@ -2396,13 +2393,13 @@ const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
return best_marker ? best_marker->name : NULL;
}
-int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int cfra)
+int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int frame)
{
const int fps = round_db_to_int(FPS * interval_in_seconds);
- const int second_prev = cfra - mod_i(cfra, fps);
+ const int second_prev = frame - mod_i(frame, fps);
const int second_next = second_prev + fps;
- const int delta_prev = cfra - second_prev;
- const int delta_next = second_next - cfra;
+ const int delta_prev = frame - second_prev;
+ const int delta_next = second_next - frame;
return (delta_prev < delta_next) ? second_prev : second_next;
}
@@ -2444,16 +2441,17 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
return true;
}
-/**
- * This function is needed to cope with fractional frames, needed for motion blur & physics.
- */
-float BKE_scene_frame_get(const Scene *scene)
+/* Return fractional frame number taking into account subframes and time
+ * remapping. This the time value used by animation, modifiers and physics
+ * evaluation. */
+float BKE_scene_ctime_get(const Scene *scene)
{
return BKE_scene_frame_to_ctime(scene, scene->r.cfra);
}
-/* This function is used to obtain arbitrary fractional frames */
-float BKE_scene_frame_to_ctime(const Scene *scene, const float frame)
+/* Convert integer frame number to fractional frame number taking into account
+ * subframes and time remapping. */
+float BKE_scene_frame_to_ctime(const Scene *scene, const int frame)
{
float ctime = frame;
ctime += scene->r.subframe;
@@ -2461,13 +2459,18 @@ float BKE_scene_frame_to_ctime(const Scene *scene, const float frame)
return ctime;
}
-/**
- * Sets the frame int/float components.
- */
-void BKE_scene_frame_set(struct Scene *scene, double cfra)
+
+/* Get current fractional frame based on frame and subframe. */
+float BKE_scene_frame_get(const Scene *scene)
+{
+ return scene->r.cfra + scene->r.subframe;
+}
+
+/* Set current frame and subframe based on a fractional frame. */
+void BKE_scene_frame_set(Scene *scene, float frame)
{
double intpart;
- scene->r.subframe = modf(cfra, &intpart);
+ scene->r.subframe = modf((double)frame, &intpart);
scene->r.cfra = (int)intpart;
}
@@ -2736,8 +2739,8 @@ void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, const bool cle
* edits from callback are properly taken into account. Doing a time update on those would
* lose any possible unkeyed changes made by the handler. */
if (pass == 0) {
- const float ctime = BKE_scene_frame_get(scene);
- DEG_evaluate_on_framechange(depsgraph, ctime);
+ const float frame = BKE_scene_frame_get(scene);
+ DEG_evaluate_on_framechange(depsgraph, frame);
}
else {
DEG_evaluate_on_refresh(depsgraph);
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 608317933f5..c3885b5dcf7 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -101,7 +101,7 @@ void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area
{
BKE_LIB_FOREACHID_PROCESS(data, area->full, IDWALK_CB_NOP);
- /* TODO this should be moved to a callback in `SpaceType`, defined in each editor's own code.
+ /* TODO: this should be moved to a callback in `SpaceType`, defined in each editor's own code.
* Will be for a later round of cleanup though... */
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
switch (sl->spacetype) {
@@ -289,7 +289,7 @@ bool BKE_screen_blend_read_data(BlendDataReader *reader, bScreen *screen)
return success;
}
-/* note: file read without screens option G_FILE_NO_UI;
+/* NOTE: file read without screens option G_FILE_NO_UI;
* check lib pointers in call below */
static void screen_blend_read_lib(BlendLibReader *reader, ID *id)
{
@@ -682,19 +682,13 @@ void BKE_area_region_free(SpaceType *st, ARegion *region)
BKE_area_region_panels_free(&region->panels);
LISTBASE_FOREACH (uiList *, uilst, &region->ui_lists) {
- if (uilst->dyn_data) {
- uiListDyn *dyn_data = uilst->dyn_data;
- if (dyn_data->items_filter_flags) {
- MEM_freeN(dyn_data->items_filter_flags);
- }
- if (dyn_data->items_filter_neworder) {
- MEM_freeN(dyn_data->items_filter_neworder);
- }
- MEM_freeN(dyn_data);
+ if (uilst->dyn_data && uilst->dyn_data->free_runtime_data_fn) {
+ uilst->dyn_data->free_runtime_data_fn(uilst);
}
if (uilst->properties) {
IDP_FreeProperty(uilst->properties);
}
+ MEM_SAFE_FREE(uilst->dyn_data);
}
if (region->gizmo_map != NULL) {
@@ -1734,6 +1728,12 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
sfile->runtime = NULL;
BLO_read_data_address(reader, &sfile->params);
BLO_read_data_address(reader, &sfile->asset_params);
+ if (sfile->params) {
+ sfile->params->rename_id = NULL;
+ }
+ if (sfile->asset_params) {
+ sfile->asset_params->base_params.rename_id = NULL;
+ }
}
else if (sl->spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)sl;
diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c
index b537bdc5479..29cbe05f4d1 100644
--- a/source/blender/blenkernel/intern/shader_fx.c
+++ b/source/blender/blenkernel/intern/shader_fx.c
@@ -81,7 +81,7 @@ ShaderFxData *BKE_shaderfx_new(int type)
const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type);
ShaderFxData *fx = MEM_callocN(fxi->struct_size, fxi->struct_name);
- /* note, this name must be made unique later */
+ /* NOTE: this name must be made unique later. */
BLI_strncpy(fx->name, DATA_(fxi->name), sizeof(fx->name));
fx->type = type;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index aeb8133974e..7c0c28d664e 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -493,7 +493,7 @@ bool BKE_shrinkwrap_project_normal(char options,
}
if (options & MOD_SHRINKWRAP_CULL_TARGET_MASK) {
- /* apply backface */
+ /* Apply back-face. */
const float dot = dot_v3v3(dir, hit_tmp.no);
if (((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) ||
((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)) {
@@ -502,7 +502,7 @@ bool BKE_shrinkwrap_project_normal(char options,
}
if (transf) {
- /* Inverting space transform (TODO make coeherent with the initial dist readjust) */
+ /* Inverting space transform (TODO: make coherent with the initial dist readjust). */
BLI_space_transform_invert(transf, hit_tmp.co);
#ifdef USE_DIST_CORRECT
hit_tmp.dist = len_v3v3(vert, hit_tmp.co);
@@ -1440,7 +1440,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
Object *ob_target = DEG_get_evaluated_object(ctx->depsgraph, smd->target);
calc.target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false);
- /* TODO there might be several "bugs" with non-uniform scales matrices
+ /* TODO: there might be several "bugs" with non-uniform scales matrices
* because it will no longer be nearest surface, not sphere projection
* because space has been deformed */
BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, ob_target);
@@ -1460,7 +1460,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
ssmd.subdivType = ME_CC_SUBSURF; /* catmull clark */
ssmd.levels = smd->subsurfLevels; /* levels */
- /* TODO to be moved to Mesh once we are done with changes in subsurf code. */
+ /* TODO: to be moved to Mesh once we are done with changes in subsurf code. */
DerivedMesh *dm = CDDM_from_mesh(mesh);
ss_mesh = subsurf_make_derived_from_derived(
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 9d871777c61..e4e2ed94b41 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -901,7 +901,7 @@ static void free_softbody_baked(SoftBody *sb)
static void free_scratch(SoftBody *sb)
{
if (sb->scratch) {
- /* todo make sure everything is cleaned up nicly */
+ /* TODO: make sure everything is cleaned up nicely. */
if (sb->scratch->colliderhash) {
BLI_ghash_free(sb->scratch->colliderhash,
NULL,
@@ -973,7 +973,7 @@ static void free_softbody_intern(SoftBody *sb)
* and need to tell their neighbors exactly what happens via spring forces
* unless sbObjectStep( .. ) is called on sub frame timing level
* BTW that also questions the use of a 'implicit' solvers on softbodies
- * since that would only valid for 'slow' moving collision targets and dito particles
+ * since that would only valid for 'slow' moving collision targets and ditto particles.
*/
/* +++ dependency information functions. */
@@ -1907,7 +1907,7 @@ static void sb_spring_force(
#endif
}
else {
- /* TODO make this debug option */
+ /* TODO: make this debug option. */
CLOG_WARN(&LOG, "bodypoint <bpi> is not attached to spring <*bs>");
return;
}
@@ -1994,12 +1994,12 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene,
return 999;
}
- /* debugerin */
+ /* Debugging. */
if (sb->totpoint < ifirst) {
printf("Aye 998");
return 998;
}
- /* debugerin */
+ /* Debugging. */
bp = &sb->bpoint[ifirst];
for (bb = number_of_points_here; bb > 0; bb--, bp++) {
@@ -2413,9 +2413,9 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
copy_v3_v3(dx, bp->vec);
}
- /* so here is (x)'= v(elocity) */
- /* the euler step for location then becomes */
- /* x(t + dt) = x(t) + v(t~) * dt */
+ /* So here is: `(x)'= v(elocity)`.
+ * The euler step for location then becomes:
+ * `x(t + dt) = x(t) + v(t~) * dt` */
mul_v3_fl(dx, forcetime);
/* the freezer coming sooner or later */
@@ -2644,7 +2644,7 @@ static void interpolate_exciter(Object *ob, int timescale, int time)
*/
/* Resetting a Mesh SB object's springs */
-/* Spring length are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */
+/* Spring length are calculated from 'raw' mesh vertices that are NOT altered by modifier stack. */
static void springs_from_mesh(Object *ob)
{
SoftBody *sb;
@@ -2704,8 +2704,8 @@ static void mesh_to_softbody(Object *ob)
bp = sb->bpoint;
defgroup_index = me->dvert ? (sb->vertgroup - 1) : -1;
- defgroup_index_mass = me->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Mass) : -1;
- defgroup_index_spring = me->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Spring_K) :
+ defgroup_index_mass = me->dvert ? BKE_id_defgroup_name_index(&me->id, sb->namedVG_Mass) : -1;
+ defgroup_index_spring = me->dvert ? BKE_id_defgroup_name_index(&me->id, sb->namedVG_Spring_K) :
-1;
for (a = 0; a < me->totvert; a++, bp++) {
@@ -2934,8 +2934,8 @@ static void lattice_to_softbody(Object *ob)
bp = sb->bpoint;
defgroup_index = lt->dvert ? (sb->vertgroup - 1) : -1;
- defgroup_index_mass = lt->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Mass) : -1;
- defgroup_index_spring = lt->dvert ? BKE_object_defgroup_name_index(ob, sb->namedVG_Spring_K) :
+ defgroup_index_mass = lt->dvert ? BKE_id_defgroup_name_index(&lt->id, sb->namedVG_Mass) : -1;
+ defgroup_index_spring = lt->dvert ? BKE_id_defgroup_name_index(&lt->id, sb->namedVG_Spring_K) :
-1;
/* same code used as for mesh vertices */
@@ -3009,7 +3009,7 @@ static void curve_surf_to_softbody(Object *ob)
for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->bezt) {
- /* Bezier case; this is nicly said naive; who ever wrote this part,
+ /* Bezier case; this is nicely said naive; who ever wrote this part,
* it was not me (JOW) :).
*
* a: never ever make tangent handles (sub) and or (ob)ject to collision.
@@ -3086,7 +3086,7 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts,
if (sb->solverflags & SBSO_ESTIMATEIPO) {
SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale);
}
- /* inverse matrix is not uptodate... */
+ /* Inverse matrix is not up to date. */
invert_m4_m4(ob->imat, ob->obmat);
for (a = 0; a < numVerts; a++, bp++) {
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index f4a9d328d86..fcb992e1535 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -824,7 +824,7 @@ void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated)
void BKE_sound_update_sequencer(Main *main, bSound *sound)
{
- BLI_assert(!"is not supposed to be used, is weird function.");
+ BLI_assert_msg(0, "is not supposed to be used, is weird function.");
Scene *scene;
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index aa0d95d4d61..6234cdf87e2 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -512,6 +512,10 @@ void Spline::sample_with_index_factors(const GVArray &src,
using T = decltype(dummy);
const GVArray_Typed<T> src_typed = src.typed<T>();
MutableSpan<T> dst_typed = dst.typed<T>();
+ if (src.size() == 1) {
+ dst_typed.fill(src_typed[0]);
+ return;
+ }
blender::threading::parallel_for(dst_typed.index_range(), 1024, [&](IndexRange range) {
for (const int i : range) {
const LookupResult interp = this->lookup_data_from_index_factor(index_factors[i]);
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index 02d26ac715b..b6764f65631 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -333,6 +333,46 @@ void BezierSpline::correct_end_tangents() const
}
}
+/**
+ * De Casteljau Bezier subdivision.
+ * \param index: The index of the segment's start control point.
+ * \param next_index: The index of the control point at the end of the segment. Could be 0,
+ * if the spline is cyclic.
+ * \param parameter: The factor along the segment, between 0 and 1. Note that this is used
+ * directly by the calculation, it doesn't correspond to a portion of the evaluated length.
+ *
+ * <pre>
+ * handle_prev handle_next
+ * x----------------x
+ * / \
+ * / x---O---x \
+ * / result \
+ * / \
+ * O O
+ * point_prev point_next
+ * </pre>
+ */
+BezierSpline::InsertResult BezierSpline::calculate_segment_insertion(const int index,
+ const int next_index,
+ const float parameter)
+{
+ BLI_assert(parameter <= 1.0f && parameter >= 0.0f);
+ BLI_assert(next_index == 0 || next_index == index + 1);
+ const float3 &point_prev = positions_[index];
+ const float3 &handle_prev = handle_positions_right_[index];
+ const float3 &handle_next = handle_positions_left_[next_index];
+ const float3 &point_next = positions_[next_index];
+ const float3 center_point = float3::interpolate(handle_prev, handle_next, parameter);
+
+ BezierSpline::InsertResult result;
+ result.handle_prev = float3::interpolate(point_prev, handle_prev, parameter);
+ result.handle_next = float3::interpolate(handle_next, point_next, parameter);
+ result.left_handle = float3::interpolate(result.handle_prev, center_point, parameter);
+ result.right_handle = float3::interpolate(center_point, result.handle_next, parameter);
+ result.position = float3::interpolate(result.left_handle, result.right_handle, parameter);
+ return result;
+}
+
static void bezier_forward_difference_3d(const float3 &point_0,
const float3 &point_1,
const float3 &point_2,
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index 76d046337c0..ac6f1bd082c 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -346,7 +346,10 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const
const int size = this->size();
const int eval_size = this->evaluated_points_size();
- BLI_assert(this->evaluated_edges_size() > 0);
+ if (eval_size == 0) {
+ return {};
+ }
+
basis_cache_.resize(eval_size);
const int order = this->order();
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 4cc2d101b02..dc5162f201e 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -1352,7 +1352,7 @@ static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl)
ITER_PIXELS_END;
}
-void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4])
+void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3])
{
copy_v3_fl3(light_ambient, 0.0, 0.0, 0.0);
diff --git a/source/blender/blenkernel/intern/subdiv.c b/source/blender/blenkernel/intern/subdiv.c
index e6b51c586c3..fd32f52351a 100644
--- a/source/blender/blenkernel/intern/subdiv.c
+++ b/source/blender/blenkernel/intern/subdiv.c
@@ -68,7 +68,7 @@ eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int
case SUBSURF_UV_SMOOTH_ALL:
return SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE;
}
- BLI_assert(!"Unknown uv smooth flag");
+ BLI_assert_msg(0, "Unknown uv smooth flag");
return SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL;
}
@@ -81,7 +81,7 @@ eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsu
case SUBSURF_BOUNDARY_SMOOTH_ALL:
return SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
}
- BLI_assert(!"Unknown boundary smooth flag");
+ BLI_assert_msg(0, "Unknown boundary smooth flag");
return SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
}
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 8b672b2cb49..95f51a72b70 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -1509,7 +1509,7 @@ static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_cc
++result.y;
}
else {
- BLI_assert(!"non-boundary element given");
+ BLI_assert_msg(0, "non-boundary element given");
}
return result;
}
diff --git a/source/blender/blenkernel/intern/subdiv_converter.c b/source/blender/blenkernel/intern/subdiv_converter.c
index d5c75503500..39b701da262 100644
--- a/source/blender/blenkernel/intern/subdiv_converter.c
+++ b/source/blender/blenkernel/intern/subdiv_converter.c
@@ -44,7 +44,7 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe
case SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER:
return OSD_VTX_BOUNDARY_EDGE_AND_CORNER;
}
- BLI_assert(!"Unknown vtx boundary interpolation");
+ BLI_assert_msg(0, "Unknown vtx boundary interpolation");
return OSD_VTX_BOUNDARY_EDGE_ONLY;
}
@@ -65,6 +65,6 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe
case SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL:
return OSD_FVAR_LINEAR_INTERPOLATION_ALL;
}
- BLI_assert(!"Unknown fvar linear interpolation");
+ BLI_assert_msg(0, "Unknown fvar linear interpolation");
return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
}
diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c
index 693827f99ac..0001eb8a205 100644
--- a/source/blender/blenkernel/intern/subdiv_eval.c
+++ b/source/blender/blenkernel/intern/subdiv_eval.c
@@ -137,7 +137,7 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
{
if (subdiv->evaluator == NULL) {
/* NOTE: This situation is supposed to be handled by begin(). */
- BLI_assert(!"Is not supposed to happen");
+ BLI_assert_msg(0, "Is not supposed to happen");
return false;
}
/* Set coordinates of base mesh vertices. */
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 0dbfeaaaadb..cff2c5cc562 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2352,7 +2352,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm,
const bool ignore_simplify = (flags & SUBSURF_IGNORE_SIMPLIFY);
CCGDerivedMesh *result;
- /* note: editmode calculation can only run once per
+ /* NOTE: editmode calculation can only run once per
* modifier stack evaluation (uses freed cache) T36299. */
if (flags & SUBSURF_FOR_EDIT_MODE) {
int levels = (scene != NULL && !ignore_simplify) ?
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 74845e3f1b9..80ff8ce9162 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -176,7 +176,7 @@ static void text_blend_write(BlendWriter *writer, ID *id, const void *id_address
}
Text *text = (Text *)id;
- /* Note: we are clearing local temp data here, *not* the flag in the actual 'real' ID. */
+ /* NOTE: we are clearing local temp data here, *not* the flag in the actual 'real' ID. */
if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
text->flags &= ~TXT_ISEXT;
}
@@ -2397,7 +2397,7 @@ int text_check_bracket(const char ch)
return 0;
}
-/* TODO, have a function for operators -
+/* TODO: have a function for operators -
* http://docs.python.org/py3k/reference/lexical_analysis.html#operators */
bool text_check_delim(const char ch)
{
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index f3d6bc4a6e3..068d048fd08 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -1525,7 +1525,7 @@ MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int fram
const int num_markers = track->markersnr;
if (num_markers == 0) {
- BLI_assert(!"Detected degenerated track, should never happen.");
+ BLI_assert_msg(0, "Detected degenerated track, should never happen.");
return NULL;
}
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index ef36acdc3d5..179def0a6f2 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -155,7 +155,7 @@ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip,
return tracking_context_get_frame_ibuf(clip, user, clip_flag, keyed_framenr);
}
-/* Get image buffer which si used as reference for track. */
+/* Get image buffer which is used as reference for track. */
static ImBuf *tracking_context_get_reference_ibuf(MovieClip *clip,
MovieClipUser *user,
int clip_flag,
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 3dff750edfb..d5585116f7e 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -376,7 +376,7 @@ static MovieTrackingMarker *get_tracking_data_point(StabContext *ctx,
* always guesswork.
*
* As a simple default, we use the weighted average of the location markers
- * of the current frame as pivot point. TODO It is planned to add further
+ * of the current frame as pivot point. TODO: It is planned to add further
* options, like e.g. anchoring the pivot point at the canvas. Moreover,
* it is planned to allow for a user controllable offset.
*/
@@ -661,7 +661,7 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
int next_higher = MAXFRAME;
use_values_from_fcurves(ctx, true);
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
- /* Note: we deliberately do not care if this track
+ /* NOTE: we deliberately do not care if this track
* is already initialized for stabilization. */
if (track->flag & TRACK_USE_2D_STAB) {
int startpoint = search_closest_marker_index(track, framenr);
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index ea0d92cf78e..16b36e94328 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -523,7 +523,7 @@ static void distortion_model_parameters_from_options(
/* Libmv returned distortion model which is not known to Blender. This is a logical error in code
* and Blender side is to be updated to match Libmv. */
- BLI_assert(!"Unknown distortion model");
+ BLI_assert_msg(0, "Unknown distortion model");
}
/* Fill in Libmv C-API camera intrinsics options from tracking structure. */
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 14dd286a315..e524bd254bb 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -140,7 +140,7 @@ static void undosys_id_ref_store(void *UNUSED(user_data), UndoRefID *id_ref)
static void undosys_id_ref_resolve(void *user_data, UndoRefID *id_ref)
{
- /* Note: we could optimize this,
+ /* NOTE: we could optimize this,
* for now it's not too bad since it only runs when we access undo! */
Main *bmain = user_data;
ListBase *lb = which_libbase(bmain, GS(id_ref->name));
@@ -717,11 +717,31 @@ eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack,
}
}
- BLI_assert(!"Target undo step not found, this should not happen and may indicate an undo stack corruption");
+ BLI_assert_msg(0,
+ "Target undo step not found, this should not happen and may indicate an undo "
+ "stack corruption");
return STEP_INVALID;
}
/**
+ * When reading undo steps for undo/redo,
+ * some extra checks are needed when so the correct undo step is decoded.
+ */
+static UndoStep *undosys_step_iter_first(UndoStep *us_reference, const eUndoStepDir undo_dir)
+{
+ if (us_reference->type->flags & UNDOTYPE_FLAG_DECODE_ACTIVE_STEP) {
+ /* Reading this step means an undo action reads undo twice.
+ * This should be avoided where possible, however some undo systems require it.
+ *
+ * Redo skips the current state as this represents the currently loaded state. */
+ return (undo_dir == -1) ? us_reference : us_reference->next;
+ }
+
+ /* Typical case, skip reading the current undo step. */
+ return (undo_dir == -1) ? us_reference->prev : us_reference->next;
+}
+
+/**
* Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
*
* \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the
@@ -786,15 +806,10 @@ bool BKE_undosys_step_load_data_ex(UndoStack *ustack,
us_target->type->name,
undo_dir);
- /* Undo/Redo steps until we reach given target step (or beyond if it has to be skipped), from
- * given reference step.
- *
- * NOTE: Unlike with redo case, where we can expect current active step to fully reflect current
- * data status, in undo case we also do reload the active step.
- * FIXME: this feels weak, and should probably not be actually needed? Or should also be done in
- * redo case? */
+ /* Undo/Redo steps until we reach given target step (or beyond if it has to be skipped),
+ * from given reference step. */
bool is_processing_extra_skipped_steps = false;
- for (UndoStep *us_iter = (undo_dir == -1) ? us_reference : us_reference->next; us_iter != NULL;
+ for (UndoStep *us_iter = undosys_step_iter_first(us_reference, undo_dir); us_iter != NULL;
us_iter = (undo_dir == -1) ? us_iter->prev : us_iter->next) {
BLI_assert(us_iter != NULL);
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 290b880934e..d9f02ce4c75 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -833,7 +833,7 @@ static char *find_next_op(const char *str, char *remaining_str, int len_max)
return remaining_str + i;
}
}
- BLI_assert(!"String should be NULL terminated");
+ BLI_assert_msg(0, "String should be NULL terminated");
return remaining_str + i;
}
@@ -917,7 +917,7 @@ static int unit_scale_str(char *str,
return 0;
}
- /* XXX - investigate, does not respect len_max properly. */
+ /* XXX: investigate, does not respect len_max properly. */
char *str_found = (char *)unit_find_str(str, replace_str, case_sensitive);
if (str_found == NULL) {
@@ -931,7 +931,7 @@ static int unit_scale_str(char *str,
/* Deal with unit bias for temperature units. Order of operations is important, so we
* have to add parentheses, add the bias, then multiply by the scalar like usual.
*
- * Note: If these changes don't fit in the buffer properly unit evaluation has failed,
+ * NOTE: If these changes don't fit in the buffer properly unit evaluation has failed,
* just try not to destroy anything while failing. */
if (unit->bias != 0.0) {
/* Add the open parenthesis. */
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 272ecc71833..b28d17df814 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -197,7 +197,7 @@ static struct VolumeFileCache {
Entry &entry = (Entry &)*it;
entry.num_metadata_users++;
- /* Note: pointers to unordered_set values are not invalidated when adding
+ /* NOTE: pointers to unordered_set values are not invalidated when adding
* or removing other values. */
return &entry;
}
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 533107b2bf6..5cac149c503 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -29,6 +29,7 @@
#include "BLT_translation.h"
+#include "BKE_asset.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
@@ -53,6 +54,13 @@
/* -------------------------------------------------------------------- */
+static void workspace_init_data(ID *id)
+{
+ WorkSpace *workspace = (WorkSpace *)id;
+
+ BKE_asset_library_reference_init_default(&workspace->active_asset_library);
+}
+
static void workspace_free_data(ID *id)
{
WorkSpace *workspace = (WorkSpace *)id;
@@ -180,7 +188,7 @@ IDTypeInfo IDType_ID_WS = {
.translation_context = BLT_I18NCONTEXT_ID_WORKSPACE,
.flags = IDTYPE_FLAGS_NO_COPY | IDTYPE_FLAGS_NO_MAKELOCAL | IDTYPE_FLAGS_NO_ANIMDATA,
- .init_data = NULL,
+ .init_data = workspace_init_data,
.copy_data = NULL,
.free_data = workspace_free_data,
.make_local = NULL,
diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h
index 2847bc960ad..52d41173a0e 100644
--- a/source/blender/blenlib/BLI_array_utils.h
+++ b/source/blender/blenlib/BLI_array_utils.h
@@ -28,52 +28,53 @@
extern "C" {
#endif
-void _bli_array_reverse(void *arr, unsigned int arr_len, size_t arr_stride);
+void _bli_array_reverse(void *arr, uint arr_len, size_t arr_stride);
#define BLI_array_reverse(arr, arr_len) _bli_array_reverse(arr, arr_len, sizeof(*(arr)))
-void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir);
+void _bli_array_wrap(void *arr, uint arr_len, size_t arr_stride, int dir);
#define BLI_array_wrap(arr, arr_len, dir) _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir)
-void _bli_array_permute(void *arr,
- const unsigned int arr_len,
- const size_t arr_stride,
- const unsigned int *order,
- void *arr_temp);
+void _bli_array_permute(
+ void *arr, const uint arr_len, const size_t arr_stride, const uint *order, void *arr_temp);
#define BLI_array_permute(arr, arr_len, order) \
_bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL)
#define BLI_array_permute_ex(arr, arr_len, order, arr_temp) \
_bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp)
-int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
+uint _bli_array_deduplicate_ordered(void *arr, uint arr_len, size_t arr_stride);
+#define BLI_array_deduplicate_ordered(arr, arr_len) \
+ _bli_array_deduplicate_ordered(arr, arr_len, sizeof(*(arr)))
+
+int _bli_array_findindex(const void *arr, uint arr_len, size_t arr_stride, const void *p);
#define BLI_array_findindex(arr, arr_len, p) _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)
-int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
+int _bli_array_rfindindex(const void *arr, uint arr_len, size_t arr_stride, const void *p);
#define BLI_array_rfindindex(arr, arr_len, p) \
_bli_array_rfindindex(arr, arr_len, sizeof(*(arr)), p)
void _bli_array_binary_and(
- void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride);
+ void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride);
#define BLI_array_binary_and(arr, arr_a, arr_b, arr_len) \
(CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_a)), \
CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_b)), \
_bli_array_binary_and(arr, arr_a, arr_b, arr_len, sizeof(*(arr))))
void _bli_array_binary_or(
- void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride);
+ void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride);
#define BLI_array_binary_or(arr, arr_a, arr_b, arr_len) \
(CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_a)), \
CHECK_TYPE_PAIR_INLINE(*(arr), *(arr_b)), \
_bli_array_binary_or(arr, arr_a, arr_b, arr_len, sizeof(*(arr))))
bool _bli_array_iter_span(const void *arr,
- unsigned int arr_len,
+ uint arr_len,
size_t arr_stride,
bool use_wrap,
bool use_delimit_bounds,
bool (*test_fn)(const void *arr_item, void *user_data),
void *user_data,
- unsigned int span_step[2],
- unsigned int *r_span_len);
+ uint span_step[2],
+ uint *r_span_len);
#define BLI_array_iter_span( \
arr, arr_len, use_wrap, use_delimit_bounds, test_fn, user_data, span_step, r_span_len) \
_bli_array_iter_span(arr, \
@@ -86,7 +87,7 @@ bool _bli_array_iter_span(const void *arr,
span_step, \
r_span_len)
-bool _bli_array_is_zeroed(const void *arr, unsigned int arr_len, size_t arr_stride);
+bool _bli_array_is_zeroed(const void *arr, uint arr_len, size_t arr_stride);
#define BLI_array_is_zeroed(arr, arr_len) _bli_array_is_zeroed(arr, arr_len, sizeof(*(arr)))
bool _bli_array_iter_spiral_square(const void *arr_v,
diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h
index 685f526b4ad..6019f0f3566 100644
--- a/source/blender/blenlib/BLI_assert.h
+++ b/source/blender/blenlib/BLI_assert.h
@@ -31,6 +31,7 @@ extern "C" {
/* Utility functions. */
void _BLI_assert_print_pos(const char *file, const int line, const char *function, const char *id);
+void _BLI_assert_print_extra(const char *str);
void _BLI_assert_print_backtrace(void);
void _BLI_assert_abort(void);
void _BLI_assert_unreachable_print(const char *file, const int line, const char *function);
@@ -61,8 +62,17 @@ void _BLI_assert_unreachable_print(const char *file, const int line, const char
_BLI_ASSERT_ABORT(), \
NULL)) : \
NULL)
+/** A version of #BLI_assert() to pass an additional message to be printed on failure. */
+# define BLI_assert_msg(a, msg) \
+ (void)((!(a)) ? ((_BLI_assert_print_backtrace(), \
+ _BLI_ASSERT_PRINT_POS(a), \
+ _BLI_assert_print_extra(msg), \
+ _BLI_ASSERT_ABORT(), \
+ NULL)) : \
+ NULL)
#else
# define BLI_assert(a) ((void)0)
+# define BLI_assert_msg(a, msg) ((void)0)
#endif
#if defined(__cplusplus)
@@ -96,7 +106,7 @@ void _BLI_assert_unreachable_print(const char *file, const int line, const char
#define BLI_assert_unreachable() \
{ \
_BLI_assert_unreachable_print(__FILE__, __LINE__, __func__); \
- BLI_assert(!"This line of code is marked to be unreachable."); \
+ BLI_assert_msg(0, "This line of code is marked to be unreachable."); \
} \
((void)0)
diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h
index d42126fbe61..ec4cfe4801a 100644
--- a/source/blender/blenlib/BLI_endian_switch_inline.h
+++ b/source/blender/blenlib/BLI_endian_switch_inline.h
@@ -29,7 +29,7 @@ extern "C" {
* \ingroup bli
*/
-/* note: using a temp char to switch endian is a lot slower,
+/* NOTE: using a temp char to switch endian is a lot slower,
* use bit shifting instead. */
/* *** 16 *** */
diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh
index a05f7724dd2..3051d980d45 100644
--- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh
+++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh
@@ -46,25 +46,72 @@ template<typename T> class EnumerableThreadSpecific : NonCopyable, NonMovable {
tbb::enumerable_thread_specific<T> values_;
public:
+ using iterator = typename tbb::enumerable_thread_specific<T>::iterator;
+
+ EnumerableThreadSpecific() = default;
+
+ template<typename F> EnumerableThreadSpecific(F initializer) : values_(std::move(initializer))
+ {
+ }
+
T &local()
{
return values_.local();
}
+ iterator begin()
+ {
+ return values_.begin();
+ }
+
+ iterator end()
+ {
+ return values_.end();
+ }
+
#else /* WITH_TBB */
private:
std::mutex mutex_;
/* Maps thread ids to their corresponding values. The values are not embedded in the map, so that
* their addresses do not change when the map grows. */
- Map<int, std::unique_ptr<T>> values_;
+ Map<int, std::reference_wrapper<T>> values_;
+ Vector<std::unique_ptr<T>> owned_values_;
+ std::function<void(void *)> initializer_;
public:
+ using iterator = typename Map<int, std::reference_wrapper<T>>::MutableValueIterator;
+
+ EnumerableThreadSpecific() : initializer_([](void *buffer) { new (buffer) T(); })
+ {
+ }
+
+ template<typename F>
+ EnumerableThreadSpecific(F initializer)
+ : initializer_([=](void *buffer) { new (buffer) T(initializer()); })
+ {
+ }
+
T &local()
{
const int thread_id = enumerable_thread_specific_utils::thread_id;
std::lock_guard lock{mutex_};
- return *values_.lookup_or_add_cb(thread_id, []() { return std::make_unique<T>(); });
+ return values_.lookup_or_add_cb(thread_id, [&]() {
+ T *value = (T *)::operator new(sizeof(T));
+ initializer_(value);
+ owned_values_.append(std::unique_ptr<T>{value});
+ return std::reference_wrapper<T>{*value};
+ });
+ }
+
+ iterator begin()
+ {
+ return values_.values().begin();
+ }
+
+ iterator end()
+ {
+ return values_.values().end();
}
#endif /* WITH_TBB */
diff --git a/source/blender/blenlib/BLI_function_ref.hh b/source/blender/blenlib/BLI_function_ref.hh
index 38e1ba593c5..70a064adc5d 100644
--- a/source/blender/blenlib/BLI_function_ref.hh
+++ b/source/blender/blenlib/BLI_function_ref.hh
@@ -95,7 +95,7 @@ template<typename Ret, typename... Params> class FunctionRef<Ret(Params...)> {
* A pointer to the referenced callable object. This can be a C function, a lambda object or any
* other callable.
*
- * The value does not need to be initialized because it is not used unless callback_ is set as
+ * The value does not need to be initialized because it is not used unless `callback_` is set as
* well, in which case it will be initialized as well.
*
* Use `intptr_t` to avoid warnings when casting to function pointers.
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 43b31d76bb0..9ac14a6edfe 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -255,7 +255,7 @@ void limit_dist_v3(float v1[3], float v2[3], const float dist);
/******************************* Intersection ********************************/
-/* TODO int return value consistency */
+/* TODO: int return value consistency. */
/* line-line */
#define ISECT_LINE_LINE_COLINEAR -1
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 54df88ca541..e38df58c1ca 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -211,6 +211,7 @@ void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
void mul_m3_v3_double(const float M[3][3], double r[3]);
void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4]);
void mul_m3_fl(float R[3][3], float f);
void mul_m4_fl(float R[4][4], float f);
@@ -277,7 +278,7 @@ bool is_orthonormal_m4(const float mat[4][4]);
bool is_uniform_scaled_m3(const float mat[3][3]);
bool is_uniform_scaled_m4(const float m[4][4]);
-/* Note: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
+/* NOTE: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
* Nowadays 'adjoint' usually refers to the conjugate transpose,
* which for real-valued matrices is simply the transpose.
*/
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index ef10d02f10f..461b5a60c9d 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -90,7 +90,7 @@ void tri_to_quat_ex(float quat[4],
const float no_orig[3]);
float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3]);
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag);
-/* note: v1 and v2 must be normalized */
+/* NOTE: v1 and v2 must be normalized. */
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3]);
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]);
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]);
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
index d7798f12fcc..b2e05b00735 100644
--- a/source/blender/blenlib/BLI_memarena.h
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -50,6 +50,8 @@ void *BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESU
void *BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2);
+void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) ATTR_NONNULL(1, 2);
+
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1);
#ifdef __cplusplus
diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh
index bdbbda9f0c7..14eca49d126 100644
--- a/source/blender/blenlib/BLI_memory_utils.hh
+++ b/source/blender/blenlib/BLI_memory_utils.hh
@@ -309,6 +309,12 @@ template<typename T> void uninitialized_fill_n(T *dst, int64_t n, const T &value
}
template<typename T> struct DestructValueAtAddress {
+ DestructValueAtAddress() = default;
+
+ template<typename U> DestructValueAtAddress(const U &)
+ {
+ }
+
void operator()(T *ptr)
{
ptr->~T();
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index e5e0df02033..61b572a4943 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -65,7 +65,10 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool,
void BLI_mempool_set_memory_debug(void);
#endif
-/** iteration stuff. note: this may easy to produce bugs with */
+/**
+ * Iteration stuff.
+ * NOTE: this may easy to produce bugs with.
+ */
/* private structure */
typedef struct BLI_mempool_iter {
BLI_mempool *pool;
diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh
index 6b8e79f376c..f28be9bf59b 100644
--- a/source/blender/blenlib/BLI_mesh_intersect.hh
+++ b/source/blender/blenlib/BLI_mesh_intersect.hh
@@ -225,6 +225,7 @@ class IMeshArena : NonCopyable, NonMovable {
*/
const Vert *add_or_find_vert(const mpq3 &co, int orig);
const Vert *add_or_find_vert(const double3 &co, int orig);
+ const Vert *add_or_find_vert(Vert *vert);
Face *add_face(Span<const Vert *> verts,
int orig,
@@ -405,7 +406,7 @@ bool bbs_might_intersect(const BoundingBox &bb_a, const BoundingBox &bb_b);
* that the output triangle was a part of (input can have -1 for that field and then
* the index in `tri[]` will be used as the original index).
* The orig structure of the output #IMesh gives the originals for vertices and edges.
- * Note: if the input tm_in has a non-empty orig structure, then it is ignored.
+ * NOTE: if the input tm_in has a non-empty orig structure, then it is ignored.
*/
IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena);
diff --git a/source/blender/blenlib/BLI_multi_value_map.hh b/source/blender/blenlib/BLI_multi_value_map.hh
index fb52ac78243..d3073c98417 100644
--- a/source/blender/blenlib/BLI_multi_value_map.hh
+++ b/source/blender/blenlib/BLI_multi_value_map.hh
@@ -129,7 +129,7 @@ template<typename Key, typename Value> class MultiValueMap {
}
/**
- * Note: This signature will change when the implementation changes.
+ * NOTE: This signature will change when the implementation changes.
*/
typename MapType::ItemIterator items() const
{
@@ -137,7 +137,7 @@ template<typename Key, typename Value> class MultiValueMap {
}
/**
- * Note: This signature will change when the implementation changes.
+ * NOTE: This signature will change when the implementation changes.
*/
typename MapType::KeyIterator keys() const
{
@@ -145,7 +145,7 @@ template<typename Key, typename Value> class MultiValueMap {
}
/**
- * Note: This signature will change when the implementation changes.
+ * NOTE: This signature will change when the implementation changes.
*/
typename MapType::ValueIterator values() const
{
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index fa57f0486e5..8f281023177 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -97,15 +97,15 @@ struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx,
struct ScanFillVert *v2);
enum {
- /* note: using BLI_SCANFILL_CALC_REMOVE_DOUBLES
+ /* NOTE(campbell): using BLI_SCANFILL_CALC_REMOVE_DOUBLES
* Assumes ordered edges, otherwise we risk an eternal loop
- * removing double verts. - campbell */
+ * removing double verts. */
BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1),
/* calculate isolated polygons */
BLI_SCANFILL_CALC_POLYS = (1 << 2),
- /* note: This flag removes checks for overlapping polygons.
+ /* NOTE: This flag removes checks for overlapping polygons.
* when this flag is set, we'll never get back more faces than (totvert - 2) */
BLI_SCANFILL_CALC_HOLES = (1 << 3),
diff --git a/source/blender/blenlib/BLI_set_slots.hh b/source/blender/blenlib/BLI_set_slots.hh
index a4d01dfdb68..d50ef95f11e 100644
--- a/source/blender/blenlib/BLI_set_slots.hh
+++ b/source/blender/blenlib/BLI_set_slots.hh
@@ -249,7 +249,7 @@ template<typename Key> class HashedSetSlot {
template<typename ForwardKey, typename IsEqual>
bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t hash) const
{
- /* hash_ might be uninitialized here, but that is ok. */
+ /* `hash_` might be uninitialized here, but that is ok. */
if (hash_ == hash) {
if (state_ == Occupied) {
return is_equal(key, *key_buffer_);
diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh
index c3876d4eaf8..e04295b0e51 100644
--- a/source/blender/blenlib/BLI_span.hh
+++ b/source/blender/blenlib/BLI_span.hh
@@ -58,7 +58,7 @@
* its task, without having to worry about memory allocation. Alternatively, a function could
* return an Array or Vector.
*
- * Note: When a function has a MutableSpan<T> output parameter and T is not a trivial type,
+ * NOTE: When a function has a MutableSpan<T> output parameter and T is not a trivial type,
* then the function has to specify whether the referenced array is expected to be initialized or
* not.
*
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index dbe8ec3dcc0..418db14e2f3 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -129,6 +129,9 @@ typedef struct TaskParallelTLS {
typedef void (*TaskParallelRangeFunc)(void *__restrict userdata,
const int iter,
const TaskParallelTLS *__restrict tls);
+
+typedef void (*TaskParallelInitFunc)(const void *__restrict userdata, void *__restrict chunk);
+
typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata,
void *__restrict chunk_join,
void *__restrict chunk);
@@ -151,6 +154,10 @@ typedef struct TaskParallelSettings {
/* Function called from calling thread once whole range have been
* processed.
*/
+ /* Function called to initialize user data chunk,
+ * typically to allocate data, freed by `func_free`.
+ */
+ TaskParallelInitFunc func_init;
/* Function called to join user data chunk into another, to reduce
* the result to the original userdata_chunk memory.
* The reduce functions should have no side effects, so that they
diff --git a/source/blender/blenlib/BLI_task.hh b/source/blender/blenlib/BLI_task.hh
index 5f5a17f6b58..e2446ad143e 100644
--- a/source/blender/blenlib/BLI_task.hh
+++ b/source/blender/blenlib/BLI_task.hh
@@ -28,6 +28,7 @@
# define NOMINMAX
# define TBB_MIN_MAX_CLEANUP
# endif
+# include "tbb/parallel_reduce.h"
# include <tbb/blocked_range.h>
# include <tbb/parallel_for.h>
# include <tbb/parallel_for_each.h>
@@ -76,6 +77,27 @@ void parallel_for(IndexRange range, int64_t grain_size, const Function &function
#endif
}
+template<typename Value, typename Function, typename Reduction>
+Value parallel_reduce(IndexRange range,
+ int64_t grain_size,
+ const Value &identity,
+ const Function &function,
+ const Reduction &reduction)
+{
+#ifdef WITH_TBB
+ return tbb::parallel_reduce(
+ tbb::blocked_range<int64_t>(range.first(), range.one_after_last(), grain_size),
+ identity,
+ [&](const tbb::blocked_range<int64_t> &subrange, const Value &ident) {
+ return function(IndexRange(subrange.begin(), subrange.size()), ident);
+ },
+ reduction);
+#else
+ UNUSED_VARS(grain_size, reduction);
+ return function(range, identity);
+#endif
+}
+
/** See #BLI_task_isolate for a description of what isolating a task means. */
template<typename Function> void isolate_task(const Function &function)
{
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 677df9db026..ea5572f1c8a 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -188,6 +188,7 @@ set(SRC
BLI_dynstr.h
BLI_easing.h
BLI_edgehash.h
+ BLI_endian_defines.h
BLI_endian_switch.h
BLI_endian_switch_inline.h
BLI_enumerable_thread_specific.hh
diff --git a/source/blender/blenlib/intern/BLI_assert.c b/source/blender/blenlib/intern/BLI_assert.c
index 887f583242f..cebc6f8957f 100644
--- a/source/blender/blenlib/intern/BLI_assert.c
+++ b/source/blender/blenlib/intern/BLI_assert.c
@@ -31,6 +31,11 @@ void _BLI_assert_print_pos(const char *file, const int line, const char *functio
fprintf(stderr, "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", file, line, function, id);
}
+void _BLI_assert_print_extra(const char *str)
+{
+ fprintf(stderr, " %s\n", str);
+}
+
void _BLI_assert_unreachable_print(const char *file, const int line, const char *function)
{
fprintf(stderr, "Code marked as unreachable has been executed. Please report this as a bug.\n");
diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c
index 55fd28667fc..f05dea46dc8 100644
--- a/source/blender/blenlib/intern/BLI_filelist.c
+++ b/source/blender/blenlib/intern/BLI_filelist.c
@@ -432,7 +432,7 @@ void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *s
}
/**
- * Deep-duplicate of an array of direntries, including the array itself.
+ * Deep-duplicate of a #direntry array including the array itself.
*/
void BLI_filelist_duplicate(struct direntry **dest_filelist,
struct direntry *const src_filelist,
@@ -462,7 +462,7 @@ void BLI_filelist_entry_free(struct direntry *entry)
}
/**
- * frees storage for an array of direntries, including the array itself.
+ * Frees storage for an array of #direntry, including the array itself.
*/
void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries)
{
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 8463c0ec511..46e599b7cf3 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -611,7 +611,7 @@ static Entry *ghash_pop(GHash *gh, GHashIterState *state)
return NULL;
}
- /* Note: using first_bucket_index here allows us to avoid potential
+ /* NOTE: using first_bucket_index here allows us to avoid potential
* huge number of loops over buckets,
* in case we are popping from a large ghash with few items in it... */
curr_bucket = ghash_find_next_bucket_index(gh, curr_bucket);
@@ -677,7 +677,7 @@ static GHash *ghash_copy(const GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopy
* This means entries in buckets in new copy will be in reversed order!
* This shall not be an issue though, since order should never be assumed in ghash. */
- /* Note: We can use 'i' here, since we are sure that
+ /* NOTE: We can use 'i' here, since we are sure that
* 'gh' and 'gh_new' have the same number of buckets! */
e_new->next = gh_new->buckets[i];
gh_new->buckets[i] = e_new;
diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c
index 83f64043cd0..182c27aed6d 100644
--- a/source/blender/blenlib/intern/BLI_ghash_utils.c
+++ b/source/blender/blenlib/intern/BLI_ghash_utils.c
@@ -53,7 +53,7 @@ uint BLI_ghashutil_ptrhash(const void *key)
/* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
* excessive hash collisions for dicts and sets */
- /* Note: Unlike Python 'sizeof(uint)' is used instead of 'sizeof(void *)',
+ /* NOTE: Unlike Python 'sizeof(uint)' is used instead of 'sizeof(void *)',
* Otherwise casting to 'uint' ignores the upper bits on 64bit platforms. */
return (uint)(y >> 4) | ((uint)y << (sizeof(uint[8]) - 4));
}
@@ -141,7 +141,7 @@ size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
* string, is updated: ``hash = hash * 33 + c``. This
* function uses the signed value of each byte.
*
- * note: this is the same hash method that glib 2.34.0 uses.
+ * NOTE: this is the same hash method that glib 2.34.0 uses.
*/
uint BLI_ghashutil_strhash_n(const char *key, size_t n)
{
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 8f556e0ddb6..25939323b73 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -26,7 +26,7 @@
*
* See: http://www.gris.uni-tuebingen.de/people/staff/jmezger/papers/bvh.pdf
*
- * implements a bvh-tree structure with support for:
+ * implements a BVH-tree structure with support for:
*
* - Ray-cast:
* #BLI_bvhtree_ray_cast, #BVHRayCastData
@@ -98,8 +98,8 @@ struct BVHTree {
int totleaf; /* leafs */
int totbranch;
axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */
- axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */
- char tree_type; /* type of tree (4 => quadtree) */
+ axis_t axis; /* KDOP type (6 => OBB, 7 => AABB, ...) */
+ char tree_type; /* type of tree (4 => quad-tree). */
};
/* optimization, ensure we stay small */
@@ -726,7 +726,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
/* Save split axis (this can be used on ray-tracing to speedup the query time) */
parent->main_axis = split_axis / 2;
- /* Split the children along the split_axis, note: its not needed to sort the whole leafs array
+ /* Split the children along the split_axis, NOTE: its not needed to sort the whole leafs array
* Only to assure that the elements are partitioned on a way that each child takes the elements
* it would take in case the whole array was sorted.
* Split_leafs takes care of that "sort" problem. */
@@ -881,7 +881,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
/* tree epsilon must be >= FLT_EPSILON
* so that tangent rays can still hit a bounding volume..
- * this bug would show up when casting a ray aligned with a kdop-axis
+ * this bug would show up when casting a ray aligned with a KDOP-axis
* and with an edge of 2 faces */
epsilon = max_ff(FLT_EPSILON, epsilon);
@@ -1423,7 +1423,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(
static bool tree_intersect_plane_test(const float *bv, const float plane[4])
{
- /* TODO(germano): Support other kdop geometries. */
+ /* TODO(germano): Support other KDOP geometries. */
const float bb_min[3] = {bv[0], bv[2], bv[4]};
const float bb_max[3] = {bv[1], bv[3], bv[5]};
float bb_near[3], bb_far[3];
@@ -1805,7 +1805,7 @@ static float ray_nearest_hit(const BVHRayCastData *data, const float bv[6])
* Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe
* [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9]
*
- * TODO this doesn't take data->ray.radius into consideration */
+ * TODO: this doesn't take data->ray.radius into consideration. */
static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node)
{
const float *bv = node->bv;
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index fc381c22315..0ab27a5adad 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -45,6 +45,7 @@
# define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) UNUSED_VARS(pool, rzB, is_zeroed)
# define VALGRIND_DESTROY_MEMPOOL(pool) UNUSED_VARS(pool)
# define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) UNUSED_VARS(pool, addr, size)
+# define VALGRIND_MOVE_MEMPOOL(pool_a, pool_b) UNUSED_VARS(pool_a, pool_b)
#endif
struct MemBuf {
@@ -179,6 +180,58 @@ void *BLI_memarena_calloc(MemArena *ma, size_t size)
}
/**
+ * Transfer ownership of allocated blocks from `ma_src` into `ma_dst`,
+ * cleaning the contents of `ma_src`.
+ *
+ * \note Useful for multi-threaded tasks that need a thread-local #MemArena
+ * that is kept after the multi-threaded operation is completed.
+ *
+ * \note Avoid accumulating memory pools where possible
+ * as any unused memory in `ma_src` is wasted every merge.
+ */
+void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src)
+{
+ /* Memory arenas must be compatible. */
+ BLI_assert(ma_dst != ma_src);
+ BLI_assert(ma_dst->align == ma_src->align);
+ BLI_assert(ma_dst->use_calloc == ma_src->use_calloc);
+ BLI_assert(ma_dst->bufsize == ma_src->bufsize);
+
+ if (ma_src->bufs == NULL) {
+ return;
+ }
+
+ if (UNLIKELY(ma_dst->bufs == NULL)) {
+ BLI_assert(ma_dst->curbuf == NULL);
+ ma_dst->bufs = ma_src->bufs;
+ ma_dst->curbuf = ma_src->curbuf;
+ ma_dst->cursize = ma_src->cursize;
+ }
+ else {
+ /* Keep the 'ma_dst->curbuf' for simplicity.
+ * Insert buffers after the first. */
+ if (ma_dst->bufs->next != NULL) {
+ /* Loop over `ma_src` instead of `ma_dst` since it's likely the destination is larger
+ * when used for accumulating from multiple sources. */
+ struct MemBuf *mb_src = ma_src->bufs;
+ mb_src = ma_src->bufs;
+ while (mb_src && mb_src->next) {
+ mb_src = mb_src->next;
+ }
+ mb_src->next = ma_dst->bufs->next;
+ }
+ ma_dst->bufs->next = ma_src->bufs;
+ }
+
+ ma_src->bufs = NULL;
+ ma_src->curbuf = NULL;
+ ma_src->cursize = 0;
+
+ VALGRIND_MOVE_MEMPOOL(ma_src, ma_dst);
+ VALGRIND_CREATE_MEMPOOL(ma_src, 0, false);
+}
+
+/**
* Clear for reuse, avoids re-allocation when an arena may
* otherwise be free'd and recreated.
*/
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 8196438eb25..5263af2ae56 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -47,7 +47,7 @@
# include "valgrind/memcheck.h"
#endif
-/* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */
+/* NOTE: copied from BLO_blend_defs.h, don't use here because we're in BLI. */
#ifdef __BIG_ENDIAN__
/* Big Endian */
# define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
@@ -387,7 +387,7 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
}
}
if (!found) {
- BLI_assert(!"Attempt to free data which is not in pool.\n");
+ BLI_assert_msg(0, "Attempt to free data which is not in pool.\n");
}
}
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 250915383cf..e1a7ee98ce5 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -191,7 +191,7 @@
# define BCHUNK_SIZE_MIN_DIV 8
/* Disallow chunks bigger than the regular chunk size scaled by this value
- * note: must be at least 2!
+ * NOTE: must be at least 2!
* however, this code runs won't run in tests unless it's ~1.1 ugh.
* so lower only to check splitting works.
*/
@@ -980,7 +980,7 @@ static const BChunkRef *table_lookup(const BArrayInfo *info,
const size_t offset,
const hash_key *UNUSED(table_hash_array))
{
- const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */
+ const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO: cache. */
size_t size_left = data_len - offset;
hash_key key = hash_data(&data[offset], MIN2(data_hash_len, size_left));
@@ -1155,7 +1155,7 @@ static BChunkList *bchunk_list_from_data_merge(const BArrayInfo *info,
use_aligned = true;
}
else {
- /* TODO, walk over chunks and check if some arbitrary amount align */
+ /* TODO: walk over chunks and check if some arbitrary amount align. */
}
}
#endif /* USE_ALIGN_CHUNKS_TEST */
@@ -1787,7 +1787,7 @@ bool BLI_array_store_is_valid(BArrayStore *bs)
}
return ok;
- /* TODO, dangling pointer checks */
+ /* TODO: dangling pointer checks. */
}
/** \} */
diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c
index 25261e82cc9..9a12a7442b7 100644
--- a/source/blender/blenlib/intern/array_utils.c
+++ b/source/blender/blenlib/intern/array_utils.c
@@ -40,11 +40,11 @@
*
* Access via #BLI_array_reverse
*/
-void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride)
+void _bli_array_reverse(void *arr_v, uint arr_len, size_t arr_stride)
{
- const unsigned int arr_stride_uint = (unsigned int)arr_stride;
- const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint;
- unsigned int i, i_end;
+ const uint arr_stride_uint = (uint)arr_stride;
+ const uint arr_half_stride = (arr_len / 2) * arr_stride_uint;
+ uint i, i_end;
char *arr = arr_v;
char *buf = BLI_array_alloca(buf, arr_stride);
@@ -62,7 +62,7 @@ void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride)
*
* Access via #BLI_array_wrap
*/
-void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int dir)
+void _bli_array_wrap(void *arr_v, uint arr_len, size_t arr_stride, int dir)
{
char *arr = arr_v;
char *buf = BLI_array_alloca(buf, arr_stride);
@@ -88,16 +88,13 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d
*
* Access via #BLI_array_wrap
*/
-void _bli_array_permute(void *arr,
- const unsigned int arr_len,
- const size_t arr_stride,
- const unsigned int *order,
- void *arr_temp)
+void _bli_array_permute(
+ void *arr, const uint arr_len, const size_t arr_stride, const uint *order, void *arr_temp)
{
const size_t len = arr_len * arr_stride;
- const unsigned int arr_stride_uint = (unsigned int)arr_stride;
+ const uint arr_stride_uint = (uint)arr_stride;
void *arr_orig;
- unsigned int i;
+ uint i;
if (arr_temp == NULL) {
arr_orig = MEM_mallocN(len, __func__);
@@ -121,16 +118,45 @@ void _bli_array_permute(void *arr,
}
/**
+ * In-place array de-duplication of an ordered array.
+ *
+ * \return The new length of the array.
+ *
+ * Access via #BLI_array_deduplicate_ordered
+ */
+uint _bli_array_deduplicate_ordered(void *arr, uint arr_len, size_t arr_stride)
+{
+ if (UNLIKELY(arr_len <= 1)) {
+ return arr_len;
+ }
+
+ const uint arr_stride_uint = (uint)arr_stride;
+ uint j = 0;
+ for (uint i = 0; i < arr_len; i++) {
+ if ((i == j) || (memcmp(POINTER_OFFSET(arr, arr_stride_uint * i),
+ POINTER_OFFSET(arr, arr_stride_uint * j),
+ arr_stride) == 0)) {
+ continue;
+ }
+ j += 1;
+ memcpy(POINTER_OFFSET(arr, arr_stride_uint * j),
+ POINTER_OFFSET(arr, arr_stride_uint * i),
+ arr_stride);
+ }
+ return j + 1;
+}
+
+/**
* Find the first index of an item in an array.
*
* Access via #BLI_array_findindex
*
* \note Not efficient, use for error checks/asserts.
*/
-int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
+int _bli_array_findindex(const void *arr, uint arr_len, size_t arr_stride, const void *p)
{
const char *arr_step = (const char *)arr;
- for (unsigned int i = 0; i < arr_len; i++, arr_step += arr_stride) {
+ for (uint i = 0; i < arr_len; i++, arr_step += arr_stride) {
if (memcmp(arr_step, p, arr_stride) == 0) {
return (int)i;
}
@@ -141,10 +167,10 @@ int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_strid
/**
* A version of #BLI_array_findindex that searches from the end of the list.
*/
-int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
+int _bli_array_rfindindex(const void *arr, uint arr_len, size_t arr_stride, const void *p)
{
const char *arr_step = (const char *)arr + (arr_stride * arr_len);
- for (unsigned int i = arr_len; i-- != 0;) {
+ for (uint i = arr_len; i-- != 0;) {
arr_step -= arr_stride;
if (memcmp(arr_step, p, arr_stride) == 0) {
return (int)i;
@@ -154,7 +180,7 @@ int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stri
}
void _bli_array_binary_and(
- void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride)
+ void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride)
{
char *dst = arr;
const char *src_a = arr_a;
@@ -167,7 +193,7 @@ void _bli_array_binary_and(
}
void _bli_array_binary_or(
- void *arr, const void *arr_a, const void *arr_b, unsigned int arr_len, size_t arr_stride)
+ void *arr, const void *arr_a, const void *arr_b, uint arr_len, size_t arr_stride)
{
char *dst = arr;
const char *src_a = arr_a;
@@ -196,14 +222,14 @@ void _bli_array_binary_or(
* where calculating the length isn't a simple subtraction.
*/
bool _bli_array_iter_span(const void *arr,
- unsigned int arr_len,
+ uint arr_len,
size_t arr_stride,
bool use_wrap,
bool use_delimit_bounds,
bool (*test_fn)(const void *arr_item, void *user_data),
void *user_data,
- unsigned int span_step[2],
- unsigned int *r_span_len)
+ uint span_step[2],
+ uint *r_span_len)
{
if (arr_len == 0) {
return false;
@@ -212,11 +238,11 @@ bool _bli_array_iter_span(const void *arr,
return false;
}
- const unsigned int arr_stride_uint = (unsigned int)arr_stride;
+ const uint arr_stride_uint = (uint)arr_stride;
const void *item_prev;
bool test_prev;
- unsigned int i_curr;
+ uint i_curr;
if ((span_step[0] == arr_len) && (span_step[1] == arr_len)) {
if (use_wrap) {
@@ -249,11 +275,11 @@ bool _bli_array_iter_span(const void *arr,
while (i_curr < arr_len) {
bool test_curr = test_fn(item_curr, user_data);
if ((test_prev == false) && (test_curr == true)) {
- unsigned int span_len;
- unsigned int i_step_prev = i_curr;
+ uint span_len;
+ uint i_step_prev = i_curr;
if (use_wrap) {
- unsigned int i_step = i_curr + 1;
+ uint i_step = i_curr + 1;
if (UNLIKELY(i_step == arr_len)) {
i_step = 0;
}
@@ -273,7 +299,7 @@ bool _bli_array_iter_span(const void *arr,
}
}
else {
- unsigned int i_step = i_curr + 1;
+ uint i_step = i_curr + 1;
while ((i_step != arr_len) &&
test_fn(POINTER_OFFSET(arr, i_step * arr_stride_uint), user_data)) {
i_step_prev = i_step;
@@ -307,7 +333,7 @@ bool _bli_array_iter_span(const void *arr,
/**
* Simple utility to check memory is zeroed.
*/
-bool _bli_array_is_zeroed(const void *arr_v, unsigned int arr_len, size_t arr_stride)
+bool _bli_array_is_zeroed(const void *arr_v, uint arr_len, size_t arr_stride)
{
const char *arr_step = (const char *)arr_v;
size_t i = arr_stride * arr_len;
diff --git a/source/blender/blenlib/intern/bitmap_draw_2d.c b/source/blender/blenlib/intern/bitmap_draw_2d.c
index 9d3b66d72d7..b0afe1349ad 100644
--- a/source/blender/blenlib/intern/bitmap_draw_2d.c
+++ b/source/blender/blenlib/intern/bitmap_draw_2d.c
@@ -496,7 +496,7 @@ void BLI_bitmap_draw_2d_poly_v2i_n(const int xmin,
/* Scan for new x-nodes */
while ((span_y_index < span_y_len) && (verts[span_y[span_y_index][0]][1] == pixel_y)) {
- /* note, node_x these are just added at the end,
+ /* NOTE: node_x these are just added at the end,
* not ideal but sorting once will resolve. */
/* x is initialized for the next pixel_y */
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index eb3e64c49e6..24a58103a10 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -896,7 +896,9 @@ template<typename T> inline bool is_original_vert(const CDTVert<T> *v, CDT_state
return (v->index < cdt->input_vert_tot);
}
-/* Return the Symedge that goes from v1 to v2, if it exists, else return nullptr. */
+/**
+ * Return the #SymEdge that goes from v1 to v2, if it exists, else return nullptr.
+ */
template<typename T>
SymEdge<T> *find_symedge_between_verts(const CDTVert<T> *v1, const CDTVert<T> *v2)
{
@@ -2106,7 +2108,7 @@ template<typename T> void add_edge_constraints(CDT_state<T> *cdt_state, const CD
* for the boundary of the input face.
* fedge_start..fedge_end is the inclusive range of edge input ids that are for the given face.
*
- * Note: if the input face is not CCW oriented, we'll be labeling the outside, not the inside.
+ * NOTE: if the input face is not CCW oriented, we'll be labeling the outside, not the inside.
* Note 2: if the boundary has self-crossings, this method will arbitrarily pick one of the
* contiguous set of faces enclosed by parts of the boundary, leaving the other such un-tagged.
* This may be a feature instead of a bug if the first contiguous section is most of the face and
diff --git a/source/blender/blenlib/intern/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c
index a5d4130cb20..4d1ba190c14 100644
--- a/source/blender/blenlib/intern/expr_pylike_eval.c
+++ b/source/blender/blenlib/intern/expr_pylike_eval.c
@@ -569,7 +569,7 @@ static int opcode_arg_count(eOpCode code)
case OPCODE_FUNC3:
return 3;
default:
- BLI_assert(!"unexpected opcode");
+ BLI_assert_msg(0, "unexpected opcode");
return -1;
}
}
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index 107c27da6a2..1a00142ddb1 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -64,7 +64,7 @@
#if 0 /* UNUSED */
/* gzip the file in from and write it to "to".
* return -1 if zlib fails, -2 if the originating file does not exist
- * note: will remove the "from" file
+ * NOTE: will remove the "from" file
*/
int BLI_file_gzip(const char *from, const char *to)
{
@@ -355,7 +355,7 @@ void *BLI_gzopen(const char *filename, const char *mode)
BLI_assert(!BLI_path_is_rel(filename));
- /* xxx Creates file before transcribing the path */
+ /* XXX: Creates file before transcribing the path. */
if (mode[0] == 'w') {
FILE *file = ufopen(filename, "a");
if (file == NULL) {
diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h
index 2aec3ce082a..0c9de0aa128 100644
--- a/source/blender/blenlib/intern/kdtree_impl.h
+++ b/source/blender/blenlib/intern/kdtree_impl.h
@@ -132,7 +132,7 @@ void BLI_kdtree_nd_(insert)(KDTree *tree, int index, const float co[KD_DIMS])
BLI_assert(tree->nodes_len <= tree->nodes_len_capacity);
#endif
- /* note, array isn't calloc'd,
+ /* NOTE: array isn't calloc'd,
* need to initialize all struct members */
node->left = node->right = KD_NODE_UNSET;
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 263c508c07c..da97e697f2f 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -153,7 +153,7 @@ void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr,
cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f;
break;
default:
- BLI_assert(!"invalid colorspace");
+ BLI_assert_msg(0, "invalid colorspace");
break;
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 3175bf116a0..80f0008c7eb 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -1756,8 +1756,8 @@ bool isect_ray_tri_v3(const float ray_origin[3],
float *r_lambda,
float r_uv[2])
{
- /* note: these values were 0.000001 in 2.4x but for projection snapping on
- * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
+ /* NOTE(campbell): these values were 0.000001 in 2.4x but for projection snapping on
+ * a human head (1BU == 1m), subsurf level 2, this gave many errors. */
const float epsilon = 0.00000001f;
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
@@ -3287,8 +3287,8 @@ bool isect_ray_aabb_v3(const struct IsectRayAABB_Precalc *data,
tmin = tzmin;
}
- /* Note: tmax does not need to be updated since we don't use it
- * keeping this here for future reference - jwilkins */
+ /* NOTE(jwilkins): tmax does not need to be updated since we don't use it
+ * keeping this here for future reference. */
// if (tzmax < tmax) tmax = tzmax;
if (tmin_out) {
@@ -3559,7 +3559,7 @@ static bool point_in_slice(const float p[3],
sub_v3_v3v3(rp, p, v1);
h = dot_v3v3(q, rp) / dot_v3v3(q, q);
- /* note: when 'h' is nan/-nan, this check returns false
+ /* NOTE: when 'h' is nan/-nan, this check returns false
* without explicit check - covering the degenerate case */
return (h >= 0.0f && h <= 1.0f);
}
@@ -4020,7 +4020,7 @@ void barycentric_weights_v2_persp(
/**
* same as #barycentric_weights_v2 but works with a quad,
- * note: untested for values outside the quad's bounds
+ * NOTE: untested for values outside the quad's bounds
* this is #interp_weights_poly_v2 expanded for quads only
*/
void barycentric_weights_v2_quad(const float v1[2],
@@ -4030,10 +4030,11 @@ void barycentric_weights_v2_quad(const float v1[2],
const float co[2],
float w[4])
{
- /* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2).
- * but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results
- * without adding absf(). If this becomes an issue for more general usage we could have
- * this optional or use a different function - Campbell */
+ /* NOTE(campbell): fabsf() here is not needed for convex quads
+ * (and not used in #interp_weights_poly_v2).
+ * But in the case of concave/bow-tie quads for the mask rasterizer it
+ * gives unreliable results without adding absf(). If this becomes an issue for more general
+ * usage we could have this optional or use a different function. */
#define MEAN_VALUE_HALF_TAN_V2(_area, i1, i2) \
((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \
fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : \
@@ -4820,7 +4821,7 @@ void orthographic_m4(float matrix[4][4],
matrix[3][0] = -(right + left) / Xdelta;
matrix[1][1] = 2.0f / Ydelta;
matrix[3][1] = -(top + bottom) / Ydelta;
- matrix[2][2] = -2.0f / Zdelta; /* note: negate Z */
+ matrix[2][2] = -2.0f / Zdelta; /* NOTE: negate Z. */
matrix[3][2] = -(farClip + nearClip) / Zdelta;
}
@@ -4844,7 +4845,7 @@ void perspective_m4(float mat[4][4],
}
mat[0][0] = nearClip * 2.0f / Xdelta;
mat[1][1] = nearClip * 2.0f / Ydelta;
- mat[2][0] = (right + left) / Xdelta; /* note: negate Z */
+ mat[2][0] = (right + left) / Xdelta; /* NOTE: negate Z. */
mat[2][1] = (top + bottom) / Ydelta;
mat[2][2] = -(farClip + nearClip) / Zdelta;
mat[2][3] = -1.0f;
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
index 163a3ab5fe3..04fae6a0e68 100644
--- a/source/blender/blenlib/intern/math_interp.c
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -655,7 +655,7 @@ void BLI_ewa_filter(const int width,
v2 = (int)(ceilf(V0 + ve));
/* sane clamping to avoid unnecessarily huge loops */
- /* note: if eccentricity gets clamped (see above),
+ /* NOTE: if eccentricity gets clamped (see above),
* the ue/ve limits can also be lowered accordingly
*/
if (U0 - (float)u1 > EWA_MAXIDX) {
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 5eb0125062d..5920788821c 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1290,6 +1290,9 @@ bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
* Combines transformations, handling scale separately in a manner equivalent
* to the Aligned Inherit Scale mode, in order to avoid creating shear.
* If A scale is uniform, the result is equivalent to ordinary multiplication.
+ *
+ * NOTE: this effectively takes output location from simple multiplication,
+ * and uses mul_m4_m4m4_split_channels for rotation and scale.
*/
void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4])
{
@@ -1307,6 +1310,25 @@ void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B
loc_rot_size_to_mat4(R, loc_r, rot_r, size_r);
}
+/**
+ * Separately combines location, rotation and scale of the input matrices.
+ */
+void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4])
+{
+ float loc_a[3], rot_a[3][3], size_a[3];
+ float loc_b[3], rot_b[3][3], size_b[3];
+ float loc_r[3], rot_r[3][3], size_r[3];
+
+ mat4_to_loc_rot_size(loc_a, rot_a, size_a, A);
+ mat4_to_loc_rot_size(loc_b, rot_b, size_b, B);
+
+ add_v3_v3v3(loc_r, loc_a, loc_b);
+ mul_m3_m3m3_uniq(rot_r, rot_a, rot_b);
+ mul_v3_v3v3(size_r, size_a, size_b);
+
+ loc_rot_size_to_mat4(R, loc_r, rot_r, size_r);
+}
+
/****************************** Linear Algebra *******************************/
void transpose_m3(float R[3][3])
@@ -2252,8 +2274,8 @@ void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4])
copy_m3_m4(mat3, wmat);
normalize_m3_m3(mat3_n, mat3);
- /* so scale doesn't interfere with rotation T24291. */
- /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */
+ /* So scale doesn't interfere with rotation T24291. */
+ /* FIXME: this is a workaround for negative matrix not working for rotation conversion. */
if (is_negative_m3(mat3)) {
negate_m3(mat3_n);
}
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 52737de227b..34baac6f2a4 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -167,7 +167,7 @@ void invert_qt_qt_normalized(float q1[4], const float q2[4])
invert_qt_normalized(q1);
}
-/* simple mult */
+/* Simple multiply. */
void mul_qt_fl(float q[4], const float f)
{
q[0] *= f;
@@ -373,7 +373,7 @@ void mat3_normalized_to_quat(float q[4], const float mat[3][3])
q[2] = (mat[2][1] + mat[1][2]) * s;
}
- /* Make sure w is nonnegative for a canonical result. */
+ /* Make sure W is non-negative for a canonical result. */
if (q[0] < 0) {
negate_v4(q);
}
@@ -511,7 +511,7 @@ void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float
}
}
-/* note: expects vectors to be normalized */
+/* NOTE: expects vectors to be normalized. */
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
{
float axis[3];
diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index 9f7824a0029..8b8850c7cdb 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -21,6 +21,7 @@
#ifdef WITH_GMP
# include <algorithm>
+# include <atomic>
# include <fstream>
# include <iostream>
@@ -50,6 +51,7 @@
# include "BLI_mesh_boolean.hh"
# ifdef WITH_TBB
+# include "tbb/parallel_reduce.h"
# include "tbb/spin_mutex.h"
# endif
@@ -201,9 +203,14 @@ TriMeshTopology::TriMeshTopology(const IMesh &tm)
BLI_assert(edges != nullptr);
}
edges->append_non_duplicates(e);
- auto createf = [t](Vector<int> **pvec) { *pvec = new Vector<int>{t}; };
- auto modifyf = [t](Vector<int> **pvec) { (*pvec)->append_non_duplicates(t); };
- this->edge_tri_.add_or_modify(Edge(v, vnext), createf, modifyf);
+
+ auto p = edge_tri_.lookup_ptr(Edge(v, vnext));
+ if (p == nullptr) {
+ edge_tri_.add_new(e, new Vector<int>{t});
+ }
+ else {
+ (*p)->append_non_duplicates(t);
+ }
}
}
/* Debugging. */
@@ -228,9 +235,18 @@ TriMeshTopology::TriMeshTopology(const IMesh &tm)
TriMeshTopology::~TriMeshTopology()
{
- for (const Vector<int> *vec : edge_tri_.values()) {
- delete vec;
+ Vector<Vector<int> *> values;
+
+ /* Deconstructing is faster in parallel, so it is worth building an array of things to delete. */
+ for (auto item : edge_tri_.values()) {
+ values.append(item);
}
+
+ threading::parallel_for(values.index_range(), 256, [&](IndexRange range) {
+ for (int i : range) {
+ delete values[i];
+ }
+ });
}
/** A Patch is a maximal set of triangles that share manifold edges only. */
@@ -719,6 +735,18 @@ static PatchesInfo find_patches(const IMesh &tm, const TriMeshTopology &tmtopo)
PatchesInfo pinfo(ntri);
/* Algorithm: Grow patches across manifold edges as long as there are unassigned triangles. */
Stack<int> cur_patch_grow;
+
+ /* Create an Array containing indices of adjacent faces. */
+ Array<std::array<int, 3>> t_others(tm.face_size());
+ threading::parallel_for(tm.face_index_range(), 2048, [&](IndexRange range) {
+ for (int t : range) {
+ const Face &tri = *tm.face(t);
+ for (int i = 0; i < 3; ++i) {
+ Edge e(tri[i], tri[(i + 1) % 3]);
+ t_others[t][i] = tmtopo.other_tri_if_manifold(e, t);
+ }
+ }
+ });
for (int t : tm.face_index_range()) {
if (pinfo.tri_patch(t) == -1) {
cur_patch_grow.push(t);
@@ -739,7 +767,7 @@ static PatchesInfo find_patches(const IMesh &tm, const TriMeshTopology &tmtopo)
const Face &tri = *tm.face(tcand);
for (int i = 0; i < 3; ++i) {
Edge e(tri[i], tri[(i + 1) % 3]);
- int t_other = tmtopo.other_tri_if_manifold(e, tcand);
+ int t_other = t_others[tcand][i];
if (dbg_level > 1) {
std::cout << " edge " << e << " generates t_other=" << t_other << "\n";
}
@@ -953,12 +981,8 @@ static void sort_by_signed_triangle_index(Vector<int> &g,
* To accommodate this:
* If extra_tri is non-null, then an index of EXTRA_TRI_INDEX should use it for the triangle.
*/
-static Array<int> sort_tris_around_edge(const IMesh &tm,
- const TriMeshTopology &tmtopo,
- const Edge e,
- const Span<int> tris,
- const int t0,
- const Face *extra_tri)
+static Array<int> sort_tris_around_edge(
+ const IMesh &tm, const Edge e, const Span<int> tris, const int t0, const Face *extra_tri)
{
/* Divide and conquer, quick-sort-like sort.
* Pick a triangle t0, then partition into groups:
@@ -1023,14 +1047,14 @@ static Array<int> sort_tris_around_edge(const IMesh &tm,
}
}
if (g3.size() > 1) {
- Array<int> g3sorted = sort_tris_around_edge(tm, tmtopo, e, g3, t0, extra_tri);
+ Array<int> g3sorted = sort_tris_around_edge(tm, e, g3, t0, extra_tri);
std::copy(g3sorted.begin(), g3sorted.end(), g3.begin());
if (dbg_level > 1) {
std::cout << "g3 sorted: " << g3 << "\n";
}
}
if (g4.size() > 1) {
- Array<int> g4sorted = sort_tris_around_edge(tm, tmtopo, e, g4, t0, extra_tri);
+ Array<int> g4sorted = sort_tris_around_edge(tm, e, g4, t0, extra_tri);
std::copy(g4sorted.begin(), g4sorted.end(), g4.begin());
if (dbg_level > 1) {
std::cout << "g4 sorted: " << g4 << "\n";
@@ -1076,7 +1100,7 @@ static void find_cells_from_edge(const IMesh &tm,
const Vector<int> *edge_tris = tmtopo.edge_tris(e);
BLI_assert(edge_tris != nullptr);
Array<int> sorted_tris = sort_tris_around_edge(
- tm, tmtopo, e, Span<int>(*edge_tris), (*edge_tris)[0], nullptr);
+ tm, e, Span<int>(*edge_tris), (*edge_tris)[0], nullptr);
int n_edge_tris = edge_tris->size();
Array<int> edge_patches(n_edge_tris);
@@ -1338,34 +1362,46 @@ static bool patch_cell_graph_ok(const CellsInfo &cinfo, const PatchesInfo &pinfo
static bool is_pwn(const IMesh &tm, const TriMeshTopology &tmtopo)
{
constexpr int dbg_level = 0;
+ std::atomic<bool> is_pwn = true;
+ Vector<std::pair<Edge, Vector<int> *>> tris;
+
for (auto item : tmtopo.edge_tri_map_items()) {
- const Edge &edge = item.key;
- int tot_orient = 0;
- /* For each face t attached to edge, add +1 if the edge
- * is positively in t, and -1 if negatively in t. */
- for (int t : *item.value) {
- const Face &face = *tm.face(t);
- BLI_assert(face.size() == 3);
- for (int i : face.index_range()) {
- if (face[i] == edge.v0()) {
- if (face[(i + 1) % 3] == edge.v1()) {
- ++tot_orient;
- }
- else {
- BLI_assert(face[(i + 3 - 1) % 3] == edge.v1());
- --tot_orient;
+ tris.append(std::pair<Edge, Vector<int> *>(item.key, item.value));
+ }
+
+ threading::parallel_for(tris.index_range(), 2048, [&](IndexRange range) {
+ for (int j : range) {
+ const Edge &edge = tris[j].first;
+ int tot_orient = 0;
+ /* For each face t attached to edge, add +1 if the edge
+ * is positively in t, and -1 if negatively in t. */
+ for (int t : *tris[j].second) {
+ const Face &face = *tm.face(t);
+ BLI_assert(face.size() == 3);
+ for (int i : face.index_range()) {
+ if (face[i] == edge.v0()) {
+ if (face[(i + 1) % 3] == edge.v1()) {
+ ++tot_orient;
+ }
+ else {
+ BLI_assert(face[(i + 3 - 1) % 3] == edge.v1());
+ --tot_orient;
+ }
}
}
}
- }
- if (tot_orient != 0) {
- if (dbg_level > 0) {
- std::cout << "edge causing non-pwn: " << edge << "\n";
+ if (tot_orient != 0) {
+ if (dbg_level > 0) {
+ std::cout << "edge causing non-pwn: " << edge << "\n";
+ }
+ is_pwn = false;
+# ifdef WITH_TBB
+ tbb::task::self().cancel_group_execution();
+# endif
}
- return false;
}
- }
- return true;
+ });
+ return is_pwn.load();
}
/**
@@ -1396,8 +1432,7 @@ static int find_cell_for_point_near_edge(mpq3 p,
Array<int> edge_tris(etris->size() + 1);
std::copy(etris->begin(), etris->end(), edge_tris.begin());
edge_tris[edge_tris.size() - 1] = EXTRA_TRI_INDEX;
- Array<int> sorted_tris = sort_tris_around_edge(
- tm, tmtopo, e, edge_tris, edge_tris[0], dummy_tri);
+ Array<int> sorted_tris = sort_tris_around_edge(tm, e, edge_tris, edge_tris[0], dummy_tri);
if (dbg_level > 0) {
std::cout << "sorted tris = " << sorted_tris << "\n";
}
@@ -1452,39 +1487,66 @@ static int find_ambient_cell(const IMesh &tm,
/* First find a vertex with the maximum x value. */
/* Prefer not to populate the verts in the #IMesh just for this. */
const Vert *v_extreme;
- mpq_class extreme_x;
+ auto max_x_vert = [](const Vert *a, const Vert *b) {
+ return (a->co_exact.x > b->co_exact.x) ? a : b;
+ };
if (component_patches == nullptr) {
- v_extreme = (*tm.face(0))[0];
- extreme_x = v_extreme->co_exact.x;
- for (const Face *f : tm.faces()) {
- for (const Vert *v : *f) {
- const mpq_class &x = v->co_exact.x;
- if (x > extreme_x) {
- v_extreme = v;
- extreme_x = x;
- }
- }
- }
+ v_extreme = threading::parallel_reduce(
+ tm.face_index_range(),
+ 2048,
+ (*tm.face(0))[0],
+ [&](IndexRange range, const Vert *init) {
+ const Vert *ans = init;
+ for (int i : range) {
+ const Face *f = tm.face(i);
+ for (const Vert *v : *f) {
+ if (v->co_exact.x > ans->co_exact.x) {
+ ans = v;
+ }
+ }
+ }
+ return ans;
+ },
+ max_x_vert);
}
else {
if (dbg_level > 0) {
std::cout << "restrict to patches " << *component_patches << "\n";
}
int p0 = (*component_patches)[0];
- v_extreme = (*tm.face(pinfo.patch(p0).tri(0)))[0];
- extreme_x = v_extreme->co_exact.x;
- for (int p : *component_patches) {
- for (int t : pinfo.patch(p).tris()) {
- const Face *f = tm.face(t);
- for (const Vert *v : *f) {
- const mpq_class &x = v->co_exact.x;
- if (x > extreme_x) {
- v_extreme = v;
- extreme_x = x;
+ v_extreme = threading::parallel_reduce(
+ component_patches->index_range(),
+ 2048,
+ (*tm.face(pinfo.patch(p0).tri(0)))[0],
+ [&](IndexRange range, const Vert *init) {
+ const Vert *ans = init;
+ for (int pi : range) {
+ int p = (*component_patches)[pi];
+ const Vert *tris_ans = threading::parallel_reduce(
+ IndexRange(pinfo.patch(p).tot_tri()),
+ 2048,
+ init,
+ [&](IndexRange tris_range, const Vert *t_init) {
+ const Vert *v_ans = t_init;
+ for (int i : tris_range) {
+ int t = pinfo.patch(p).tri(i);
+ const Face *f = tm.face(t);
+ for (const Vert *v : *f) {
+ if (v->co_exact.x > v_ans->co_exact.x) {
+ v_ans = v;
+ }
+ }
+ }
+ return v_ans;
+ },
+ max_x_vert);
+ if (tris_ans->co_exact.x > ans->co_exact.x) {
+ ans = tris_ans;
+ }
}
- }
- }
- }
+ return ans;
+ },
+ max_x_vert);
}
if (dbg_level > 0) {
std::cout << "v_extreme = " << v_extreme << "\n";
@@ -1493,7 +1555,8 @@ static int find_ambient_cell(const IMesh &tm,
* when projected onto the XY plane. That edge is guaranteed to
* be on the convex hull of the mesh. */
const Vector<Edge> &edges = tmtopo.vert_edges(v_extreme);
- const mpq_class extreme_y = v_extreme->co_exact.y;
+ const mpq_class &extreme_x = v_extreme->co_exact.x;
+ const mpq_class &extreme_y = v_extreme->co_exact.y;
Edge ehull;
mpq_class max_abs_slope = -1;
for (Edge e : edges) {
@@ -1514,8 +1577,8 @@ static int find_ambient_cell(const IMesh &tm,
if (dbg_level > 0) {
std::cout << "ehull = " << ehull << " slope = " << max_abs_slope << "\n";
}
- /* Sort triangles around ehull, including a dummy triangle that include a known point in ambient
- * cell. */
+ /* Sort triangles around ehull, including a dummy triangle that include a known point in
+ * ambient cell. */
mpq3 p_in_ambient = v_extreme->co_exact;
p_in_ambient.x += 1;
int c_ambient = find_cell_for_point_near_edge(p_in_ambient, ehull, tm, tmtopo, pinfo, arena);
@@ -2816,7 +2879,8 @@ static IMesh raycast_patches_boolean(const IMesh &tm,
}
/**
* If \a tri1 and \a tri2 have a common edge (in opposite orientation),
- * return the indices into \a tri1 and \a tri2 where that common edge starts. Else return (-1,-1).
+ * return the indices into \a tri1 and \a tri2 where that common edge starts. Else return
+ * (-1,-1).
*/
static std::pair<int, int> find_tris_common_edge(const Face &tri1, const Face &tri2)
{
@@ -3378,8 +3442,8 @@ static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena
* will have an original edge that is NO_INDEX.
* Not all triangulation edges can be removed: if they ended up non-trivially overlapping a real
* input edge, then we need to keep it. Also, some are necessary to make the output satisfy
- * the "valid #BMesh" property: we can't produce output faces that have repeated vertices in them,
- * or have several disconnected boundaries (e.g., faces with holes).
+ * the "valid #BMesh" property: we can't produce output faces that have repeated vertices in
+ * them, or have several disconnected boundaries (e.g., faces with holes).
*/
static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
const IMesh &imesh_in,
diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc
index 988988179fd..f91dd762e70 100644
--- a/source/blender/blenlib/intern/mesh_intersect.cc
+++ b/source/blender/blenlib/intern/mesh_intersect.cc
@@ -43,6 +43,7 @@
# include "BLI_set.hh"
# include "BLI_span.hh"
# include "BLI_task.h"
+# include "BLI_task.hh"
# include "BLI_threads.h"
# include "BLI_vector.hh"
# include "BLI_vector_set.hh"
@@ -51,6 +52,10 @@
# include "BLI_mesh_intersect.hh"
+# ifdef WITH_TBB
+# include "tbb/parallel_sort.h"
+# endif
+
// # define PERFDEBUG
namespace blender::meshintersect {
@@ -406,6 +411,11 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable {
return add_or_find_vert(mco, co, orig);
}
+ const Vert *add_or_find_vert(Vert *vert)
+ {
+ return add_or_find_vert_(vert);
+ }
+
Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs, Span<bool> is_intersect)
{
Face *f = new Face(verts, next_face_id_++, orig, edge_origs, is_intersect);
@@ -486,10 +496,9 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable {
private:
const Vert *add_or_find_vert(const mpq3 &mco, const double3 &dco, int orig)
{
- /* Don't allocate Vert yet, in case it is already there. */
- Vert vtry(mco, dco, NO_INDEX, NO_INDEX);
+ Vert *vtry = new Vert(mco, dco, NO_INDEX, NO_INDEX);
const Vert *ans;
- VSetKey vskey(&vtry);
+ VSetKey vskey(vtry);
if (intersect_use_threading) {
# ifdef USE_SPINLOCK
BLI_spin_lock(&lock_);
@@ -499,7 +508,9 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable {
}
const VSetKey *lookup = vset_.lookup_key_ptr(vskey);
if (!lookup) {
- vskey.vert = new Vert(mco, dco, next_vert_id_++, orig);
+ vtry->id = next_vert_id_++;
+ vtry->orig = orig;
+ vskey.vert = vtry; // new Vert(mco, dco, next_vert_id_++, orig);
vset_.add_new(vskey);
allocated_verts_.append(std::unique_ptr<Vert>(vskey.vert));
ans = vskey.vert;
@@ -510,6 +521,45 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable {
* This is the intended semantics: if the Vert already
* exists then we are merging verts and using the first-seen
* one as the canonical one. */
+ delete vtry;
+ ans = lookup->vert;
+ }
+ if (intersect_use_threading) {
+# ifdef USE_SPINLOCK
+ BLI_spin_unlock(&lock_);
+# else
+ BLI_mutex_unlock(mutex_);
+# endif
+ }
+ return ans;
+ };
+
+ const Vert *add_or_find_vert_(Vert *vtry)
+ {
+ const Vert *ans;
+ VSetKey vskey(vtry);
+ if (intersect_use_threading) {
+# ifdef USE_SPINLOCK
+ BLI_spin_lock(&lock_);
+# else
+ BLI_mutex_lock(mutex_);
+# endif
+ }
+ const VSetKey *lookup = vset_.lookup_key_ptr(vskey);
+ if (!lookup) {
+ vtry->id = next_vert_id_++;
+ vskey.vert = vtry; // new Vert(mco, dco, next_vert_id_++, orig);
+ vset_.add_new(vskey);
+ allocated_verts_.append(std::unique_ptr<Vert>(vskey.vert));
+ ans = vskey.vert;
+ }
+ else {
+ /* It was a duplicate, so return the existing one.
+ * Note that the returned Vert may have a different orig.
+ * This is the intended semantics: if the Vert already
+ * exists then we are merging verts and using the first-seen
+ * one as the canonical one. */
+ delete vtry;
ans = lookup->vert;
}
if (intersect_use_threading) {
@@ -550,6 +600,11 @@ const Vert *IMeshArena::add_or_find_vert(const mpq3 &co, int orig)
return pimpl_->add_or_find_vert(co, orig);
}
+const Vert *IMeshArena::add_or_find_vert(Vert *vert)
+{
+ return pimpl_->add_or_find_vert(vert);
+}
+
Face *IMeshArena::add_face(Span<const Vert *> verts,
int orig,
Span<int> edge_origs,
@@ -633,7 +688,11 @@ void IMesh::populate_vert(int max_verts)
* TODO: when all debugged, set fix_order = false. */
const bool fix_order = true;
if (fix_order) {
+# ifdef WITH_TBB
+ tbb::parallel_sort(vert_.begin(), vert_.end(), [](const Vert *a, const Vert *b) {
+# else
std::sort(vert_.begin(), vert_.end(), [](const Vert *a, const Vert *b) {
+# endif
if (a->orig != NO_INDEX && b->orig != NO_INDEX) {
return a->orig < b->orig;
}
@@ -1037,7 +1096,7 @@ static mpq2 project_3d_to_2d(const mpq3 &p3d, int proj_axis)
* So the sign of E is the same as the sign of E_exact if
* |E| > supremum(E) * index(E) * DBL_EPSILON
*
- * Note: a possible speedup would be to have a simple function
+ * NOTE: a possible speedup would be to have a simple function
* that calculates the error bound if one knows that all values
* are less than some global maximum - most of the function would
* be calculated ahead of time. The global max could be passed
@@ -1918,9 +1977,22 @@ static Face *cdt_tri_as_imesh_face(
return facep;
}
+/* Like BLI_math's is_quad_flip_v3_first_third_fast_with_normal, with const double3's. */
+static bool is_quad_flip_first_third(const double3 &v1,
+ const double3 &v2,
+ const double3 &v3,
+ const double3 &v4,
+ const double3 &normal)
+{
+ double3 dir_v3v1 = v3 - v1;
+ double3 tangent = double3::cross_high_precision(dir_v3v1, normal);
+ double dot = double3::dot(v1, tangent);
+ return (double3::dot(v4, tangent) >= dot) || (double3::dot(v2, tangent) <= dot);
+}
+
/**
* Tessellate face f into triangles and return an array of `const Face *`
- * giving that triangulation. Intended to be used when f has > 4 vertices.
+ * giving that triangulation. Intended to be used when f has => 4 vertices.
* Care is taken so that the original edge index associated with
* each edge in the output triangles either matches the original edge
* for the (identical) edge of f, or else is -1. So diagonals added
@@ -1932,21 +2004,40 @@ static Face *cdt_tri_as_imesh_face(
*/
static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
{
- /* Similar to loop body in BM_mesh_calc_tesselation. */
+ /* Similar to loop body in #BM_mesh_calc_tessellation. */
int flen = f->size();
- BLI_assert(flen > 4);
+ BLI_assert(flen >= 4);
if (!f->plane_populated()) {
f->populate_plane(false);
}
- /* Project along negative face normal so (x,y) can be used in 2d. */
const double3 &poly_normal = f->plane->norm;
float no[3] = {float(poly_normal[0]), float(poly_normal[1]), float(poly_normal[2])};
normalize_v3(no);
- float axis_mat[3][3];
+ if (flen == 4) {
+ const Vert *v0 = (*f)[0];
+ const Vert *v1 = (*f)[1];
+ const Vert *v2 = (*f)[2];
+ const Vert *v3 = (*f)[3];
+ int eo_01 = f->edge_orig[0];
+ int eo_12 = f->edge_orig[1];
+ int eo_23 = f->edge_orig[2];
+ int eo_30 = f->edge_orig[3];
+ Face *f0, *f1;
+ if (UNLIKELY(is_quad_flip_first_third(v0->co, v1->co, v2->co, v3->co, f->plane->norm))) {
+ f0 = arena->add_face({v0, v1, v3}, f->orig, {eo_01, -1, eo_30}, {false, false, false});
+ f1 = arena->add_face({v1, v2, v3}, f->orig, {eo_12, eo_23, -1}, {false, false, false});
+ }
+ else {
+ f0 = arena->add_face({v0, v1, v2}, f->orig, {eo_01, eo_12, -1}, {false, false, false});
+ f1 = arena->add_face({v0, v2, v3}, f->orig, {-1, eo_23, eo_30}, {false, false, false});
+ }
+ return Array<Face *>{f0, f1};
+ }
+ /* Project along negative face normal so (x,y) can be used in 2d. */ float axis_mat[3][3];
float(*projverts)[2];
unsigned int(*tris)[3];
const int totfilltri = flen - 2;
- /* Prepare projected vertices and array to receive triangles in tesselation. */
+ /* Prepare projected vertices and array to receive triangles in tessellation. */
tris = static_cast<unsigned int(*)[3]>(MEM_malloc_arrayN(totfilltri, sizeof(*tris), __func__));
projverts = static_cast<float(*)[2]>(MEM_malloc_arrayN(flen, sizeof(*projverts), __func__));
axis_dominant_v3_to_m3_negate(axis_mat, no);
@@ -1956,7 +2047,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
mul_v2_m3v3(projverts[j], axis_mat, co);
}
BLI_polyfill_calc(projverts, flen, 1, tris);
- /* Put tesselation triangles into Face form. Record original edges where they exist. */
+ /* Put tessellation triangles into Face form. Record original edges where they exist. */
Array<Face *> ans(totfilltri);
for (int t = 0; t < totfilltri; ++t) {
unsigned int *tri = tris[t];
@@ -1986,11 +2077,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
/**
* Tessellate face f into triangles and return an array of `const Face *`
- * giving that triangulation.
- * Care is taken so that the original edge index associated with
- * each edge in the output triangles either matches the original edge
- * for the (identical) edge of f, or else is -1. So diagonals added
- * for triangulation can later be identified by having #NO_INDEX for original.
+ * giving that triangulation, using an exact triangulation method.
*
* The method used is to use the CDT triangulation. Usually that triangulation
* will only use the existing vertices. However, if the face self-intersects
@@ -2003,7 +2090,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
* is by far the usual case, we need to know if the quad is convex when
* projected before doing so, and that takes a fair amount of computation by itself.
*/
-static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena)
+static Array<Face *> exact_triangulate_poly(Face *f, IMeshArena *arena)
{
int flen = f->size();
CDT_input<mpq_class> cdt_in;
@@ -2086,6 +2173,68 @@ static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena)
return ans;
}
+static bool face_is_degenerate(const Face *f)
+{
+ const Face &face = *f;
+ const Vert *v0 = face[0];
+ const Vert *v1 = face[1];
+ const Vert *v2 = face[2];
+ if (v0 == v1 || v0 == v2 || v1 == v2) {
+ return true;
+ }
+ double3 da = v2->co - v0->co;
+ double3 db = v2->co - v1->co;
+ double3 dab = double3::cross_high_precision(da, db);
+ double dab_length_squared = dab.length_squared();
+ double err_bound = supremum_dot_cross(dab, dab) * index_dot_cross * DBL_EPSILON;
+ if (dab_length_squared > err_bound) {
+ return false;
+ }
+ mpq3 a = v2->co_exact - v0->co_exact;
+ mpq3 b = v2->co_exact - v1->co_exact;
+ mpq3 ab = mpq3::cross(a, b);
+ if (ab.x == 0 && ab.y == 0 && ab.z == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+/** Fast check for degenerate tris. Only tests for when verts are identical,
+ * not cases where there are zero-length edges. */
+static bool any_degenerate_tris_fast(const Array<Face *> triangulation)
+{
+ for (const Face *f : triangulation) {
+ const Vert *v0 = (*f)[0];
+ const Vert *v1 = (*f)[1];
+ const Vert *v2 = (*f)[2];
+ if (v0 == v1 || v0 == v2 || v1 == v2) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Tessellate face f into triangles and return an array of `const Face *`
+ * giving that triangulation.
+ * Care is taken so that the original edge index associated with
+ * each edge in the output triangles either matches the original edge
+ * for the (identical) edge of f, or else is -1. So diagonals added
+ * for triangulation can later be identified by having #NO_INDEX for original.
+ */
+static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena)
+{
+ /* Try the much faster method using Blender's BLI_polyfill_calc. */
+ Array<Face *> ans = polyfill_triangulate_poly(f, arena);
+
+ /* This may create degenerate triangles. If so, try the exact CDT-based triangulator. */
+ if (any_degenerate_tris_fast(ans)) {
+ return exact_triangulate_poly(f, arena);
+ }
+ return ans;
+}
+
/**
* Return an #IMesh that is a triangulation of a mesh with general
* polygonal faces, #IMesh.
@@ -2097,8 +2246,16 @@ IMesh triangulate_polymesh(IMesh &imesh, IMeshArena *arena)
Vector<Face *> face_tris;
constexpr int estimated_tris_per_face = 3;
face_tris.reserve(estimated_tris_per_face * imesh.face_size());
+ threading::parallel_for(imesh.face_index_range(), 2048, [&](IndexRange range) {
+ for (int i : range) {
+ Face *f = imesh.face(i);
+ if (!f->plane_populated() && f->size() >= 4) {
+ f->populate_plane(false);
+ }
+ }
+ });
for (Face *f : imesh.faces()) {
- /* Tessellate face f, following plan similar to #BM_face_calc_tesselation. */
+ /* Tessellate face f, following plan similar to #BM_face_calc_tessellation. */
int flen = f->size();
if (flen == 3) {
face_tris.append(f);
@@ -2188,12 +2345,22 @@ class TriOverlaps {
if (two_trees_no_self) {
tree_b_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6);
}
+
+ /* Create a Vector containing face shape. */
+ Vector<int> shapes;
+ shapes.resize(tm.face_size());
+ threading::parallel_for(tm.face_index_range(), 2048, [&](IndexRange range) {
+ for (int t : range) {
+ shapes[t] = shape_fn(tm.face(t)->orig);
+ }
+ });
+
float bbpts[6];
for (int t : tm.face_index_range()) {
const BoundingBox &bb = tri_bb[t];
copy_v3_v3(bbpts, bb.min);
copy_v3_v3(bbpts + 3, bb.max);
- int shape = shape_fn(tm.face(t)->orig);
+ int shape = shapes[t];
if (two_trees_no_self) {
if (shape == 0) {
BLI_bvhtree_insert(tree_, t, bbpts, 2);
@@ -2485,11 +2652,13 @@ static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided,
0, overlap_tri_range_tot, &data, calc_subdivided_tri_range_func, &settings);
/* Now have to put in the triangles that are the same as the input ones, and not in clusters.
*/
- for (int t : tm.face_index_range()) {
- if (r_tri_subdivided[t].face_size() == 0 && clinfo.tri_cluster(t) == NO_INDEX) {
- r_tri_subdivided[t] = IMesh({tm.face(t)});
+ threading::parallel_for(tm.face_index_range(), 2048, [&](IndexRange range) {
+ for (int t : range) {
+ if (r_tri_subdivided[t].face_size() == 0 && clinfo.tri_cluster(t) == NO_INDEX) {
+ r_tri_subdivided[t] = IMesh({tm.face(t)});
+ }
}
- }
+ });
}
/**
@@ -2725,33 +2894,6 @@ static CoplanarClusterInfo find_clusters(const IMesh &tm,
return ans;
}
-static bool face_is_degenerate(const Face *f)
-{
- const Face &face = *f;
- const Vert *v0 = face[0];
- const Vert *v1 = face[1];
- const Vert *v2 = face[2];
- if (v0 == v1 || v0 == v2 || v1 == v2) {
- return true;
- }
- double3 da = v2->co - v0->co;
- double3 db = v2->co - v1->co;
- double3 dab = double3::cross_high_precision(da, db);
- double dab_length_squared = dab.length_squared();
- double err_bound = supremum_dot_cross(dab, dab) * index_dot_cross * DBL_EPSILON;
- if (dab_length_squared > err_bound) {
- return false;
- }
- mpq3 a = v2->co_exact - v0->co_exact;
- mpq3 b = v2->co_exact - v1->co_exact;
- mpq3 ab = mpq3::cross(a, b);
- if (ab.x == 0 && ab.y == 0 && ab.z == 0) {
- return true;
- }
-
- return false;
-}
-
/* Data and functions to test triangle degeneracy in parallel. */
struct DegenData {
const IMesh &tm;
@@ -2873,11 +3015,15 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
double overlap_time = PIL_check_seconds_timer();
std::cout << "intersect overlaps calculated, time = " << overlap_time - bb_calc_time << "\n";
# endif
- for (int t : tm_clean->face_index_range()) {
- if (tri_ov.first_overlap_index(t) != -1) {
- tm_clean->face(t)->populate_plane(true);
+ Array<IMesh> tri_subdivided(tm_clean->face_size(), NoInitialization());
+ threading::parallel_for(tm_clean->face_index_range(), 1024, [&](IndexRange range) {
+ for (int t : range) {
+ if (tri_ov.first_overlap_index(t) != -1) {
+ tm_clean->face(t)->populate_plane(true);
+ }
+ new (static_cast<void *>(&tri_subdivided[t])) IMesh;
}
- }
+ });
# ifdef PERFDEBUG
double plane_populate = PIL_check_seconds_timer();
std::cout << "planes populated, time = " << plane_populate - overlap_time << "\n";
@@ -2902,7 +3048,6 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
doperfmax(1, clinfo.tot_cluster());
doperfmax(2, tri_ov.overlap().size());
# endif
- Array<IMesh> tri_subdivided(tm_clean->face_size());
calc_subdivided_non_cluster_tris(tri_subdivided, *tm_clean, itt_map, clinfo, tri_ov, arena);
# ifdef PERFDEBUG
double subdivided_tris_time = PIL_check_seconds_timer();
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index 8e28088c9fa..01aad5b078f 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -884,7 +884,7 @@ static float dist_Real(float x, float y, float z, float e)
(void)e;
return sqrtf(x * x + y * y + z * z);
}
-/* manhattan/taxicab/cityblock distance */
+/* Manhattan/Taxi-Cab/City-Block distance. */
static float dist_Manhattan(float x, float y, float z, float e)
{
(void)e;
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index f3c348b2b44..4d0dc43ed1e 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -235,13 +235,13 @@ void BLI_path_normalize(const char *relabase, char *path)
memmove(path + a, eind, strlen(eind) + 1);
}
else {
- /* support for odd paths: eg /../home/me --> /home/me
+ /* Support for odd paths: eg `/../home/me` --> `/home/me`
* this is a valid path in blender but we can't handle this the usual way below
* simply strip this prefix then evaluate the path as usual.
- * pythons os.path.normpath() does this */
+ * Python's `os.path.normpath()` does this. */
- /* Note: previous version of following call used an offset of 3 instead of 4,
- * which meant that the "/../home/me" example actually became "home/me".
+ /* NOTE: previous version of following call used an offset of 3 instead of 4,
+ * which meant that the `/../home/me` example actually became `home/me`.
* Using offset of 3 gives behavior consistent with the aforementioned
* Python routine. */
memmove(path, path + 3, strlen(path + 3) + 1);
@@ -1070,8 +1070,8 @@ bool BLI_path_abs(char *path, const char *basepath)
* paths relative to the .blend file -elubie */
BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/');
- /* Paths starting with // will get the blend file as their base,
- * this isn't standard in any os but is used in blender all over the place */
+ /* Paths starting with `//` will get the blend file as their base,
+ * this isn't standard in any OS but is used in blender all over the place. */
if (wasrelative) {
const char *lslash;
BLI_strncpy(base, basepath, sizeof(base));
@@ -1275,7 +1275,7 @@ void BLI_setenv(const char *env, const char *val)
{
/* free windows */
-#if (defined(WIN32) || defined(WIN64))
+#if (defined(_WIN32) || defined(_WIN64))
uputenv(env, val);
#else
diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c
index dadef979b09..817572ba85c 100644
--- a/source/blender/blenlib/intern/polyfill_2d.c
+++ b/source/blender/blenlib/intern/polyfill_2d.c
@@ -719,7 +719,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
* the area sign will be positive if the point is strictly inside.
* It will be 0 on the edge, which we want to include as well. */
- /* note: check (v3, v1) first since it fails _far_ more often than the other 2 checks
+ /* NOTE: check (v3, v1) first since it fails _far_ more often than the other 2 checks
* (those fail equally).
* It's logical - the chance is low that points exist on the
* same side as the ear we're clipping off. */
diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c
index 7425bab885c..7781e3a0f6f 100644
--- a/source/blender/blenlib/intern/polyfill_2d_beautify.c
+++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c
@@ -175,7 +175,7 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2],
len_13 = len_v2v2(v1, v3);
len_24 = len_v2v2(v2, v4);
- /* note, area is in fact (area * 2),
+ /* NOTE: area is in fact (area * 2),
* but in this case its OK, since we're comparing ratios */
/* edge (2-4), current state */
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 8c9a229860e..b0d00007580 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -397,7 +397,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
if (eve->edge_tot == 1) {
/* find the edge which has vertex eve,
- * note: we _know_ this will crash if 'ed1' becomes NULL
+ * NOTE: we _know_ this will crash if 'ed1' becomes NULL
* but this will never happen. */
for (ed1 = sf_ctx->filledgebase.first; !(ed1->v1 == eve || ed1->v2 == eve);
ed1 = ed1->next) {
@@ -529,7 +529,7 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl
eve->f = SF_VERT_NEW; /* Flag for connect edges later on. */
sc->vert = eve;
sc->edge_first = sc->edge_last = NULL;
- /* Note, debug print only will work for curve poly-fill, union is in use for mesh. */
+ /* NOTE: debug print only will work for curve poly-fill, union is in use for mesh. */
/* if (even->tmp.v == NULL) eve->tmp.u = verts; */
sc++;
}
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index 5961893cae3..6e5a3e961a5 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -124,7 +124,7 @@ BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t
BLI_assert(key != SMHASH_KEY_UNUSED);
- /* note: there are always more buckets than entries,
+ /* NOTE: there are always more buckets than entries,
* so we know there will always be a free bucket if the key isn't found. */
for (e = &sh->buckets[h % sh->nbuckets]; e->val != SMHASH_CELL_FREE;
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets]) {
@@ -353,8 +353,8 @@ void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr
/** \name Debugging & Introspection
* \{ */
-/* note, this was called _print_smhash in knifetool.c
- * it may not be intended for general use - campbell */
+/* NOTE(campbell): this was called _print_smhash in knifetool.c
+ * it may not be intended for general use. */
#if 0
void BLI_smallhash_print(SmallHash *sh)
{
diff --git a/source/blender/blenlib/intern/sort.c b/source/blender/blenlib/intern/sort.c
index 6a13c0aa6f0..0d52faaa8c6 100644
--- a/source/blender/blenlib/intern/sort.c
+++ b/source/blender/blenlib/intern/sort.c
@@ -31,7 +31,7 @@
# include "BLI_sort.h"
-# ifdef min /* for msvc */
+# ifdef min /* For MSVC. */
# undef min
# endif
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 3a02ddaa349..19ff8764259 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -43,7 +43,7 @@
// #define DEBUG_STRSIZE
/* array copied from glib's gutf8.c, */
-/* Note: last two values (0xfe and 0xff) are forbidden in utf-8,
+/* NOTE: last two values (0xfe and 0xff) are forbidden in utf-8,
* so they are considered 1 byte length too. */
static const size_t utf8_skip_data[256] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -265,7 +265,7 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
memset(dst, 0xff, sizeof(*dst) * maxncpy);
#endif
- /* note: currently we don't attempt to deal with invalid utf8 chars */
+ /* NOTE: currently we don't attempt to deal with invalid utf8 chars. */
BLI_STR_UTF8_CPY(dst, src, maxncpy);
return r_dst;
@@ -281,7 +281,7 @@ size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, s
memset(dst, 0xff, sizeof(*dst) * maxncpy);
#endif
- /* note: currently we don't attempt to deal with invalid utf8 chars */
+ /* NOTE: currently we don't attempt to deal with invalid utf8 chars. */
BLI_STR_UTF8_CPY(dst, src, maxncpy);
return (size_t)(dst - r_dst);
@@ -444,8 +444,8 @@ int BLI_str_utf8_char_width_safe(const char *p)
/* copied from glib's gutf8.c, added 'Err' arg */
-/* note, glib uses uint for unicode, best we do the same,
- * though we don't typedef it - campbell */
+/* NOTE(campbell): glib uses uint for unicode, best we do the same,
+ * though we don't typedef it. */
#define UTF8_COMPUTE(Char, Mask, Len, Err) \
if (Char < 128) { \
@@ -580,8 +580,10 @@ uint BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__r
return result;
}
-/* another variant that steps over the index,
- * note, currently this also falls back to latin1 for text drawing. */
+/**
+ * Another variant that steps over the index.
+ * \note currently this also falls back to latin1 for text drawing.
+ */
uint BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index)
{
int i, len;
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c
index f4110c65a6d..66d0b44cfb3 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -100,8 +100,8 @@ void BLI_system_backtrace(FILE *fp)
# undef SIZE
# else
- /* ------------------ */
- /* non msvc/osx/linux */
+ /* --------------------- */
+ /* Non MSVC/Apple/Linux. */
(void)fp;
# endif
}
@@ -184,7 +184,7 @@ size_t BLI_system_memory_max_in_megabytes(void)
/* Maximum addressable bytes on this platform.
*
* NOTE: Due to the shift arithmetic this is a half of the memory. */
- const size_t limit_bytes_half = (((size_t)1) << ((sizeof(size_t[8])) - 1));
+ const size_t limit_bytes_half = (((size_t)1) << (sizeof(size_t[8]) - 1));
/* Convert it to megabytes and return. */
return (limit_bytes_half >> 20) * 2;
}
diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c
index f67671c65e0..06087869685 100644
--- a/source/blender/blenlib/intern/task_iterator.c
+++ b/source/blender/blenlib/intern/task_iterator.c
@@ -80,7 +80,7 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin
* else 3 if num_tasks < 48;
* else 4 if num_tasks < 64;
* etc.
- * Note: If we wanted to keep the 'power of two' multiplier, we'd need something like:
+ * NOTE: If we wanted to keep the 'power of two' multiplier, we'd need something like:
* 1 << max_ii(0, (int)(sizeof(int) * 8) - 1 - bitscan_reverse_i(num_tasks) - 3)
*/
const int num_tasks_factor = max_ii(1, num_tasks >> 3);
@@ -186,6 +186,9 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin
if (use_userdata_chunk) {
userdata_chunk_local = MALLOCA(userdata_chunk_size);
memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
+ if (settings->func_init != NULL) {
+ settings->func_init(state->userdata, userdata_chunk_local);
+ }
}
/* Also marking it as non-threaded for the iterator callback. */
@@ -247,6 +250,9 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings,
if (use_userdata_chunk) {
userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
+ if (settings->func_init != NULL) {
+ settings->func_init(state->userdata, userdata_chunk_local);
+ }
}
/* Use this pool's pre-allocated tasks. */
BLI_task_pool_push(task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL);
@@ -403,11 +409,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
TaskParallelMempoolFunc func,
const TaskParallelSettings *settings)
{
- TaskPool *task_pool;
- ParallelMempoolState state;
- int i, num_threads, num_tasks;
-
- if (BLI_mempool_len(mempool) == 0) {
+ if (UNLIKELY(BLI_mempool_len(mempool) == 0)) {
return;
}
@@ -422,6 +424,9 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
if (use_userdata_chunk) {
userdata_chunk_local = MALLOCA(userdata_chunk_size);
memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
+ if (settings->func_init != NULL) {
+ settings->func_init(userdata, userdata_chunk_local);
+ }
tls.userdata_chunk = userdata_chunk_local;
}
@@ -442,14 +447,15 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
return;
}
- task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH);
- num_threads = BLI_task_scheduler_num_threads();
+ ParallelMempoolState state;
+ TaskPool *task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH);
+ const int num_threads = BLI_task_scheduler_num_threads();
/* The idea here is to prevent creating task for each of the loop iterations
* and instead have tasks which are evenly distributed across CPU cores and
* pull next item to be crunched using the threaded-aware BLI_mempool_iter.
*/
- num_tasks = num_threads + 2;
+ const int num_tasks = num_threads + 2;
state.userdata = userdata;
state.func = func;
@@ -461,10 +467,13 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
ParallelMempoolTaskData *mempool_iterator_data = mempool_iter_threadsafe_create(
mempool, (size_t)num_tasks);
- for (i = 0; i < num_tasks; i++) {
+ for (int i = 0; i < num_tasks; i++) {
if (use_userdata_chunk) {
userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
+ if (settings->func_init != NULL) {
+ settings->func_init(userdata, userdata_chunk_local);
+ }
}
mempool_iterator_data[i].tls.userdata_chunk = userdata_chunk_local;
@@ -477,7 +486,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
if (use_userdata_chunk) {
if ((settings->func_free != NULL) || (settings->func_reduce != NULL)) {
- for (i = 0; i < num_tasks; i++) {
+ for (int i = 0; i < num_tasks; i++) {
if (settings->func_reduce) {
settings->func_reduce(
userdata, userdata_chunk, mempool_iterator_data[i].tls.userdata_chunk);
diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc
index 871d04c1f35..8407be2cb2b 100644
--- a/source/blender/blenlib/intern/task_range.cc
+++ b/source/blender/blenlib/intern/task_range.cc
@@ -156,7 +156,7 @@ int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls))
if (thread_id == -1) {
thread_id = atomic_fetch_and_add_int32(&tbb_thread_id_counter, 1);
if (thread_id >= BLENDER_MAX_THREADS) {
- BLI_assert(!"Maximum number of threads exceeded for sculpting");
+ BLI_assert_msg(0, "Maximum number of threads exceeded for sculpting");
thread_id = thread_id % BLENDER_MAX_THREADS;
}
}
diff --git a/source/blender/blenlib/tests/BLI_array_utils_test.cc b/source/blender/blenlib/tests/BLI_array_utils_test.cc
index 5d12b8fbd4d..1bf221c5335 100644
--- a/source/blender/blenlib/tests/BLI_array_utils_test.cc
+++ b/source/blender/blenlib/tests/BLI_array_utils_test.cc
@@ -189,3 +189,53 @@ TEST(array_utils, BinaryOrInt4Mix)
BINARY_OR_TEST(data_cmp, data_a, data_b, data_combine, ARRAY_SIZE(data_cmp));
}
#undef BINARY_OR_TEST
+
+/* BLI_array_deduplicate_ordered */
+#define DEDUPLICATE_ORDERED_TEST(data, data_cmp) \
+ { \
+ const uint data_len_new = BLI_array_deduplicate_ordered(data, ARRAY_SIZE(data)); \
+ EXPECT_EQ(data_len_new, ARRAY_SIZE(data_cmp)); \
+ EXPECT_EQ_ARRAY(data, data_cmp, data_len_new); \
+ /* Ensure running a second time does nothing. */ \
+ const uint data_len_test = BLI_array_deduplicate_ordered(data, data_len_new); \
+ EXPECT_EQ(data_len_test, ARRAY_SIZE(data_cmp)); \
+ EXPECT_EQ_ARRAY(data, data_cmp, data_len_new); \
+ } \
+ ((void)0)
+
+TEST(array_utils, DeduplicateOrdered1)
+{
+ int data[] = {0};
+ const int data_cmp[] = {0};
+ DEDUPLICATE_ORDERED_TEST(data, data_cmp);
+}
+
+TEST(array_utils, DeduplicateOrdered2)
+{
+ int data[] = {1, 2};
+ const int data_cmp[] = {1, 2};
+ DEDUPLICATE_ORDERED_TEST(data, data_cmp);
+}
+
+TEST(array_utils, DeduplicateOrdered2Same)
+{
+ int data[] = {1, 1};
+ const int data_cmp[] = {1};
+ DEDUPLICATE_ORDERED_TEST(data, data_cmp);
+}
+
+TEST(array_utils, DeduplicateOrdered3Same)
+{
+ int data[] = {1, 1, 1};
+ const int data_cmp[] = {1};
+ DEDUPLICATE_ORDERED_TEST(data, data_cmp);
+}
+
+TEST(array_utils, DeduplicateOrdered3)
+{
+ int data[] = {3, 3, 2, 2, 1, 1};
+ const int data_cmp[] = {3, 2, 1};
+ DEDUPLICATE_ORDERED_TEST(data, data_cmp);
+}
+
+#undef DEDUPLICATE_ORDERED_TEST
diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
index 59c4be6d952..08a3818e18f 100644
--- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
+++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
@@ -353,27 +353,27 @@ void graph_draw(const std::string &label,
const vec2<T> &uco = verts[e.first];
const vec2<T> &vco = verts[e.second];
int strokew = thin_line;
- f << "<line fill=\"none\" stroke=\"black\" stroke-width=\"" << strokew << "\" x1=\""
+ f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
<< SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\""
<< SY(vco[1]) << "\">\n";
f << " <title>[" << e.first << "][" << e.second << "]</title>\n";
f << "</line>\n";
if (draw_edge_labels) {
f << "<text x=\"" << SX(0.5 * (uco[0] + vco[0])) << "\" y=\"" << SY(0.5 * (uco[1] + vco[1]))
- << "\" font-size=\"small\">";
+ << R"(" font-size="small">)";
f << "[" << e.first << "][" << e.second << "]</text>\n";
}
}
int i = 0;
for (const vec2<T> &vco : verts) {
- f << "<circle fill=\"black\" cx=\"" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\""
+ f << R"(<circle fill="black" cx=")" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\""
<< vert_radius << "\">\n";
f << " <title>[" << i << "]" << vco << "</title>\n";
f << "</circle>\n";
if (draw_vert_labels) {
f << "<text x=\"" << SX(vco[0]) + vert_radius << "\" y=\"" << SY(vco[1]) - vert_radius
- << "\" font-size=\"small\">[" << i << "]</text>\n";
+ << R"(" font-size="small">[)" << i << "]</text>\n";
}
++i;
}
diff --git a/source/blender/blenlib/tests/BLI_ghash_test.cc b/source/blender/blenlib/tests/BLI_ghash_test.cc
index a0b24e96fcc..1eb29a006db 100644
--- a/source/blender/blenlib/tests/BLI_ghash_test.cc
+++ b/source/blender/blenlib/tests/BLI_ghash_test.cc
@@ -31,7 +31,7 @@
} \
void(0)
-/* Note: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here
+/* NOTE: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here
* we just use mere random integers stored in pointers. */
static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed)
diff --git a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc
index c7bea8e15de..c6d3265881d 100644
--- a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc
+++ b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc
@@ -4,7 +4,7 @@
#include "BLI_hash_mm2a.h"
-/* Note: Reference results are taken from reference implementation
+/* NOTE: Reference results are taken from reference implementation
* (cpp code, CMurmurHash2A variant):
* https://smhasher.googlecode.com/svn-history/r130/trunk/MurmurHash2.cpp
*/
diff --git a/source/blender/blenlib/tests/BLI_math_base_test.cc b/source/blender/blenlib/tests/BLI_math_base_test.cc
index d006a2eb59a..f354dd4ce23 100644
--- a/source/blender/blenlib/tests/BLI_math_base_test.cc
+++ b/source/blender/blenlib/tests/BLI_math_base_test.cc
@@ -72,7 +72,7 @@ TEST(math_base, CompareFFRelativeZero)
EXPECT_TRUE(compare_ff_relative(f0, fn1, max_diff, 1));
EXPECT_TRUE(compare_ff_relative(fn1, f0, max_diff, 1));
- /* Note: in theory, this should return false, since 0.0f and -0.0f have 0x80000000 diff,
+ /* NOTE: in theory, this should return false, since 0.0f and -0.0f have 0x80000000 diff,
* but overflow in subtraction seems to break something here
* (abs(*(int *)&fn0 - *(int *)&f0) == 0x80000000 == fn0), probably because int32 cannot
* hold this abs value. this is yet another illustration of why one shall never use (near-)zero
diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
index 1a9ffbd3403..24fa7f1a476 100644
--- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
+++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
@@ -459,7 +459,7 @@ TEST(mesh_intersect, TwoTris)
{4, 13, 6, 2}, /* 11: non-parallel planes, not intersecting, all one side. */
{0, 14, 6, 2}, /* 12: non-paralel planes, not intersecting, alternate sides. */
/* Following are all coplanar cases. */
- {15, 16, 6, 8}, /* 13: T16 inside T15. Note: dup'd tri is expected. */
+ {15, 16, 6, 8}, /* 13: T16 inside T15. NOTE: dup'd tri is expected. */
{15, 17, 8, 8}, /* 14: T17 intersects one edge of T15 at (1,1,0)(3,3,0). */
{15, 18, 10, 12}, /* 15: T18 intersects T15 at (1,1,0)(3,3,0)(3,15/4,1/2)(0,3,2). */
{15, 19, 8, 10}, /* 16: T19 intersects T15 at (3,3,0)(0,3,2). */
diff --git a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc
index c5b0f86e384..dd1a084037b 100644
--- a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc
+++ b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc
@@ -21,7 +21,7 @@
static uint gen_pseudo_random_number(uint num)
{
- /* Note: this is taken from BLI_ghashutil_uinthash(), don't want to depend on external code that
+ /* NOTE: this is taken from BLI_ghashutil_uinthash(), don't want to depend on external code that
* might change here... */
num += ~(num << 16);
num ^= (num >> 5);
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 52ef577fceb..04e13fbd1d6 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -74,7 +74,7 @@ typedef struct BlendFileData {
int globalf;
char filename[1024]; /* 1024 = FILE_MAX */
- struct bScreen *curscreen; /* TODO think this isn't needed anymore? */
+ struct bScreen *curscreen; /* TODO: think this isn't needed anymore? */
struct Scene *curscene;
struct ViewLayer *cur_view_layer; /* layer to activate in workspaces when reading without UI */
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 61a00ccdaa4..f5baf0dcb83 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -58,8 +58,8 @@ set(SRC
intern/versioning_280.c
intern/versioning_290.c
intern/versioning_300.c
- intern/versioning_cycles.c
intern/versioning_common.cc
+ intern/versioning_cycles.c
intern/versioning_defaults.c
intern/versioning_dna.c
intern/versioning_legacy.c
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 5b668bf12eb..03fb4149d7b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2311,7 +2311,7 @@ static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id)
static void lib_link_id(BlendLibReader *reader, ID *id)
{
- /* Note: WM IDProperties are never written to file, hence they should always be NULL here. */
+ /* NOTE: WM IDProperties are never written to file, hence they should always be NULL here. */
BLI_assert((GS(id->name) != ID_WM) || id->properties == NULL);
IDP_BlendReadLib(reader, id->properties);
@@ -2728,7 +2728,7 @@ static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data)
struct IDNameLib_Map *id_map = cb_data->user_data;
- /* Note: Handling of usercount here is really bad, defining its own system...
+ /* NOTE: Handling of usercount here is really bad, defining its own system...
* Will have to be refactored at some point, but that is not top priority task for now.
* And all user-counts are properly recomputed at the end of the undo management code anyway. */
*id_pointer = restore_pointer_by_name(
@@ -3067,7 +3067,7 @@ void blo_lib_link_restore(Main *oldmain,
/* keep cursor location through undo */
memcpy(&win->scene->cursor, &oldscene->cursor, sizeof(win->scene->cursor));
- /* Note: even though that function seems to redo part of what is done by
+ /* NOTE: even though that function seems to redo part of what is done by
* `lib_link_workspace_layout_restore()` above, it seems to have a slightly different scope:
* while the former updates the whole UI pointers from Main db (going over all layouts of
* all workspaces), that one only focuses one current active screen, takes care of
@@ -3780,7 +3780,7 @@ BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_a
/** \name Read Global Data
* \{ */
-/* note, this has to be kept for reading older files... */
+/* NOTE: this has to be kept for reading older files... */
/* also version info is written here */
static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
{
@@ -3828,7 +3828,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
return blo_bhead_next(fd, bhead);
}
-/* note, this has to be kept for reading older files... */
+/* NOTE: this has to be kept for reading older files... */
static void link_global(FileData *fd, BlendFileData *bfd)
{
bfd->cur_view_layer = blo_read_get_new_globaldata_address(fd, bfd->cur_view_layer);
@@ -5611,7 +5611,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
lib_link_all(mainptr->curlib->filedata, mainptr);
}
- /* Note: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute()
+ /* NOTE: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute()
* here, as this function is only called for library 'subset' data handling, as part of
* either full blendfile reading (#blo_read_file_internal()), or library-data linking
* (#library_link_end()). */
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index d1f69d35fe5..2eeeac2e8d7 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -225,7 +225,7 @@ bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename)
MemFileChunk *chunk;
int file, oflags;
- /* note: This is currently used for autosave and 'quit.blend',
+ /* NOTE: This is currently used for autosave and 'quit.blend',
* where _not_ following symlinks is OK,
* however if this is ever executed explicitly by the user,
* we may want to allow writing to symlinks.
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 9399af5eb11..8a7bc375ea9 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -1274,7 +1274,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
*/
if (ob->pose && ob->data) {
bArmature *arm = blo_do_versions_newlibadr(fd, lib, ob->data);
- if (arm) { /* XXX - why does this fail in some cases? */
+ if (arm) { /* XXX: why does this fail in some cases? */
bAnimVizSettings *avs = &ob->pose->avs;
/* path settings --------------------- */
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 070dd181509..5bf4d3b68b5 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -169,7 +169,7 @@ static void do_versions_image_settings_2_60(Scene *sce)
R_JPEG2K_CINE_48FPS = (1 << 9),
};
- /* note: rd->subimtype is moved into individual settings now and no longer
+ /* NOTE: rd->subimtype is moved into individual settings now and no longer
* exists */
RenderData *rd = &sce->r;
ImageFormatData *imf = &sce->r.im_format;
@@ -2594,11 +2594,11 @@ void do_versions_after_linking_260(Main *bmain)
*
* This assumes valid typeinfo pointers, as set in lib_link_ntree.
*
- * Note: theoretically only needed in node groups (main->nodetree),
+ * NOTE: theoretically only needed in node groups (main->nodetree),
* but due to a temporary bug such links could have been added in all trees,
* so have to clean up all of them ...
*
- * Note: this always runs, without it links with NULL fromnode and tonode remain
+ * NOTE: this always runs, without it links with NULL fromnode and tonode remain
* which causes problems.
*/
if (!MAIN_VERSION_ATLEAST(bmain, 266, 3)) {
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 399761ead8d..0645380c4cb 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -670,7 +670,7 @@ static ARegion *do_versions_find_region(ListBase *regionbase, int regiontype)
{
ARegion *region = do_versions_find_region_or_null(regionbase, regiontype);
if (region == NULL) {
- BLI_assert(!"Did not find expected region in versioning");
+ BLI_assert_msg(0, "Did not find expected region in versioning");
}
return region;
}
@@ -1268,7 +1268,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
/* We need to assign lib pointer to generated hidden collections *after* all have been
* created, otherwise we'll end up with several data-blocks sharing same name/library,
- * which is FORBIDDEN! Note: we need this to be recursive, since a child collection may be
+ * which is FORBIDDEN! NOTE: we need this to be recursive, since a child collection may be
* sorted before its parent in bmain. */
for (Collection *collection = bmain->collections.first; collection != NULL;
collection = collection->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index ecee14d3d58..313ce734bbc 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -28,12 +28,18 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
+#include "DNA_collection_types.h"
#include "DNA_genfile.h"
#include "DNA_listBase.h"
#include "DNA_modifier_types.h"
#include "DNA_text_types.h"
+#include "DNA_workspace_types.h"
+#include "BKE_action.h"
#include "BKE_animsys.h"
+#include "BKE_asset.h"
+#include "BKE_collection.h"
+#include "BKE_deform.h"
#include "BKE_fcurve_driver.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -87,6 +93,19 @@ static void assert_sorted_ids(Main *bmain)
#endif
}
+static void move_vertex_group_names_to_object_data(Main *bmain)
+{
+ LISTBASE_FOREACH (Object *, object, &bmain->objects) {
+ if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
+ ListBase *new_defbase = BKE_object_defgroup_list_mutable(object);
+
+ /* Clear the list in case the it was already assigned from another object. */
+ BLI_freelistN(new_defbase);
+ *new_defbase = object->defbase;
+ }
+ }
+}
+
void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
{
if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
@@ -131,6 +150,10 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
assert_sorted_ids(bmain);
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 11)) {
+ move_vertex_group_names_to_object_data(bmain);
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -468,6 +491,55 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 8)) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->master_collection != NULL) {
+ BLI_strncpy(scene->master_collection->id.name + 2,
+ BKE_SCENE_COLLECTION_NAME,
+ sizeof(scene->master_collection->id.name) - 2);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 9)) {
+ /* Fix a bug where reordering FCurves and bActionGroups could cause some corruption. Just
+ * reconstruct all the action groups & ensure that the FCurves of a group are continuously
+ * stored (i.e. not mixed with other groups) to be sure. See T89435. */
+ LISTBASE_FOREACH (bAction *, act, &bmain->actions) {
+ BKE_action_groups_reconstruct(act);
+ }
+
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type == GEO_NODE_MESH_SUBDIVIDE) {
+ strcpy(node->idname, "GeometryNodeMeshSubdivide");
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ {
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "WorkSpace", "AssetLibraryReference", "active_asset_library")) {
+ LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
+ BKE_asset_library_reference_init_default(&workspace->active_asset_library);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 10)) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ ToolSettings *tool_settings = scene->toolsettings;
+ if (tool_settings->snap_uv_mode & (1 << 4)) {
+ tool_settings->snap_uv_mode |= (1 << 6); /* SCE_SNAP_MODE_INCREMENT */
+ tool_settings->snap_uv_mode &= ~(1 << 4);
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -479,5 +551,24 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
+
+ /* Convert Surface Deform to sparse-capable bind structure. */
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "SurfaceDeformModifierData", "int", "num_mesh_verts")) {
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
+ if (md->type == eModifierType_SurfaceDeform) {
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ if (smd->num_bind_verts && smd->verts) {
+ smd->num_mesh_verts = smd->num_bind_verts;
+
+ for (unsigned int i = 0; i < smd->num_bind_verts; i++) {
+ smd->verts[i].vertex_idx = i;
+ }
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 46e25251fd4..95cfc9975d7 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1311,7 +1311,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
}
}
- /* Note: #BKE_pose_rebuild is further only called on leave edit-mode. */
+ /* NOTE: #BKE_pose_rebuild is further only called on leave edit-mode. */
if (ob->type == OB_ARMATURE) {
if (ob->pose) {
BKE_pose_tag_recalc(bmain, ob->pose);
@@ -1436,7 +1436,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
bPoseChannel *pchan;
bConstraint *con;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* note, pchan->bone is also lib-link stuff */
+ /* NOTE: pchan->bone is also lib-link stuff. */
if (pchan->limitmin[0] == 0.0f && pchan->limitmax[0] == 0.0f) {
pchan->limitmin[0] = pchan->limitmin[1] = pchan->limitmin[2] = -180.0f;
pchan->limitmax[0] = pchan->limitmax[1] = pchan->limitmax[2] = 180.0f;
@@ -2501,7 +2501,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
if (!MAIN_VERSION_ATLEAST(bmain, 248, 2)) {
Scene *sce;
- /* Note, these will need to be added for painting */
+ /* NOTE: these will need to be added for painting. */
for (sce = bmain->scenes.first; sce; sce = sce->id.next) {
sce->toolsettings->imapaint.seam_bleed = 2;
sce->toolsettings->imapaint.normal_angle = 80;
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 42b27f57e2c..30587418f84 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -894,6 +894,7 @@ void blo_do_versions_userdef(UserDef *userdef)
*/
{
/* Keep this block, even when empty. */
+ BKE_addon_ensure(&userdef->addons, "pose_library");
}
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 930ce0ba06f..fc29b1d8915 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -304,7 +304,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, size_t memlen)
}
if (memlen > INT_MAX) {
- BLI_assert(!"Cannot write chunks bigger than INT_MAX.");
+ BLI_assert_msg(0, "Cannot write chunks bigger than INT_MAX.");
return;
}
@@ -538,7 +538,7 @@ static void writedata(WriteData *wd, int filecode, size_t len, const void *adr)
}
if (len > INT_MAX) {
- BLI_assert(!"Cannot write chunks bigger than INT_MAX.");
+ BLI_assert_msg(0, "Cannot write chunks bigger than INT_MAX.");
return;
}
@@ -896,9 +896,10 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
writestruct(wd, GLOB, FileGlobal, 1, &fg);
}
-/* preview image, first 2 values are width and height
- * second are an RGBA image (uchar)
- * note, this uses 'TEST' since new types will segfault on file load for older blender versions.
+/**
+ * Preview image, first 2 values are width and height
+ * second are an RGBA image (uchar).
+ * \note this uses 'TEST' since new types will segfault on file load for older blender versions.
*/
static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
{
diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt
index 70e68ca06d7..bfb812ac64d 100644
--- a/source/blender/blentranslation/CMakeLists.txt
+++ b/source/blender/blentranslation/CMakeLists.txt
@@ -59,7 +59,7 @@ if(WITH_PYTHON)
)
endif()
-if(WIN32)
+if(WIN32 OR APPLE)
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
diff --git a/source/blender/blentranslation/intern/blt_translation.c b/source/blender/blentranslation/intern/blt_translation.c
index b5c0addfdfa..89a2f6c3ac0 100644
--- a/source/blender/blentranslation/intern/blt_translation.c
+++ b/source/blender/blentranslation/intern/blt_translation.c
@@ -47,7 +47,7 @@ bool BLT_is_default_context(const char *msgctxt)
/* We use the "short" test, a more complete one could be:
* return (!msgctxt || !msgctxt[0] || STREQ(msgctxt, BLT_I18NCONTEXT_DEFAULT_BPYRNA))
*/
- /* Note: trying without the void string check for now, it *should* not be necessary... */
+ /* NOTE: trying without the void string check for now, it *should* not be necessary... */
return (!msgctxt || msgctxt[0] == BLT_I18NCONTEXT_DEFAULT_BPYRNA[0]);
}
diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c
index 720be11d3b7..f95bf2a9037 100644
--- a/source/blender/blentranslation/msgfmt/msgfmt.c
+++ b/source/blender/blentranslation/msgfmt/msgfmt.c
@@ -313,7 +313,7 @@ static int make(const char *input_file_name, const char *output_file_name)
const size_t msgid_plural_len = strlen(msgid_plural_kw);
const size_t msgstr_len = strlen(msgstr_kw);
- /* Note: For now, we assume file encoding is always utf-8. */
+ /* NOTE: For now, we assume file encoding is always utf-8. */
eSectionType section = SECTION_NONE;
bool is_plural = false;
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index e3efeec951e..423d64ba62c 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -23,6 +23,8 @@
* that benefit from accessing connectivity information.
*/
+#include "BLI_assert.h"
+
/* disable holes for now,
* these are ifdef'd because they use more memory and can't be saved in DNA currently */
// #define USE_BMESH_HOLES
@@ -37,7 +39,7 @@ struct MLoopNorSpaceArray;
struct BLI_mempool;
-/* note: it is very important for BMHeader to start with two
+/* NOTE: it is very important for BMHeader to start with two
* pointers. this is a requirement of mempool's method of
* iteration.
*
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index f79f1925560..6f7b2cbc79f 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -415,7 +415,7 @@ static void bm_vert_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, CustomDataMask mask_exclude)
{
if ((bm_src == bm_dst) && (v_src == v_dst)) {
- BLI_assert(!"BMVert: source and target match");
+ BLI_assert_msg(0, "BMVert: source and target match");
return;
}
if ((mask_exclude & CD_MASK_NORMAL) == 0) {
@@ -430,7 +430,7 @@ static void bm_edge_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, CustomDataMask mask_exclude)
{
if ((bm_src == bm_dst) && (e_src == e_dst)) {
- BLI_assert(!"BMEdge: source and target match");
+ BLI_assert_msg(0, "BMEdge: source and target match");
return;
}
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->edata, e_dst->head.data, mask_exclude);
@@ -442,7 +442,7 @@ static void bm_loop_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude)
{
if ((bm_src == bm_dst) && (l_src == l_dst)) {
- BLI_assert(!"BMLoop: source and target match");
+ BLI_assert_msg(0, "BMLoop: source and target match");
return;
}
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->ldata, l_dst->head.data, mask_exclude);
@@ -454,7 +454,7 @@ static void bm_face_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, CustomDataMask mask_exclude)
{
if ((bm_src == bm_dst) && (f_src == f_dst)) {
- BLI_assert(!"BMFace: source and target match");
+ BLI_assert_msg(0, "BMFace: source and target match");
return;
}
if ((mask_exclude & CD_MASK_NORMAL) == 0) {
@@ -800,7 +800,7 @@ short BM_edge_flag_to_mflag(BMEdge *e)
((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
- ((BM_edge_is_wire(e)) ? ME_LOOSEEDGE : 0) | /* not typical */
+ (BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */
ME_EDGERENDER);
}
char BM_face_flag_to_mflag(BMFace *f)
diff --git a/source/blender/bmesh/intern/bmesh_delete.c b/source/blender/bmesh/intern/bmesh_delete.c
index f470361e5fb..9f2fb1370bb 100644
--- a/source/blender/bmesh/intern/bmesh_delete.c
+++ b/source/blender/bmesh/intern/bmesh_delete.c
@@ -205,7 +205,7 @@ void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
/* BM functions
*
- * note! this is just a duplicate of the code above (bad!)
+ * NOTE: this is just a duplicate of the code above (bad!)
* but for now keep in sync, its less hassle than having to create bmesh operator flags,
* each time we need to remove some geometry.
*/
diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h
index e9cdc120657..7694d4dbfb6 100644
--- a/source/blender/bmesh/intern/bmesh_error.h
+++ b/source/blender/bmesh/intern/bmesh_error.h
@@ -24,17 +24,46 @@
/*----------- bmop error system ----------*/
+/**
+ * \note More can be added as needed.
+ */
+typedef enum eBMOpErrorLevel {
+ /**
+ * Use when the operation could not succeed,
+ * typically from input that isn't sufficient for completing the operation.
+ */
+ BMO_ERROR_CANCEL = 0,
+ /**
+ * Use this when one or more operations could not succeed,
+ * when the resulting mesh can be used (since some operations succeeded or no change was made).
+ * This is used by default.
+ */
+ BMO_ERROR_WARN = 1,
+ /**
+ * The mesh resulting from this operation should not be used (where possible).
+ * It should not be left in a corrupt state either.
+ *
+ * See #BMBackup type & function calls.
+ */
+ BMO_ERROR_FATAL = 2,
+} eBMOpErrorLevel;
+
/* Pushes an error onto the bmesh error stack.
* if msg is null, then the default message for the `errcode` is used. */
-void BMO_error_raise(BMesh *bm, BMOperator *owner, const char *msg) ATTR_NONNULL(1, 2, 3);
+void BMO_error_raise(BMesh *bm, BMOperator *owner, eBMOpErrorLevel level, const char *msg)
+ ATTR_NONNULL(1, 2, 4);
/* Gets the topmost error from the stack.
* returns error code or 0 if no error. */
-bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op);
-bool BMO_error_occurred(BMesh *bm);
+bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level);
+bool BMO_error_get_at_level(BMesh *bm,
+ eBMOpErrorLevel level,
+ const char **r_msg,
+ BMOperator **r_op);
+bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level);
/* Same as #BMO_error_get, only pops the error off the stack as well. */
-bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op);
+bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level);
void BMO_error_clear(BMesh *bm);
/* This is meant for handling errors, like self-intersection test failures.
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index ff6274cff12..bd28022de4b 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -221,21 +221,21 @@ void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
{
BMOIter iter;
BMElem *ele;
- int count = BMO_slot_buffer_count(slot_args, slot_name);
+ const int slot_len = BMO_slot_buffer_len(slot_args, slot_name);
BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
- if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) {
- BMElem **array = count > stack_array_size ? MEM_mallocN(sizeof(ele) * count, __func__) :
- stack_array;
+ if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && slot_len > 0) {
+ BMElem **array = slot_len > stack_array_size ? MEM_mallocN(sizeof(ele) * slot_len, __func__) :
+ stack_array;
int i = 0;
do {
array[i++] = ele;
} while ((ele = BMO_iter_step(&iter)));
- BLI_assert(i <= count);
+ BLI_assert(i <= slot_len);
- if (i != count) {
+ if (i != slot_len) {
if ((void **)array != stack_array) {
array = MEM_reallocN(array, sizeof(ele) * i);
}
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 470aceeb756..4bb83492548 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -158,7 +158,7 @@ typedef void (*BMIter__begin_cb)(void *);
typedef void *(*BMIter__step_cb)(void *);
/* Iterator Structure */
-/* note: some of these vars are not used,
+/* NOTE: some of these vars are not used,
* so they have been commented to save stack space since this struct is used all over */
typedef struct BMIter {
/* keep union first */
@@ -180,7 +180,7 @@ typedef struct BMIter {
BMIter__begin_cb begin;
BMIter__step_cb step;
- int count; /* note, only some iterators set this, don't rely on it */
+ int count; /* NOTE: only some iterators set this, don't rely on it. */
char itype;
} BMIter;
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 40eed6238ca..9033e43374b 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -397,7 +397,7 @@ static BMLogEntry *bm_log_entry_create(void)
/* Free the data in a log entry
*
- * Note: does not free the log entry itself */
+ * NOTE: does not free the log entry itself. */
static void bm_log_entry_free(BMLogEntry *entry)
{
BLI_ghash_free(entry->deleted_verts, NULL, NULL);
@@ -740,7 +740,7 @@ void BM_log_entry_drop(BMLogEntry *entry)
bm_log_id_ghash_release(log, entry->added_verts);
}
else {
- BLI_assert(!"Cannot drop BMLogEntry from middle");
+ BLI_assert_msg(0, "Cannot drop BMLogEntry from middle");
}
if (log->current_entry == entry) {
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 190698f504c..b70e26f51ea 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -1386,7 +1386,7 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm,
BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
- /* note, better not attempt a fast path for selection as done with de-select
+ /* NOTE: better not attempt a fast path for selection as done with de-select
* because hidden geometry and different selection modes can give different results,
* we could of course check for no hidden faces and then use
* quicker method but its not worth it. */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 456275cf157..bd0504b038a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -24,8 +24,8 @@
struct BMAllocTemplate;
struct BMLoopNorEditDataArray;
-struct MLoopNorSpaceArray;
struct BMPartialUpdate;
+struct MLoopNorSpaceArray;
void BM_mesh_elem_toolflags_ensure(BMesh *bm);
void BM_mesh_elem_toolflags_clear(BMesh *bm);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c
index 6ab7b8a2057..dea6561fe9a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_normals.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c
@@ -19,7 +19,7 @@
*
* BM mesh normal calculation functions.
*
- * \see mesh_normals.c for the equivalent #Mesh functionality.
+ * \see mesh_normals.cc for the equivalent #Mesh functionality.
*/
#include "MEM_guardedalloc.h"
@@ -33,6 +33,7 @@
#include "BLI_task.h"
#include "BLI_utildefines.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -525,7 +526,7 @@ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
}
/**
- * BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c
+ * BMesh version of BKE_mesh_normals_loop_split() in `mesh_evaluate.cc`
* Will use first clnors_data array, and fallback to cd_loop_clnors_offset
* (use NULL and -1 to not use clnors).
*
@@ -604,7 +605,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
* If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge
* as 'entry point', otherwise we can skip it. */
- /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store
+ /* NOTE: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store
* mlfan_pivot's in a stack, to avoid having to fan again around
* the vert during actual computation of clnor & clnorspace. However, this would complicate
* the code, add more memory usage, and
@@ -630,11 +631,14 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
{
const BMVert *v_pivot = l_curr->v;
const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
- const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot);
+ const BMVert *v_1 = l_curr->next->v;
const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co;
- const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot);
+ const BMVert *v_2 = l_curr->prev->v;
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
+ BLI_assert(v_1 == BM_edge_other_vert(l_curr->e, v_pivot));
+ BLI_assert(v_2 == BM_edge_other_vert(l_curr->prev->e, v_pivot));
+
sub_v3_v3v3(vec_curr, co_1, co_pivot);
normalize_v3(vec_curr);
sub_v3_v3v3(vec_prev, co_2, co_pivot);
@@ -700,9 +704,11 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
/* Only need to compute previous edge's vector once,
* then we can just reuse old current one! */
{
- const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
+ const BMVert *v_2 = lfan_pivot->next->v;
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
+ BLI_assert(v_2 == BM_edge_other_vert(e_next, v_pivot));
+
sub_v3_v3v3(vec_org, co_2, co_pivot);
normalize_v3(vec_org);
copy_v3_v3(vec_curr, vec_org);
@@ -1281,7 +1287,7 @@ void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all)
BMVert *v;
BMLoop *l;
BMIter viter, liter;
- /* Note: we could use temp tag of BMItem for that,
+ /* NOTE: we could use temp tag of BMItem for that,
* but probably better not use it in such a low-level func?
* --mont29 */
BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__);
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index f75497f2f19..5fa12397a07 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -183,7 +183,7 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v)
}
/* collapse the vertex */
- /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */
+ /* NOTE: the baseedge can be a boundary of manifold, use this as join_faces arg. */
e = BM_vert_collapse_faces(
bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true, true);
@@ -873,7 +873,7 @@ bool BM_edge_rotate_check(BMEdge *e)
*/
bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
{
- /* note: for these vars 'old' just means initial edge state. */
+ /* NOTE: for these vars 'old' just means initial edge state. */
float ed_dir_old[3]; /* edge vector */
float ed_dir_new[3]; /* edge vector */
@@ -1054,7 +1054,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f
return NULL;
}
- /* note, this assumes joining the faces _didnt_ also remove the verts.
+ /* NOTE: this assumes joining the faces _didnt_ also remove the verts.
* the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits
* break this */
if ((l1 = BM_face_vert_share_loop(f, v1)) && (l2 = BM_face_vert_share_loop(f, v2)) &&
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index a5cce41eee4..3978959a425 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -567,7 +567,7 @@ static BMOpDefine bmo_contextual_create_def = {
},
/* slots_out */
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */
- /* note, this is for stand-alone edges only, not edges which are a part of newly created faces */
+ /* NOTE: this is for stand-alone edges only, not edges which are a part of newly created faces. */
{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */
{{'\0'}},
},
@@ -724,7 +724,7 @@ static BMOpDefine bmo_edgenet_fill_def = {
};
/*
- * Edgenet Prepare.
+ * Edge-net Prepare.
*
* Identifies several useful edge loop cases and modifies them so
* they'll become a face when edgenet_fill is called. The cases covered are:
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index d09c0ee428d..0f9488bd091 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -537,7 +537,7 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
const bool do_flush);
/* puts every element of type 'type' (which is a bitmask) with header
- * flag 'flag', into a slot. note: ignores hidden elements
+ * flag 'flag', into a slot. NOTE: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set). */
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm,
BMOperator *op,
@@ -547,7 +547,7 @@ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm,
const char hflag);
/* puts every element of type 'type' (which is a bitmask) without
- * header flag 'flag', into a slot. note: ignores hidden elements
+ * header flag 'flag', into a slot. NOTE: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set). */
void BMO_slot_buffer_from_disabled_hflag(BMesh *bm,
BMOperator *op,
@@ -565,8 +565,8 @@ void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele);
void *BMO_slot_buffer_get_single(BMOpSlot *slot);
/* counts number of elements inside a slot array. */
-int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data);
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 303b5336a5c..cf7697ad35f 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -678,7 +678,7 @@ void BMO_mesh_selected_remap(BMesh *bm,
}
}
-int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
+int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
@@ -691,7 +691,7 @@ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot
return slot->len;
}
-int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
+int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
@@ -829,7 +829,7 @@ void BMO_slot_buffer_from_all(BMesh *bm,
BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
- /* TODO - collapse these loops into one */
+ /* TODO: collapse these loops into one. */
if (htype & BM_VERT) {
BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
@@ -890,7 +890,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm,
BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
- /* TODO - collapse these loops into one */
+ /* TODO: collapse these loops into one. */
if (htype & BM_VERT) {
BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
@@ -1061,7 +1061,7 @@ static void bmo_slot_buffer_from_flag(BMesh *bm,
ele_array = (BMHeader **)slot->data.buf;
- /* TODO - collapse these loops into one */
+ /* TODO: collapse these loops into one. */
if (htype & BM_VERT) {
BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
@@ -1553,32 +1553,39 @@ typedef struct BMOpError {
struct BMOpError *next, *prev;
BMOperator *op;
const char *msg;
+ eBMOpErrorLevel level;
} BMOpError;
void BMO_error_clear(BMesh *bm)
{
- while (BMO_error_pop(bm, NULL, NULL)) {
+ while (BMO_error_pop(bm, NULL, NULL, NULL)) {
/* pass */
}
}
-void BMO_error_raise(BMesh *bm, BMOperator *owner, const char *msg)
+void BMO_error_raise(BMesh *bm, BMOperator *owner, eBMOpErrorLevel level, const char *msg)
{
BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
err->msg = msg;
err->op = owner;
+ err->level = level;
BLI_addhead(&bm->errorstack, err);
}
-bool BMO_error_occurred(BMesh *bm)
+bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level)
{
- return (BLI_listbase_is_empty(&bm->errorstack) == false);
+ for (const BMOpError *err = bm->errorstack.first; err; err = err->next) {
+ if (err->level == level) {
+ return true;
+ }
+ }
+ return false;
}
/* returns error code or 0 if no error */
-bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op)
+bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
{
BMOpError *err = bm->errorstack.first;
if (err == NULL) {
@@ -1591,13 +1598,36 @@ bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op)
if (r_op) {
*r_op = err->op;
}
+ if (r_level) {
+ *r_level = err->level;
+ }
return true;
}
-bool BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op)
+bool BMO_error_get_at_level(BMesh *bm,
+ eBMOpErrorLevel level,
+ const char **r_msg,
+ BMOperator **r_op)
+{
+ for (BMOpError *err = bm->errorstack.first; err; err = err->next) {
+ if (err->level >= level) {
+ if (r_msg) {
+ *r_msg = err->msg;
+ }
+ if (r_op) {
+ *r_op = err->op;
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool BMO_error_pop(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
{
- bool result = BMO_error_get(bm, msg, op);
+ bool result = BMO_error_get(bm, r_msg, r_op, r_level);
if (result) {
BMOpError *err = bm->errorstack.first;
@@ -1953,7 +1983,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
return true;
error:
- /* non urgent todo - explain exactly what is failing */
+ /* TODO: explain exactly what is failing (not urgent). */
fprintf(stderr, "%s: error parsing formatting string\n", __func__);
fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt));
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 5397098a7f3..0aab10e7b1a 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -1296,7 +1296,7 @@ void BM_face_triangulate(BMesh *bm,
r_edges_new[ne_i++] = e;
}
}
- /* note, never disable tag's */
+ /* NOTE: never disable tag's. */
} while ((l_iter = l_iter->next) != l_first);
}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 2c32cd39002..5be7f4a5f3b 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -20,8 +20,8 @@
* \ingroup bmesh
*/
-struct Heap;
struct BMPartialUpdate;
+struct Heap;
#include "BLI_compiler_attrs.h"
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 0754564fa47..86a7d8153f0 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -49,7 +49,7 @@
*
* \{ */
-/* Note: All these flags _must_ be cleared on exit */
+/* NOTE: All these flags _must_ be cleared on exit. */
/* face is a part of the edge-net (including the original face we're splitting) */
#define FACE_NET _FLAG_WALK
@@ -337,7 +337,7 @@ static bool bm_face_split_edgenet_find_loop_walk(BMVert *v_init,
/* in rare cases there may be edges with a single connecting vertex */
if (e_next != e_first) {
do {
- if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
+ if (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET) &&
(bm_edge_flagged_radial_count(e_next) < 2)) {
BMVert *v_next;
@@ -519,7 +519,7 @@ bool BM_face_split_edgenet(BMesh *bm,
} while ((l_iter = l_iter->next) != l_first);
#endif
- /* Note: 'VERT_IN_QUEUE' is often not needed at all,
+ /* NOTE: 'VERT_IN_QUEUE' is often not needed at all,
* however in rare cases verts are added multiple times to the queue,
* that on its own is harmless but in _very_ rare cases,
* the queue will overflow its maximum size,
@@ -1299,7 +1299,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm,
BMVert *v_delimit = (&edge_arr[i]->v1)[j];
BMVert *v_other;
- /* note, remapping will _never_ map a vertex to an already mapped vertex */
+ /* NOTE: remapping will _never_ map a vertex to an already mapped vertex. */
while (UNLIKELY((v_other = bm_face_split_edgenet_partial_connect(bm, v_delimit, f)))) {
struct TempVertPair *tvp = BLI_memarena_alloc(mem_arena, sizeof(*tvp));
tvp->next = temp_vert_pairs.list;
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 8047b52b625..bc881040e4e 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -1544,12 +1544,12 @@ float BM_loop_calc_face_angle(const BMLoop *l)
*/
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
{
- /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors
+ /* NOTE: we cannot use result of normal_tri_v3 here to detect colinear vectors
* (vertex on a straight line) from zero value,
* because it does not normalize both vectors before making cross-product.
* Instead of adding two costly normalize computations,
* just check ourselves for colinear case. */
- /* Note: FEPSILON might need some finer tweaking at some point?
+ /* NOTE: FEPSILON might need some finer tweaking at some point?
* Seems to be working OK for now though. */
float v1[3], v2[3], v_tmp[3];
sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
@@ -1807,7 +1807,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta
BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop);
sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */
- /* note, we could average the tangents of both loops,
+ /* NOTE: we could average the tangents of both loops,
* for non flat ngons it will give a better direction */
cross_v3_v3v3(r_tangent, tvec, e_loop->f->no);
normalize_v3(r_tangent);
@@ -2591,7 +2591,7 @@ double BM_mesh_calc_volume(BMesh *bm, bool is_signed)
return vol;
}
-/* note, almost duplicate of BM_mesh_calc_edge_groups, keep in sync */
+/* NOTE: almost duplicate of #BM_mesh_calc_edge_groups, keep in sync. */
/**
* Calculate isolated groups of faces with optional filtering.
*
@@ -2753,7 +2753,7 @@ int BM_mesh_calc_face_groups(BMesh *bm,
return group_curr;
}
-/* note, almost duplicate of BM_mesh_calc_face_groups, keep in sync */
+/* NOTE: almost duplicate of #BM_mesh_calc_face_groups, keep in sync. */
/**
* Calculate isolated groups of edges with optional filtering.
*
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index b3b9536618c..ca51a9c39de 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -63,7 +63,7 @@ BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WAR
void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL();
void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL();
-/* note:
+/* NOTE:
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 40f09d7e719..e66afcd88d9 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -842,7 +842,7 @@ static void *bmw_IslandManifoldWalker_step(BMWalker *walker)
/* utility function to see if an edge is a part of an ngon boundary */
static bool bm_edge_is_single(BMEdge *e)
{
- return ((BM_edge_is_boundary(e)) && (e->l->f->len > 4) &&
+ return (BM_edge_is_boundary(e) && (e->l->f->len > 4) &&
(BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e)));
}
diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c
index de26ca5ebd2..a72ff6363ed 100644
--- a/source/blender/bmesh/operators/bmo_beautify.c
+++ b/source/blender/bmesh/operators/bmo_beautify.c
@@ -59,7 +59,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
/* will over alloc if some edges can't be rotated */
edge_array = MEM_mallocN(
- sizeof(*edge_array) * (size_t)BMO_slot_buffer_count(op->slots_in, "edges"), __func__);
+ sizeof(*edge_array) * (size_t)BMO_slot_buffer_len(op->slots_in, "edges"), __func__);
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c
index 2663f271b6e..6296694f121 100644
--- a/source/blender/bmesh/operators/bmo_bisect_plane.c
+++ b/source/blender/bmesh/operators/bmo_bisect_plane.c
@@ -50,7 +50,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
BMO_slot_vec_get(op->slots_in, "plane_no", plane_no);
if (is_zero_v3(plane_no)) {
- BMO_error_raise(bm, op, "Zero normal given");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Zero normal given");
return;
}
@@ -68,7 +68,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
/* Use an array of vertices because 'geom' contains both verts and edges that may use them.
* Removing a vert may remove and edge which is later checked by #BMO_ITER.
* over-allocate the total possible vert count. */
- const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_count(op->slots_in, "geom"));
+ const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_len(op->slots_in, "geom"));
BMVert **vert_arr = MEM_mallocN(sizeof(*vert_arr) * (size_t)vert_arr_max, __func__);
BMOIter siter;
BMVert *v;
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 005b8a2f5e8..fb913d4f19f 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -576,12 +576,12 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
BM_mesh_edgeloops_calc_center(bm, &eloops);
if (count < 2) {
- BMO_error_raise(bm, op, "Select at least two edge loops");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Select at least two edge loops");
goto cleanup;
}
if (use_pairs && (count % 2)) {
- BMO_error_raise(bm, op, "Select an even number of loops to bridge pairs");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Select an even number of loops to bridge pairs");
goto cleanup;
}
@@ -595,7 +595,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
}
}
if (!match) {
- BMO_error_raise(bm, op, "Selected loops must have equal edge counts");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Selected loops must have equal edge counts");
goto cleanup;
}
}
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index b701c1291a6..abc040f7564 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -211,7 +211,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
/* connect faces */
while ((f = BLI_LINKSTACK_POP(faces))) {
if (bm_face_connect_verts(bm, f, check_degenerate) == -1) {
- BMO_error_raise(bm, op, "Could not connect vertices");
+ BMO_error_raise(bm, op, BMO_ERROR_FATAL, "Could not connect vertices");
}
}
diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c
index bc1111676a3..15ed930afd8 100644
--- a/source/blender/bmesh/operators/bmo_connect_concave.c
+++ b/source/blender/bmesh/operators/bmo_connect_concave.c
@@ -51,10 +51,10 @@ static int bm_edge_length_cmp(const void *a_, const void *b_)
const BMEdge *e_a = *(const void **)a_;
const BMEdge *e_b = *(const void **)b_;
- int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) &&
- (BM_elem_flag_test(e_a->v2, BM_ELEM_TAG)));
- int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) &&
- (BM_elem_flag_test(e_b->v2, BM_ELEM_TAG)));
+ int e_a_concave = (BM_elem_flag_test(e_a->v1, BM_ELEM_TAG) &&
+ BM_elem_flag_test(e_a->v2, BM_ELEM_TAG));
+ int e_b_concave = (BM_elem_flag_test(e_b->v1, BM_ELEM_TAG) &&
+ BM_elem_flag_test(e_b->v2, BM_ELEM_TAG));
/* merge edges between concave edges last since these
* are most likely to remain and be the main dividers */
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index b57c8686e1c..660633e8a0f 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -571,7 +571,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
}
/* create a new 'basis_nor' from the best direction.
- * note: we could add the directions,
+ * NOTE: we could add the directions,
* but this more often gives 45d rotated matrix, so just use the best one. */
copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor);
project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir);
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index f38e2e08f33..a740e4d66e8 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -172,7 +172,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMO_op_exec(bm, &op_sub);
/* return if edge net create did something */
- if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
+ if (BMO_slot_buffer_len(op_sub.slots_out, "faces.out")) {
BMO_slot_copy(&op_sub, slots_out, "faces.out", op, slots_out, "faces.out");
BMO_op_finish(bm, &op_sub);
return;
@@ -184,14 +184,14 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* -------------------------------------------------------------------- */
/* Dissolve Face */
if (totf != 0) { /* should be (totf > 1)... see below */
- /* note: allow this to run on single faces so running on a single face
+ /* NOTE: allow this to run on single faces so running on a single face
* won't go on to create a face, treating them as random */
BMOperator op_sub;
BMO_op_initf(bm, &op_sub, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
BMO_op_exec(bm, &op_sub);
/* if we dissolved anything, then return */
- if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) {
+ if (BMO_slot_buffer_len(op_sub.slots_out, "region.out")) {
BMO_slot_copy(&op_sub, slots_out, "region.out", op, slots_out, "faces.out");
BMO_op_finish(bm, &op_sub);
return;
@@ -204,14 +204,14 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* Fill EdgeLoop's - fills isolated loops, different from edgenet */
if (tote > 2) {
BMOperator op_sub;
- /* note: in most cases 'edgenet_fill' will handle this case since in common cases
+ /* NOTE: in most cases 'edgenet_fill' will handle this case since in common cases
* users fill in empty spaces, however its possible to have an edge selection around
* existing geometry that makes 'edgenet_fill' fail. */
BMO_op_initf(bm, &op_sub, op->flag, "edgeloop_fill edges=%fe", ELE_NEW);
BMO_op_exec(bm, &op_sub);
/* return if edge loop fill did something */
- if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
+ if (BMO_slot_buffer_len(op_sub.slots_out, "faces.out")) {
BMO_slot_copy(&op_sub, slots_out, "faces.out", op, slots_out, "faces.out");
BMO_op_finish(bm, &op_sub);
return;
@@ -280,7 +280,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
* last resort when all else fails.
*/
if (totv > 2) {
- /* TODO, some of these vertices may be connected by edges,
+ /* TODO: some of these vertices may be connected by edges,
* this connectivity could be used rather than treating
* them as a bunch of isolated verts. */
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 30c80d43b9c..efba0ec99ec 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -128,7 +128,11 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
{
BMOIter oiter;
BMFace *f;
- BMFace ***regions = NULL;
+ /* List of face arrays, the first element in each array in the length. */
+ struct {
+ BMFace **faces;
+ int faces_len;
+ } *regions = NULL, *region;
BMFace **faces = NULL;
BLI_array_declare(regions);
BLI_array_declare(faces);
@@ -158,9 +162,6 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
continue;
}
- BLI_array_clear(faces);
- faces = NULL; /* Forces different allocation. */
-
BMW_init(&regwalker,
bm,
BMW_ISLAND_MANIFOLD,
@@ -171,56 +172,71 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
BMW_FLAG_NOP,
BMW_NIL_LAY);
- for (f_iter = BMW_begin(&regwalker, f); f_iter; f_iter = BMW_step(&regwalker)) {
- BLI_array_append(faces, f_iter);
- }
- BMW_end(&regwalker);
+ /* Check there are at least two faces before creating the array. */
+ BMFace *faces_init[2];
+ if ((faces_init[0] = BMW_begin(&regwalker, f)) && (faces_init[1] = BMW_step(&regwalker))) {
+
+ BLI_assert(BLI_array_len(faces) == 0);
+
+ BLI_array_append(faces, faces_init[0]);
+ BLI_array_append(faces, faces_init[1]);
+
+ while ((f_iter = BMW_step(&regwalker))) {
+ BLI_array_append(faces, f_iter);
+ }
+
+ for (i = 0; i < BLI_array_len(faces); i++) {
+ f_iter = faces[i];
+ BMO_face_flag_disable(bm, f_iter, FACE_TAG);
+ BMO_face_flag_enable(bm, f_iter, FACE_ORIG);
+ }
+
+ region = BLI_array_append_ret(regions);
+ region->faces = faces;
+ region->faces_len = BLI_array_len(faces);
- for (i = 0; i < BLI_array_len(faces); i++) {
- f_iter = faces[i];
- BMO_face_flag_disable(bm, f_iter, FACE_TAG);
- BMO_face_flag_enable(bm, f_iter, FACE_ORIG);
+ BLI_array_clear(faces);
+ /* Forces a new allocation. */
+ faces = NULL;
}
- BLI_array_append(faces, NULL);
- BLI_array_append(regions, faces);
+ BMW_end(&regwalker);
}
/* track how many faces we should end up with */
int totface_target = bm->totface;
for (i = 0; i < BLI_array_len(regions); i++) {
- BMFace *f_new;
- int tot = 0;
-
- faces = regions[i];
- if (!faces[0]) {
- BMO_error_raise(bm, op, "Could not find boundary of dissolve region");
- goto cleanup;
- }
-
- while (faces[tot]) {
- tot++;
- }
+ region = &regions[i];
- f_new = BM_faces_join(bm, faces, tot, true);
+ const int faces_len = region->faces_len;
+ faces = region->faces;
- if (f_new) {
- /* maintain active face */
+ BMFace *f_new = BM_faces_join(bm, faces, faces_len, true);
+ if (f_new != NULL) {
+ /* Maintain the active face. */
if (act_face && bm->act_face == NULL) {
bm->act_face = f_new;
}
- totface_target -= tot - 1;
+ totface_target -= faces_len - 1;
+
+ /* If making the new face failed (e.g. overlapping test)
+ * un-mark the original faces for deletion. */
+ BMO_face_flag_disable(bm, f_new, FACE_ORIG);
+ BMO_face_flag_enable(bm, f_new, FACE_NEW);
}
else {
- BMO_error_raise(bm, op, "Could not create merged face");
- goto cleanup;
+ /* NOTE: prior to 3.0 this raised an error: "Could not create merged face".
+ * Change behavior since it's not useful to fail entirely when a single face-group
+ * can't be merged into one face. Continue with other face groups instead.
+ *
+ * This could optionally do a partial merge, where some faces are joined. */
+
+ /* Prevent these faces from being removed. */
+ for (i = 0; i < faces_len; i++) {
+ BMO_face_flag_disable(bm, faces[i], FACE_ORIG);
+ }
}
-
- /* if making the new face failed (e.g. overlapping test)
- * unmark the original faces for deletion */
- BMO_face_flag_disable(bm, f_new, FACE_ORIG);
- BMO_face_flag_enable(bm, f_new, FACE_NEW);
}
/* Typically no faces need to be deleted */
@@ -241,18 +257,13 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
}
}
- if (BMO_error_occurred(bm)) {
- goto cleanup;
- }
+ BLI_assert(!BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL));
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW);
-cleanup:
/* free/cleanup */
for (i = 0; i < BLI_array_len(regions); i++) {
- if (regions[i]) {
- MEM_freeN(regions[i]);
- }
+ MEM_freeN(regions[i].faces);
}
BLI_array_free(regions);
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 53a2a3b2bba..7f70c452af3 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -52,7 +52,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BM_mesh_edgenet(bm, true, true); /* TODO, sides */
+ BM_mesh_edgenet(bm, true, true); /* TODO: sides. */
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
@@ -79,7 +79,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
BMO_op_exec(bm, &op_attr);
/* check if some faces couldn't be touched */
- if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
+ if (BMO_slot_buffer_len(op_attr.slots_out, "faces_fail.out")) {
BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
}
BMO_op_finish(bm, &op_attr);
@@ -93,7 +93,7 @@ static BMEdge *edge_next(BMesh *bm, BMEdge *e)
for (i = 0; i < 2; i++) {
BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) {
- if ((BMO_edge_flag_test(bm, e2, EDGE_MARK)) &&
+ if (BMO_edge_flag_test(bm, e2, EDGE_MARK) &&
(BMO_edge_flag_test(bm, e2, EDGE_VIS) == false) && (e2 != e)) {
return e2;
}
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index ffdce943d9f..0cedc2324f2 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -459,7 +459,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
}
/* Allocate array to store possible vertices that will be dissolved. */
- int boundary_edges_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out");
+ int boundary_edges_len = BMO_slot_map_len(dupeop.slots_out, "boundary_map.out");
/* We do not know the real number of boundary vertices. */
int boundary_verts_len_maybe = 2 * boundary_edges_len;
dissolve_verts = MEM_mallocN(boundary_verts_len_maybe * sizeof(*dissolve_verts), __func__);
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index e377fa6079b..5e8924c4a3b 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -161,7 +161,7 @@ void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
/* now we can copy adjacent data */
face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data);
- if (face_tot != BMO_slot_buffer_count(op->slots_in, "faces")) {
+ if (face_tot != BMO_slot_buffer_len(op->slots_in, "faces")) {
/* any remaining tags will be skipped */
BMO_slot_buffer_from_enabled_hflag(
bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG);
diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
index 16f9922b21d..da4567d947b 100644
--- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c
+++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
@@ -35,7 +35,7 @@
void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
{
/* first collect an array of unique from the edges */
- const int tote = BMO_slot_buffer_count(op->slots_in, "edges");
+ const int tote = BMO_slot_buffer_len(op->slots_in, "edges");
const int totv = tote; /* these should be the same */
BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
@@ -85,7 +85,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
}
if (ok) {
- /* note: in the case of multiple loops, this over-allocs (which is fine) */
+ /* NOTE: in the case of multiple loops, this over-allocs (which is fine). */
BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
BMIter eiter;
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 4ba7dbad736..6734cc60cad 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -619,6 +619,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
* extract two 'rail' loops from a single edge loop, see T72075. */
BMO_error_raise(bm,
op,
+ BMO_ERROR_CANCEL,
"Select two edge loops "
"or a single closed edge loop from which two edge loops can be calculated");
goto cleanup;
@@ -633,7 +634,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
v_b_last = ((LinkData *)BM_edgeloop_verts_get(estore_b)->last)->data;
if (BM_edgeloop_is_closed(estore_a) || BM_edgeloop_is_closed(estore_b)) {
- BMO_error_raise(bm, op, "Closed loops unsupported");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Closed loops unsupported");
goto cleanup;
}
@@ -644,20 +645,20 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, true);
bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, true);
- if ((BM_mesh_edgeloops_find_path(
- bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first)) &&
- (BM_mesh_edgeloops_find_path(
- bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last))) {
+ if (BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first) &&
+ BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last)) {
estore_rail_a = eloops_rail.first;
estore_rail_b = eloops_rail.last;
}
else {
BM_mesh_edgeloops_free(&eloops_rail);
- if ((BM_mesh_edgeloops_find_path(
- bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last)) &&
- (BM_mesh_edgeloops_find_path(
- bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first))) {
+ if (BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last) &&
+ BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first)) {
estore_rail_a = eloops_rail.first;
estore_rail_b = eloops_rail.last;
BM_edgeloop_flip(bm, estore_b);
@@ -671,7 +672,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, false);
if (BLI_listbase_is_empty(&eloops_rail)) {
- BMO_error_raise(bm, op, "Loops are not connected by wire/boundary edges");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Loops are not connected by wire/boundary edges");
goto cleanup;
}
@@ -679,7 +680,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
BLI_assert(v_a_last != v_b_last);
if (BM_edgeloop_overlap_check(estore_rail_a, estore_rail_b)) {
- BMO_error_raise(bm, op, "Connecting edge loops overlap");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Connecting edge loops overlap");
goto cleanup;
}
diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c
index 5801db582e1..a24d81c5bdb 100644
--- a/source/blender/bmesh/operators/bmo_fill_holes.c
+++ b/source/blender/bmesh/operators/bmo_fill_holes.c
@@ -35,7 +35,7 @@ void bmo_holes_fill_exec(BMesh *bm, BMOperator *op)
BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
- BM_mesh_edgenet(bm, true, true); // TODO, sides
+ BM_mesh_edgenet(bm, true, true); // TODO: sides
/* bad - remove faces after as a workaround */
if (sides != 0) {
@@ -66,7 +66,7 @@ void bmo_holes_fill_exec(BMesh *bm, BMOperator *op)
BMO_op_exec(bm, &op_attr);
/* check if some faces couldn't be touched */
- if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
+ if (BMO_slot_buffer_len(op_attr.slots_out, "faces_fail.out")) {
BMOIter siter;
BMFace *f;
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 956d55695d6..740815691cc 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -278,7 +278,7 @@ static void hull_remove_overlapping(BMesh *bm,
}
}
- /* Note: can't change ghash while iterating, so mark
+ /* NOTE: can't change ghash while iterating, so mark
* with 'skip' flag rather than deleting triangles */
if (BM_vert_in_face(t->v[1], f) && BM_vert_in_face(t->v[2], f) && f_on_hull) {
t->skip = true;
@@ -465,7 +465,7 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull,
hull_verts[i] = input_verts[original_index];
}
else {
- BLI_assert(!"Unexpected new vertex in hull output");
+ BLI_assert_msg(0, "Unexpected new vertex in hull output");
}
}
@@ -505,7 +505,7 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, BLI_mempool *hull_triang
BLI_array_grow_items(fvi, len);
plConvexHullGetFaceVertices(hull, i, fvi);
- /* Note: here we throw away any NGons from Bullet and turn
+ /* NOTE: here we throw away any NGons from Bullet and turn
* them into triangle fans. Would be nice to use these
* directly, but will have to wait until HullTriangle goes
* away (TODO) */
@@ -554,7 +554,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op)
/* Verify that at least three verts in the input */
if (!hull_num_input_verts_is_ok(op)) {
- BMO_error_raise(bm, op, "Requires at least three vertices");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Requires at least three vertices");
return;
}
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 39f8f41432a..4833290aa0b 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -822,7 +822,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
/* this could go in its own loop,
* only use the 'es->l->f' so we don't store loops for faces which have no mixed selection
*
- * note: faces on the other side of the inset will be interpolated too since this is hard to
+ * NOTE: faces on the other side of the inset will be interpolated too since this is hard to
* detect, just allow it even though it will cause some redundant interpolation */
if (use_interpolate) {
BMIter viter;
@@ -1016,8 +1016,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
if (use_even_boundary) {
/**
- * This case where only one edge attached to #v_split
- * is used - ei - the face to inset is on a boundary.
+ * This case where only one edge attached to #v_split is used.
+ * i.e. the face to inset is on a boundary.
*
* <pre>
* We want the inset to align flush with the
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index c3e96a9b08e..8b456bb0925 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -44,7 +44,7 @@ static float quad_calc_error(const float v1[3],
{
/* Gives a 'weight' to a pair of triangles that join an edge
* to decide how good a join they would make. */
- /* Note: this is more complicated than it needs to be and should be cleaned up. */
+ /* NOTE: this is more complicated than it needs to be and should be cleaned up. */
float error = 0.0f;
/* Normal difference */
diff --git a/source/blender/bmesh/operators/bmo_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
index 2c7e478b549..28f2c9a47aa 100644
--- a/source/blender/bmesh/operators/bmo_offset_edgeloops.c
+++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
@@ -74,7 +74,7 @@ static BMFace *bm_face_split_walk_back(BMesh *bm, BMLoop *l_src, BMLoop **r_l)
void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
{
- const int edges_num = BMO_slot_buffer_count(op->slots_in, "edges");
+ const int edges_num = BMO_slot_buffer_len(op->slots_in, "edges");
BMVert **verts;
STACK_DECLARE(verts);
int i;
@@ -221,7 +221,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
}
}
- /* Note: instead of duplicate code in alternate direction,
+ /* NOTE: instead of duplicate code in alternate direction,
* we can be sure to hit the other vertex, so the code above runs. */
#if 0
else if (BM_elem_index_get(l->prev->v) == -1) {
diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c
index c8f9d9a38dd..53cfc379269 100644
--- a/source/blender/bmesh/operators/bmo_planar_faces.c
+++ b/source/blender/bmesh/operators/bmo_planar_faces.c
@@ -41,7 +41,7 @@ void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
{
const float fac = BMO_slot_float_get(op->slots_in, "factor");
const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
- const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
+ const int faces_num = BMO_slot_buffer_len(op->slots_in, "faces");
const float eps = 0.00001f;
const float eps_sq = square_f(eps);
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index f47c8dfb405..8d5963cfb1c 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -788,7 +788,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
}
/**
- * Fills first available UVmap with grid-like UVs for all faces OpFlag-ged by given flag.
+ * Fills first available UV-map with grid-like UV's for all faces with `oflag` set.
*
* \param bm: The BMesh to operate on
* \param x_segments: The x-resolution of the grid
@@ -1131,7 +1131,7 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
}
/**
- * Fills first available UVmap with spherical projected UVs for all faces OpFlag-ged by given flag.
+ * Fills first available UV-map with spherical projected UVs for all faces with `oflag` set.
*
* \param bm: The BMesh to operate on
* \param oflag: The flag to check faces with.
@@ -1344,7 +1344,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
}
/**
- * Fills first available UVmap with 2D projected UVs for all faces OpFlag-ged by given flag.
+ * Fills first available UV-map with 2D projected UVs for all faces with `oflag` set.
*
* \param bm: The BMesh to operate on.
* \param mat: The transform matrix applied to the created circle.
@@ -1536,7 +1536,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
}
/**
- * Fills first available UVmap with cylinder/cone-like UVs for all faces OpFlag-ged by given flag.
+ * Fills first available UV-map with cylinder/cone-like UVs for all faces with `oflag` set.
*
* \param bm: The BMesh to operate on.
* \param mat: The transform matrix applied to the created cone/cylinder.
@@ -1712,7 +1712,7 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
}
/**
- * Fills first available UVmap with cube-like UVs for all faces OpFlag-ged by given flag.
+ * Fills first available UV-map with cube-like UVs for all faces with `oflag` set.
*
* \note Expects tagged faces to be six quads.
* \note Caller must order faces for correct alignment.
diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c
index b684aa390cf..10dd9dcc9b7 100644
--- a/source/blender/bmesh/operators/bmo_rotate_edges.c
+++ b/source/blender/bmesh/operators/bmo_rotate_edges.c
@@ -191,7 +191,7 @@ static void bm_rotate_edges_shared(
edges_len_rotate += 1;
- /* Note: we could validate all edges which have not been rotated
+ /* NOTE: we could validate all edges which have not been rotated
* (not just previously degenerate edges).
* However there is no real need -
* they can be left until they're popped off the queue. */
@@ -234,7 +234,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
BMEdge *e;
- const int edges_len = BMO_slot_buffer_count(op->slots_in, "edges");
+ const int edges_len = BMO_slot_buffer_len(op->slots_in, "edges");
const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
const bool is_single = (edges_len == 1);
short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS :
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index ae4fa65b55c..7311c94a0d8 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -79,7 +79,7 @@ typedef void (*subd_pattern_fill_fp)(BMesh *bm,
const SubDParams *params);
/*
- * note: this is a pattern-based edge subdivider.
+ * NOTE: this is a pattern-based edge subdivider.
* it tries to match a pattern to edge selections on faces,
* then executes functions to cut them.
*/
@@ -138,7 +138,7 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace
* multiple faces yet. that might require a convexity test to figure out which
* face is "best" and who knows what for non-manifold conditions.
*
- * note: we allow adjacent here, since there's no chance this happens.
+ * NOTE: we allow adjacent here, since there's no chance this happens.
*/
f = BM_vert_pair_share_face_by_len(v_a, v_b, &l_a, &l_b, true);
@@ -469,7 +469,7 @@ static void bm_subdivide_multicut(
alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp);
}
-/* note: the patterns are rotated as necessary to
+/* NOTE: the patterns are rotated as necessary to
* match the input geometry. they're based on the
* pre-split state of the face */
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index d9bfe96ddc4..6a80f360f59 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -83,8 +83,8 @@ static float bezier_handle_calc_length_v3(const float co_a[3],
float fac = 1.333333f;
float len;
if (dot < 0.0f) {
- /* scale down to 0.666 if we point directly at each other rough but ok */
- /* TODO, current blend from dot may not be optimal but its also a detail */
+ /* Scale down to 0.666 if we point directly at each other rough but ok. */
+ /* TODO: current blend from dot may not be optimal but its also a detail. */
const float t = 1.0f + dot;
fac = (fac * t) + (0.75f * (1.0f - t));
}
@@ -821,7 +821,7 @@ static void bm_edgering_pair_interpolate(BMesh *bm,
*/
static void bm_face_slice(BMesh *bm, BMLoop *l, const int cuts)
{
- /* TODO, interpolate edge data */
+ /* TODO: interpolate edge data. */
BMLoop *l_new = l;
int i;
@@ -860,12 +860,12 @@ static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm),
/* step around any fan-faces on both sides */
do {
v_iter_a_step = v_iter_a_step->next;
- } while (v_iter_a_step && ((BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data)) ||
- (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data))));
+ } while (v_iter_a_step && (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data) ||
+ BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data)));
do {
v_iter_b_step = v_iter_b_step->next;
- } while (v_iter_b_step && ((BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data)) ||
- (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data))));
+ } while (v_iter_b_step && (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data) ||
+ BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data)));
v_iter_a_step = v_iter_a_step ? v_iter_a_step->prev : lb_a->last;
v_iter_b_step = v_iter_b_step ? v_iter_b_step->prev : lb_b->last;
@@ -1143,7 +1143,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
count = BM_mesh_edgeloops_find(bm, &eloops_rim, bm_edge_rim_test_cb, (void *)bm);
if (count < 2) {
- BMO_error_raise(bm, op, "No edge rings found");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "No edge rings found");
goto cleanup;
}
else if (count == 2) {
@@ -1167,7 +1167,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
changed = true;
}
else {
- BMO_error_raise(bm, op, "Edge-ring pair isn't connected");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Edge-ring pair isn't connected");
goto cleanup;
}
}
@@ -1179,7 +1179,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
LoopPairStore **lpair_arr;
if (eloop_pairs_gs == NULL) {
- BMO_error_raise(bm, op, "Edge-rings are not connected");
+ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "Edge-rings are not connected");
goto cleanup;
}
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index f6d612f31eb..9fa74bb64c3 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -74,7 +74,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
uint nors_tot;
bool calc_winding = false;
- sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
+ sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_len(op->slots_in, "edges"));
BMO_slot_vec_get(op->slots_in, "normal", normal);
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index c056302ca0f..7d2b6b73455 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -393,7 +393,7 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op)
BMIter iter;
BMVert *v;
BMEdge *e;
- float(*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_count(op->slots_in, "verts"),
+ float(*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_len(op->slots_in, "verts"),
__func__);
float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist");
const float fac = BMO_slot_float_get(op->slots_in, "factor");
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 4ef165fe6c1..d5c5063f2cb 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -429,7 +429,7 @@ void BM_mesh_beautify_fill(BMesh *bm,
GSet *e_state_set = edge_state_arr[i];
/* add the new state into the set so we don't move into this state again
- * note: we could add the previous state too but this isn't essential)
+ * NOTE: we could add the previous state too but this isn't essential)
* for avoiding eternal loops */
EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
erot_state_current(e, e_state);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 65cceb8dcfd..1e8ef9737d3 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -321,7 +321,7 @@ typedef struct BevelParams {
GHash *vert_hash;
/** Records new faces: key BMFace*, value one of {VERT/EDGE/RECON}_POLY. */
GHash *face_hash;
- /** Use for all allocs while bevel runs. Note: If we need to free we can switch to mempool. */
+ /** Use for all allocs while bevel runs. NOTE: If we need to free we can switch to mempool. */
MemArena *mem_arena;
/** Profile vertex location and spacings. */
ProfileSpacing pro_spacing;
@@ -1225,7 +1225,7 @@ static void offset_meet_lines_percent_or_absolute(BevelParams *bp,
float r_l2b[3])
{
/* Get points the specified distance along each leg.
- * Note: not all BevVerts and EdgeHalfs have been made yet, so we have
+ * NOTE: not all BevVerts and EdgeHalfs have been made yet, so we have
* to find required edges by moving around faces and use fake EdgeHalfs for
* some of the edges. If there aren't faces to move around, we have to give up.
* The legs we need are:
@@ -1676,7 +1676,7 @@ static void project_to_edge(const BMEdge *e,
float otherco[3];
if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) {
#ifdef BEVEL_ASSERT_PROJECT
- BLI_assert(!"project meet failure");
+ BLI_assert_msg(0, "project meet failure");
#endif
copy_v3_v3(projco, e->v1->co);
}
@@ -3621,7 +3621,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
} while (v && v != vstart);
EIG_linear_solver_solve(solver);
#ifdef DEBUG_ADJUST
- /* Note: this print only works after solve, but by that time b has been cleared. */
+ /* NOTE: this print only works after solve, but by that time b has been cleared. */
EIG_linear_solver_print_matrix(solver);
printf("\nSolution:\n");
for (i = 0; i < np; i++) {
@@ -3682,7 +3682,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
static void adjust_offsets(BevelParams *bp, BMesh *bm)
{
/* Find and process chains and cycles of unvisited BoundVerts that have eon set. */
- /* Note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts. */
+ /* NOTE: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts. */
BMIter iter;
BMVert *bmv;
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
@@ -6194,7 +6194,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
bv->offset *= weight;
}
- /* Find center axis. Note: Don't use vert normal, can give unwanted results. */
+ /* Find center axis. NOTE: Don't use vert normal, can give unwanted results. */
if (ELEM(bp->offset_type, BEVEL_AMT_WIDTH, BEVEL_AMT_DEPTH)) {
float edge_dir[3];
EdgeHalf *e = bv->edges;
@@ -6262,7 +6262,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
break;
}
default: {
- BLI_assert(!"bad bevel offset kind");
+ BLI_assert_msg(0, "bad bevel offset kind");
e->offset_l_spec = bp->offset;
break;
}
@@ -6872,7 +6872,7 @@ static double find_superellipse_chord_endpoint(double x0, double dtarget, float
double ymin = superellipse_co(xmin, r, rbig);
double ymax = superellipse_co(xmax, r, rbig);
- /* Note: using distance**2 (no sqrt needed) does not converge that well. */
+ /* NOTE: using distance**2 (no sqrt needed) does not converge that well. */
double dmaxerr = sqrt(pow((xmax - x0), 2) + pow((ymax - y0), 2)) - dtarget;
double dminerr = sqrt(pow((xmin - x0), 2) + pow((ymin - y0), 2)) - dtarget;
@@ -7253,7 +7253,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
return no_collide_offset;
}
float kb = eb->offset_l_spec;
- EdgeHalf *ea = eb->next; /* Note: this is in direction b --> a. */
+ EdgeHalf *ea = eb->next; /* NOTE: this is in direction b --> a. */
float ka = ea->offset_r_spec;
BMVert *vb, *vc;
if (eb->is_rev) {
@@ -7282,7 +7282,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
return no_collide_offset;
}
if (ebother != NULL) {
- ec = ebother->prev; /* Note: this is in direction c --> d. */
+ ec = ebother->prev; /* NOTE: this is in direction c --> d. */
vc = bvc->v;
kc = ec->offset_l_spec;
vd = ec->is_rev ? ec->e->v1 : ec->e->v2;
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index a1630d9d2ff..20b6903b239 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -285,7 +285,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
cost = (BLI_quadric_evaluate(q1, optimize_co) + BLI_quadric_evaluate(q2, optimize_co));
}
- /* note, 'cost' shouldn't be negative but happens sometimes with small values.
+ /* NOTE: 'cost' shouldn't be negative but happens sometimes with small values.
* this can cause faces that make up a flat surface to over-collapse, see T37121. */
cost = fabsf(cost);
@@ -303,7 +303,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
const float e_weight = (vweights[BM_elem_index_get(e->v1)] +
vweights[BM_elem_index_get(e->v2)]);
cost = bm_decim_build_edge_cost_single__topology(e) - cost;
- /* note, this is rather arbitrary max weight is 2 here,
+ /* NOTE: this is rather arbitrary max weight is 2 here,
* allow for skipping edges 4x the length, based on weights */
if (e_weight) {
cost *= 1.0f + (e_weight * vweight_factor);
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index 036dae1b9bd..d8a586acee5 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -55,7 +55,7 @@ static float bm_vert_edge_face_angle(BMVert *v,
#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE)
const float angle = BM_vert_calc_edge_angle(v);
- /* note: could be either edge, it doesn't matter */
+ /* NOTE: could be either edge, it doesn't matter. */
if (v->e && BM_edge_is_manifold(v->e)) {
/* Checking delimited is important here,
* otherwise the boundary between two materials for e.g.
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 51af4d24e52..242b269ed47 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -17,7 +17,7 @@
/** \file
* \ingroup bmesh
*
- * Edgenet Fill.
+ * Edge-net Fill.
*/
#include <limits.h>
diff --git a/source/blender/bmesh/tools/bmesh_intersect_edges.c b/source/blender/bmesh/tools/bmesh_intersect_edges.c
index 1e9adea2615..eb56075e136 100644
--- a/source/blender/bmesh/tools/bmesh_intersect_edges.c
+++ b/source/blender/bmesh/tools/bmesh_intersect_edges.c
@@ -938,7 +938,7 @@ bool BM_mesh_intersect_edges(
}
if (va_dest == v_other_dest) {
- /* Edge/Edgenet to vertex - we can't split the face. */
+ /* Edge/Edge-net to vertex - we can't split the face. */
break;
}
if (edgenet_len == 0 && BM_edge_exists(va_dest, v_other_dest)) {
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index cb75f47acf3..ea1e7eb1e43 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -142,7 +142,7 @@ LinkNode *BM_mesh_calc_path_vert(BMesh *bm,
BMVert **verts_prev;
int i, totvert;
- /* Note, would pass #BM_EDGE except we are looping over all faces anyway. */
+ /* NOTE: would pass #BM_EDGE except we are looping over all faces anyway. */
// BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
@@ -322,7 +322,7 @@ LinkNode *BM_mesh_calc_path_edge(BMesh *bm,
BMEdge **edges_prev;
int i, totedge;
- /* Note, would pass #BM_EDGE except we are looping over all edges anyway. */
+ /* NOTE: would pass #BM_EDGE except we are looping over all edges anyway. */
BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */);
BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
@@ -523,7 +523,7 @@ LinkNode *BM_mesh_calc_path_face(BMesh *bm,
/* Start measuring face path at the face edges, ignoring their centers. */
const void *const f_endpoints[2] = {f_src, f_dst};
- /* Note, would pass #BM_EDGE except we are looping over all faces anyway. */
+ /* NOTE: would pass #BM_EDGE except we are looping over all faces anyway. */
// BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
diff --git a/source/blender/bmesh/tools/bmesh_path_uv.c b/source/blender/bmesh/tools/bmesh_path_uv.c
index 57a70645187..30b109d4731 100644
--- a/source/blender/bmesh/tools/bmesh_path_uv.c
+++ b/source/blender/bmesh/tools/bmesh_path_uv.c
@@ -139,7 +139,7 @@ struct LinkNode *BM_mesh_calc_path_uv_vert(BMesh *bm,
int i = 0, totloop;
BMFace *f;
- /* Note, would pass BM_EDGE except we are looping over all faces anyway. */
+ /* NOTE: would pass BM_EDGE except we are looping over all faces anyway. */
// BM_mesh_elem_index_ensure(bm, BM_LOOP); // NOT NEEDED FOR FACETAG
BM_ITER_MESH (f, &viter, bm, BM_FACES_OF_MESH) {
@@ -377,7 +377,7 @@ struct LinkNode *BM_mesh_calc_path_uv_face(BMesh *bm,
/* Start measuring face path at the face edges, ignoring their centers. */
const void *const f_endpoints[2] = {f_src, f_dst};
- /* Note, would pass BM_EDGE except we are looping over all faces anyway. */
+ /* NOTE: would pass BM_EDGE except we are looping over all faces anyway. */
// BM_mesh_elem_index_ensure(bm, BM_LOOP); // NOT NEEDED FOR FACETAG
{
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index c538d5b17cd..4ae5bfb7fb2 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -1053,7 +1053,7 @@ static BMEdge *bm_face_region_pivot_edge_find(BMFace **faces_region,
uint verts_region_len,
uint *r_depth)
{
- /* note, keep deterministic where possible (geometry order independent)
+ /* NOTE: keep deterministic where possible (geometry order independent)
* this function assumed all visit faces & edges are tagged */
BLI_LINKSTACK_DECLARE(vert_queue_prev, BMVert *);
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index de2deee2929..af4a4424103 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -77,7 +77,7 @@ static void bm_vert_boundary_tangent(
}
if (e_a && e_b) {
- /* note, with an incorrectly flushed selection this can crash */
+ /* NOTE: with an incorrectly flushed selection this can crash. */
l_a = bm_edge_tag_faceloop(e_a);
l_b = bm_edge_tag_faceloop(e_b);
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index ac59d832013..20b56ceb55f 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -59,6 +59,8 @@ set(SRC
intern/COM_ChunkOrderHotspot.h
intern/COM_CompositorContext.cc
intern/COM_CompositorContext.h
+ intern/COM_ConstantFolder.cc
+ intern/COM_ConstantFolder.h
intern/COM_Converter.cc
intern/COM_Converter.h
intern/COM_Debug.cc
@@ -66,6 +68,7 @@ set(SRC
intern/COM_Device.cc
intern/COM_Device.h
intern/COM_Enums.cc
+ intern/COM_Enums.h
intern/COM_ExecutionGroup.cc
intern/COM_ExecutionGroup.h
intern/COM_ExecutionModel.cc
@@ -82,6 +85,8 @@ set(SRC
intern/COM_MetaData.h
intern/COM_MultiThreadedOperation.cc
intern/COM_MultiThreadedOperation.h
+ intern/COM_MultiThreadedRowOperation.cc
+ intern/COM_MultiThreadedRowOperation.h
intern/COM_Node.cc
intern/COM_Node.h
intern/COM_NodeConverter.cc
@@ -442,6 +447,8 @@ set(SRC
operations/COM_BrightnessOperation.h
operations/COM_ColorCorrectionOperation.cc
operations/COM_ColorCorrectionOperation.h
+ operations/COM_ConstantOperation.cc
+ operations/COM_ConstantOperation.h
operations/COM_GammaOperation.cc
operations/COM_GammaOperation.h
operations/COM_MixOperation.cc
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 857cbf0beee..9f8e6f10215 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -60,9 +60,12 @@ constexpr int COM_data_type_num_channels(const DataType datatype)
}
constexpr int COM_DATA_TYPE_VALUE_CHANNELS = COM_data_type_num_channels(DataType::Value);
+constexpr int COM_DATA_TYPE_VECTOR_CHANNELS = COM_data_type_num_channels(DataType::Vector);
constexpr int COM_DATA_TYPE_COLOR_CHANNELS = COM_data_type_num_channels(DataType::Color);
+constexpr float COM_VECTOR_ZERO[3] = {0.0f, 0.0f, 0.0f};
constexpr float COM_VALUE_ZERO[1] = {0.0f};
+constexpr float COM_VALUE_ONE[1] = {1.0f};
/**
* Utility to get data type for given number of channels.
diff --git a/source/blender/compositor/intern/COM_BufferOperation.cc b/source/blender/compositor/intern/COM_BufferOperation.cc
index 8464d01801f..90c97f2a9c7 100644
--- a/source/blender/compositor/intern/COM_BufferOperation.cc
+++ b/source/blender/compositor/intern/COM_BufferOperation.cc
@@ -23,6 +23,7 @@ namespace blender::compositor {
BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type)
{
buffer_ = buffer;
+ inflated_buffer_ = nullptr;
/* TODO: Implement a MemoryBuffer get_size() method returning a Size2d type. Shorten following
* code to: set_resolution(buffer.get_size()) */
unsigned int resolution[2];
@@ -30,11 +31,30 @@ BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type)
resolution[1] = buffer->getHeight();
setResolution(resolution);
addOutputSocket(data_type);
+ flags.is_constant_operation = buffer_->is_a_single_elem();
+}
+
+const float *BufferOperation::get_constant_elem()
+{
+ BLI_assert(buffer_->is_a_single_elem());
+ return buffer_->getBuffer();
}
void *BufferOperation::initializeTileData(rcti * /*rect*/)
{
- return buffer_;
+ if (buffer_->is_a_single_elem() == false) {
+ return buffer_;
+ }
+
+ if (!inflated_buffer_) {
+ inflated_buffer_ = buffer_->inflate();
+ }
+ return inflated_buffer_;
+}
+
+void BufferOperation::deinitExecution()
+{
+ delete inflated_buffer_;
}
void BufferOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
diff --git a/source/blender/compositor/intern/COM_BufferOperation.h b/source/blender/compositor/intern/COM_BufferOperation.h
index f87cd4db94e..705264c37b7 100644
--- a/source/blender/compositor/intern/COM_BufferOperation.h
+++ b/source/blender/compositor/intern/COM_BufferOperation.h
@@ -18,18 +18,21 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
namespace blender::compositor {
-class BufferOperation : public NodeOperation {
+class BufferOperation : public ConstantOperation {
private:
MemoryBuffer *buffer_;
+ MemoryBuffer *inflated_buffer_;
public:
BufferOperation(MemoryBuffer *buffer, DataType data_type);
+ const float *get_constant_elem() override;
void *initializeTileData(rcti *rect) override;
+ void deinitExecution() override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]) override;
};
diff --git a/source/blender/compositor/intern/COM_CompositorContext.cc b/source/blender/compositor/intern/COM_CompositorContext.cc
index 61e299c045e..a93820b66dc 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.cc
+++ b/source/blender/compositor/intern/COM_CompositorContext.cc
@@ -53,7 +53,7 @@ eExecutionModel CompositorContext::get_execution_model() const
case 0:
return eExecutionModel::Tiled;
default:
- BLI_assert(!"Invalid execution mode");
+ BLI_assert_msg(0, "Invalid execution mode");
}
}
return eExecutionModel::Tiled;
diff --git a/source/blender/compositor/intern/COM_ConstantFolder.cc b/source/blender/compositor/intern/COM_ConstantFolder.cc
new file mode 100644
index 00000000000..f20324de342
--- /dev/null
+++ b/source/blender/compositor/intern/COM_ConstantFolder.cc
@@ -0,0 +1,191 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "BLI_rect.h"
+
+#include "COM_ConstantFolder.h"
+#include "COM_ConstantOperation.h"
+#include "COM_SetColorOperation.h"
+#include "COM_SetValueOperation.h"
+#include "COM_SetVectorOperation.h"
+#include "COM_WorkScheduler.h"
+
+namespace blender::compositor {
+
+using Link = NodeOperationBuilder::Link;
+
+/**
+ * \param operations_builder: Contains all operations to fold.
+ * \param exec_system: Execution system.
+ */
+ConstantFolder::ConstantFolder(NodeOperationBuilder &operations_builder)
+ : operations_builder_(operations_builder)
+{
+ BLI_rcti_init(&max_area_, INT_MIN, INT_MAX, INT_MIN, INT_MAX);
+ BLI_rcti_init(&first_elem_area_, 0, 1, 0, 1);
+}
+
+static bool is_constant_foldable(NodeOperation *operation)
+{
+ if (operation->get_flags().can_be_constant && !operation->get_flags().is_constant_operation) {
+ for (int i = 0; i < operation->getNumberOfInputSockets(); i++) {
+ if (!operation->get_input_operation(i)->get_flags().is_constant_operation) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+static Vector<NodeOperation *> find_constant_foldable_operations(Span<NodeOperation *> operations)
+{
+ Vector<NodeOperation *> foldable_ops;
+ for (NodeOperation *op : operations) {
+ if (is_constant_foldable(op)) {
+ foldable_ops.append(op);
+ }
+ }
+ return foldable_ops;
+}
+
+static ConstantOperation *create_constant_operation(DataType data_type, const float *constant_elem)
+{
+ switch (data_type) {
+ case DataType::Color: {
+ SetColorOperation *color_op = new SetColorOperation();
+ color_op->setChannels(constant_elem);
+ return color_op;
+ }
+ case DataType::Vector: {
+ SetVectorOperation *vector_op = new SetVectorOperation();
+ vector_op->setVector(constant_elem);
+ return vector_op;
+ }
+ case DataType::Value: {
+ SetValueOperation *value_op = new SetValueOperation();
+ value_op->setValue(*constant_elem);
+ return value_op;
+ }
+ default: {
+ BLI_assert_msg(0, "Non implemented data type");
+ return nullptr;
+ }
+ }
+}
+
+ConstantOperation *ConstantFolder::fold_operation(NodeOperation *operation)
+{
+ const DataType data_type = operation->getOutputSocket()->getDataType();
+ MemoryBuffer fold_buf(data_type, first_elem_area_);
+ Vector<MemoryBuffer *> input_bufs = get_constant_input_buffers(operation);
+ operation->render(&fold_buf, {first_elem_area_}, input_bufs);
+
+ MemoryBuffer *constant_buf = create_constant_buffer(data_type);
+ constant_buf->copy_from(&fold_buf, first_elem_area_);
+ ConstantOperation *constant_op = create_constant_operation(data_type, constant_buf->getBuffer());
+ operations_builder_.replace_operation_with_constant(operation, constant_op);
+ constant_buffers_.add_new(constant_op, constant_buf);
+ return constant_op;
+}
+
+MemoryBuffer *ConstantFolder::create_constant_buffer(const DataType data_type)
+{
+ /* Create a single elem buffer with maximum area possible so readers can read any coordinate
+ * returning always same element. */
+ return new MemoryBuffer(data_type, max_area_, true);
+}
+
+Vector<MemoryBuffer *> ConstantFolder::get_constant_input_buffers(NodeOperation *operation)
+{
+ const int num_inputs = operation->getNumberOfInputSockets();
+ Vector<MemoryBuffer *> inputs_bufs(num_inputs);
+ for (int i = 0; i < num_inputs; i++) {
+ BLI_assert(operation->get_input_operation(i)->get_flags().is_constant_operation);
+ ConstantOperation *constant_op = static_cast<ConstantOperation *>(
+ operation->get_input_operation(i));
+ MemoryBuffer *constant_buf = constant_buffers_.lookup_or_add_cb(constant_op, [=] {
+ MemoryBuffer *buf = create_constant_buffer(constant_op->getOutputSocket()->getDataType());
+ constant_op->render(buf, {first_elem_area_}, {});
+ return buf;
+ });
+ inputs_bufs[i] = constant_buf;
+ }
+ return inputs_bufs;
+}
+
+/** Returns constant operations resulted from folded operations. */
+Vector<ConstantOperation *> ConstantFolder::try_fold_operations(Span<NodeOperation *> operations)
+{
+ Vector<NodeOperation *> foldable_ops = find_constant_foldable_operations(operations);
+ if (foldable_ops.size() == 0) {
+ return Vector<ConstantOperation *>();
+ }
+
+ Vector<ConstantOperation *> new_folds;
+ for (NodeOperation *op : foldable_ops) {
+ ConstantOperation *constant_op = fold_operation(op);
+ new_folds.append(constant_op);
+ }
+ return new_folds;
+}
+
+/**
+ * Evaluate operations with constant elements into primitive constant operations.
+ */
+int ConstantFolder::fold_operations()
+{
+ WorkScheduler::start(operations_builder_.context());
+ Vector<ConstantOperation *> last_folds = try_fold_operations(
+ operations_builder_.get_operations());
+ int folds_count = last_folds.size();
+ while (last_folds.size() > 0) {
+ Vector<NodeOperation *> ops_to_fold;
+ for (ConstantOperation *fold : last_folds) {
+ get_operation_output_operations(fold, ops_to_fold);
+ }
+ last_folds = try_fold_operations(ops_to_fold);
+ folds_count += last_folds.size();
+ }
+ WorkScheduler::stop();
+
+ delete_constant_buffers();
+
+ return folds_count;
+}
+
+void ConstantFolder::delete_constant_buffers()
+{
+ for (MemoryBuffer *buf : constant_buffers_.values()) {
+ delete buf;
+ }
+ constant_buffers_.clear();
+}
+
+void ConstantFolder::get_operation_output_operations(NodeOperation *operation,
+ Vector<NodeOperation *> &r_outputs)
+{
+ const Vector<Link> &links = operations_builder_.get_links();
+ for (const Link &link : links) {
+ if (&link.from()->getOperation() == operation) {
+ r_outputs.append(&link.to()->getOperation());
+ }
+ }
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ConstantFolder.h b/source/blender/compositor/intern/COM_ConstantFolder.h
new file mode 100644
index 00000000000..2432e859a5a
--- /dev/null
+++ b/source/blender/compositor/intern/COM_ConstantFolder.h
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "BLI_map.hh"
+#include "BLI_set.hh"
+#include "BLI_vector.hh"
+
+#include "COM_NodeOperationBuilder.h"
+#include "COM_defines.h"
+
+namespace blender::compositor {
+
+class NodeOperation;
+class ConstantOperation;
+class MemoryBuffer;
+
+/**
+ * Evaluates all operations with constant elements into primitive constant operations
+ * (Value/Vector/Color).
+ */
+class ConstantFolder {
+ private:
+ NodeOperationBuilder &operations_builder_;
+
+ /** Constant operations buffers. */
+ Map<ConstantOperation *, MemoryBuffer *> constant_buffers_;
+
+ rcti max_area_;
+ rcti first_elem_area_;
+
+ public:
+ ConstantFolder(NodeOperationBuilder &operations_builder);
+ int fold_operations();
+
+ private:
+ Vector<ConstantOperation *> try_fold_operations(Span<NodeOperation *> operations);
+ ConstantOperation *fold_operation(NodeOperation *operation);
+
+ MemoryBuffer *create_constant_buffer(DataType data_type);
+ Vector<MemoryBuffer *> get_constant_input_buffers(NodeOperation *operation);
+ void delete_constant_buffers();
+
+ void get_operation_output_operations(NodeOperation *operation,
+ Vector<NodeOperation *> &r_outputs);
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Converter.cc b/source/blender/compositor/intern/COM_Converter.cc
index af593b2e1b5..18973bb5a00 100644
--- a/source/blender/compositor/intern/COM_Converter.cc
+++ b/source/blender/compositor/intern/COM_Converter.cc
@@ -460,6 +460,9 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
NodeOperationOutput *fromSocket,
NodeOperationInput *toSocket)
{
+ /* Data type conversions are executed before resolutions to ensure convert operations have
+ * resolution. This method have to ensure same datatypes are linked for new operations. */
+ BLI_assert(fromSocket->getDataType() == toSocket->getDataType());
ResizeMode mode = toSocket->getResizeMode();
NodeOperation *toOperation = &toSocket->getOperation();
@@ -515,7 +518,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
NodeOperation *first = nullptr;
ScaleOperation *scaleOperation = nullptr;
if (doScale) {
- scaleOperation = new ScaleOperation();
+ scaleOperation = new ScaleOperation(fromSocket->getDataType());
scaleOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
scaleOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
first = scaleOperation;
@@ -535,7 +538,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
builder.addOperation(scaleOperation);
}
- TranslateOperation *translateOperation = new TranslateOperation();
+ TranslateOperation *translateOperation = new TranslateOperation(toSocket->getDataType());
translateOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
translateOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
if (!first) {
diff --git a/source/blender/compositor/intern/COM_Debug.cc b/source/blender/compositor/intern/COM_Debug.cc
index 4cf7e09a7d8..abef4517b3e 100644
--- a/source/blender/compositor/intern/COM_Debug.cc
+++ b/source/blender/compositor/intern/COM_Debug.cc
@@ -37,6 +37,7 @@ extern "C" {
#include "COM_Node.h"
#include "COM_ReadBufferOperation.h"
+#include "COM_SetValueOperation.h"
#include "COM_ViewerOperation.h"
#include "COM_WriteBufferOperation.h"
@@ -49,6 +50,15 @@ std::string DebugInfo::m_current_node_name;
std::string DebugInfo::m_current_op_name;
DebugInfo::GroupStateMap DebugInfo::m_group_states;
+static std::string operation_class_name(NodeOperation *op)
+{
+ std::string full_name = typeid(*op).name();
+ /* Remove name-spaces. */
+ size_t pos = full_name.find_last_of(':');
+ BLI_assert(pos != std::string::npos);
+ return full_name.substr(pos + 1);
+}
+
std::string DebugInfo::node_name(const Node *node)
{
NodeNameMap::const_iterator it = m_node_names.find(node);
@@ -135,15 +145,23 @@ int DebugInfo::graphviz_operation(const ExecutionSystem *system,
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
}
+ if (COM_GRAPHVIZ_SHOW_NODE_NAME) {
+ std::string op_node_name = operation->get_name();
+ if (!op_node_name.empty()) {
+ len += snprintf(
+ str + len, maxlen > len ? maxlen - len : 0, "%s\\n", (op_node_name + " Node").c_str());
+ }
+ }
+
len += snprintf(str + len,
maxlen > len ? maxlen - len : 0,
- "%s\\n(%s)",
- m_op_names[operation].c_str(),
- typeid(*operation).name());
+ "%s\\n",
+ operation_class_name(operation).c_str());
len += snprintf(str + len,
maxlen > len ? maxlen - len : 0,
- " (%u,%u)",
+ "#%d (%u,%u)",
+ operation->get_id(),
operation->getWidth(),
operation->getHeight());
@@ -159,7 +177,13 @@ int DebugInfo::graphviz_operation(const ExecutionSystem *system,
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<OUT_%p>", socket);
switch (socket->getDataType()) {
case DataType::Value:
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
+ if (typeid(*operation) == typeid(SetValueOperation)) {
+ const float value = ((SetValueOperation *)operation)->getValue();
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value\\n%12.4g", value);
+ }
+ else {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
+ }
break;
case DataType::Vector:
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
@@ -401,7 +425,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
return (len < maxlen);
}
-void DebugInfo::graphviz(const ExecutionSystem *system)
+void DebugInfo::graphviz(const ExecutionSystem *system, StringRefNull name)
{
if (!COM_EXPORT_GRAPHVIZ) {
return;
@@ -411,7 +435,12 @@ void DebugInfo::graphviz(const ExecutionSystem *system)
char basename[FILE_MAX];
char filename[FILE_MAX];
- BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
+ if (name.is_empty()) {
+ BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
+ }
+ else {
+ BLI_strncpy(basename, (name + ".dot").c_str(), sizeof(basename));
+ }
BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), basename);
m_file_index++;
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
index 0de3a5e39dc..53461e13f48 100644
--- a/source/blender/compositor/intern/COM_Debug.h
+++ b/source/blender/compositor/intern/COM_Debug.h
@@ -28,6 +28,8 @@
namespace blender::compositor {
static constexpr bool COM_EXPORT_GRAPHVIZ = false;
+static constexpr bool COM_GRAPHVIZ_SHOW_NODE_NAME = false;
+
class Node;
class ExecutionSystem;
class ExecutionGroup;
@@ -116,7 +118,7 @@ class DebugInfo {
}
};
- static void graphviz(const ExecutionSystem *system);
+ static void graphviz(const ExecutionSystem *system, StringRefNull name = "");
protected:
static int graphviz_operation(const ExecutionSystem *system,
diff --git a/source/blender/compositor/intern/COM_ExecutionModel.cc b/source/blender/compositor/intern/COM_ExecutionModel.cc
index 4d7f62e091b..b75b277e92c 100644
--- a/source/blender/compositor/intern/COM_ExecutionModel.cc
+++ b/source/blender/compositor/intern/COM_ExecutionModel.cc
@@ -39,10 +39,4 @@ ExecutionModel::ExecutionModel(CompositorContext &context, Span<NodeOperation *>
border_.render_border = &rd->border;
}
-bool ExecutionModel::is_breaked() const
-{
- const bNodeTree *btree = context_.getbNodeTree();
- return btree->test_break(btree->tbh);
-}
-
} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionModel.h b/source/blender/compositor/intern/COM_ExecutionModel.h
index 9e8466b9282..452861ae4be 100644
--- a/source/blender/compositor/intern/COM_ExecutionModel.h
+++ b/source/blender/compositor/intern/COM_ExecutionModel.h
@@ -67,15 +67,6 @@ class ExecutionModel {
virtual void execute(ExecutionSystem &exec_system) = 0;
- virtual void execute_work(const rcti &UNUSED(work_rect),
- std::function<void(const rcti &split_rect)> UNUSED(work_func))
- {
- BLI_assert(!"Method not supported by current execution model");
- }
-
- protected:
- bool is_breaked() const;
-
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:BaseExecutionModel")
#endif
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cc b/source/blender/compositor/intern/COM_ExecutionSystem.cc
index a12ec774032..60caf22be1b 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cc
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cc
@@ -63,8 +63,11 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
this->m_context.setViewSettings(viewSettings);
this->m_context.setDisplaySettings(displaySettings);
+ BLI_mutex_init(&work_mutex_);
+ BLI_condition_init(&work_finished_cond_);
+
{
- NodeOperationBuilder builder(&m_context, editingtree);
+ NodeOperationBuilder builder(&m_context, editingtree, this);
builder.convertToOperations(this);
}
@@ -76,13 +79,16 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
execution_model_ = new FullFrameExecutionModel(m_context, active_buffers_, m_operations);
break;
default:
- BLI_assert(!"Non implemented execution model");
+ BLI_assert_msg(0, "Non implemented execution model");
break;
}
}
ExecutionSystem::~ExecutionSystem()
{
+ BLI_condition_end(&work_finished_cond_);
+ BLI_mutex_end(&work_mutex_);
+
delete execution_model_;
for (NodeOperation *operation : m_operations) {
@@ -109,10 +115,74 @@ void ExecutionSystem::execute()
execution_model_->execute(*this);
}
+/**
+ * Multi-threadedly execute given work function passing work_rect splits as argument.
+ */
void ExecutionSystem::execute_work(const rcti &work_rect,
std::function<void(const rcti &split_rect)> work_func)
{
- execution_model_->execute_work(work_rect, work_func);
+ if (is_breaked()) {
+ return;
+ }
+
+ /* Split work vertically to maximize continuous memory. */
+ const int work_height = BLI_rcti_size_y(&work_rect);
+ const int num_sub_works = MIN2(WorkScheduler::get_num_cpu_threads(), work_height);
+ const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works;
+ int remaining_height = work_height - split_height * num_sub_works;
+
+ Vector<WorkPackage> sub_works(num_sub_works);
+ int sub_work_y = work_rect.ymin;
+ int num_sub_works_finished = 0;
+ for (int i = 0; i < num_sub_works; i++) {
+ int sub_work_height = split_height;
+
+ /* Distribute remaining height between sub-works. */
+ if (remaining_height > 0) {
+ sub_work_height++;
+ remaining_height--;
+ }
+
+ WorkPackage &sub_work = sub_works[i];
+ sub_work.type = eWorkPackageType::CustomFunction;
+ sub_work.execute_fn = [=, &work_func, &work_rect]() {
+ if (is_breaked()) {
+ return;
+ }
+ rcti split_rect;
+ BLI_rcti_init(
+ &split_rect, work_rect.xmin, work_rect.xmax, sub_work_y, sub_work_y + sub_work_height);
+ work_func(split_rect);
+ };
+ sub_work.executed_fn = [&]() {
+ BLI_mutex_lock(&work_mutex_);
+ num_sub_works_finished++;
+ if (num_sub_works_finished == num_sub_works) {
+ BLI_condition_notify_one(&work_finished_cond_);
+ }
+ BLI_mutex_unlock(&work_mutex_);
+ };
+ WorkScheduler::schedule(&sub_work);
+ sub_work_y += sub_work_height;
+ }
+ BLI_assert(sub_work_y == work_rect.ymax);
+
+ WorkScheduler::finish();
+
+ /* Ensure all sub-works finished.
+ * TODO: This a workaround for WorkScheduler::finish() not waiting all works on queue threading
+ * model. Sync code should be removed once it's fixed. */
+ BLI_mutex_lock(&work_mutex_);
+ if (num_sub_works_finished < num_sub_works) {
+ BLI_condition_wait(&work_finished_cond_, &work_mutex_);
+ }
+ BLI_mutex_unlock(&work_mutex_);
+}
+
+bool ExecutionSystem::is_breaked() const
+{
+ const bNodeTree *btree = m_context.getbNodeTree();
+ return btree->test_break(btree->tbh);
}
} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index e106209651c..38c3432a8ec 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -150,7 +150,9 @@ class ExecutionSystem {
*/
ExecutionModel *execution_model_;
- private: // methods
+ ThreadMutex work_mutex_;
+ ThreadCondition work_finished_cond_;
+
public:
/**
* \brief Create a new ExecutionSystem and initialize it with the
@@ -199,6 +201,8 @@ class ExecutionSystem {
void execute_work(const rcti &work_rect, std::function<void(const rcti &split_rect)> work_func);
+ bool is_breaked() const;
+
private:
/* allow the DebugInfo class to look at internals */
friend class DebugInfo;
diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
index 21075bb7255..3b0a9172871 100644
--- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
+++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc
@@ -35,24 +35,13 @@ FullFrameExecutionModel::FullFrameExecutionModel(CompositorContext &context,
Span<NodeOperation *> operations)
: ExecutionModel(context, operations),
active_buffers_(shared_buffers),
- num_operations_finished_(0),
- work_mutex_(),
- work_finished_cond_()
+ num_operations_finished_(0)
{
priorities_.append(eCompositorPriority::High);
if (!context.isFastCalculation()) {
priorities_.append(eCompositorPriority::Medium);
priorities_.append(eCompositorPriority::Low);
}
-
- BLI_mutex_init(&work_mutex_);
- BLI_condition_init(&work_finished_cond_);
-}
-
-FullFrameExecutionModel::~FullFrameExecutionModel()
-{
- BLI_condition_end(&work_finished_cond_);
- BLI_mutex_end(&work_mutex_);
}
void FullFrameExecutionModel::execute(ExecutionSystem &exec_system)
@@ -60,10 +49,10 @@ void FullFrameExecutionModel::execute(ExecutionSystem &exec_system)
const bNodeTree *node_tree = this->context_.getbNodeTree();
node_tree->stats_draw(node_tree->sdh, TIP_("Compositing | Initializing execution"));
- DebugInfo::graphviz(&exec_system);
+ DebugInfo::graphviz(&exec_system, "compositor_prior_rendering");
determine_areas_to_render_and_reads();
- render_operations(exec_system);
+ render_operations();
}
void FullFrameExecutionModel::determine_areas_to_render_and_reads()
@@ -101,20 +90,18 @@ MemoryBuffer *FullFrameExecutionModel::create_operation_buffer(NodeOperation *op
BLI_rcti_init(&op_rect, 0, op->getWidth(), 0, op->getHeight());
const DataType data_type = op->getOutputSocket(0)->getDataType();
- /* TODO: We should check if the operation is constant instead of is_set_operation. Finding a way
- * to know if an operation is constant has to be implemented yet. */
- const bool is_a_single_elem = op->get_flags().is_set_operation;
+ const bool is_a_single_elem = op->get_flags().is_constant_operation;
return new MemoryBuffer(data_type, op_rect, is_a_single_elem);
}
-void FullFrameExecutionModel::render_operation(NodeOperation *op, ExecutionSystem &exec_system)
+void FullFrameExecutionModel::render_operation(NodeOperation *op)
{
Vector<MemoryBuffer *> input_bufs = get_input_buffers(op);
const bool has_outputs = op->getNumberOfOutputSockets() > 0;
MemoryBuffer *op_buf = has_outputs ? create_operation_buffer(op) : nullptr;
Span<rcti> areas = active_buffers_.get_areas_to_render(op);
- op->render(op_buf, areas, input_bufs, exec_system);
+ op->render(op_buf, areas, input_bufs);
active_buffers_.set_rendered_buffer(op, std::unique_ptr<MemoryBuffer>(op_buf));
operation_finished(op);
@@ -123,7 +110,7 @@ void FullFrameExecutionModel::render_operation(NodeOperation *op, ExecutionSyste
/**
* Render output operations in order of priority.
*/
-void FullFrameExecutionModel::render_operations(ExecutionSystem &exec_system)
+void FullFrameExecutionModel::render_operations()
{
const bool is_rendering = context_.isRendering();
@@ -131,8 +118,8 @@ void FullFrameExecutionModel::render_operations(ExecutionSystem &exec_system)
for (eCompositorPriority priority : priorities_) {
for (NodeOperation *op : operations_) {
if (op->isOutputOperation(is_rendering) && op->getRenderPriority() == priority) {
- render_output_dependencies(op, exec_system);
- render_operation(op, exec_system);
+ render_output_dependencies(op);
+ render_operation(op);
}
}
}
@@ -166,14 +153,13 @@ static Vector<NodeOperation *> get_operation_dependencies(NodeOperation *operati
return dependencies;
}
-void FullFrameExecutionModel::render_output_dependencies(NodeOperation *output_op,
- ExecutionSystem &exec_system)
+void FullFrameExecutionModel::render_output_dependencies(NodeOperation *output_op)
{
BLI_assert(output_op->isOutputOperation(context_.isRendering()));
Vector<NodeOperation *> dependencies = get_operation_dependencies(output_op);
for (NodeOperation *op : dependencies) {
if (!active_buffers_.is_operation_rendered(op)) {
- render_operation(op, exec_system);
+ render_operation(op);
}
}
}
@@ -266,70 +252,6 @@ void FullFrameExecutionModel::get_output_render_area(NodeOperation *output_op, r
}
}
-/**
- * Multi-threadedly execute given work function passing work_rect splits as argument.
- */
-void FullFrameExecutionModel::execute_work(const rcti &work_rect,
- std::function<void(const rcti &split_rect)> work_func)
-{
- if (is_breaked()) {
- return;
- }
-
- /* Split work vertically to maximize continuous memory. */
- const int work_height = BLI_rcti_size_y(&work_rect);
- const int num_sub_works = MIN2(WorkScheduler::get_num_cpu_threads(), work_height);
- const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works;
- int remaining_height = work_height - split_height * num_sub_works;
-
- Vector<WorkPackage> sub_works(num_sub_works);
- int sub_work_y = work_rect.ymin;
- int num_sub_works_finished = 0;
- for (int i = 0; i < num_sub_works; i++) {
- int sub_work_height = split_height;
-
- /* Distribute remaining height between sub-works. */
- if (remaining_height > 0) {
- sub_work_height++;
- remaining_height--;
- }
-
- WorkPackage &sub_work = sub_works[i];
- sub_work.type = eWorkPackageType::CustomFunction;
- sub_work.execute_fn = [=, &work_func, &work_rect]() {
- if (is_breaked()) {
- return;
- }
- rcti split_rect;
- BLI_rcti_init(
- &split_rect, work_rect.xmin, work_rect.xmax, sub_work_y, sub_work_y + sub_work_height);
- work_func(split_rect);
- };
- sub_work.executed_fn = [&]() {
- BLI_mutex_lock(&work_mutex_);
- num_sub_works_finished++;
- if (num_sub_works_finished == num_sub_works) {
- BLI_condition_notify_one(&work_finished_cond_);
- }
- BLI_mutex_unlock(&work_mutex_);
- };
- WorkScheduler::schedule(&sub_work);
- sub_work_y += sub_work_height;
- }
- BLI_assert(sub_work_y == work_rect.ymax);
-
- WorkScheduler::finish();
-
- /* Ensure all sub-works finished.
- * TODO: This a workaround for WorkScheduler::finish() not waiting all works on queue threading
- * model. Sync code should be removed once it's fixed. */
- BLI_mutex_lock(&work_mutex_);
- if (num_sub_works_finished < num_sub_works) {
- BLI_condition_wait(&work_finished_cond_, &work_mutex_);
- }
- BLI_mutex_unlock(&work_mutex_);
-}
-
void FullFrameExecutionModel::operation_finished(NodeOperation *operation)
{
/* Report inputs reads so that buffers may be freed/reused. */
diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.h b/source/blender/compositor/intern/COM_FullFrameExecutionModel.h
index e68ad93b407..f75d4f1afdc 100644
--- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.h
+++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.h
@@ -50,27 +50,20 @@ class FullFrameExecutionModel : public ExecutionModel {
*/
Vector<eCompositorPriority> priorities_;
- ThreadMutex work_mutex_;
- ThreadCondition work_finished_cond_;
-
public:
FullFrameExecutionModel(CompositorContext &context,
SharedOperationBuffers &shared_buffers,
Span<NodeOperation *> operations);
- ~FullFrameExecutionModel();
void execute(ExecutionSystem &exec_system) override;
- void execute_work(const rcti &work_rect,
- std::function<void(const rcti &split_rect)> work_func) override;
-
private:
void determine_areas_to_render_and_reads();
- void render_operations(ExecutionSystem &exec_system);
- void render_output_dependencies(NodeOperation *output_op, ExecutionSystem &exec_system);
+ void render_operations();
+ void render_output_dependencies(NodeOperation *output_op);
Vector<MemoryBuffer *> get_input_buffers(NodeOperation *op);
MemoryBuffer *create_operation_buffer(NodeOperation *op);
- void render_operation(NodeOperation *op, ExecutionSystem &exec_system);
+ void render_operation(NodeOperation *op);
void operation_finished(NodeOperation *operation);
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc
index 44d3f059374..c7bddddd0e6 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cc
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc
@@ -129,6 +129,18 @@ void MemoryBuffer::clear()
memset(m_buffer, 0, buffer_len() * m_num_channels * sizeof(float));
}
+/**
+ * Converts a single elem buffer to a full size buffer (allocates memory for all
+ * elements in resolution).
+ */
+MemoryBuffer *MemoryBuffer::inflate() const
+{
+ BLI_assert(is_a_single_elem());
+ MemoryBuffer *inflated = new MemoryBuffer(this->m_datatype, this->m_rect, false);
+ inflated->copy_from(this, this->m_rect);
+ return inflated;
+}
+
float MemoryBuffer::get_max_value() const
{
float result = this->m_buffer[0];
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index fdfd1c1c37b..4ad0872b0b7 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -247,6 +247,8 @@ class MemoryBuffer {
return this->m_buffer;
}
+ MemoryBuffer *inflate() const;
+
inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
{
const int w = getWidth();
@@ -262,11 +264,14 @@ class MemoryBuffer {
x = 0;
}
if (x >= w) {
- x = w;
+ x = w - 1;
}
break;
case MemoryBufferExtend::Repeat:
- x = (x >= 0.0f ? (x % w) : (x % w) + w);
+ x %= w;
+ if (x < 0) {
+ x += w;
+ }
break;
}
@@ -278,13 +283,19 @@ class MemoryBuffer {
y = 0;
}
if (y >= h) {
- y = h;
+ y = h - 1;
}
break;
case MemoryBufferExtend::Repeat:
- y = (y >= 0.0f ? (y % h) : (y % h) + h);
+ y %= h;
+ if (y < 0) {
+ y += h;
+ }
break;
}
+
+ x = x + m_rect.xmin;
+ y = y + m_rect.ymin;
}
inline void wrap_pixel(float &x,
@@ -305,11 +316,14 @@ class MemoryBuffer {
x = 0.0f;
}
if (x >= w) {
- x = w;
+ x = w - 1;
}
break;
case MemoryBufferExtend::Repeat:
x = fmodf(x, w);
+ if (x < 0.0f) {
+ x += w;
+ }
break;
}
@@ -321,13 +335,19 @@ class MemoryBuffer {
y = 0.0f;
}
if (y >= h) {
- y = h;
+ y = h - 1;
}
break;
case MemoryBufferExtend::Repeat:
y = fmodf(y, h);
+ if (y < 0.0f) {
+ y += h;
+ }
break;
}
+
+ x = x + m_rect.xmin;
+ y = y + m_rect.ymin;
}
inline void read(float *result,
diff --git a/source/blender/compositor/intern/COM_MultiThreadedOperation.cc b/source/blender/compositor/intern/COM_MultiThreadedOperation.cc
index e6e98d69b36..7ccf6f76d9f 100644
--- a/source/blender/compositor/intern/COM_MultiThreadedOperation.cc
+++ b/source/blender/compositor/intern/COM_MultiThreadedOperation.cc
@@ -12,12 +12,11 @@ MultiThreadedOperation::MultiThreadedOperation()
void MultiThreadedOperation::update_memory_buffer(MemoryBuffer *output,
const rcti &area,
- Span<MemoryBuffer *> inputs,
- ExecutionSystem &exec_system)
+ Span<MemoryBuffer *> inputs)
{
for (current_pass_ = 0; current_pass_ < num_passes_; current_pass_++) {
update_memory_buffer_started(output, area, inputs);
- exec_system.execute_work(area, [=](const rcti &split_rect) {
+ exec_system_->execute_work(area, [=](const rcti &split_rect) {
update_memory_buffer_partial(output, split_rect, inputs);
});
update_memory_buffer_finished(output, area, inputs);
diff --git a/source/blender/compositor/intern/COM_MultiThreadedOperation.h b/source/blender/compositor/intern/COM_MultiThreadedOperation.h
index ad09c4df089..a7e574ca745 100644
--- a/source/blender/compositor/intern/COM_MultiThreadedOperation.h
+++ b/source/blender/compositor/intern/COM_MultiThreadedOperation.h
@@ -64,8 +64,7 @@ class MultiThreadedOperation : public NodeOperation {
private:
void update_memory_buffer(MemoryBuffer *output,
const rcti &area,
- Span<MemoryBuffer *> inputs,
- ExecutionSystem &exec_system) override;
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc
new file mode 100644
index 00000000000..6bf318bb96b
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.cc
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_MultiThreadedRowOperation.h"
+
+namespace blender::compositor {
+
+MultiThreadedRowOperation::PixelCursor::PixelCursor(const int num_inputs)
+ : out(nullptr), out_stride(0), row_end(nullptr), ins(num_inputs), in_strides(num_inputs)
+{
+}
+
+void MultiThreadedRowOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ BLI_assert(output != nullptr);
+ const int width = BLI_rcti_size_x(&area);
+ PixelCursor p(inputs.size());
+ p.out_stride = output->elem_stride;
+ for (int i = 0; i < p.in_strides.size(); i++) {
+ p.in_strides[i] = inputs[i]->elem_stride;
+ }
+
+ for (int y = area.ymin; y < area.ymax; y++) {
+ p.out = output->get_elem(area.xmin, y);
+ for (int i = 0; i < p.ins.size(); i++) {
+ p.ins[i] = inputs[i]->get_elem(area.xmin, y);
+ }
+ p.row_end = p.out + width * p.out_stride;
+ update_memory_buffer_row(p);
+ }
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MultiThreadedRowOperation.h b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.h
new file mode 100644
index 00000000000..3daa9eec474
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MultiThreadedRowOperation.h
@@ -0,0 +1,60 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_MultiThreadedOperation.h"
+
+namespace blender::compositor {
+
+/**
+ * Executes buffer updates per row. To be inherited only by operations with correlated coordinates
+ * between inputs and output.
+ */
+class MultiThreadedRowOperation : public MultiThreadedOperation {
+ protected:
+ struct PixelCursor {
+ float *out;
+ int out_stride;
+ const float *row_end;
+ Array<const float *> ins;
+ Array<int> in_strides;
+
+ public:
+ PixelCursor(int num_inputs);
+
+ void next()
+ {
+ BLI_assert(out < row_end);
+ out += out_stride;
+ for (int i = 0; i < ins.size(); i++) {
+ ins[i] += in_strides[i];
+ }
+ }
+ };
+
+ protected:
+ virtual void update_memory_buffer_row(PixelCursor &p) = 0;
+
+ private:
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) final;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cc b/source/blender/compositor/intern/COM_NodeGraph.cc
index fbe56dd4b5a..205fbcc0440 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cc
+++ b/source/blender/compositor/intern/COM_NodeGraph.cc
@@ -174,7 +174,7 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink
return;
}
- /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
+ /* NOTE: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
* The output then gets linked to each one of them.
*/
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cc b/source/blender/compositor/intern/COM_NodeOperation.cc
index b943ab6af7f..4e115cb3f2f 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cc
+++ b/source/blender/compositor/intern/COM_NodeOperation.cc
@@ -218,7 +218,7 @@ void NodeOperation::get_area_of_interest(NodeOperation *input_op,
return;
}
}
- BLI_assert(!"input_op is not an input operation.");
+ BLI_assert_msg(0, "input_op is not an input operation.");
}
/**
@@ -226,18 +226,16 @@ void NodeOperation::get_area_of_interest(NodeOperation *input_op,
* \param output_buf: Buffer to write result to.
* \param areas: Areas within this operation bounds to render.
* \param inputs_bufs: Inputs operations buffers.
- * \param exec_system: Execution system.
*/
void NodeOperation::render(MemoryBuffer *output_buf,
Span<rcti> areas,
- Span<MemoryBuffer *> inputs_bufs,
- ExecutionSystem &exec_system)
+ Span<MemoryBuffer *> inputs_bufs)
{
if (get_flags().is_fullframe_operation) {
- render_full_frame(output_buf, areas, inputs_bufs, exec_system);
+ render_full_frame(output_buf, areas, inputs_bufs);
}
else {
- render_full_frame_fallback(output_buf, areas, inputs_bufs, exec_system);
+ render_full_frame_fallback(output_buf, areas, inputs_bufs);
}
}
@@ -246,12 +244,11 @@ void NodeOperation::render(MemoryBuffer *output_buf,
*/
void NodeOperation::render_full_frame(MemoryBuffer *output_buf,
Span<rcti> areas,
- Span<MemoryBuffer *> inputs_bufs,
- ExecutionSystem &exec_system)
+ Span<MemoryBuffer *> inputs_bufs)
{
initExecution();
for (const rcti &area : areas) {
- update_memory_buffer(output_buf, area, inputs_bufs, exec_system);
+ update_memory_buffer(output_buf, area, inputs_bufs);
}
deinitExecution();
}
@@ -261,8 +258,7 @@ void NodeOperation::render_full_frame(MemoryBuffer *output_buf,
*/
void NodeOperation::render_full_frame_fallback(MemoryBuffer *output_buf,
Span<rcti> areas,
- Span<MemoryBuffer *> inputs_bufs,
- ExecutionSystem &exec_system)
+ Span<MemoryBuffer *> inputs_bufs)
{
Vector<NodeOperationOutput *> orig_input_links = replace_inputs_with_buffers(inputs_bufs);
@@ -274,7 +270,7 @@ void NodeOperation::render_full_frame_fallback(MemoryBuffer *output_buf,
}
else {
for (const rcti &rect : areas) {
- exec_system.execute_work(rect, [=](const rcti &split_rect) {
+ exec_system_->execute_work(rect, [=](const rcti &split_rect) {
rcti tile_rect = split_rect;
if (is_output_operation) {
executeRegion(&tile_rect, 0);
@@ -328,6 +324,7 @@ Vector<NodeOperationOutput *> NodeOperation::replace_inputs_with_buffers(
BufferOperation *buffer_op = new BufferOperation(inputs_bufs[i], input_socket->getDataType());
orig_links[i] = input_socket->getLink();
input_socket->setLink(buffer_op->getOutputSocket());
+ buffer_op->initExecution();
}
return orig_links;
}
@@ -340,6 +337,7 @@ void NodeOperation::remove_buffers_and_restore_original_inputs(
NodeOperation *buffer_op = get_input_operation(i);
BLI_assert(buffer_op != nullptr);
BLI_assert(typeid(*buffer_op) == typeid(BufferOperation));
+ buffer_op->deinitExecution();
NodeOperationInput *input_socket = getInputSocket(i);
input_socket->setLink(original_inputs_links[i]);
delete buffer_op;
@@ -443,6 +441,12 @@ std::ostream &operator<<(std::ostream &os, const NodeOperationFlags &node_operat
if (node_operation_flags.is_fullframe_operation) {
os << "full_frame,";
}
+ if (node_operation_flags.is_constant_operation) {
+ os << "contant_operation,";
+ }
+ if (node_operation_flags.can_be_constant) {
+ os << "can_be_constant,";
+ }
return os;
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 5ae0aae67d5..fb9ec1e7a83 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -221,6 +221,7 @@ struct NodeOperationFlags {
/**
* Is this a set operation (value, color, vector).
+ * TODO: To be replaced by is_constant_operation flag once tiled implementation is removed.
*/
bool is_set_operation : 1;
bool is_write_buffer_operation : 1;
@@ -242,6 +243,17 @@ struct NodeOperationFlags {
*/
bool is_fullframe_operation : 1;
+ /**
+ * Whether operation is a primitive constant operation (Color/Vector/Value).
+ */
+ bool is_constant_operation : 1;
+
+ /**
+ * Whether operation have constant elements/pixels values when all its inputs are constant
+ * operations.
+ */
+ bool can_be_constant : 1;
+
NodeOperationFlags()
{
complex = false;
@@ -258,6 +270,8 @@ struct NodeOperationFlags {
is_preview_operation = false;
use_datatype_conversion = true;
is_fullframe_operation = false;
+ is_constant_operation = false;
+ can_be_constant = false;
}
};
@@ -316,6 +330,8 @@ class NodeOperation {
*/
NodeOperationFlags flags;
+ ExecutionSystem *exec_system_;
+
public:
virtual ~NodeOperation()
{
@@ -402,6 +418,12 @@ class NodeOperation {
{
this->m_btree = tree;
}
+
+ void set_execution_system(ExecutionSystem *system)
+ {
+ exec_system_ = system;
+ }
+
virtual void initExecution();
/**
@@ -569,18 +591,14 @@ class NodeOperation {
/** \name Full Frame Methods
* \{ */
- void render(MemoryBuffer *output_buf,
- Span<rcti> areas,
- Span<MemoryBuffer *> inputs_bufs,
- ExecutionSystem &exec_system);
+ void render(MemoryBuffer *output_buf, Span<rcti> areas, Span<MemoryBuffer *> inputs_bufs);
/**
* Executes operation updating output memory buffer. Single-threaded calls.
*/
virtual void update_memory_buffer(MemoryBuffer *UNUSED(output),
const rcti &UNUSED(area),
- Span<MemoryBuffer *> UNUSED(inputs),
- ExecutionSystem &UNUSED(exec_system))
+ Span<MemoryBuffer *> UNUSED(inputs))
{
}
@@ -678,13 +696,11 @@ class NodeOperation {
void render_full_frame(MemoryBuffer *output_buf,
Span<rcti> areas,
- Span<MemoryBuffer *> inputs_bufs,
- ExecutionSystem &exec_system);
+ Span<MemoryBuffer *> inputs_bufs);
void render_full_frame_fallback(MemoryBuffer *output_buf,
Span<rcti> areas,
- Span<MemoryBuffer *> inputs,
- ExecutionSystem &exec_system);
+ Span<MemoryBuffer *> inputs);
void render_tile(MemoryBuffer *output_buf, rcti *tile_rect);
Vector<NodeOperationOutput *> replace_inputs_with_buffers(Span<MemoryBuffer *> inputs_bufs);
void remove_buffers_and_restore_original_inputs(
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cc b/source/blender/compositor/intern/COM_NodeOperationBuilder.cc
index 1beb83bb477..10a91bbcd3e 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cc
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cc
@@ -36,12 +36,15 @@
#include "COM_ViewerOperation.h"
#include "COM_WriteBufferOperation.h"
+#include "COM_ConstantFolder.h"
#include "COM_NodeOperationBuilder.h" /* own include */
namespace blender::compositor {
-NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree)
- : m_context(context), m_current_node(nullptr), m_active_viewer(nullptr)
+NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context,
+ bNodeTree *b_nodetree,
+ ExecutionSystem *system)
+ : m_context(context), exec_system_(system), m_current_node(nullptr), m_active_viewer(nullptr)
{
m_graph.from_bNodeTree(*context, b_nodetree);
}
@@ -79,7 +82,7 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
if (!op_from || op_to_list.is_empty()) {
/* XXX allow this? error/debug message? */
// BLI_assert(false);
- /* XXX note: this can happen with certain nodes (e.g. OutputFile)
+ /* XXX NOTE: this can happen with certain nodes (e.g. OutputFile)
* which only generate operations in certain circumstances (rendering)
* just let this pass silently for now ...
*/
@@ -97,6 +100,15 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
add_datatype_conversions();
+ if (m_context->get_execution_model() == eExecutionModel::FullFrame) {
+ /* Copy operations to system. Needed for graphviz. */
+ system->set_operations(m_operations, {});
+
+ DebugInfo::graphviz(system, "compositor_prior_folding");
+ ConstantFolder folder(*this);
+ folder.fold_operations();
+ }
+
determineResolutions();
if (m_context->get_execution_model() == eExecutionModel::Tiled) {
@@ -130,6 +142,29 @@ void NodeOperationBuilder::addOperation(NodeOperation *operation)
operation->set_name(m_current_node->getbNode()->name);
}
operation->set_execution_model(m_context->get_execution_model());
+ operation->set_execution_system(exec_system_);
+}
+
+void NodeOperationBuilder::replace_operation_with_constant(NodeOperation *operation,
+ ConstantOperation *constant_operation)
+{
+ BLI_assert(constant_operation->getNumberOfInputSockets() == 0);
+ int i = 0;
+ while (i < m_links.size()) {
+ Link &link = m_links[i];
+ if (&link.to()->getOperation() == operation) {
+ link.to()->setLink(nullptr);
+ m_links.remove(i);
+ continue;
+ }
+
+ if (&link.from()->getOperation() == operation) {
+ link.to()->setLink(constant_operation->getOutputSocket());
+ m_links[i] = Link(constant_operation->getOutputSocket(), link.to());
+ }
+ i++;
+ }
+ addOperation(constant_operation);
}
void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket,
@@ -138,7 +173,7 @@ void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket,
BLI_assert(m_current_node);
BLI_assert(node_socket->getNode() == m_current_node);
- /* note: this maps operation sockets to node sockets.
+ /* NOTE: this maps operation sockets to node sockets.
* for resolving links the map will be inverted first in convertToOperations,
* to get a list of links for each node input socket.
*/
@@ -284,7 +319,7 @@ void NodeOperationBuilder::add_datatype_conversions()
void NodeOperationBuilder::add_operation_input_constants()
{
- /* Note: unconnected inputs cached first to avoid modifying
+ /* NOTE: unconnected inputs cached first to avoid modifying
* m_operations while iterating over it
*/
Vector<NodeOperationInput *> pending_inputs;
@@ -537,7 +572,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation,
void NodeOperationBuilder::add_complex_operation_buffers()
{
- /* note: complex ops and get cached here first, since adding operations
+ /* NOTE: complex ops and get cached here first, since adding operations
* will invalidate iterators over the main m_operations
*/
Vector<NodeOperation *> complex_ops;
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
index b2fb822af25..1f76765c846 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.h
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
@@ -41,6 +41,7 @@ class NodeOperationOutput;
class PreviewOperation;
class WriteBufferOperation;
class ViewerOperation;
+class ConstantOperation;
class NodeOperationBuilder {
public:
@@ -67,6 +68,7 @@ class NodeOperationBuilder {
private:
const CompositorContext *m_context;
NodeGraph m_graph;
+ ExecutionSystem *exec_system_;
Vector<NodeOperation *> m_operations;
Vector<Link> m_links;
@@ -86,7 +88,9 @@ class NodeOperationBuilder {
ViewerOperation *m_active_viewer;
public:
- NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree);
+ NodeOperationBuilder(const CompositorContext *context,
+ bNodeTree *b_nodetree,
+ ExecutionSystem *system);
const CompositorContext &context() const
{
@@ -96,6 +100,8 @@ class NodeOperationBuilder {
void convertToOperations(ExecutionSystem *system);
void addOperation(NodeOperation *operation);
+ void replace_operation_with_constant(NodeOperation *operation,
+ ConstantOperation *constant_operation);
/** Map input socket of the current node to an operation socket */
void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cc b/source/blender/compositor/intern/COM_OpenCLDevice.cc
index 0f6ed0dbd2b..3409c8fa3bc 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cc
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cc
@@ -110,7 +110,7 @@ const cl_image_format *OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBu
return &IMAGE_FORMAT_COLOR;
break;
default:
- BLI_assert(!"Unsupported num_channels.");
+ BLI_assert_msg(0, "Unsupported num_channels.");
}
return &IMAGE_FORMAT_COLOR;
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cc b/source/blender/compositor/intern/COM_WorkScheduler.cc
index 157ded943d6..8e49bf34b51 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cc
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cc
@@ -126,7 +126,7 @@ static void *thread_execute_gpu(void *data)
return nullptr;
}
-static void opencl_start(CompositorContext &context)
+static void opencl_start(const CompositorContext &context)
{
if (context.getHasActiveOpenCLDevices()) {
g_work_scheduler.opencl.queue = BLI_thread_queue_init();
@@ -458,7 +458,7 @@ void WorkScheduler::schedule(WorkPackage *package)
}
}
-void WorkScheduler::start(CompositorContext &context)
+void WorkScheduler::start(const CompositorContext &context)
{
if (COM_is_opencl_enabled()) {
opencl_start(context);
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h
index be88859be7c..297943aa63b 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.h
+++ b/source/blender/compositor/intern/COM_WorkScheduler.h
@@ -65,7 +65,7 @@ struct WorkScheduler {
* for every device a thread is created.
* \see initialize Initialization and query of the number of devices
*/
- static void start(CompositorContext &context);
+ static void start(const CompositorContext &context);
/**
* \brief stop the execution
diff --git a/source/blender/compositor/intern/COM_compositor.cc b/source/blender/compositor/intern/COM_compositor.cc
index 5839f53976b..c05234f3bd0 100644
--- a/source/blender/compositor/intern/COM_compositor.cc
+++ b/source/blender/compositor/intern/COM_compositor.cc
@@ -70,7 +70,7 @@ void COM_execute(RenderData *render_data,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName)
{
- /* Initialize mutex, TODO this mutex init is actually not thread safe and
+ /* Initialize mutex, TODO: this mutex init is actually not thread safe and
* should be done somewhere as part of blender startup, all the other
* initializations can be done lazily. */
if (!g_compositor.is_initialized) {
diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.cc b/source/blender/compositor/nodes/COM_CornerPinNode.cc
index 6a120cffe0a..3cfa20f4e05 100644
--- a/source/blender/compositor/nodes/COM_CornerPinNode.cc
+++ b/source/blender/compositor/nodes/COM_CornerPinNode.cc
@@ -30,7 +30,7 @@ void CornerPinNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
NodeInput *input_image = this->getInputSocket(0);
- /* note: socket order differs between UI node and operations:
+ /* NOTE: socket order differs between UI node and operations:
* bNode uses intuitive order following top-down layout:
* upper-left, upper-right, lower-left, lower-right
* Operations use same order as the tracking blenkernel functions expect:
diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.cc b/source/blender/compositor/nodes/COM_IDMaskNode.cc
index 9798dabd035..b51e79f2dea 100644
--- a/source/blender/compositor/nodes/COM_IDMaskNode.cc
+++ b/source/blender/compositor/nodes/COM_IDMaskNode.cc
@@ -17,9 +17,9 @@
*/
#include "COM_IDMaskNode.h"
-#include "COM_AntiAliasOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_IDMaskOperation.h"
+#include "COM_SMAAOperation.h"
namespace blender::compositor {
@@ -42,11 +42,27 @@ void IDMaskNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
else {
- AntiAliasOperation *antiAliasOperation = new AntiAliasOperation();
- converter.addOperation(antiAliasOperation);
+ SMAAEdgeDetectionOperation *operation1 = nullptr;
- converter.addLink(operation->getOutputSocket(), antiAliasOperation->getInputSocket(0));
- converter.mapOutputSocket(getOutputSocket(0), antiAliasOperation->getOutputSocket(0));
+ operation1 = new SMAAEdgeDetectionOperation();
+ converter.addOperation(operation1);
+
+ converter.addLink(operation->getOutputSocket(0), operation1->getInputSocket(0));
+
+ /* Blending Weight Calculation Pixel Shader (Second Pass). */
+ SMAABlendingWeightCalculationOperation *operation2 =
+ new SMAABlendingWeightCalculationOperation();
+ converter.addOperation(operation2);
+
+ converter.addLink(operation1->getOutputSocket(), operation2->getInputSocket(0));
+
+ /* Neighborhood Blending Pixel Shader (Third Pass). */
+ SMAANeighborhoodBlendingOperation *operation3 = new SMAANeighborhoodBlendingOperation();
+ converter.addOperation(operation3);
+
+ converter.addLink(operation->getOutputSocket(0), operation3->getInputSocket(0));
+ converter.addLink(operation2->getOutputSocket(), operation3->getInputSocket(1));
+ converter.mapOutputSocket(getOutputSocket(0), operation3->getOutputSocket());
}
}
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cc b/source/blender/compositor/nodes/COM_OutputFileNode.cc
index 8b5140636c1..25ec7331849 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cc
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cc
@@ -36,7 +36,7 @@ void OutputFileNode::add_input_sockets(OutputOpenExrMultiLayerOperation &operati
for (NodeInput *input : inputs) {
NodeImageMultiFileSocket *sockdata =
(NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
- /* note: layer becomes an empty placeholder if the input is not linked */
+ /* NOTE: layer becomes an empty placeholder if the input is not linked. */
operation.add_layer(sockdata->layer, input->getDataType(), input->isLinked());
}
}
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cc b/source/blender/compositor/nodes/COM_RenderLayersNode.cc
index 851d0366546..253ca542c04 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cc
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cc
@@ -107,7 +107,7 @@ void RenderLayersNode::testRenderLink(NodeConverter &converter,
type = DataType::Value;
break;
default:
- BLI_assert(!"Unexpected number of channels for pass");
+ BLI_assert_msg(0, "Unexpected number of channels for pass");
type = DataType::Value;
break;
}
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cc b/source/blender/compositor/nodes/COM_TranslateNode.cc
index 1b2ce341a66..3a3e98c3472 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.cc
+++ b/source/blender/compositor/nodes/COM_TranslateNode.cc
@@ -42,6 +42,7 @@ void TranslateNode::convertToOperations(NodeConverter &converter,
NodeOutput *outputSocket = this->getOutputSocket(0);
TranslateOperation *operation = new TranslateOperation();
+ operation->set_wrapping(data->wrap_axis);
if (data->relative) {
const RenderData *rd = context.getRenderData();
const float render_size_factor = context.getRenderPercentageAsFactor();
@@ -55,11 +56,8 @@ void TranslateNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputXSocket, operation->getInputSocket(1));
converter.mapInputSocket(inputYSocket, operation->getInputSocket(2));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
-
- /* FullFrame does not support using WriteBufferOperation.
- * TODO: Implement TranslateOperation with wrap support in FullFrame.
- */
if (data->wrap_axis && context.get_execution_model() != eExecutionModel::FullFrame) {
+ /* TODO: To be removed with tiled implementation. */
WriteBufferOperation *writeOperation = new WriteBufferOperation(DataType::Color);
WrapOperation *wrapOperation = new WrapOperation(DataType::Color);
wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy());
diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc
index d1d3752e402..aee8c0d52e8 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc
@@ -41,6 +41,7 @@ ColorBalanceASCCDLOperation::ColorBalanceASCCDLOperation()
this->m_inputValueOperation = nullptr;
this->m_inputColorOperation = nullptr;
this->setResolutionInputSocketIndex(1);
+ flags.can_be_constant = true;
}
void ColorBalanceASCCDLOperation::initExecution()
@@ -76,6 +77,23 @@ void ColorBalanceASCCDLOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ColorBalanceASCCDLOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *in_factor = p.ins[0];
+ const float *in_color = p.ins[1];
+ const float fac = MIN2(1.0f, in_factor[0]);
+ const float fac_m = 1.0f - fac;
+ p.out[0] = fac_m * in_color[0] +
+ fac * colorbalance_cdl(in_color[0], m_offset[0], m_power[0], m_slope[0]);
+ p.out[1] = fac_m * in_color[1] +
+ fac * colorbalance_cdl(in_color[1], m_offset[1], m_power[1], m_slope[1]);
+ p.out[2] = fac_m * in_color[2] +
+ fac * colorbalance_cdl(in_color[2], m_offset[2], m_power[2], m_slope[2]);
+ p.out[3] = in_color[3];
+ }
+}
+
void ColorBalanceASCCDLOperation::deinitExecution()
{
this->m_inputValueOperation = nullptr;
diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
index 5851600190f..d161ea66af2 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
+++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedRowOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ColorBalanceASCCDLOperation : public NodeOperation {
+class ColorBalanceASCCDLOperation : public MultiThreadedRowOperation {
protected:
/**
* Prefetched reference to the inputProgram
@@ -71,6 +71,8 @@ class ColorBalanceASCCDLOperation : public NodeOperation {
{
copy_v3_v3(this->m_slope, slope);
}
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc
index cac16a3f7b0..674cb79a238 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc
@@ -46,6 +46,7 @@ ColorBalanceLGGOperation::ColorBalanceLGGOperation()
this->m_inputValueOperation = nullptr;
this->m_inputColorOperation = nullptr;
this->setResolutionInputSocketIndex(1);
+ flags.can_be_constant = true;
}
void ColorBalanceLGGOperation::initExecution()
@@ -81,6 +82,23 @@ void ColorBalanceLGGOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
+void ColorBalanceLGGOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *in_factor = p.ins[0];
+ const float *in_color = p.ins[1];
+ const float fac = MIN2(1.0f, in_factor[0]);
+ const float fac_m = 1.0f - fac;
+ p.out[0] = fac_m * in_color[0] +
+ fac * colorbalance_lgg(in_color[0], m_lift[0], m_gamma_inv[0], m_gain[0]);
+ p.out[1] = fac_m * in_color[1] +
+ fac * colorbalance_lgg(in_color[1], m_lift[1], m_gamma_inv[1], m_gain[1]);
+ p.out[2] = fac_m * in_color[2] +
+ fac * colorbalance_lgg(in_color[2], m_lift[2], m_gamma_inv[2], m_gain[2]);
+ p.out[3] = in_color[3];
+ }
+}
+
void ColorBalanceLGGOperation::deinitExecution()
{
this->m_inputValueOperation = nullptr;
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
index 23f70247b66..4bc929ed76c 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedRowOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ColorBalanceLGGOperation : public NodeOperation {
+class ColorBalanceLGGOperation : public MultiThreadedRowOperation {
protected:
/**
* Prefetched reference to the inputProgram
@@ -71,6 +71,8 @@ class ColorBalanceLGGOperation : public NodeOperation {
{
copy_v3_v3(this->m_gamma_inv, gamma_inv);
}
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc
index 168e9b57eb2..b50145b106d 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc
@@ -33,6 +33,7 @@ ColorCorrectionOperation::ColorCorrectionOperation()
this->m_redChannelEnabled = true;
this->m_greenChannelEnabled = true;
this->m_blueChannelEnabled = true;
+ flags.can_be_constant = true;
}
void ColorCorrectionOperation::initExecution()
{
@@ -157,6 +158,86 @@ void ColorCorrectionOperation::executePixelSampled(float output[4],
output[3] = inputImageColor[3];
}
+void ColorCorrectionOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *in_color = p.ins[0];
+ const float *in_mask = p.ins[1];
+
+ const float level = (in_color[0] + in_color[1] + in_color[2]) / 3.0f;
+ float level_shadows = 0.0f;
+ float level_midtones = 0.0f;
+ float level_highlights = 0.0f;
+ constexpr float MARGIN = 0.10f;
+ constexpr float MARGIN_DIV = 0.5f / MARGIN;
+ if (level < this->m_data->startmidtones - MARGIN) {
+ level_shadows = 1.0f;
+ }
+ else if (level < this->m_data->startmidtones + MARGIN) {
+ level_midtones = ((level - this->m_data->startmidtones) * MARGIN_DIV) + 0.5f;
+ level_shadows = 1.0f - level_midtones;
+ }
+ else if (level < this->m_data->endmidtones - MARGIN) {
+ level_midtones = 1.0f;
+ }
+ else if (level < this->m_data->endmidtones + MARGIN) {
+ level_highlights = ((level - this->m_data->endmidtones) * MARGIN_DIV) + 0.5f;
+ level_midtones = 1.0f - level_highlights;
+ }
+ else {
+ level_highlights = 1.0f;
+ }
+ float contrast = this->m_data->master.contrast;
+ float saturation = this->m_data->master.saturation;
+ float gamma = this->m_data->master.gamma;
+ float gain = this->m_data->master.gain;
+ float lift = this->m_data->master.lift;
+ contrast *= level_shadows * this->m_data->shadows.contrast +
+ level_midtones * this->m_data->midtones.contrast +
+ level_highlights * this->m_data->highlights.contrast;
+ saturation *= level_shadows * this->m_data->shadows.saturation +
+ level_midtones * this->m_data->midtones.saturation +
+ level_highlights * this->m_data->highlights.saturation;
+ gamma *= level_shadows * this->m_data->shadows.gamma +
+ level_midtones * this->m_data->midtones.gamma +
+ level_highlights * this->m_data->highlights.gamma;
+ gain *= level_shadows * this->m_data->shadows.gain +
+ level_midtones * this->m_data->midtones.gain +
+ level_highlights * this->m_data->highlights.gain;
+ lift += level_shadows * this->m_data->shadows.lift +
+ level_midtones * this->m_data->midtones.lift +
+ level_highlights * this->m_data->highlights.lift;
+
+ const float inv_gamma = 1.0f / gamma;
+ const float luma = IMB_colormanagement_get_luminance(in_color);
+
+ float r = luma + saturation * (in_color[0] - luma);
+ float g = luma + saturation * (in_color[1] - luma);
+ float b = luma + saturation * (in_color[2] - luma);
+
+ r = 0.5f + (r - 0.5f) * contrast;
+ g = 0.5f + (g - 0.5f) * contrast;
+ b = 0.5f + (b - 0.5f) * contrast;
+
+ /* Check for negative values to avoid nan. */
+ r = color_correct_powf_safe(r * gain + lift, inv_gamma, r);
+ g = color_correct_powf_safe(g * gain + lift, inv_gamma, g);
+ b = color_correct_powf_safe(b * gain + lift, inv_gamma, b);
+
+ /* Mix with mask. */
+ const float value = MIN2(1.0f, in_mask[0]);
+ const float m_value = 1.0f - value;
+ r = m_value * in_color[0] + value * r;
+ g = m_value * in_color[1] + value * g;
+ b = m_value * in_color[2] + value * b;
+
+ p.out[0] = m_redChannelEnabled ? r : in_color[0];
+ p.out[1] = m_greenChannelEnabled ? g : in_color[1];
+ p.out[2] = m_blueChannelEnabled ? b : in_color[2];
+ p.out[3] = in_color[3];
+ }
+}
+
void ColorCorrectionOperation::deinitExecution()
{
this->m_inputImage = nullptr;
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
index c5826ed0152..32b5e02e77a 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedRowOperation.h"
namespace blender::compositor {
-class ColorCorrectionOperation : public NodeOperation {
+class ColorCorrectionOperation : public MultiThreadedRowOperation {
private:
/**
* Cached reference to the inputProgram
@@ -69,6 +69,8 @@ class ColorCorrectionOperation : public NodeOperation {
{
this->m_blueChannelEnabled = enabled;
}
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.cc b/source/blender/compositor/operations/COM_ColorExposureOperation.cc
index 1512ff87658..228550a31c5 100644
--- a/source/blender/compositor/operations/COM_ColorExposureOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorExposureOperation.cc
@@ -26,6 +26,7 @@ ExposureOperation::ExposureOperation()
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
+ flags.can_be_constant = true;
}
void ExposureOperation::initExecution()
@@ -52,6 +53,19 @@ void ExposureOperation::executePixelSampled(float output[4],
output[3] = inputValue[3];
}
+void ExposureOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *in_value = p.ins[0];
+ const float *in_exposure = p.ins[1];
+ const float exposure = pow(2, in_exposure[0]);
+ p.out[0] = in_value[0] * exposure;
+ p.out[1] = in_value[1] * exposure;
+ p.out[2] = in_value[2] * exposure;
+ p.out[3] = in_value[3];
+ }
+}
+
void ExposureOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.h b/source/blender/compositor/operations/COM_ColorExposureOperation.h
index 0cfaa059e41..1eb790e8d52 100644
--- a/source/blender/compositor/operations/COM_ColorExposureOperation.h
+++ b/source/blender/compositor/operations/COM_ColorExposureOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedRowOperation.h"
namespace blender::compositor {
-class ExposureOperation : public NodeOperation {
+class ExposureOperation : public MultiThreadedRowOperation {
private:
/**
* Cached reference to the inputProgram
@@ -47,6 +47,8 @@ class ExposureOperation : public NodeOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConstantOperation.cc b/source/blender/compositor/operations/COM_ConstantOperation.cc
new file mode 100644
index 00000000000..f905edbde76
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConstantOperation.cc
@@ -0,0 +1,28 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_ConstantOperation.h"
+
+namespace blender::compositor {
+
+ConstantOperation::ConstantOperation()
+{
+ flags.is_constant_operation = true;
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConstantOperation.h b/source/blender/compositor/operations/COM_ConstantOperation.h
new file mode 100644
index 00000000000..2709efeebd8
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConstantOperation.h
@@ -0,0 +1,36 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_NodeOperation.h"
+
+namespace blender::compositor {
+
+/**
+ * Base class for primitive constant operations (Color/Vector/Value). The rest of operations that
+ * can be constant are evaluated into primitives during constant folding.
+ */
+class ConstantOperation : public NodeOperation {
+ public:
+ ConstantOperation();
+
+ virtual const float *get_constant_elem() = 0;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
index 9e18a8e2f2c..2454f507664 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
@@ -370,7 +370,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
int bwidth = rect->xmax - rect->xmin;
int bheight = rect->ymax - rect->ymin;
- // Note: Cache buffer has original tilesize width, but new height.
+ // NOTE: Cache buffer has original tilesize width, but new height.
// We have to calculate the additional rows in the first pass,
// to have valid data available for the second pass.
tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax);
@@ -500,7 +500,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
int bwidth = rect->xmax - rect->xmin;
int bheight = rect->ymax - rect->ymin;
- // Note: Cache buffer has original tilesize width, but new height.
+ // NOTE: Cache buffer has original tilesize width, but new height.
// We have to calculate the additional rows in the first pass,
// to have valid data available for the second pass.
tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax);
diff --git a/source/blender/compositor/operations/COM_GammaOperation.cc b/source/blender/compositor/operations/COM_GammaOperation.cc
index 343e335070a..396d3942b06 100644
--- a/source/blender/compositor/operations/COM_GammaOperation.cc
+++ b/source/blender/compositor/operations/COM_GammaOperation.cc
@@ -28,6 +28,7 @@ GammaOperation::GammaOperation()
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
this->m_inputGammaProgram = nullptr;
+ flags.can_be_constant = true;
}
void GammaOperation::initExecution()
{
@@ -51,6 +52,20 @@ void GammaOperation::executePixelSampled(float output[4], float x, float y, Pixe
output[3] = inputValue[3];
}
+void GammaOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *in_value = p.ins[0];
+ const float *in_gamma = p.ins[1];
+ const float gamma = in_gamma[0];
+ /* Check for negative to avoid nan's. */
+ p.out[0] = in_value[0] > 0.0f ? powf(in_value[0], gamma) : in_value[0];
+ p.out[1] = in_value[1] > 0.0f ? powf(in_value[1], gamma) : in_value[1];
+ p.out[2] = in_value[2] > 0.0f ? powf(in_value[2], gamma) : in_value[2];
+ p.out[3] = in_value[3];
+ }
+}
+
void GammaOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
diff --git a/source/blender/compositor/operations/COM_GammaOperation.h b/source/blender/compositor/operations/COM_GammaOperation.h
index 034046106d6..713d3d8484f 100644
--- a/source/blender/compositor/operations/COM_GammaOperation.h
+++ b/source/blender/compositor/operations/COM_GammaOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedRowOperation.h"
namespace blender::compositor {
-class GammaOperation : public NodeOperation {
+class GammaOperation : public MultiThreadedRowOperation {
private:
/**
* Cached reference to the inputProgram
@@ -47,6 +47,8 @@ class GammaOperation : public NodeOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h
index 7ae15595e3b..50db4e02940 100644
--- a/source/blender/compositor/operations/COM_GlareBaseOperation.h
+++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h
@@ -27,7 +27,7 @@ namespace blender::compositor {
/* soms macros for color handling */
typedef float fRGB[4];
-/* TODO - replace with BLI_math_vector */
+/* TODO: replace with BLI_math_vector. */
/* multiply c2 by color rgb, rgb as separate arguments */
#define fRGB_rgbmult(c, r, g, b) \
{ \
diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.cc b/source/blender/compositor/operations/COM_IDMaskOperation.cc
index 38f8b7e075f..bb11ac8b1be 100644
--- a/source/blender/compositor/operations/COM_IDMaskOperation.cc
+++ b/source/blender/compositor/operations/COM_IDMaskOperation.cc
@@ -25,6 +25,7 @@ IDMaskOperation::IDMaskOperation()
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
this->flags.complex = true;
+ flags.can_be_constant = true;
}
void *IDMaskOperation::initializeTileData(rcti *rect)
diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h
index 92a2c291a72..e8cd9c722df 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.h
+++ b/source/blender/compositor/operations/COM_MaskOperation.h
@@ -35,7 +35,7 @@ class MaskOperation : public NodeOperation {
protected:
Mask *m_mask;
- /* note, these are used more like aspect,
+ /* NOTE: these are used more like aspect,
* but they _do_ impact on mask detail */
int m_maskWidth;
int m_maskHeight;
diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cc b/source/blender/compositor/operations/COM_NormalizeOperation.cc
index faacb429f71..f93afcaab95 100644
--- a/source/blender/compositor/operations/COM_NormalizeOperation.cc
+++ b/source/blender/compositor/operations/COM_NormalizeOperation.cc
@@ -36,7 +36,7 @@ void NormalizeOperation::initExecution()
void NormalizeOperation::executePixel(float output[4], int x, int y, void *data)
{
- /* using generic two floats struct to store x: min y: mult */
+ /* using generic two floats struct to store `x: min`, `y: multiply` */
NodeTwoFloats *minmult = (NodeTwoFloats *)data;
this->m_imageReader->read(output, x, y, nullptr);
@@ -89,7 +89,7 @@ void *NormalizeOperation::initializeTileData(rcti *rect)
lockMutex();
if (this->m_cachedInstance == nullptr) {
MemoryBuffer *tile = (MemoryBuffer *)this->m_imageReader->initializeTileData(rect);
- /* using generic two floats struct to store x: min y: mult */
+ /* using generic two floats struct to store `x: min`, `y: multiply`. */
NodeTwoFloats *minmult = new NodeTwoFloats();
float *buffer = tile->getBuffer();
diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.h b/source/blender/compositor/operations/COM_NormalizeOperation.h
index 93d4a0fc67d..c89ba372189 100644
--- a/source/blender/compositor/operations/COM_NormalizeOperation.h
+++ b/source/blender/compositor/operations/COM_NormalizeOperation.h
@@ -36,7 +36,7 @@ class NormalizeOperation : public NodeOperation {
/**
* \brief temporarily cache of the execution storage
- * it stores x->min and y->mult
+ * it stores `x->min` and `y->multiply`.
*/
NodeTwoFloats *m_cachedInstance;
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc
index 1ee749b1a49..7e896046f01 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cc
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc
@@ -426,8 +426,8 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
IMB_exr_write_channels(exrhandle);
}
else {
- /* TODO, get the error from openexr's exception */
- /* XXX nice way to do report? */
+ /* TODO: get the error from openexr's exception. */
+ /* XXX: nice way to do report? */
printf("Error Writing Render Result, see console\n");
}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
index d240c8b06e9..3bae230aa06 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
@@ -37,7 +37,7 @@ class PlaneTrackCommon {
char m_trackingObjectName[64];
char m_planeTrackName[64];
- /* note: this class is not an operation itself (to prevent virtual inheritance issues)
+ /* NOTE: this class is not an operation itself (to prevent virtual inheritance issues)
* implementation classes must make wrappers to use these methods, see below.
*/
void read_and_calculate_corners(PlaneDistortBaseOperation *distort_op);
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cc b/source/blender/compositor/operations/COM_ReadBufferOperation.cc
index cc58f29e8d9..d35d2516f16 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.cc
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cc
@@ -44,7 +44,7 @@ void ReadBufferOperation::determineResolution(unsigned int resolution[2],
operation->determineResolution(resolution, preferredResolution);
operation->setResolution(resolution);
- /** \todo: may not occur!, but does with blur node */
+ /** \todo may not occur! But does with blur node. */
if (this->m_memoryProxy->getExecutor()) {
this->m_memoryProxy->getExecutor()->setResolution(resolution);
}
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cc b/source/blender/compositor/operations/COM_RenderLayersProg.cc
index 1ac451b95c2..72e2c92c9cf 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cc
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cc
@@ -43,6 +43,7 @@ RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elem
this->m_inputBuffer = nullptr;
this->m_elementsize = elementsize;
this->m_rd = nullptr;
+ layer_buffer_ = nullptr;
this->addOutputSocket(type);
}
@@ -65,6 +66,9 @@ void RenderLayersProg::initExecution()
if (rl) {
this->m_inputBuffer = RE_RenderLayerGetPass(
rl, this->m_passName.c_str(), this->m_viewName);
+ if (m_inputBuffer) {
+ layer_buffer_ = new MemoryBuffer(m_inputBuffer, m_elementsize, getWidth(), getHeight());
+ }
}
}
}
@@ -159,7 +163,7 @@ void RenderLayersProg::executePixelSampled(float output[4], float x, float y, Pi
}
else {
expected_element_size = 0;
- BLI_assert(!"Something horribly wrong just happened");
+ BLI_assert_msg(0, "Something horribly wrong just happened");
}
BLI_assert(expected_element_size == actual_element_size);
}
@@ -186,6 +190,10 @@ void RenderLayersProg::executePixelSampled(float output[4], float x, float y, Pi
void RenderLayersProg::deinitExecution()
{
this->m_inputBuffer = nullptr;
+ if (layer_buffer_) {
+ delete layer_buffer_;
+ layer_buffer_ = nullptr;
+ }
}
void RenderLayersProg::determineResolution(unsigned int resolution[2],
@@ -255,6 +263,20 @@ std::unique_ptr<MetaData> RenderLayersProg::getMetaData()
return std::move(callback_data.meta_data);
}
+void RenderLayersProg::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ BLI_assert(output->get_num_channels() >= m_elementsize);
+ if (layer_buffer_) {
+ output->copy_from(layer_buffer_, area, 0, m_elementsize, 0);
+ }
+ else {
+ std::unique_ptr<float[]> zero_elem = std::make_unique<float[]>(m_elementsize);
+ output->fill(area, 0, zero_elem.get(), m_elementsize);
+ }
+}
+
/* ******** Render Layers AO Operation ******** */
void RenderLayersAOOperation::executePixelSampled(float output[4],
float x,
@@ -271,6 +293,21 @@ void RenderLayersAOOperation::executePixelSampled(float output[4],
output[3] = 1.0f;
}
+void RenderLayersAOOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ BLI_assert(output->get_num_channels() == COM_DATA_TYPE_COLOR_CHANNELS);
+ BLI_assert(m_elementsize == COM_DATA_TYPE_COLOR_CHANNELS);
+ if (layer_buffer_) {
+ output->copy_from(layer_buffer_, area, 0, COM_DATA_TYPE_VECTOR_CHANNELS, 0);
+ }
+ else {
+ output->fill(area, 0, COM_VECTOR_ZERO, COM_DATA_TYPE_VECTOR_CHANNELS);
+ }
+ output->fill(area, 3, COM_VALUE_ONE, COM_DATA_TYPE_VALUE_CHANNELS);
+}
+
/* ******** Render Layers Alpha Operation ******** */
void RenderLayersAlphaProg::executePixelSampled(float output[4],
float x,
@@ -289,6 +326,20 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4],
}
}
+void RenderLayersAlphaProg::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ BLI_assert(output->get_num_channels() == COM_DATA_TYPE_VALUE_CHANNELS);
+ BLI_assert(m_elementsize == COM_DATA_TYPE_COLOR_CHANNELS);
+ if (layer_buffer_) {
+ output->copy_from(layer_buffer_, area, 3, COM_DATA_TYPE_VALUE_CHANNELS, 0);
+ }
+ else {
+ output->fill(area, COM_VALUE_ZERO);
+ }
+}
+
/* ******** Render Layers Depth Operation ******** */
void RenderLayersDepthProg::executePixelSampled(float output[4],
float x,
@@ -309,4 +360,19 @@ void RenderLayersDepthProg::executePixelSampled(float output[4],
}
}
+void RenderLayersDepthProg::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ BLI_assert(output->get_num_channels() == COM_DATA_TYPE_VALUE_CHANNELS);
+ BLI_assert(m_elementsize == COM_DATA_TYPE_VALUE_CHANNELS);
+ if (layer_buffer_) {
+ output->copy_from(layer_buffer_, area);
+ }
+ else {
+ const float default_depth = 10e10f;
+ output->fill(area, &default_depth);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index 33e4fb163c5..dd76a56d645 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -20,7 +20,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -31,9 +31,9 @@ namespace blender::compositor {
/**
* Base class for all renderlayeroperations
*
- * \todo: rename to operation.
+ * \todo Rename to operation.
*/
-class RenderLayersProg : public NodeOperation {
+class RenderLayersProg : public MultiThreadedOperation {
protected:
/**
* Reference to the scene object.
@@ -50,8 +50,11 @@ class RenderLayersProg : public NodeOperation {
*/
const char *m_viewName;
+ const MemoryBuffer *layer_buffer_;
+
/**
- * cached instance to the float buffer inside the layer
+ * Cached instance to the float buffer inside the layer.
+ * TODO: To be removed with tiled implementation.
*/
float *m_inputBuffer;
@@ -126,6 +129,10 @@ class RenderLayersProg : public NodeOperation {
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
std::unique_ptr<MetaData> getMetaData() override;
+
+ virtual void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class RenderLayersAOOperation : public RenderLayersProg {
@@ -135,6 +142,10 @@ class RenderLayersAOOperation : public RenderLayersProg {
{
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class RenderLayersAlphaProg : public RenderLayersProg {
@@ -144,6 +155,10 @@ class RenderLayersAlphaProg : public RenderLayersProg {
{
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class RenderLayersDepthProg : public RenderLayersProg {
@@ -153,6 +168,10 @@ class RenderLayersDepthProg : public RenderLayersProg {
{
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SMAAOperation.cc b/source/blender/compositor/operations/COM_SMAAOperation.cc
index 7a272fa8795..3c753591ced 100644
--- a/source/blender/compositor/operations/COM_SMAAOperation.cc
+++ b/source/blender/compositor/operations/COM_SMAAOperation.cc
@@ -21,6 +21,7 @@
#include "COM_SMAAOperation.h"
#include "BLI_math.h"
#include "COM_SMAAAreaTexture.h"
+#include "BKE_node.h"
extern "C" {
#include "IMB_colormanagement.h"
@@ -36,14 +37,14 @@ namespace blender::compositor {
*
* http://www.iryoku.com/smaa/
*
- * This file is based on smaa-cpp:
+ * This file is based on SMAA-CPP:
*
* https://github.com/iRi-E/smaa-cpp
*
* Currently only SMAA 1x mode is provided, so the operation will be done
- * with no spatial multisampling nor temporal supersampling.
+ * with no spatial multi-sampling nor temporal super-sampling.
*
- * Note: This program assumes the screen coordinates are DirectX style, so
+ * NOTE: This program assumes the screen coordinates are DirectX style, so
* the vertical direction is upside-down. "top" and "bottom" actually mean
* bottom and top, respectively.
*/
@@ -166,8 +167,8 @@ SMAAEdgeDetectionOperation::SMAAEdgeDetectionOperation()
this->flags.complex = true;
this->m_imageReader = nullptr;
this->m_valueReader = nullptr;
- this->m_threshold = 0.1f;
- this->m_contrast_limit = 2.0f;
+ this->setThreshold(CMP_DEFAULT_SMAA_THRESHOLD);
+ this->setLocalContrastAdaptationFactor(CMP_DEFAULT_SMAA_CONTRAST_LIMIT);
}
void SMAAEdgeDetectionOperation::initExecution()
@@ -297,7 +298,7 @@ SMAABlendingWeightCalculationOperation::SMAABlendingWeightCalculationOperation()
this->addOutputSocket(DataType::Color);
this->flags.complex = true;
this->m_imageReader = nullptr;
- this->m_corner_rounding = 25;
+ this->setCornerRounding(CMP_DEFAULT_SMAA_CORNER_ROUNDING);
}
void *SMAABlendingWeightCalculationOperation::initializeTileData(rcti *rect)
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cc b/source/blender/compositor/operations/COM_ScaleOperation.cc
index 03525d4ea01..f03b9fcf34d 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cc
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cc
@@ -21,10 +21,10 @@
namespace blender::compositor {
#define USE_FORCE_BILINEAR
-/* XXX - ignore input and use default from old compositor,
- * could become an option like the transform node - campbell
+/* XXX(campbell): ignore input and use default from old compositor,
+ * could become an option like the transform node.
*
- * note: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1)
+ * NOTE: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1)
*/
BaseScaleOperation::BaseScaleOperation()
@@ -37,12 +37,16 @@ BaseScaleOperation::BaseScaleOperation()
m_variable_size = false;
}
-ScaleOperation::ScaleOperation() : BaseScaleOperation()
+ScaleOperation::ScaleOperation() : ScaleOperation(DataType::Color)
{
- this->addInputSocket(DataType::Color);
+}
+
+ScaleOperation::ScaleOperation(DataType data_type) : BaseScaleOperation()
+{
+ this->addInputSocket(data_type);
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
- this->addOutputSocket(DataType::Color);
+ this->addOutputSocket(data_type);
this->setResolutionInputSocketIndex(0);
this->m_inputOperation = nullptr;
this->m_inputXOperation = nullptr;
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h
index dc3de3602bf..2f9a7be92e6 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.h
+++ b/source/blender/compositor/operations/COM_ScaleOperation.h
@@ -55,6 +55,7 @@ class ScaleOperation : public BaseScaleOperation {
public:
ScaleOperation();
+ ScaleOperation(DataType data_type);
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cc b/source/blender/compositor/operations/COM_SetColorOperation.cc
index 79dee33e266..bfe735aab15 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.cc
+++ b/source/blender/compositor/operations/COM_SetColorOperation.cc
@@ -44,8 +44,7 @@ void SetColorOperation::determineResolution(unsigned int resolution[2],
void SetColorOperation::update_memory_buffer(MemoryBuffer *output,
const rcti &area,
- Span<MemoryBuffer *> UNUSED(inputs),
- ExecutionSystem &UNUSED(exec_system))
+ Span<MemoryBuffer *> UNUSED(inputs))
{
BLI_assert(output->is_a_single_elem());
float *out_elem = output->get_elem(area.xmin, area.ymin);
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h
index 2e22ef60ba4..f4c0948ee1b 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.h
+++ b/source/blender/compositor/operations/COM_SetColorOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class SetColorOperation : public NodeOperation {
+class SetColorOperation : public ConstantOperation {
private:
float m_color[4];
@@ -36,6 +36,11 @@ class SetColorOperation : public NodeOperation {
*/
SetColorOperation();
+ const float *get_constant_elem() override
+ {
+ return m_color;
+ }
+
float getChannel1()
{
return this->m_color[0];
@@ -83,8 +88,7 @@ class SetColorOperation : public NodeOperation {
void update_memory_buffer(MemoryBuffer *output,
const rcti &area,
- Span<MemoryBuffer *> inputs,
- ExecutionSystem &exec_system) override;
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.cc b/source/blender/compositor/operations/COM_SetValueOperation.cc
index 359647c8fe3..c12fb106afd 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.cc
+++ b/source/blender/compositor/operations/COM_SetValueOperation.cc
@@ -44,8 +44,7 @@ void SetValueOperation::determineResolution(unsigned int resolution[2],
void SetValueOperation::update_memory_buffer(MemoryBuffer *output,
const rcti &area,
- Span<MemoryBuffer *> UNUSED(inputs),
- ExecutionSystem &UNUSED(exec_system))
+ Span<MemoryBuffer *> UNUSED(inputs))
{
BLI_assert(output->is_a_single_elem());
float *out_elem = output->get_elem(area.xmin, area.ymin);
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h
index acde5aa03b7..f18d44d9554 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.h
+++ b/source/blender/compositor/operations/COM_SetValueOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class SetValueOperation : public NodeOperation {
+class SetValueOperation : public ConstantOperation {
private:
float m_value;
@@ -36,6 +36,11 @@ class SetValueOperation : public NodeOperation {
*/
SetValueOperation();
+ const float *get_constant_elem() override
+ {
+ return &m_value;
+ }
+
float getValue()
{
return this->m_value;
@@ -53,8 +58,7 @@ class SetValueOperation : public NodeOperation {
unsigned int preferredResolution[2]) override;
void update_memory_buffer(MemoryBuffer *output,
const rcti &area,
- Span<MemoryBuffer *> inputs,
- ExecutionSystem &exec_system) override;
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cc b/source/blender/compositor/operations/COM_SetVectorOperation.cc
index 7152d5e61d4..7b8cf44048c 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.cc
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.cc
@@ -32,9 +32,9 @@ void SetVectorOperation::executePixelSampled(float output[4],
float /*y*/,
PixelSampler /*sampler*/)
{
- output[0] = this->m_x;
- output[1] = this->m_y;
- output[2] = this->m_z;
+ output[0] = vector_.x;
+ output[1] = vector_.y;
+ output[2] = vector_.z;
}
void SetVectorOperation::determineResolution(unsigned int resolution[2],
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.h b/source/blender/compositor/operations/COM_SetVectorOperation.h
index b444339fcb2..41fd06659d6 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.h
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
namespace blender::compositor {
@@ -26,12 +26,14 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class SetVectorOperation : public NodeOperation {
+class SetVectorOperation : public ConstantOperation {
private:
- float m_x;
- float m_y;
- float m_z;
- float m_w;
+ struct {
+ float x;
+ float y;
+ float z;
+ float w;
+ } vector_;
public:
/**
@@ -39,37 +41,42 @@ class SetVectorOperation : public NodeOperation {
*/
SetVectorOperation();
+ const float *get_constant_elem() override
+ {
+ return reinterpret_cast<float *>(&vector_);
+ }
+
float getX()
{
- return this->m_x;
+ return vector_.x;
}
void setX(float value)
{
- this->m_x = value;
+ vector_.x = value;
}
float getY()
{
- return this->m_y;
+ return vector_.y;
}
void setY(float value)
{
- this->m_y = value;
+ vector_.y = value;
}
float getZ()
{
- return this->m_z;
+ return vector_.z;
}
void setZ(float value)
{
- this->m_z = value;
+ vector_.z = value;
}
float getW()
{
- return this->m_w;
+ return vector_.w;
}
void setW(float value)
{
- this->m_w = value;
+ vector_.w = value;
}
/**
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cc b/source/blender/compositor/operations/COM_SunBeamsOperation.cc
index 839eeb9ff8f..ff117841e8e 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cc
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cc
@@ -197,7 +197,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
madd_v4_v4fl(output, border, border[3] * weight);
}
- /* TODO implement proper filtering here, see
+ /* TODO: implement proper filtering here, see
* https://en.wikipedia.org/wiki/Lanczos_resampling
* https://en.wikipedia.org/wiki/Sinc_function
*
diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h
index e5f56673694..6fec9ab8f33 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.h
+++ b/source/blender/compositor/operations/COM_TextureOperation.h
@@ -31,7 +31,7 @@ namespace blender::compositor {
/**
* Base class for all renderlayeroperations
*
- * \todo: rename to operation.
+ * \todo Rename to operation.
*/
class TextureBaseOperation : public NodeOperation {
private:
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cc b/source/blender/compositor/operations/COM_TranslateOperation.cc
index 49135f25320..a3db086e974 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.cc
+++ b/source/blender/compositor/operations/COM_TranslateOperation.cc
@@ -20,12 +20,15 @@
namespace blender::compositor {
-TranslateOperation::TranslateOperation()
+TranslateOperation::TranslateOperation() : TranslateOperation(DataType::Color)
{
- this->addInputSocket(DataType::Color);
+}
+TranslateOperation::TranslateOperation(DataType data_type)
+{
+ this->addInputSocket(data_type);
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
- this->addOutputSocket(DataType::Color);
+ this->addOutputSocket(data_type);
this->setResolutionInputSocketIndex(0);
this->m_inputOperation = nullptr;
this->m_inputXOperation = nullptr;
@@ -33,6 +36,8 @@ TranslateOperation::TranslateOperation()
this->m_isDeltaSet = false;
this->m_factorX = 1.0f;
this->m_factorY = 1.0f;
+ this->x_extend_mode_ = MemoryBufferExtend::Clip;
+ this->y_extend_mode_ = MemoryBufferExtend::Clip;
}
void TranslateOperation::initExecution()
{
@@ -83,4 +88,58 @@ void TranslateOperation::setFactorXY(float factorX, float factorY)
m_factorY = factorY;
}
+void TranslateOperation::set_wrapping(int wrapping_type)
+{
+ switch (wrapping_type) {
+ case CMP_NODE_WRAP_X:
+ x_extend_mode_ = MemoryBufferExtend::Repeat;
+ break;
+ case CMP_NODE_WRAP_Y:
+ y_extend_mode_ = MemoryBufferExtend::Repeat;
+ break;
+ case CMP_NODE_WRAP_XY:
+ x_extend_mode_ = MemoryBufferExtend::Repeat;
+ y_extend_mode_ = MemoryBufferExtend::Repeat;
+ break;
+ default:
+ break;
+ }
+}
+
+void TranslateOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx == 0) {
+ ensureDelta();
+ r_input_area = output_area;
+ if (x_extend_mode_ == MemoryBufferExtend::Clip) {
+ const int delta_x = this->getDeltaX();
+ BLI_rcti_translate(&r_input_area, -delta_x, 0);
+ }
+ if (y_extend_mode_ == MemoryBufferExtend::Clip) {
+ const int delta_y = this->getDeltaY();
+ BLI_rcti_translate(&r_input_area, 0, -delta_y);
+ }
+ }
+}
+
+void TranslateOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ MemoryBuffer *input = inputs[0];
+ const int delta_x = this->getDeltaX();
+ const int delta_y = this->getDeltaY();
+ for (int y = area.ymin; y < area.ymax; y++) {
+ float *out = output->get_elem(area.xmin, y);
+ for (int x = area.xmin; x < area.xmax; x++) {
+ const int input_x = x - delta_x;
+ const int input_y = y - delta_y;
+ input->read(out, input_x, input_y, x_extend_mode_, y_extend_mode_);
+ out += output->elem_stride;
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h
index eb3a664159f..ce1965cecef 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.h
+++ b/source/blender/compositor/operations/COM_TranslateOperation.h
@@ -18,11 +18,12 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class TranslateOperation : public NodeOperation {
+class TranslateOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputOperation;
SocketReader *m_inputXOperation;
@@ -32,9 +33,12 @@ class TranslateOperation : public NodeOperation {
bool m_isDeltaSet;
float m_factorX;
float m_factorY;
+ MemoryBufferExtend x_extend_mode_;
+ MemoryBufferExtend y_extend_mode_;
public:
TranslateOperation();
+ TranslateOperation(DataType data_type);
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
@@ -55,16 +59,38 @@ class TranslateOperation : public NodeOperation {
inline void ensureDelta()
{
if (!this->m_isDeltaSet) {
- float tempDelta[4];
- this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
- this->m_deltaX = tempDelta[0];
- this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
- this->m_deltaY = tempDelta[0];
+ if (execution_model_ == eExecutionModel::Tiled) {
+ float tempDelta[4];
+ this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
+ this->m_deltaX = tempDelta[0];
+ this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
+ this->m_deltaY = tempDelta[0];
+ }
+ else {
+ this->m_deltaX = 0;
+ NodeOperation *x_op = getInputOperation(1);
+ if (x_op->get_flags().is_constant_operation) {
+ this->m_deltaX = ((ConstantOperation *)x_op)->get_constant_elem()[0];
+ }
+ this->m_deltaY = 0;
+ NodeOperation *y_op = getInputOperation(2);
+ if (y_op->get_flags().is_constant_operation) {
+ this->m_deltaY = ((ConstantOperation *)y_op)->get_constant_elem()[0];
+ }
+ }
+
this->m_isDeltaSet = true;
}
}
void setFactorXY(float factorX, float factorY);
+ void set_wrapping(int wrapping_type);
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cc b/source/blender/compositor/operations/COM_VectorBlurOperation.cc
index fd64bda156b..b5b5d426338 100644
--- a/source/blender/compositor/operations/COM_VectorBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cc
@@ -432,7 +432,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove)
}
}
- /* 2: evaluate horizontal scanlines and calculate alphas */
+ /* 2: evaluate horizontal scan-lines and calculate alphas. */
row1 = rectmove;
for (y = 0; y < ysize; y++) {
row1++;
@@ -449,7 +449,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove)
/* now we can blend values */
next = row1[step];
- /* note, prev value can be next value, but we do this loop to clear 128 then */
+ /* NOTE: prev value can be next value, but we do this loop to clear 128 then. */
for (a = 0; a < step; a++) {
int fac, mfac;
@@ -463,7 +463,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove)
}
}
- /* 3: evaluate vertical scanlines and calculate alphas */
+ /* 3: evaluate vertical scan-lines and calculate alphas */
/* use for reading a copy of the original tagged buffer */
for (x = 0; x < xsize; x++) {
row1 = rectmove + x + xsize;
@@ -480,7 +480,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove)
if (y + step != ysize) {
/* now we can blend values */
next = row1[step * xsize];
- /* note, prev value can be next value, but we do this loop to clear 128 then */
+ /* NOTE: prev value can be next value, but we do this loop to clear 128 then. */
for (a = 0; a < step; a++) {
int fac, mfac;
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cc b/source/blender/compositor/operations/COM_WriteBufferOperation.cc
index 1aa19f26e2b..e2dc6287baf 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.cc
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cc
@@ -124,7 +124,7 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device,
* 3. schedule read back from opencl to main device (outputbuffer)
* 4. schedule native callback
*
- * note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4
+ * NOTE: list of cl_mem will be filled by 2, and needs to be cleaned up by 4
*/
// STEP 1
const unsigned int outputBufferWidth = outputBuffer->getWidth();
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 27441c9a7ae..749b1bba871 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -159,7 +159,7 @@ void DEG_ids_restore_recalc(Depsgraph *depsgraph);
/* Graph Evaluation ----------------------------- */
/* Frame changed recalculation entry point. */
-void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime);
+void DEG_evaluate_on_framechange(Depsgraph *graph, float frame);
/* Data changed recalculation entry point. */
void DEG_evaluate_on_refresh(Depsgraph *graph);
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index 42c9cccceed..c029d203574 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -33,6 +33,7 @@ struct Depsgraph;
/* ------------------------------------------------ */
struct CacheFile;
+struct Collection;
struct CustomData_MeshMasks;
struct ID;
struct Main;
@@ -40,7 +41,6 @@ struct Object;
struct Scene;
struct Simulation;
struct bNodeTree;
-struct Collection;
#include "BLI_sys_types.h"
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index f877e99b16b..17f5ca0db79 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -95,7 +95,7 @@ struct ViewLayer *DEG_get_evaluated_view_layer(const struct Depsgraph *graph);
/* Get evaluated version of object for given original one. */
struct Object *DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object);
-/* Get evaluated version of given ID datablock. */
+/* Get evaluated version of given ID data-block. */
struct ID *DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id);
/* Get evaluated version of data pointed to by RNA pointer */
@@ -106,7 +106,7 @@ void DEG_get_evaluated_rna_pointer(const struct Depsgraph *depsgraph,
/* Get original version of object for given evaluated one. */
struct Object *DEG_get_original_object(struct Object *object);
-/* Get original version of given evaluated ID datablock. */
+/* Get original version of given evaluated ID data-block. */
struct ID *DEG_get_original_id(struct ID *id);
/* Check whether given ID is an original,
@@ -122,7 +122,7 @@ bool DEG_is_original_object(const struct Object *object);
bool DEG_is_evaluated_id(const struct ID *id);
bool DEG_is_evaluated_object(const struct Object *object);
-/* Check whether depsgraph os fully evaluated. This includes the following checks:
+/* Check whether depsgraph is fully evaluated. This includes the following checks:
* - Relations are up-to-date.
* - Nothing is tagged for update. */
bool DEG_is_fully_evaluated(const struct Depsgraph *depsgraph);
@@ -180,7 +180,7 @@ void DEG_iterator_objects_next(struct BLI_Iterator *iter);
void DEG_iterator_objects_end(struct BLI_Iterator *iter);
/**
- * Note: Be careful with DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY objects.
+ * NOTE: Be careful with DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY objects.
* Although they are available they have no overrides (collection_properties)
* and will crash if you try to access it.
*/
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index f4d65698bee..41512168f57 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -97,7 +97,7 @@ bool DepsgraphBuilder::need_pull_base_into_graph(Base *base)
property_id = AnimatedPropertyID(&object->id, &RNA_Object, "hide_render");
}
else {
- BLI_assert(!"Unknown evaluation mode.");
+ BLI_assert_msg(0, "Unknown evaluation mode.");
return false;
}
return cache_->isPropertyAnimated(&object->id, property_id);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 56168739fae..e561d0b653c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -114,6 +114,7 @@
#include "SEQ_iterator.h"
#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_rna.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_tag.h"
#include "intern/depsgraph_type.h"
@@ -226,7 +227,7 @@ OperationNode *DepsgraphNodeBuilder::add_operation_node(ComponentNode *comp_node
comp_node->identifier().c_str(),
op_node->identifier().c_str(),
op_node);
- BLI_assert(!"Should not happen!");
+ BLI_assert_msg(0, "Should not happen!");
}
return op_node;
}
@@ -1199,7 +1200,7 @@ void DepsgraphNodeBuilder::build_driver_id_property(ID *id, const char *rna_path
if (prop == nullptr) {
return;
}
- if (!RNA_property_is_idprop(prop)) {
+ if (!rna_prop_affects_parameters_node(&ptr, prop)) {
return;
}
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
@@ -1495,7 +1496,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob
add_operation_node(
&object->id,
NodeType::BATCH_CACHE,
- OperationCode::GEOMETRY_SELECT_UPDATE,
+ OperationCode::BATCH_UPDATE_SELECT,
[object_cow](::Depsgraph *depsgraph) { BKE_object_select_update(depsgraph, object_cow); });
}
@@ -1516,33 +1517,37 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool
if (key) {
build_shapekeys(key);
}
- /* Nodes for result of obdata's evaluation, and geometry
- * evaluation on object. */
+
+ /* Geometry evaluation. */
+ /* Entry operation, takes care of initialization, and some other
+ * relations which needs to be run prior to actual geometry evaluation. */
+ op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ op_node->set_as_entry();
+
+ add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM);
+
const ID_Type id_type = GS(obdata->name);
switch (id_type) {
case ID_ME: {
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- [obdata_cow](::Depsgraph *depsgraph) {
- BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow);
- });
- op_node->set_as_entry();
+ add_operation_node(obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow);
+ });
break;
}
case ID_MB: {
- op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- op_node->set_as_entry();
+ add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
break;
}
case ID_CU: {
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- [obdata_cow](::Depsgraph *depsgraph) {
- BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow);
- });
- op_node->set_as_entry();
+ add_operation_node(obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow);
+ });
/* Make sure objects used for bevel.taper are in the graph.
* NOTE: This objects might be not linked to the scene. */
Curve *cu = (Curve *)obdata;
@@ -1558,51 +1563,45 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool
break;
}
case ID_LT: {
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- [obdata_cow](::Depsgraph *depsgraph) {
- BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow);
- });
- op_node->set_as_entry();
+ add_operation_node(obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow);
+ });
break;
}
case ID_GD: {
/* GPencil evaluation operations. */
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- [obdata_cow](::Depsgraph *depsgraph) {
- BKE_gpencil_frame_active_set(depsgraph,
- (bGPdata *)obdata_cow);
- });
- op_node->set_as_entry();
+ add_operation_node(obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_gpencil_frame_active_set(depsgraph, (bGPdata *)obdata_cow);
+ });
break;
}
case ID_HA: {
- op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- op_node->set_as_entry();
+ add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
break;
}
case ID_PT: {
- op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- op_node->set_as_entry();
+ add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
break;
}
case ID_VO: {
/* Volume frame update. */
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- [obdata_cow](::Depsgraph *depsgraph) {
- BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow);
- });
- op_node->set_as_entry();
+ add_operation_node(obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow);
+ });
break;
}
default:
- BLI_assert(!"Should not happen");
+ BLI_assert_msg(0, "Should not happen");
break;
}
op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
@@ -1612,10 +1611,22 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool
/* Batch cache. */
add_operation_node(obdata,
NodeType::BATCH_CACHE,
- OperationCode::GEOMETRY_SELECT_UPDATE,
+ OperationCode::BATCH_UPDATE_SELECT,
[obdata_cow](::Depsgraph *depsgraph) {
BKE_object_data_select_update(depsgraph, obdata_cow);
});
+ add_operation_node(obdata,
+ NodeType::BATCH_CACHE,
+ OperationCode::BATCH_UPDATE_DEFORM,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_object_data_eval_batch_cache_deform_tag(depsgraph, obdata_cow);
+ });
+ add_operation_node(obdata,
+ NodeType::BATCH_CACHE,
+ OperationCode::BATCH_UPDATE_ALL,
+ [obdata_cow](::Depsgraph *depsgraph) {
+ BKE_object_data_eval_batch_cache_dirty_tag(depsgraph, obdata_cow);
+ });
}
void DepsgraphNodeBuilder::build_armature(bArmature *armature)
@@ -1769,7 +1780,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_nodetree(group_ntree);
}
else {
- BLI_assert(!"Unknown ID type used for node");
+ BLI_assert_msg(0, "Unknown ID type used for node");
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 151e0d844b6..3b2dd44af0d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -289,7 +289,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
* setting the current state. */
Collection *collection_;
/* Accumulated flag over the hierarchy of currently building collections.
- * Denotes whether all the hierarchy from parent of collection_ to the
+ * Denotes whether all the hierarchy from parent of `collection_` to the
* very root is visible (aka not restricted.). */
bool is_parent_collection_visible_;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index c269ad16824..c63b3d825a0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -326,7 +326,7 @@ void DepsgraphRelationBuilder::add_customdata_mask(Object *object,
IDNode *id_node = graph_->find_id_node(&object->id);
if (id_node == nullptr) {
- BLI_assert(!"ID should always be valid");
+ BLI_assert_msg(0, "ID should always be valid");
}
else {
id_node->customdata_masks |= customdata_masks;
@@ -338,7 +338,7 @@ void DepsgraphRelationBuilder::add_special_eval_flag(ID *id, uint32_t flag)
{
IDNode *id_node = graph_->find_id_node(id);
if (id_node == nullptr) {
- BLI_assert(!"ID should always be valid");
+ BLI_assert_msg(0, "ID should always be valid");
}
else {
id_node->eval_flags |= flag;
@@ -647,7 +647,7 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll
/* Only create geometry relations to child objects, if they have a geometry component. */
OperationKey object_geometry_key{
- &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL};
+ &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT};
if (find_node(object_geometry_key) != nullptr) {
add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry");
}
@@ -1099,7 +1099,14 @@ void DepsgraphRelationBuilder::build_object_pointcache(Object *object)
else {
flag = FLAG_GEOMETRY;
OperationKey geometry_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry");
+ add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry Eval");
+ if (object->data) {
+ /* Geometry may change, so rebuild the Drawing Cache. */
+ OperationKey object_data_batch_all_key(
+ (ID *)object->data, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL);
+ add_relation(
+ point_cache_key, object_data_batch_all_key, "Point Cache -> Batch Update All");
+ }
}
BLI_assert(flag != -1);
/* Tag that we did handle that component. */
@@ -1610,7 +1617,7 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
}
}
}
- if (property_entry_key.prop != nullptr && RNA_property_is_idprop(property_entry_key.prop)) {
+ if (rna_prop_affects_parameters_node(&property_entry_key.ptr, property_entry_key.prop)) {
RNAPathKey property_exit_key(property_entry_key.id,
property_entry_key.ptr,
property_entry_key.prop,
@@ -1713,7 +1720,7 @@ void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_
if (prop == nullptr) {
return;
}
- if (!RNA_property_is_idprop(prop)) {
+ if (!rna_prop_affects_parameters_node(&ptr, prop)) {
return;
}
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
@@ -1868,7 +1875,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
void DepsgraphRelationBuilder::build_particle_systems(Object *object)
{
TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ OperationKey obdata_ubereval_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
OperationKey eval_init_key(
&object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT);
OperationKey eval_done_key(
@@ -2016,7 +2024,8 @@ void DepsgraphRelationBuilder::build_particle_system_visualization_object(Object
{
OperationKey psys_key(
&object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name);
- OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ OperationKey obdata_ubereval_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
if (draw_object->type == OB_MBALL) {
@@ -2073,15 +2082,15 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
/* Get nodes for result of obdata's evaluation, and geometry evaluation
* on object. */
ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
- ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
- /* Link components to each other. */
- add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ /* Link components to each other. */
+ add_relation(obdata_geom_key, obdata_ubereval_key, "Object Geometry Base Data");
+
/* Special case: modifiers evaluation queries scene for various things like
* data mask to be used. We add relation here to ensure object is never
* evaluated prior to Scene's CoW is ready. */
OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
- Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
+ Relation *rel = add_relation(scene_key, geom_init_key, "CoW Relation");
rel->flag |= RELATION_FLAG_NO_FLUSH;
/* Modifiers */
if (object->modifiers.first != nullptr) {
@@ -2091,13 +2100,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ DepsNodeHandle handle = create_node_handle(geom_init_key);
ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
mti->updateDepsgraph(md, &ctx);
}
if (BKE_object_modifier_use_time(object, md)) {
TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ add_relation(time_src_key, geom_init_key, "Time Source");
}
}
}
@@ -2110,13 +2119,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(
(GpencilModifierType)md->type);
if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ DepsNodeHandle handle = create_node_handle(geom_init_key);
ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
mti->updateDepsgraph(md, &ctx, graph_->mode);
}
if (BKE_object_modifier_gpencil_use_time(object, md)) {
TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ add_relation(time_src_key, geom_init_key, "Time Source");
}
}
}
@@ -2128,13 +2137,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type);
if (fxi->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ DepsNodeHandle handle = create_node_handle(geom_init_key);
ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
fxi->updateDepsgraph(fx, &ctx);
}
if (BKE_object_shaderfx_use_time(object, fx)) {
TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ add_relation(time_src_key, geom_init_key, "Time Source");
}
}
}
@@ -2160,6 +2169,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry");
}
else {
+ ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
add_relation(geom_key, mom_geom_key, "Metaball Motherball");
add_relation(transform_key, mom_geom_key, "Metaball Motherball");
@@ -2174,9 +2184,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
* Ideally we need to get rid of this relation. */
if (object_particles_depends_on_time(object)) {
TimeSourceKey time_key;
- OperationKey obdata_ubereval_key(
- &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
+ add_relation(time_key, geom_init_key, "Legacy particle time");
}
/* Object data data-block. */
build_object_data_geometry_datablock((ID *)object->data);
@@ -2198,12 +2206,33 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
add_relation(final_geometry_key, synchronize_key, "Synchronize to Original");
/* Batch cache. */
OperationKey object_data_select_key(
- obdata, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE);
+ obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_SELECT);
OperationKey object_select_key(
- &object->id, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE);
+ &object->id, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_SELECT);
+
add_relation(object_data_select_key, object_select_key, "Data Selection -> Object Selection");
+ add_relation(final_geometry_key,
+ object_select_key,
+ "Object Geometry -> Select Update",
+ RELATION_FLAG_NO_FLUSH);
+
+ OperationKey object_data_geom_deform_key(
+ obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM);
+ OperationKey object_data_geom_init_key(
+ obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+
+ OperationKey object_data_batch_deform_key(
+ obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_DEFORM);
+ OperationKey object_data_batch_all_key(
+ obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL);
+
+ add_relation(geom_init_key, object_data_batch_all_key, "Object Geometry -> Batch Update All");
+
add_relation(
- geom_key, object_select_key, "Object Geometry -> Select Update", RELATION_FLAG_NO_FLUSH);
+ object_data_geom_init_key, object_data_batch_all_key, "Data Init -> Batch Update All");
+ add_relation(object_data_geom_deform_key,
+ object_data_batch_deform_key,
+ "Data Deform -> Batch Update Deform");
}
void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
@@ -2221,8 +2250,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
build_shapekeys(key);
}
/* Link object data evaluation node to exit operation. */
+ OperationKey obdata_geom_deform_key(
+ obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM);
+ OperationKey obdata_geom_init_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
OperationKey obdata_geom_done_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
+ add_relation(obdata_geom_init_key, obdata_geom_eval_key, "ObData Init -> Geom Eval");
+ add_relation(obdata_geom_deform_key, obdata_geom_eval_key, "ObData Deform -> Geom Eval");
add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
/* Type-specific links. */
const ID_Type id_type = GS(obdata->name);
@@ -2314,7 +2348,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
break;
}
default:
- BLI_assert(!"Should not happen");
+ BLI_assert_msg(0, "Should not happen");
break;
}
}
@@ -2497,7 +2531,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
add_relation(group_shading_key, shading_key, "Group Node");
}
else {
- BLI_assert(!"Unknown ID type used for node");
+ BLI_assert_msg(0, "Unknown ID type used for node");
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
index 035d636b977..14ed153832d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
@@ -54,7 +54,7 @@ Relation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
}
else {
if (!op_from) {
- /* XXX TODO handle as error or report if needed */
+ /* XXX TODO: handle as error or report if needed. */
fprintf(stderr,
"add_relation(%s) - Could not find op_from (%s)\n",
description,
@@ -67,7 +67,7 @@ Relation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
key_from.identifier().c_str());
}
if (!op_to) {
- /* XXX TODO handle as error or report if needed */
+ /* XXX TODO: handle as error or report if needed. */
fprintf(stderr,
"add_relation(%s) - Could not find op_to (%s)\n",
description,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index 54c51adec66..8e3960e1a15 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -180,7 +180,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
node_identifier.operation_name = "";
node_identifier.operation_name_tag = -1;
/* Handling of commonly known scenarios. */
- if (prop != nullptr && RNA_property_is_idprop(prop)) {
+ if (rna_prop_affects_parameters_node(ptr, prop)) {
node_identifier.type = NodeType::PARAMETERS;
node_identifier.operation_code = OperationCode::ID_PROPERTY;
node_identifier.operation_name = RNA_property_identifier(
@@ -397,4 +397,12 @@ RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id)
return id_data.get();
}
+bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop)
+{
+ return prop != nullptr && RNA_property_is_idprop(prop) &&
+ /* ID properties in the geometry nodes modifier don't affect that parameters node. Instead
+ they affect the modifier and therefore the geometry node directly. */
+ !RNA_struct_is_a(ptr->type, &RNA_NodesModifier);
+}
+
} // namespace blender::deg
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
index d03903d508c..24d7f5f3a30 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
@@ -108,5 +108,7 @@ class RNANodeQuery {
static bool contains(const char *prop_identifier, const char *rna_path_component);
};
+bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop);
+
} // namespace deg
} // namespace blender
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index 9afae0f2c22..57c6f062611 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -461,7 +461,7 @@ static void deg_debug_graphviz_node_relations(DotExportContext &ctx, const Node
dot::DirectedEdge &edge = ctx.digraph.new_edge(dot_tail, dot_head);
- /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
+ /* NOTE: without label an id seem necessary to avoid bugs in graphviz/dot. */
edge.attributes.set("id", rel->name);
deg_debug_graphviz_relation_color(rel, edge);
deg_debug_graphviz_relation_style(rel, edge);
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 6fe7d5f5d8b..4c036417ba0 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -68,7 +68,8 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati
scene(scene),
view_layer(view_layer),
mode(mode),
- ctime(BKE_scene_frame_get(scene)),
+ frame(BKE_scene_frame_get(scene)),
+ ctime(BKE_scene_ctime_get(scene)),
scene_cow(nullptr),
is_active(false),
is_evaluating(false),
@@ -267,7 +268,7 @@ ID *Depsgraph::get_cow_id(const ID *id_orig) const
* - Object or mesh has material at a slot which is not used (for
* example, object has material slot by materials are set to
* object data). */
- // BLI_assert(!"Request for non-existing copy-on-write ID");
+ // BLI_assert_msg(0, "Request for non-existing copy-on-write ID");
}
return (ID *)id_orig;
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index ff536c19c05..913b61ca563 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -140,7 +140,9 @@ struct Depsgraph {
ViewLayer *view_layer;
eEvaluationMode mode;
- /* Time at which dependency graph is being or was last evaluated. */
+ /* Time at which dependency graph is being or was last evaluated.
+ * frame is the value before, and ctime the value after time remapping. */
+ float frame;
float ctime;
/* Evaluated version of datablocks we access a lot.
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index c5e306f3148..3677f80469c 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -96,7 +96,7 @@ bool DEG_debug_graph_relations_validate(Depsgraph *graph,
DEG_graph_build_from_view_layer(temp_depsgraph);
if (!DEG_debug_compare(temp_depsgraph, graph)) {
fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
- BLI_assert(!"This should not happen!");
+ BLI_assert_msg(0, "This should not happen!");
valid = false;
}
DEG_graph_free(temp_depsgraph);
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index 1ad3fdbc9da..cc7ce871419 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -51,7 +51,7 @@ static void deg_flush_updates_and_refresh(deg::Depsgraph *deg_graph)
{
/* Update the time on the cow scene. */
if (deg_graph->scene_cow) {
- BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime);
+ BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->frame);
}
deg::deg_graph_flush_updates(deg_graph);
@@ -63,10 +63,12 @@ void DEG_evaluate_on_refresh(Depsgraph *graph)
{
deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph);
const Scene *scene = DEG_get_input_scene(graph);
- const float ctime = BKE_scene_frame_get(scene);
+ const float frame = BKE_scene_frame_get(scene);
+ const float ctime = BKE_scene_ctime_get(scene);
- if (ctime != deg_graph->ctime) {
+ if (deg_graph->frame != frame || ctime != deg_graph->ctime) {
deg_graph->tag_time_source();
+ deg_graph->frame = frame;
deg_graph->ctime = ctime;
}
@@ -74,10 +76,13 @@ void DEG_evaluate_on_refresh(Depsgraph *graph)
}
/* Frame-change happened for root scene that graph belongs to. */
-void DEG_evaluate_on_framechange(Depsgraph *graph, float ctime)
+void DEG_evaluate_on_framechange(Depsgraph *graph, float frame)
{
deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph);
+ const Scene *scene = DEG_get_input_scene(graph);
+
deg_graph->tag_time_source();
- deg_graph->ctime = ctime;
+ deg_graph->frame = frame;
+ deg_graph->ctime = BKE_scene_frame_to_ctime(scene, frame);
deg_flush_updates_and_refresh(deg_graph);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc
index 8f3aab19e37..a70c0c10de0 100644
--- a/source/blender/depsgraph/intern/depsgraph_physics.cc
+++ b/source/blender/depsgraph/intern/depsgraph_physics.cc
@@ -59,7 +59,7 @@ static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type
return DEG_PHYSICS_DYNAMIC_BRUSH;
}
- BLI_assert(!"Unknown collision modifier type");
+ BLI_assert_msg(0, "Unknown collision modifier type");
return DEG_PHYSICS_RELATIONS_NUM;
}
/* Get ID from an ID type object, in a safe manner. This means that object can be nullptr,
@@ -80,7 +80,7 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collect
if (hash == nullptr) {
return nullptr;
}
- /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a
+ /* NOTE: nullptr is a valid lookup key here as it means that the relation is not bound to a
* specific collection. */
ID *collection_orig = DEG_get_original_id(object_id_safe(collection));
return hash->lookup_default(collection_orig, nullptr);
@@ -96,7 +96,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph,
if (hash == nullptr) {
return nullptr;
}
- /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a
+ /* NOTE: nullptr is a valid lookup key here as it means that the relation is not bound to a
* specific collection. */
ID *collection_orig = DEG_get_original_id(object_id_safe(collection));
return hash->lookup_default(collection_orig, nullptr);
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index b00cae87311..34b33e9a6c0 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -117,7 +117,7 @@ void depsgraph_select_tag_to_component_opcode(const ID *id,
}
else if (is_selectable_data_id_type(id_type)) {
*component_type = NodeType::BATCH_CACHE;
- *operation_code = OperationCode::GEOMETRY_SELECT_UPDATE;
+ *operation_code = OperationCode::BATCH_UPDATE_SELECT;
}
else {
*component_type = NodeType::COPY_ON_WRITE;
@@ -168,6 +168,11 @@ void depsgraph_tag_to_component_opcode(const ID *id,
break;
case ID_RECALC_GEOMETRY:
depsgraph_geometry_tag_to_component(id, component_type);
+ *operation_code = OperationCode::GEOMETRY_EVAL_INIT;
+ break;
+ case ID_RECALC_GEOMETRY_DEFORM:
+ depsgraph_geometry_tag_to_component(id, component_type);
+ *operation_code = OperationCode::GEOMETRY_EVAL_DEFORM;
break;
case ID_RECALC_ANIMATION:
*component_type = NodeType::ANIMATION;
@@ -233,7 +238,7 @@ void depsgraph_tag_to_component_opcode(const ID *id,
case ID_RECALC_GEOMETRY_ALL_MODES:
case ID_RECALC_ALL:
case ID_RECALC_PSYS_ALL:
- BLI_assert(!"Should not happen");
+ BLI_assert_msg(0, "Should not happen");
break;
case ID_RECALC_TAG_FOR_UNDO:
break; /* Must be ignored by depsgraph. */
@@ -452,7 +457,7 @@ const char *update_source_as_string(eUpdateSource source)
case DEG_UPDATE_SOURCE_VISIBILITY:
return "VISIBILITY";
}
- BLI_assert(!"Should never happen.");
+ BLI_assert_msg(0, "Should never happen.");
return "UNKNOWN";
}
@@ -708,6 +713,8 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
return "GEOMETRY";
case ID_RECALC_GEOMETRY_ALL_MODES:
return "GEOMETRY_ALL_MODES";
+ case ID_RECALC_GEOMETRY_DEFORM:
+ return "GEOMETRY_DEFORM";
case ID_RECALC_ANIMATION:
return "ANIMATION";
case ID_RECALC_PSYS_REDO:
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 6f35143e28f..915b9fedcec 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -223,7 +223,7 @@ bool need_evaluate_operation_at_stage(DepsgraphEvalState *state,
case EvaluationStage::SINGLE_THREADED_WORKAROUND:
return true;
}
- BLI_assert(!"Unhandled evaluation stage, should never happen.");
+ BLI_assert_msg(0, "Unhandled evaluation stage, should never happen.");
return false;
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 0d367762b00..346eba5bbc2 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -899,7 +899,7 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
done = id_copy_inplace_no_main(id_orig, id_cow);
}
if (!done) {
- BLI_assert(!"No idea how to perform CoW on datablock");
+ BLI_assert_msg(0, "No idea how to perform CoW on datablock");
}
/* Update pointers to nested ID datablocks. */
DEG_COW_PRINT(
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 1b24e2b7ad2..2cbb0b52e34 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -144,7 +144,10 @@ inline void flush_handle_component_node(IDNode *id_node,
* special component where we don't want all operations to be tagged.
*
* TODO(sergey): Make this a more generic solution. */
- if (!ELEM(comp_node->type, NodeType::PARTICLE_SETTINGS, NodeType::PARTICLE_SYSTEM)) {
+ if (!ELEM(comp_node->type,
+ NodeType::PARTICLE_SETTINGS,
+ NodeType::PARTICLE_SYSTEM,
+ NodeType::BATCH_CACHE)) {
for (OperationNode *op : comp_node->operations) {
op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
}
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
index 0d3563ee3de..fee5342df59 100644
--- a/source/blender/depsgraph/intern/node/deg_node.cc
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -48,7 +48,7 @@ const char *nodeClassAsString(NodeClass node_class)
case NodeClass::OPERATION:
return "OPERATION";
}
- BLI_assert(!"Unhandled node class, should never happen.");
+ BLI_assert_msg(0, "Unhandled node class, should never happen.");
return "UNKNOWN";
}
@@ -121,7 +121,7 @@ const char *nodeTypeAsString(NodeType type)
case NodeType::NUM_TYPES:
return "SpecialCase";
}
- BLI_assert(!"Unhandled node type, should never happen.");
+ BLI_assert_msg(0, "Unhandled node type, should never happen.");
return "UNKNOWN";
}
@@ -177,7 +177,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
case NodeType::SIMULATION:
return DEG_SCENE_COMP_PARAMETERS;
}
- BLI_assert(!"Unhandled node type, not suppsed to happen.");
+ BLI_assert_msg(0, "Unhandled node type, not suppsed to happen.");
return DEG_SCENE_COMP_PARAMETERS;
}
@@ -253,7 +253,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
case NodeType::NUM_TYPES:
return DEG_OB_COMP_PARAMETERS;
}
- BLI_assert(!"Unhandled node type, not suppsed to happen.");
+ BLI_assert_msg(0, "Unhandled node type, not suppsed to happen.");
return DEG_OB_COMP_PARAMETERS;
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
index d824fb14718..431bf536b65 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -142,7 +142,7 @@ OperationNode *ComponentNode::get_operation(OperationIDKey key) const
"%s: find_operation(%s) failed\n",
this->identifier().c_str(),
key.identifier().c_str());
- BLI_assert(!"Request for non-existing operation, should not happen");
+ BLI_assert_msg(0, "Request for non-existing operation, should not happen");
return nullptr;
}
return node;
@@ -181,7 +181,7 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op,
OperationIDKey key(opcode, name, name_tag);
operations_map->add(key, op_node);
- /* set backlink */
+ /* Set back-link. */
op_node->owner = this;
}
else {
@@ -190,7 +190,7 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op,
this->identifier().c_str(),
op_node->identifier().c_str(),
op_node);
- BLI_assert(!"Should not happen!");
+ BLI_assert_msg(0, "Should not happen!");
}
/* attach extra data */
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
index 688afe141e9..2b1ebc663fe 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -53,7 +53,7 @@ const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state)
case DEG_ID_LINKED_DIRECTLY:
return "DIRECTLY";
}
- BLI_assert(!"Unhandled linked state, should never happen.");
+ BLI_assert_msg(0, "Unhandled linked state, should never happen.");
return "UNKNOWN";
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 7e57467f905..d98486b83a8 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -98,6 +98,8 @@ const char *operationCodeAsString(OperationCode opcode)
/* Geometry. */
case OperationCode::GEOMETRY_EVAL_INIT:
return "GEOMETRY_EVAL_INIT";
+ case OperationCode::GEOMETRY_EVAL_DEFORM:
+ return "GEOMETRY_EVAL_DEFORM";
case OperationCode::GEOMETRY_EVAL:
return "GEOMETRY_EVAL";
case OperationCode::GEOMETRY_EVAL_DONE:
@@ -160,8 +162,12 @@ const char *operationCodeAsString(OperationCode opcode)
case OperationCode::FILE_CACHE_UPDATE:
return "FILE_CACHE_UPDATE";
/* Batch cache. */
- case OperationCode::GEOMETRY_SELECT_UPDATE:
- return "GEOMETRY_SELECT_UPDATE";
+ case OperationCode::BATCH_UPDATE_SELECT:
+ return "BATCH_UPDATE_SELECT";
+ case OperationCode::BATCH_UPDATE_DEFORM:
+ return "BATCH_UPDATE_DEFORM";
+ case OperationCode::BATCH_UPDATE_ALL:
+ return "BATCH_UPDATE_ALL";
/* Masks. */
case OperationCode::MASK_ANIMATION:
return "MASK_ANIMATION";
@@ -205,7 +211,7 @@ const char *operationCodeAsString(OperationCode opcode)
case OperationCode::SIMULATION_EVAL:
return "SIMULATION_EVAL";
}
- BLI_assert(!"Unhandled operation code, should never happen.");
+ BLI_assert_msg(0, "Unhandled operation code, should never happen.");
return "UNKNOWN";
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index a17186da941..b0130d03c69 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -100,7 +100,11 @@ enum class OperationCode {
/* Initialize evaluation of the geometry. Is an entry operation of geometry
* component. */
GEOMETRY_EVAL_INIT,
- /* Evaluate the whole geometry, including modifiers. */
+ /* Evaluate the geometry, including modifiers, and update only batches that
+ * are affected by deform operations. */
+ GEOMETRY_EVAL_DEFORM,
+ /* Evaluate the geometry, including modifiers, but don't update the batch
+ * cache. */
GEOMETRY_EVAL,
/* Evaluation of geometry is completely done. */
GEOMETRY_EVAL_DONE,
@@ -178,7 +182,9 @@ enum class OperationCode {
WORLD_UPDATE,
/* Batch caches. -------------------------------------------------------- */
- GEOMETRY_SELECT_UPDATE,
+ BATCH_UPDATE_SELECT,
+ BATCH_UPDATE_DEFORM,
+ BATCH_UPDATE_ALL,
/* Masks. --------------------------------------------------------------- */
MASK_ANIMATION,
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 4f68c3fdc7e..ad154704d2c 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -51,16 +51,36 @@ set(INC
set(SRC
intern/draw_cache.c
+ intern/draw_cache_extract_mesh.cc
intern/draw_cache_extract_mesh_extractors.c
intern/draw_cache_extract_mesh_render_data.c
- intern/draw_cache_extract_mesh.cc
intern/mesh_extractors/extract_mesh_ibo_edituv.cc
intern/mesh_extractors/extract_mesh_ibo_fdots.cc
+ intern/mesh_extractors/extract_mesh_ibo_lines.cc
intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
- intern/mesh_extractors/extract_mesh_ibo_lines.cc
intern/mesh_extractors/extract_mesh_ibo_points.cc
intern/mesh_extractors/extract_mesh_ibo_tris.cc
+ intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
+ intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
+ intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
+ intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
+ intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
+ intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
+ intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
+ intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
+ intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc
+ intern/mesh_extractors/extract_mesh_vbo_lnor.cc
+ intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
+ intern/mesh_extractors/extract_mesh_vbo_orco.cc
+ intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
+ intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
+ intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
+ intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
+ intern/mesh_extractors/extract_mesh_vbo_tan.cc
+ intern/mesh_extractors/extract_mesh_vbo_uv.cc
+ intern/mesh_extractors/extract_mesh_vbo_vcol.cc
+ intern/mesh_extractors/extract_mesh_vbo_weights.cc
intern/draw_cache_impl_curve.cc
intern/draw_cache_impl_displist.c
intern/draw_cache_impl_gpencil.c
@@ -185,8 +205,8 @@ set(SRC
intern/draw_manager_profiling.h
intern/draw_manager_testing.h
intern/draw_manager_text.h
- intern/draw_view.h
intern/draw_shader.h
+ intern/draw_view.h
intern/smaa_textures.h
engines/basic/basic_engine.h
engines/eevee/eevee_engine.h
@@ -495,6 +515,8 @@ if(WITH_GTESTS)
set(TEST_SRC
tests/draw_testing.cc
tests/shaders_test.cc
+
+ tests/draw_testing.hh
)
set(TEST_INC
"../../../intern/ghost/"
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 88fd823bc72..9d4f7865c32 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -22,7 +22,7 @@
#include "DRW_render.h"
-#include "draw_color_management.h" /* TODO remove dependency */
+#include "draw_color_management.h" /* TODO: remove dependency. */
#include "BLI_rand.h"
@@ -189,7 +189,7 @@ static void eevee_cache_finish(void *vedata)
/* As renders in an HDR offscreen buffer, we need draw everything once
* during the background pass. This way the other drawing callback between
* the background and the scene pass are visible.
- * Note: we could break it up in two passes using some depth test
+ * NOTE: we could break it up in two passes using some depth test
* to reduce the fillrate */
static void eevee_draw_scene(void *vedata)
{
@@ -481,7 +481,7 @@ static void eevee_render_to_image(void *vedata,
time -= shuttertime;
break;
default:
- BLI_assert(!"Invalid motion blur position enum!");
+ BLI_assert_msg(0, "Invalid motion blur position enum!");
break;
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index cdd66759308..9a85037ac77 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -75,7 +75,7 @@
(IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_X) * \
(IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y)
-/* TODO should be replace by a more elegant alternative. */
+/* TODO: should be replace by a more elegant alternative. */
extern void DRW_opengl_context_enable(void);
extern void DRW_opengl_context_disable(void);
@@ -165,7 +165,7 @@ typedef struct EEVEE_LightBake {
bool own_resources;
/** If the light-cache was created for baking, it's first owned by the baker. */
bool own_light_cache;
- /** ms. delay the start of the baking to not slowdown interactions (TODO remove) */
+ /** ms. delay the start of the baking to not slowdown interactions (TODO: remove). */
int delay;
/** Scene frame to bake. */
int frame;
@@ -715,7 +715,7 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
* by the DRW mutex. */
lbake->lcache = eevee->light_cache_data;
- /* TODO validate irradiance and reflection cache independently... */
+ /* TODO: validate irradiance and reflection cache independently... */
if (!EEVEE_lightcache_validate(
lbake->lcache, lbake->cube_len, lbake->ref_cube_res, lbake->grid_len, lbake->irr_size)) {
eevee->light_cache_data = lbake->lcache = NULL;
@@ -764,7 +764,7 @@ wmJob *EEVEE_lightbake_job_create(struct wmWindowManager *wm,
if (old_lbake && (old_lbake->view_layer_input == view_layer) && (old_lbake->bmain == bmain)) {
lbake = MEM_callocN(sizeof(EEVEE_LightBake), "EEVEE_LightBake");
/* Cannot reuse depsgraph for now because we cannot get the update from the
- * main database directly. TODO reuse depsgraph and only update positions. */
+ * main database directly. TODO: reuse depsgraph and only update positions. */
/* lbake->depsgraph = old_lbake->depsgraph; */
lbake->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
@@ -838,7 +838,7 @@ void EEVEE_lightbake_job_data_free(void *custom_data)
{
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
- /* TODO reuse depsgraph. */
+ /* TODO: reuse depsgraph. */
/* if (lbake->own_resources) { */
DEG_graph_free(lbake->depsgraph);
/* } */
@@ -923,7 +923,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
stl->g_data->background_alpha = 1.0f;
stl->g_data->render_timesteps = 1;
- /* XXX TODO remove this. This is in order to make the init functions work. */
+ /* XXX TODO: remove this. This is in order to make the init functions work. */
if (DRW_view_default_get() == NULL) {
float winmat[4][4], viewmat[4][4];
unit_m4(viewmat);
@@ -1010,7 +1010,7 @@ static void eevee_lightbake_render_world_sample(void *ved, void *user_data)
float clamp = scene_eval->eevee.gi_glossy_clamp;
float filter_quality = scene_eval->eevee.gi_filter_quality;
- /* TODO do this once for the whole bake when we have independent DRWManagers. */
+ /* TODO: do this once for the whole bake when we have independent DRWManagers. */
eevee_lightbake_cache_create(vedata, lbake);
sldata->common_data.ray_type = EEVEE_RAY_GLOSSY;
@@ -1133,7 +1133,7 @@ static void eevee_lightbake_render_grid_sample(void *ved, void *user_data)
/* Use the previous bounce for rendering this bounce. */
SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx.tex);
- /* TODO do this once for the whole bake when we have independent DRWManagers.
+ /* TODO: do this once for the whole bake when we have independent DRWManagers.
* Warning: Some of the things above require this. */
eevee_lightbake_cache_create(vedata, lbake);
@@ -1210,7 +1210,7 @@ static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
float clamp = scene_eval->eevee.gi_glossy_clamp;
float filter_quality = scene_eval->eevee.gi_filter_quality;
- /* TODO do this once for the whole bake when we have independent DRWManagers. */
+ /* TODO: do this once for the whole bake when we have independent DRWManagers. */
eevee_lightbake_cache_create(vedata, lbake);
/* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
@@ -1420,7 +1420,7 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float
/* HACK: Sleep to delay the first rendering operation
* that causes a small freeze (caused by VBO generation)
* because this step is locking at this moment. */
- /* TODO remove this. */
+ /* TODO: remove this. */
if (lbake->delay) {
PIL_sleep_ms(lbake->delay);
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index e2e865bcfad..8598655477f 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -59,7 +59,7 @@ static struct {
/* *********** FUNCTIONS *********** */
-/* TODO find a better way than this. This does not support dupli objects if
+/* TODO: find a better way than this. This does not support dupli objects if
* the original object is hidden. */
bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data)
{
@@ -94,11 +94,11 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *fx = stl->effects;
- /* XXX TODO OPTIMIZATION: This is a complete waist of texture memory.
+ /* XXX TODO: OPTIMIZATION: This is a complete waist of texture memory.
* Instead of allocating each planar probe for each viewport,
* only alloc them once using the biggest viewport resolution. */
- /* TODO get screen percentage from layer setting */
+ /* TODO: get screen percentage from layer setting. */
// const DRWContextState *draw_ctx = DRW_context_state_get();
// ViewLayer *view_layer = draw_ctx->view_layer;
int screen_divider = 1;
@@ -1133,7 +1133,7 @@ void EEVEE_lightbake_filter_visibility(EEVEE_ViewLayerData *sldata,
EEVEE_LightProbesInfo *pinfo = sldata->probes;
LightCache *light_cache = vedata->stl->g_data->light_cache;
- pinfo->samples_len = 512.0f; /* TODO refine */
+ pinfo->samples_len = 512.0f; /* TODO: refine. */
pinfo->shres = vis_size;
pinfo->visibility_range = vis_range;
pinfo->visibility_blur = vis_blur;
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index e23a5a81169..afaf604322c 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -88,7 +88,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
/* Make illumination power constant */
if (la->type == LA_AREA) {
power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */
- 0.8f; /* XXX : Empirical, Fit cycles power */
+ 0.8f; /* XXX: Empirical, Fit cycles power. */
if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) {
/* Scale power to account for the lower area of the ellipse compared to the surrounding
* rectangle. */
@@ -99,7 +99,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* `1/(4*(r^2)*(Pi^2))` */
/* for point lights (a.k.a radius == 0.0) */
- // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
+ // power = M_PI * M_PI * 0.78; /* XXX: Empirical, Fit cycles power. */
}
else { /* LA_SUN */
power = 1.0f / (evli->radius * evli->radius * M_PI);
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index a9998b33b7e..f4dc553e982 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -205,7 +205,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
stl->lookdev_lightcache = EEVEE_lightcache_create(
1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1});
- /* XXX: Fix memleak. TODO find out why. */
+ /* XXX: Fix memleak. TODO: find out why. */
MEM_SAFE_FREE(stl->lookdev_cube_mips);
/* We do this to use a special light cache for lookdev.
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 7dd3449ad6e..9ecb737192e 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -70,7 +70,7 @@ typedef struct EeveeMaterialCache {
/* *********** FUNCTIONS *********** */
-/* XXX TODO define all shared resources in a shared place without duplication */
+/* XXX TODO: define all shared resources in a shared place without duplication. */
struct GPUTexture *EEVEE_materials_get_util_tex(void)
{
return e_data.util_tex;
@@ -691,7 +691,7 @@ static EeveeMaterialCache material_transparent(EEVEE_Data *vedata,
}
{
/* Shading */
- int ssr_id = -1; /* TODO transparent SSR */
+ int ssr_id = -1; /* TODO: transparent SSR. */
int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND;
SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
@@ -866,7 +866,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
continue;
}
- /* XXX TODO rewrite this to include the dupli objects.
+ /* XXX TODO: rewrite this to include the dupli objects.
* This means we cannot exclude dupli objects from reflections!!! */
EEVEE_ObjectEngineData *oedata = NULL;
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index ab297620afe..f51b4fa0127 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -44,12 +44,12 @@ struct RenderLayer;
extern struct DrawEngineType draw_engine_eevee_type;
/* Minimum UBO is 16384 bytes */
-#define MAX_PROBE 128 /* TODO : find size by dividing UBO max size by probe data size */
-#define MAX_GRID 64 /* TODO : find size by dividing UBO max size by grid data size */
-#define MAX_PLANAR 16 /* TODO : find size by dividing UBO max size by grid data size */
-#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */
+#define MAX_PROBE 128 /* TODO: find size by dividing UBO max size by probe data size. */
+#define MAX_GRID 64 /* TODO: find size by dividing UBO max size by grid data size. */
+#define MAX_PLANAR 16 /* TODO: find size by dividing UBO max size by grid data size. */
+#define MAX_LIGHT 128 /* TODO: find size by dividing UBO max size by light data size. */
#define MAX_CASCADE_NUM 4
-#define MAX_SHADOW 128 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */
+#define MAX_SHADOW 128 /* TODO: Make this depends on #GL_MAX_ARRAY_TEXTURE_LAYERS. */
#define MAX_SHADOW_CASCADE 8
#define MAX_SHADOW_CUBE (MAX_SHADOW - MAX_CASCADE_NUM * MAX_SHADOW_CASCADE)
#define MAX_BLOOM_STEP 16
@@ -238,7 +238,7 @@ typedef struct EEVEE_PlanarReflection {
float clip_edge_y_pos, clip_edge_y_neg;
float facing_scale, facing_bias, clipsta, pad;
float reflectionmat[4][4]; /* Used for sampling the texture. */
- float mtx[4][4]; /* Not used in shader. TODO move elsewhere. */
+ float mtx[4][4]; /* Not used in shader. TODO: move elsewhere. */
} EEVEE_PlanarReflection;
/* --------------------------------------- */
@@ -680,7 +680,7 @@ typedef struct EEVEE_GeometryMotionData {
int use_deform;
struct GPUBatch *batch; /* Batch for time = t. */
- struct GPUVertBuf *vbo[2]; /* Vbo for time = t +/- step. */
+ struct GPUVertBuf *vbo[2]; /* VBO for time = t +/- step. */
} EEVEE_GeometryMotionData;
/* ************ EFFECTS DATA ************* */
@@ -1000,7 +1000,7 @@ typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *shadow_accum_shgrp;
struct DRWCallBuffer *planar_display_shgrp;
struct GHash *material_hash;
- float background_alpha; /* TODO find a better place for this. */
+ float background_alpha; /* TODO: find a better place for this. */
/* Chosen lightcache: can come from Lookdev or the viewlayer. */
struct LightCache *light_cache;
/* For planar probes */
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index aaa087f9eb4..d214409c458 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -114,7 +114,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
/* XXX overriding viewport size. Simplify things but is not really 100% safe. */
DRW_render_viewport_size_set(final_res);
- /* TODO 32 bit depth */
+ /* TODO: 32 bit depth. */
DRW_texture_ensure_fullscreen_2d(&dtxl->depth, GPU_DEPTH24_STENCIL8, 0);
DRW_texture_ensure_fullscreen_2d(&txl->color, GPU_RGBA32F, DRW_TEX_FILTER);
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 5ada53ab98c..aa42deb13fa 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -23,7 +23,7 @@
#include "DRW_engine.h"
#include "DRW_render.h"
-#include "draw_color_management.h" /* TODO remove dependency. */
+#include "draw_color_management.h" /* TODO: remove dependency. */
#include "BKE_global.h" /* for G.debug_value */
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 7af0f60748b..17cc1a46e23 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -76,7 +76,7 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const int divisor = (effects->reflection_trace_full) ? 1 : 2;
int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
const int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]};
- const bool high_qual_input = true; /* TODO dither low quality input */
+ const bool high_qual_input = true; /* TODO: dither low quality input. */
const eGPUTextureFormat format = (high_qual_input) ? GPU_RGBA16F : GPU_RGBA8;
tracing_res[0] = max_ii(1, tracing_res[0]);
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index a4e4352ac16..56ae7185b51 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -1439,7 +1439,7 @@ static void eevee_material_post_eval(GPUMaterial *mat,
const bool is_mesh = (options & VAR_MAT_MESH) != 0;
/* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used.
- * Note: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */
+ * NOTE: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */
if (!is_hair && is_mesh && GPU_material_flag_get(mat, GPU_MATFLAG_BARYCENTRIC) &&
*geom_code == NULL) {
*geom_code = e_data.surface_geom_barycentric;
@@ -1493,7 +1493,7 @@ static struct GPUMaterial *eevee_material_get_ex(
return mat;
}
-/* Note: Compilation is not deferred. */
+/* NOTE: Compilation is not deferred. */
struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options)
{
Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() :
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index 5060c209b8b..ee1a6652809 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -193,7 +193,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
static bool sphere_bbox_intersect(const BoundSphere *bs, const EEVEE_BoundBox *bb)
{
/* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */
- /* TODO test speed with AABB vs Sphere. */
+ /* TODO: test speed with AABB vs Sphere. */
bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius);
bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius);
bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius);
diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
index 6cb4b39fafa..22ee821933c 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
@@ -112,7 +112,7 @@ static void frustum_min_bounding_sphere(const float corners[8][3],
}
}
- /* TODO try to reduce the radius further by moving the center.
+ /* TODO: try to reduce the radius further by moving the center.
* Remember we need a __stable__ solution! */
/* Try to reduce float imprecision leading to shimmering. */
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 129822ed8a9..b7bcd127859 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -144,7 +144,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata),
/* Clear texture.
* Due to the late initialization of the SSS it can happen that the `taa_current_sample` is
* already higher than one. This is noticeable when loading a file that has the diffuse light
- * pass in look dev mode active. `texture_created` will make sure that newly created textures
+ * pass in look-dev mode active. `texture_created` will make sure that newly created textures
* are cleared. */
if (effects->taa_current_sample == 1 || texture_created) {
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
@@ -198,7 +198,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
/* Limit of 8 bit stencil buffer. ID 255 is refraction. */
if (effects->sss_surface_count >= 254) {
- /* TODO : display message. */
+ /* TODO: display message. */
printf("Error: Too many different Subsurface shader in the scene.\n");
return;
}
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index e30f5d52d56..b03172a1270 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -197,7 +197,7 @@ void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const dou
}
/* Update the matrices based on the current sample.
- * Note: `DRW_MAT_PERS` and `DRW_MAT_VIEW` needs to read the original matrices. */
+ * NOTE: `DRW_MAT_PERS` and `DRW_MAT_VIEW` needs to read the original matrices. */
void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
@@ -407,7 +407,7 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
/* Do reprojection for noise reduction */
- /* TODO : do AA jitter if in only render view. */
+ /* TODO: do AA jitter if in only render view. */
if (!DRW_state_is_image_render() && (effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0 &&
stl->g_data->valid_taa_history) {
GPU_framebuffer_bind(effects->target_buffer);
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 56c5b367f7e..47e8aeeb6e2 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -129,7 +129,7 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->vol_coord_scale[2] = 1.0f / viewport_size[0];
common_data->vol_coord_scale[3] = 1.0f / viewport_size[1];
- /* TODO compute snap to maxZBuffer for clustered rendering */
+ /* TODO: compute snap to maxZBuffer for clustered rendering. */
if ((common_data->vol_tex_size[0] != tex_size[0]) ||
(common_data->vol_tex_size[1] != tex_size[1]) ||
(common_data->vol_tex_size[2] != tex_size[2])) {
@@ -554,8 +554,8 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
}
}
- /* TODO Reduce to number of slices intersecting. */
- /* TODO Preemptive culling. */
+ /* TODO: Reduce to number of slices intersecting. */
+ /* TODO: Preemptive culling. */
DRW_shgroup_call_procedural_triangles(grp, ob, sldata->common_data.vol_tex_size[2]);
vedata->stl->effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
index 4fcfac36376..e0f52338914 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
@@ -116,7 +116,7 @@ vec3 sample_uniform_cone(vec3 rand, float angle)
vec3 sample_uniform_cone(vec3 rand, float angle, vec3 N, vec3 T, vec3 B)
{
vec3 Ht = sample_uniform_cone(rand, angle);
- /* TODO pdf? */
+ /* TODO: pdf? */
return tangent_to_world(Ht, N, T, B);
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl
index da34b221104..e5b68637563 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl
@@ -324,7 +324,7 @@ float dof_coc_max_slight_focus(float coc1, float coc2)
struct DofGatherData {
vec4 color;
float weight;
- float dist; /* TODO remove */
+ float dist; /* TODO: remove. */
/* For scatter occlusion. */
float coc;
float coc_sqr;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
index 6f2619127e3..7689e730bf3 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
@@ -40,9 +40,9 @@ vec4 ssr_get_scene_color_and_mask(vec3 hit_vP, int planar_index, float mip)
}
else {
/* Find hit position in previous frame. */
- /* TODO Combine matrices. */
+ /* TODO: Combine matrices. */
vec3 hit_P = transform_point(ViewMatrixInverse, hit_vP);
- /* TODO real reprojection with motion vectors, etc... */
+ /* TODO: real reprojection with motion vectors, etc... */
uv = project_point(pastViewProjectionMatrix, hit_P).xy * 0.5 + 0.5;
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl
index cd574c6c9fd..2f1efd588f7 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_trace_frag.glsl
@@ -89,7 +89,7 @@ void main()
if (fade > 0.5) {
/* Find view vector / reflection plane intersection. */
- /* TODO optimize, use view space for all. */
+ /* TODO: optimize, use view space for all. */
vec3 P_plane = line_plane_intersect(P, V, pd.pl_plane_eq);
vP = transform_point(ViewMatrix, P_plane);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index b79cd17c567..58bbb825043 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -23,7 +23,7 @@ layout(location = 0) out vec4 sssRadiance;
void main(void)
{
- vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */
+ vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO: precompute. */
vec2 uvs = gl_FragCoord.xy * pixel_size;
vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb;
float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
index 165aed2a46f..3c49caf11a9 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
@@ -85,7 +85,7 @@ void main()
color_history.rgb = clip_to_aabb(color_history.rgb, min_col.rgb, max_col.rgb, avg_col.rgb);
/* Luminance weighting. */
- /* TODO correct luminance */
+ /* TODO: correct luminance. */
float lum0 = dot(color.rgb, vec3(0.333));
float lum1 = dot(color_history.rgb, vec3(0.333));
float diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2));
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
index 97b31a972e3..ee48c468630 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -35,8 +35,8 @@ vec3 sss_profile(float s)
float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector)
{
float power, falloff;
- /* XXX : Removing Area Power. */
- /* TODO : put this out of the shader. */
+ /* XXX: Removing Area Power. */
+ /* TODO: put this out of the shader. */
if (ld.l_type >= AREA_RECT) {
power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
if (ld.l_type == AREA_ELLIPSE) {
@@ -134,7 +134,7 @@ vec3 light_translucent(LightData ld, vec3 P, vec3 N, vec4 l_vector, vec2 rand, f
/* Size of a texel in world space.
* FIXME This is only correct if l_right is the same right vector used for shadowmap creation.
* This won't work if the shadow matrix is rotated (soft shadows).
- * TODO precompute */
+ * TODO: precompute. */
float unit_world_in_uv_space = length(mat3(scascade(data_id).shadowmat[int(id)]) * ld.l_right);
float dx_scale = 2.0 * ofs.x / unit_world_in_uv_space;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
index d06ad553ca4..c9af2753baa 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
@@ -1,7 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
-/* XXX TODO fix code duplication */
+/* XXX TODO: fix code duplication. */
struct CubeData {
vec4 position_type;
vec4 attenuation_fac_type;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
index a648e7a8b26..84626eac4cf 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
@@ -192,7 +192,7 @@ vec3 probe_evaluate_planar(int id, PlanarData pd, vec3 P, vec3 N, vec3 V, float
vec3 point_on_plane = line_plane_intersect(P, V, pd.pl_plane_eq);
/* How far the pixel is from the plane. */
- float ref_depth = 1.0; /* TODO parameter */
+ float ref_depth = 1.0; /* TODO: parameter. */
/* Compute distorded reflection vector based on the distance to the reflected object.
* In other words find intersection between reflection vector and the sphere center
@@ -278,7 +278,7 @@ vec3 probe_evaluate_grid(GridData gd, vec3 P, vec3 N, vec3 localpos)
float ws_dist_point_to_cell = length(ws_point_to_cell);
vec3 ws_light = ws_point_to_cell / ws_dist_point_to_cell;
- /* Smooth backface test */
+ /* Smooth back-face test. */
float weight = saturate(dot(ws_light, N));
/* Precomputed visibility */
diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
index 2f1fd0ce5f8..dc98a00a1cd 100644
--- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
@@ -176,7 +176,7 @@ float sample_cube_shadow(int shadow_id, vec3 P)
float dist = max(sd(shadow_id).sh_near, max_v3(abs(cubevec)) - sd(shadow_id).sh_bias);
dist = buffer_depth(true, dist, sd(shadow_id).sh_far, sd(shadow_id).sh_near);
/* Manual Shadow Cube Layer indexing. */
- /* TODO Shadow Cube Array. */
+ /* TODO: Shadow Cube Array. */
float face = cubeFaceIndexEEVEE(cubevec);
vec2 coord = cubeFaceCoordEEVEE(cubevec, face, shadowCubeTexture);
/* tex_id == data_id for cube shadowmap */
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
index f1476e4f2c4..73c4b521b05 100644
--- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -101,7 +101,7 @@ struct RayTraceParameters {
};
/* Returns true on hit. */
-/* TODO fclem remove the backface check and do it the SSR resolve code. */
+/* TODO(fclem): remove the back-face check and do it the SSR resolve code. */
bool raytrace(Ray ray,
RayTraceParameters params,
const bool discard_backface,
@@ -151,7 +151,7 @@ bool raytrace(Ray ray,
/* ... and above it with the added thickness. */
hit = hit && (delta > ss_p.z - ss_p.w || abs(delta) < abs(ssray.direction.z * stride * 2.0));
}
- /* Discard backface hits. */
+ /* Discard back-face hits. */
hit = hit && !(discard_backface && prev_delta < 0.0);
/* Reject hit if background. */
hit = hit && (depth_sample != 1.0);
diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
index 1d52dfeab26..a563291bb90 100644
--- a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
@@ -63,7 +63,7 @@ vec4 screen_space_refraction(vec3 vP, vec3 N, vec3 V, float ior, float roughness
float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos;
/* Empirical fit for refraction. */
- /* TODO find a better fit or precompute inside the LUT. */
+ /* TODO: find a better fit or precompute inside the LUT. */
cone_tan *= 0.5 * fast_sqrt(f0_from_ior((ior < 1.0) ? 1.0 / ior : ior));
float cone_footprint = hit_dist * cone_tan;
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
index b2d8a383809..5226da57a06 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
@@ -2,7 +2,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#ifdef MESH_SHADER
-/* TODO tight slices */
+/* TODO: tight slices. */
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
#else /* World */
@@ -17,7 +17,7 @@ flat out int slice;
RESOURCE_ID_VARYING
#ifdef MESH_SHADER
-/* TODO tight slices */
+/* TODO: tight slices. */
void main()
{
gl_Layer = slice = int(vPos[0].z);
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index adb21540afb..89ee3f1b293 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -314,7 +314,7 @@ static DrawEngineType draw_engine_external_type = {
NULL,
};
-/* Note: currently unused,
+/* NOTE: currently unused,
* we should not register unless we want to see this when debugging the view. */
RenderEngineType DRW_engine_viewport_external_type = {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 1921055c3d7..d3a0c40fae5 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -262,7 +262,7 @@ void GPENCIL_cache_init(void *ved)
pd->sbuffer_gpd = gpd;
pd->sbuffer_stroke = DRW_cache_gpencil_sbuffer_stroke_data_get(pd->obact);
pd->sbuffer_layer = BKE_gpencil_layer_active_get(pd->sbuffer_gpd);
- pd->do_fast_drawing = false; /* TODO option */
+ pd->do_fast_drawing = false; /* TODO: option. */
}
}
}
@@ -640,13 +640,13 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
}
}
- BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL,
- ob,
- gpencil_layer_cache_populate,
- gpencil_stroke_cache_populate,
- &iter,
- do_onion,
- pd->cfra);
+ BKE_gpencil_visible_stroke_advanced_iter(is_final_render ? pd->view_layer : NULL,
+ ob,
+ gpencil_layer_cache_populate,
+ gpencil_stroke_cache_populate,
+ &iter,
+ do_onion,
+ pd->cfra);
gpencil_drawcall_flush(&iter);
diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c
index 2522a445d8e..395d50fbc6b 100644
--- a/source/blender/draw/engines/image/image_engine.c
+++ b/source/blender/draw/engines/image/image_engine.c
@@ -31,6 +31,7 @@
#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
+#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "ED_image.h"
@@ -116,7 +117,7 @@ static void space_image_gpu_texture_get(Image *image,
const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf);
if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
if (ibuf->zbuf) {
- BLI_assert(!"Integer based depth buffers not supported");
+ BLI_assert_msg(0, "Integer based depth buffers not supported");
}
else if (ibuf->zbuf_float) {
*r_gpu_texture = GPU_texture_create_2d(
@@ -222,19 +223,30 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser
copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
}
else if ((sima_flag & SI_SHOW_R) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
+ draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
}
else if ((sima_flag & SI_SHOW_G) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
+ draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
}
else if ((sima_flag & SI_SHOW_B) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
+ draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
}
else /* RGB */ {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
}
}
if (space_type == SPACE_NODE) {
@@ -248,19 +260,30 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser
copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
}
else if ((snode->flag & SNODE_SHOW_R) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
+ draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
}
else if ((snode->flag & SNODE_SHOW_G) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
+ draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
}
else if ((snode->flag & SNODE_SHOW_B) != 0) {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
+ draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
}
else /* RGB */ {
- draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
+ }
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 0e350ea5a68..9d15f0e176d 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -37,6 +37,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_deform.h"
#include "BKE_modifier.h"
#include "DEG_depsgraph_query.h"
@@ -699,7 +700,7 @@ static void drw_shgroup_bone_ik_spline_lines(ArmatureDrawContext *ctx,
/* -------------------------------------------------------------------- */
/** \name Drawing Theme Helpers
*
- * Note, this section is duplicate of code in 'drawarmature.c'.
+ * \note this section is duplicate of code in 'drawarmature.c'.
*
* \{ */
@@ -1036,7 +1037,7 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *
float(*disp_mat)[4];
float(*disp_tail_mat)[4];
- /* TODO : This should be moved to depsgraph or armature refresh
+ /* TODO: This should be moved to depsgraph or armature refresh
* and not be tight to the draw pass creation.
* This would refresh armature without invalidating the draw cache */
if (pchan) {
@@ -1200,9 +1201,9 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc
float(*bone_mat)[4];
short bbone_segments;
- /* TODO : This should be moved to depsgraph or armature refresh
+ /* TODO: This should be moved to depsgraph or armature refresh
* and not be tight to the draw pass creation.
- * This would refresh armature without invalidating the draw cache */
+ * This would refresh armature without invalidating the draw cache. */
if (pchan) {
length = pchan->bone->length;
xwidth = pchan->bone->xwidth;
@@ -1268,7 +1269,7 @@ static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan)
float(*disp_tail_mat)[4];
float rot_mat[3][3];
- /* See TODO above */
+ /* See TODO: above. */
mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, PCHAN_CUSTOM_BONE_LENGTH(pchan));
bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat;
disp_mat = pchan->disp_mat;
@@ -2040,7 +2041,8 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
const Object *obact_orig = DEG_get_original_object(draw_ctx->obact);
- LISTBASE_FOREACH (bDeformGroup *, dg, &obact_orig->defbase) {
+ const ListBase *defbase = BKE_object_defgroup_list(obact_orig);
+ LISTBASE_FOREACH (const bDeformGroup *, dg, defbase) {
if (dg->flag & DG_LOCK_WEIGHT) {
pchan = BKE_pose_channel_find_name(ob->pose, dg->name);
diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
index 7639911286f..a7ed6c777e8 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
@@ -26,6 +26,7 @@
#include "DNA_mesh_types.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "draw_cache_impl.h"
diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c
index 01ab47ac1de..c2b130163e8 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_uv.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c
@@ -24,6 +24,7 @@
#include "draw_cache_impl.h"
#include "draw_manager_text.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_image.h"
#include "BKE_layer.h"
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index 81b07b49784..235104245cc 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -200,7 +200,7 @@ static void OVERLAY_cache_init(void *vedata)
case CTX_MODE_OBJECT:
break;
default:
- BLI_assert(!"Draw mode invalid");
+ BLI_assert_msg(0, "Draw mode invalid");
break;
}
OVERLAY_antialiasing_cache_init(vedata);
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index b70c71de188..f5be9c846d1 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -928,7 +928,7 @@ static void camera_view3d_reconstruction(OVERLAY_ExtraCallBuffers *cb,
const float *bundle_color;
if (track->flag & TRACK_CUSTOMCOLOR) {
/* Meh, hardcoded srgb transform here. */
- /* TODO change the actual DNA color to be linear. */
+ /* TODO: change the actual DNA color to be linear. */
srgb_to_linearrgb_v3_v3(bundle_color_custom, track->color);
bundle_color = bundle_color_custom;
}
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
index aa26aa47faa..5c03d70d7be 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.c
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -431,7 +431,7 @@ static void OVERLAY_gpencil_color_names(Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
int cfra = DEG_get_ctime(draw_ctx->depsgraph);
- BKE_gpencil_visible_stroke_iter(
+ BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
}
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index a2c3b5bf4aa..e3f01d968ae 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -36,7 +36,7 @@
/* Returns the normal plane in NDC space. */
static void gpencil_depth_plane(Object *ob, float r_plane[4])
{
- /* TODO put that into private data. */
+ /* TODO: put that into private data. */
float viewinv[4][4];
DRW_view_viewmat_get(NULL, viewinv, true);
float *camera_z_axis = viewinv[2];
@@ -92,7 +92,7 @@ void OVERLAY_outline_init(OVERLAY_Data *vedata)
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
if (DRW_state_is_fbo()) {
- /* TODO only alloc if needed. */
+ /* TODO: only alloc if needed. */
DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0);
DRW_texture_ensure_fullscreen_2d(&txl->outlines_id_tx, GPU_R16UI, 0);
@@ -263,13 +263,13 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
gpencil_depth_plane(ob, iter.plane);
}
- BKE_gpencil_visible_stroke_iter(NULL,
- ob,
- gpencil_layer_cache_populate,
- gpencil_stroke_cache_populate,
- &iter,
- false,
- pd->cfra);
+ BKE_gpencil_visible_stroke_advanced_iter(NULL,
+ ob,
+ gpencil_layer_cache_populate,
+ gpencil_stroke_cache_populate,
+ &iter,
+ false,
+ pd->cfra);
}
static void OVERLAY_outline_volume(OVERLAY_PrivateData *pd, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index a48b46a61fc..03bfaf56f24 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -314,7 +314,7 @@ typedef struct OVERLAY_PrivateData {
DRWView *view_edit_text;
DRWView *view_reference_images;
- /** TODO get rid of this. */
+ /** TODO: get rid of this. */
ListBase smoke_domains;
ListBase bg_movie_clips;
@@ -333,8 +333,8 @@ typedef struct OVERLAY_PrivateData {
bool xray_enabled;
bool xray_enabled_and_not_wire;
float xray_opacity;
- short v3d_flag; /* TODO move to View3DOverlay */
- short v3d_gridflag; /* TODO move to View3DOverlay */
+ short v3d_flag; /* TODO: move to #View3DOverlay. */
+ short v3d_gridflag; /* TODO: move to #View3DOverlay. */
int cfra;
DRWState clipping_state;
OVERLAY_ShadingData shdata;
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index c9c26e3faaa..7a7ae9a921b 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -1726,7 +1726,7 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void)
{
{"boneStart", DRW_ATTR_FLOAT, 3},
{"boneEnd", DRW_ATTR_FLOAT, 3},
- {"wireColor", DRW_ATTR_FLOAT, 4}, /* TODO uchar color */
+ {"wireColor", DRW_ATTR_FLOAT, 4}, /* TODO: uchar color. */
{"boneColor", DRW_ATTR_FLOAT, 4},
{"headColor", DRW_ATTR_FLOAT, 4},
{"tailColor", DRW_ATTR_FLOAT, 4},
diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
index c204949cc45..67d172fbd01 100644
--- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
@@ -105,7 +105,7 @@ void main()
float dist_raw = texelFetch(lineTex, center_texel, 0).b;
float dist = decode_line_dist(dist_raw);
- /* TODO Opti: use textureGather */
+ /* TODO: Opti: use textureGather. */
vec4 neightbor_col0 = texelFetchOffset(colorTex, center_texel, 0, ivec2(1, 0));
vec4 neightbor_col1 = texelFetchOffset(colorTex, center_texel, 0, ivec2(-1, 0));
vec4 neightbor_col2 = texelFetchOffset(colorTex, center_texel, 0, ivec2(0, 1));
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl
index 45ebad0aafe..ddc6328e6a2 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl
@@ -36,7 +36,7 @@ void main()
/* This is slow and run per vertex, but it's still faster than
* doing it per instance on CPU and sending it on via instance attribute. */
mat3 normal_mat = transpose(inverse(mat3(model_mat)));
- /* TODO FIX: there is still a problem with this vector
+ /* TODO: FIX: there is still a problem with this vector
* when the bone is scaled or in persp mode. But it's
* barely visible at the outline corners. */
ssNor = normalize(normal_world_to_view(normal_mat * snor).xy);
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl
index 17e8d0da5d9..26796c82f66 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl
@@ -9,8 +9,8 @@ layout(location = 1) out vec4 lineOutput;
void main()
{
- /* Manual backface cullling.. Not ideal for performance
- * but needed for view clarity in xray mode and support
+ /* Manual back-face culling. Not ideal for performance
+ * but needed for view clarity in X-ray mode and support
* for inverted bone matrices. */
if ((inverted == 1) == gl_FrontFacing) {
discard;
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl
index cb70a3b433c..b241a1f0568 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl
@@ -11,7 +11,7 @@ out vec4 fillColor;
out vec4 outlineColor;
out vec4 radii;
-/* TODO Theme? */
+/* TODO: Theme? */
const vec4 pinned_col = vec4(1.0, 0.0, 0.0, 1.0);
void main()
diff --git a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl
index 1c54076f3ea..df10f3f7ae2 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl
@@ -279,7 +279,7 @@ void main()
vec2 line_start, line_end;
vec2 line_ofs;
bvec4 extra_edges, extra_edges2;
- /* TODO simplify this branching hell. */
+ /* TODO: simplify this branching hell. */
switch (edge_case) {
/* Straight lines. */
case YPOS:
diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl
index 282799e1660..b89cd821b37 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_geom.glsl
@@ -40,7 +40,7 @@ void main()
/* Don't outline if concave edge. */
/* That would hide a lot of non useful edge but it flickers badly.
- * TODO revisit later... */
+ * TODO: revisit later... */
// if (dot(n0, v13) > 0.01)
// return;
diff --git a/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl
index 9d102bd4295..052ad2a7f36 100644
--- a/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/paint_point_vert.glsl
@@ -14,7 +14,7 @@ void main()
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
/* Add offset in Z to avoid zfighting and render selected wires on top. */
- /* TODO scale this bias using znear and zfar range. */
+ /* TODO: scale this bias using znear and zfar range. */
gl_Position.z -= (is_select ? 2e-4 : 1e-4);
if (is_hidden) {
diff --git a/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl
index d5a42d2d309..6a937d846c4 100644
--- a/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/paint_wire_vert.glsl
@@ -16,7 +16,7 @@ void main()
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
/* Add offset in Z to avoid zfighting and render selected wires on top. */
- /* TODO scale this bias using znear and zfar range. */
+ /* TODO: scale this bias using znear and zfar range. */
gl_Position.z -= (is_select ? 2e-4 : 1e-4);
if (is_hidden) {
diff --git a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
index 0b827601f8e..174b31b6816 100644
--- a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
@@ -33,7 +33,7 @@ const vec3 corners[4] = vec3[4](vec3(0.0, 0.2, -0.5),
const int indices[12] = int[12](0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3);
/* Straight Port from BKE_defvert_weight_to_rgb()
- * TODO port this to a color ramp. */
+ * TODO: port this to a color ramp. */
vec3 weight_to_color(float weight)
{
vec3 r_rgb = vec3(0.0);
diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c
index c9c4a2076ef..86b4a0ac727 100644
--- a/source/blender/draw/engines/select/select_engine.c
+++ b/source/blender/draw/engines/select/select_engine.c
@@ -373,7 +373,7 @@ DrawEngineType draw_engine_select_type = {
NULL,
};
-/* Note: currently unused, we may want to register so we can see this when debugging the view. */
+/* NOTE: currently unused, we may want to register so we can see this when debugging the view. */
RenderEngineType DRW_engine_viewport_select_type = {
NULL,
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
index d0d52c8485b..9038aae533b 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
@@ -43,7 +43,7 @@ void cavity_compute(vec2 screenco,
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
- /* Note. Putting noise usage here to put some ALU after texture fetch. */
+ /* NOTE: Putting noise usage here to put some ALU after texture fetch. */
vec2 rotX = noise.rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
index 6e10a656fc1..c5b2ce0fd99 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
@@ -24,7 +24,7 @@ void main()
workbench_float_pair_decode(mat_data.a, roughness, metallic);
#ifdef V3D_LIGHTING_MATCAP
- /* When using matcaps, mat_data.a is the backface sign. */
+ /* When using matcaps, mat_data.a is the back-face sign. */
N = (mat_data.a > 0.0) ? N : -N;
fragColor.rgb = get_matcap_lighting(base_color, N, I);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
index 8f6940a6062..92d5df1a13a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
@@ -394,7 +394,7 @@ void main()
vec2 pixel_size = 0.5 / vec2(textureSize(halfResColorTex, 0).xy);
vec2 uv = gl_FragCoord.xy * pixel_size;
- /* TODO MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH */
+ /* TODO: MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH. */
float depth = texelFetch(sceneDepthTex, ivec2(gl_FragCoord.xy), 0).r;
float zdepth = linear_depth(depth);
float coc = calculate_coc(zdepth);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index 9bd49bb84f8..48102b4dcca 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -198,7 +198,7 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI;
# ifdef VOLUME_SMOKE
- /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */
+ /* 800 is arbitrary and here to mimic old viewport. TODO: make it a parameter. */
scattering += emission.rgb * emission.a * 800.0;
# endif
#endif
@@ -247,7 +247,7 @@ vec4 volume_integration(vec3 ray_ori, vec3 ray_dir, float ray_inc, float ray_max
void main()
{
#ifdef VOLUME_SLICE
- /* Manual depth test. TODO remove. */
+ /* Manual depth test. TODO: remove. */
float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
if (gl_FragCoord.z >= depth) {
discard;
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
index 10a782c9987..8206add7412 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
@@ -247,7 +247,7 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(wpd->smaa_weight_tx),
});
- /* TODO could be shared for all viewports. */
+ /* TODO: could be shared for all viewports. */
if (txl->smaa_search_tx == NULL) {
txl->smaa_search_tx = GPU_texture_create_2d(
"smaa_search", SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1, GPU_R8, NULL);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.c b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
index 199abe8cb2b..b294b9a62ca 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_cavity.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
@@ -31,7 +31,7 @@
#include "BLI_rand.h"
-#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
+#include "../eevee/eevee_lut.h" /* TODO: find somewhere to share blue noise Table. */
#include "workbench_engine.h"
#include "workbench_private.h"
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 0d7f2e67598..e9d6763fbe9 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -460,7 +460,7 @@ void workbench_cache_finish(void *ved)
workbench_update_material_ubos(wpd);
- /* TODO don't free reuse next redraw. */
+ /* TODO: don't free reuse next redraw. */
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < WORKBENCH_DATATYPE_MAX; k++) {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 800d1085505..aaa1a5a6ff6 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -126,7 +126,7 @@ BLI_INLINE void workbench_material_get_image(
break;
}
default:
- BLI_assert(!"Node type not supported by workbench");
+ BLI_assert_msg(0, "Node type not supported by workbench");
}
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c
index 99d945c311e..3386d9b6390 100644
--- a/source/blender/draw/engines/workbench/workbench_shadow.c
+++ b/source/blender/draw/engines/workbench/workbench_shadow.c
@@ -65,7 +65,7 @@ static void workbench_shadow_update(WORKBENCH_PrivateData *wpd)
const float up[3] = {0.0f, 0.0f, 1.0f};
unit_m4(wpd->shadow_mat);
- /* TODO fix singularity. */
+ /* TODO: fix singularity. */
copy_v3_v3(wpd->shadow_mat[2], wpd->shadow_direction_ws);
cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up);
normalize_v3(wpd->shadow_mat[0]);
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
index edeb17cd9a4..ad855cb284c 100644
--- a/source/blender/draw/engines/workbench/workbench_transparent.c
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -46,7 +46,7 @@ void workbench_transparent_engine_init(WORKBENCH_Data *data)
DrawEngineType *owner = (DrawEngineType *)&workbench_transparent_engine_init;
/* Reuse same format as opaque pipeline to reuse the textures. */
- /* Note: Floating point texture is required for the reveal_tex as it is used for
+ /* NOTE: Floating point texture is required for the reveal_tex as it is used for
* the alpha accumulation component (see accumulation shader for more explanation). */
const eGPUTextureFormat accum_tex_format = GPU_RGBA16F;
const eGPUTextureFormat reveal_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16F : GPU_RGBA32F;
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 5d5a506c1e7..f5b95ac97ff 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -82,7 +82,7 @@ typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
typedef struct DRWView DRWView;
-/* TODO Put it somewhere else? */
+/* TODO: Put it somewhere else? */
typedef struct BoundSphere {
float center[3], radius;
} BoundSphere;
@@ -91,7 +91,7 @@ typedef struct BoundSphere {
typedef char DRWViewportEmptyList;
#define DRW_VIEWPORT_LIST_SIZE(list) \
- (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : ((sizeof(list)) / sizeof(void *)))
+ (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : (sizeof(list) / sizeof(void *)))
/* Unused members must be either pass list or 'char *' when not used. */
#define DRW_VIEWPORT_DATA_SIZE(ty) \
@@ -490,7 +490,7 @@ void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
uint write_mask,
uint reference,
uint compare_mask);
-/* TODO remove this function. Obsolete version. mask is actually reference value. */
+/* TODO: remove this function. Obsolete version. mask is actually reference value. */
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask);
/* Issue a clear command. */
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index d55da3ed83b..a2e8dc20907 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -580,7 +580,7 @@ static void circle_dashed_verts(
}
}
-/* XXX TODO move that 1 unit cube to more common/generic place? */
+/* XXX TODO: move that 1 unit cube to more common/generic place? */
static const float bone_box_verts[8][3] = {
{1.0f, 0.0f, 1.0f},
{1.0f, 0.0f, -1.0f},
@@ -762,7 +762,7 @@ GPUBatch *DRW_cache_normal_arrow_get(void)
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(vbo, 2);
- /* TODO real arrow. For now, it's a line positioned in the vertex shader. */
+ /* TODO: real arrow. For now, it's a line positioned in the vertex shader. */
SHC.drw_normal_arrow = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
@@ -802,7 +802,7 @@ GPUBatch *DRW_cache_object_all_edges_get(Object *ob)
case OB_MESH:
return DRW_cache_mesh_all_edges_get(ob);
- /* TODO, should match 'DRW_cache_object_surface_get' */
+ /* TODO: should match #DRW_cache_object_surface_get. */
default:
return NULL;
}
@@ -2181,7 +2181,7 @@ GPUBatch *DRW_cache_bone_envelope_solid_get(void)
float lat = 0.0f;
float co1[3], co2[3];
- /* Note: the poles are duplicated on purpose, to restart the strip. */
+ /* NOTE: the poles are duplicated on purpose, to restart the strip. */
/* 1st sphere */
for (int j = 0; j < lat_res; j++, lat += lat_inc) {
@@ -2627,7 +2627,7 @@ GPUBatch *DRW_cache_bone_dof_sphere_get(void)
pz = z;
}
}
- /* TODO allocate right count from the beginning. */
+ /* TODO: allocate right count from the beginning. */
GPU_vertbuf_data_resize(vbo, v);
SHC.drw_bone_dof_sphere = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
@@ -3274,8 +3274,8 @@ GPUBatch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
Lattice *lt = ob->data;
int actdef = -1;
- if (use_weight && ob->defbase.first && lt->editlatt->latt->dvert) {
- actdef = ob->actdef - 1;
+ if (use_weight && !BLI_listbase_is_empty(&lt->vertex_group_names) && lt->editlatt->latt->dvert) {
+ actdef = lt->vertex_group_active_index - 1;
}
return DRW_lattice_batch_cache_get_all_edges(lt, use_weight, actdef);
@@ -3599,7 +3599,7 @@ void drw_batch_cache_generate_requested(Object *ob)
}
DRW_curve_batch_cache_create_requested(ob, scene);
break;
- /* TODO all cases */
+ /* TODO: all cases. */
default:
break;
}
@@ -3625,7 +3625,7 @@ void DRW_batch_cache_free_old(Object *ob, int ctime)
DRW_mesh_batch_cache_free_old(mesh_eval, ctime);
}
break;
- /* TODO all cases */
+ /* TODO: all cases. */
default:
break;
}
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index be61b0a9baf..a0694a08f0b 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -36,7 +36,7 @@ typedef struct DRW_MeshWeightState {
short flags;
char alert_mode;
- /* Set of all selected bones for Multipaint. */
+ /* Set of all selected bones for Multi-paint. */
bool *defgroup_sel; /* [defgroup_len] */
int defgroup_sel_count;
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index 344150014ed..6d71b01b7e0 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -76,27 +76,23 @@ struct ExtractorRunData {
class ExtractorRunDatas : public Vector<ExtractorRunData> {
public:
- void filter_into(ExtractorRunDatas &result, eMRIterType iter_type) const
+ void filter_into(ExtractorRunDatas &result, eMRIterType iter_type, const bool is_mesh) const
{
for (const ExtractorRunData &data : *this) {
const MeshExtract *extractor = data.extractor;
- if ((iter_type & MR_ITER_LOOPTRI) && extractor->iter_looptri_bm) {
- BLI_assert(extractor->iter_looptri_mesh);
+ if ((iter_type & MR_ITER_LOOPTRI) && *(&extractor->iter_looptri_bm + is_mesh)) {
result.append(data);
continue;
}
- if ((iter_type & MR_ITER_POLY) && extractor->iter_poly_bm) {
- BLI_assert(extractor->iter_poly_mesh);
+ if ((iter_type & MR_ITER_POLY) && *(&extractor->iter_poly_bm + is_mesh)) {
result.append(data);
continue;
}
- if ((iter_type & MR_ITER_LEDGE) && extractor->iter_ledge_bm) {
- BLI_assert(extractor->iter_ledge_mesh);
+ if ((iter_type & MR_ITER_LEDGE) && *(&extractor->iter_ledge_bm + is_mesh)) {
result.append(data);
continue;
}
- if ((iter_type & MR_ITER_LVERT) && extractor->iter_lvert_bm) {
- BLI_assert(extractor->iter_lvert_mesh);
+ if ((iter_type & MR_ITER_LVERT) && *(&extractor->iter_lvert_bm + is_mesh)) {
result.append(data);
continue;
}
@@ -427,7 +423,7 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr,
return;
}
- extractors->filter_into(range_data.extractors, iter_type);
+ extractors->filter_into(range_data.extractors, iter_type, is_mesh);
BLI_task_parallel_range(0, stop, &range_data, func, settings);
}
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c
index 42cd571b089..e813f006351 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_extractors.c
@@ -25,29 +25,10 @@
#include "MEM_guardedalloc.h"
-#include "atomic_ops.h"
-
#include "DNA_object_types.h"
-#include "BLI_edgehash.h"
-#include "BLI_jitter_2d.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_string.h"
-
-#include "BKE_bvhutils.h"
-#include "BKE_deform.h"
-#include "BKE_editmesh.h"
-#include "BKE_editmesh_bvh.h"
-#include "BKE_editmesh_cache.h"
-#include "BKE_editmesh_tangent.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_tangent.h"
-#include "BKE_paint.h"
-
#include "ED_uvedit.h"
-#include "GPU_capabilities.h"
-
#include "draw_cache_extract_mesh_private.h"
#include "draw_cache_impl.h"
@@ -120,1577 +101,13 @@ const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Position and Vertex Normal
- * \{ */
-
-typedef struct PosNorLoop {
- float pos[3];
- GPUPackedNormal nor;
-} PosNorLoop;
-
-typedef struct MeshExtract_PosNor_Data {
- PosNorLoop *vbo_data;
- GPUNormal *normals;
-} MeshExtract_PosNor_Data;
-
-static void extract_pos_nor_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* WARNING Adjust #PosNorLoop struct accordingly. */
- GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_alias_add(&format, "vnor");
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
-
- /* Pack normals per vert, reduce amount of computation. */
- MeshExtract_PosNor_Data *data = tls_data;
- data->vbo_data = (PosNorLoop *)GPU_vertbuf_get_data(vbo);
- data->normals = MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__);
-
- /* Quicker than doing it for each loop. */
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMIter iter;
- BMVert *eve;
- int v;
- BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
- data->normals[v].low = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve));
- }
- }
- else {
- const MVert *mv = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mv++) {
- data->normals[v].low = GPU_normal_convert_i10_s3(mv->no);
- }
- }
-}
-
-static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- PosNorLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
- vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low;
- vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
-
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
-
- PosNorLoop *vert = &data->vbo_data[ml_index];
- const MVert *mv = &mr->mvert[ml->v];
- copy_v3_v3(vert->pos, mv->co);
- vert->nor = data->normals[ml->v].low;
- /* Flag for paint mode overlay. */
- if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
- ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
- (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
- vert->nor.w = -1;
- }
- else if (mv->flag & SELECT) {
- vert->nor.w = 1;
- }
- else {
- vert->nor.w = 0;
- }
- }
-}
-
-static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr,
- const BMEdge *eed,
- const int ledge_index,
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
-
- int l_index = mr->loop_len + ledge_index * 2;
- PosNorLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
- copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
- vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low;
- vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low;
-}
-
-static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr,
- const MEdge *med,
- const int ledge_index,
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
- const int ml_index = mr->loop_len + ledge_index * 2;
- PosNorLoop *vert = &data->vbo_data[ml_index];
- copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co);
- copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co);
- vert[0].nor = data->normals[med->v1].low;
- vert[1].nor = data->normals[med->v2].low;
-}
-
-static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr,
- const BMVert *eve,
- const int lvert_index,
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- const int l_index = offset + lvert_index;
- PosNorLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
- vert->nor = data->normals[BM_elem_index_get(eve)].low;
-}
-
-static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr,
- const MVert *mv,
- const int lvert_index,
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- const int ml_index = offset + lvert_index;
- const int v_index = mr->lverts[lvert_index];
- PosNorLoop *vert = &data->vbo_data[ml_index];
- copy_v3_v3(vert->pos, mv->co);
- vert->nor = data->normals[v_index].low;
-}
-
-static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr),
- struct MeshBatchCache *UNUSED(cache),
- void *UNUSED(buf),
- void *_data)
-{
- MeshExtract_PosNor_Data *data = _data;
- MEM_freeN(data->normals);
-}
-
-const MeshExtract extract_pos_nor = {
- .init = extract_pos_nor_init,
- .iter_poly_bm = extract_pos_nor_iter_poly_bm,
- .iter_poly_mesh = extract_pos_nor_iter_poly_mesh,
- .iter_ledge_bm = extract_pos_nor_iter_ledge_bm,
- .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh,
- .iter_lvert_bm = extract_pos_nor_iter_lvert_bm,
- .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh,
- .finish = extract_pos_nor_finish,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_PosNor_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Position and High Quality Vertex Normal
- * \{ */
-
-typedef struct PosNorHQLoop {
- float pos[3];
- short nor[4];
-} PosNorHQLoop;
-
-typedef struct MeshExtract_PosNorHQ_Data {
- PosNorHQLoop *vbo_data;
- GPUNormal *normals;
-} MeshExtract_PosNorHQ_Data;
-
-static void extract_pos_nor_hq_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* WARNING Adjust #PosNorHQLoop struct accordingly. */
- GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_alias_add(&format, "vnor");
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
-
- /* Pack normals per vert, reduce amount of computation. */
- MeshExtract_PosNorHQ_Data *data = tls_data;
- data->vbo_data = (PosNorHQLoop *)GPU_vertbuf_get_data(vbo);
- data->normals = MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__);
-
- /* Quicker than doing it for each loop. */
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMIter iter;
- BMVert *eve;
- int v;
- BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
- normal_float_to_short_v3(data->normals[v].high, bm_vert_no_get(mr, eve));
- }
- }
- else {
- const MVert *mv = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mv++) {
- copy_v3_v3_short(data->normals[v].high, mv->no);
- }
- }
-}
-
-static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- PosNorHQLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
- copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high);
-
- BMFace *efa = l_iter->f;
- vert->nor[3] = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
-
- PosNorHQLoop *vert = &data->vbo_data[ml_index];
- const MVert *mv = &mr->mvert[ml->v];
- copy_v3_v3(vert->pos, mv->co);
- copy_v3_v3_short(vert->nor, data->normals[ml->v].high);
-
- /* Flag for paint mode overlay. */
- if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
- ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
- (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
- vert->nor[3] = -1;
- }
- else if (mv->flag & SELECT) {
- vert->nor[3] = 1;
- }
- else {
- vert->nor[3] = 0;
- }
- }
-}
-
-static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr,
- const BMEdge *eed,
- const int ledge_index,
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- int l_index = mr->loop_len + ledge_index * 2;
- PosNorHQLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
- copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
- copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high);
- vert[0].nor[3] = 0;
- copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high);
- vert[1].nor[3] = 0;
-}
-
-static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr,
- const MEdge *med,
- const int ledge_index,
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- const int ml_index = mr->loop_len + ledge_index * 2;
- PosNorHQLoop *vert = &data->vbo_data[ml_index];
- copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co);
- copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co);
- copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high);
- vert[0].nor[3] = 0;
- copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high);
- vert[1].nor[3] = 0;
-}
-
-static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr,
- const BMVert *eve,
- const int lvert_index,
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- const int l_index = offset + lvert_index;
- PosNorHQLoop *vert = &data->vbo_data[l_index];
- copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
- copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high);
- vert->nor[3] = 0;
-}
-
-static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr,
- const MVert *mv,
- const int lvert_index,
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- const int ml_index = offset + lvert_index;
- const int v_index = mr->lverts[lvert_index];
- PosNorHQLoop *vert = &data->vbo_data[ml_index];
- copy_v3_v3(vert->pos, mv->co);
- copy_v3_v3_short(vert->nor, data->normals[v_index].high);
- vert->nor[3] = 0;
-}
-
-static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr),
- struct MeshBatchCache *UNUSED(cache),
- void *UNUSED(buf),
- void *_data)
-{
- MeshExtract_PosNorHQ_Data *data = _data;
- MEM_freeN(data->normals);
-}
-
-const MeshExtract extract_pos_nor_hq = {
- .init = extract_pos_nor_hq_init,
- .iter_poly_bm = extract_pos_nor_hq_iter_poly_bm,
- .iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh,
- .iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm,
- .iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh,
- .iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm,
- .iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh,
- .finish = extract_pos_nor_hq_finish,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_PosNorHQ_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)};
-
-/** \} */
-/* ---------------------------------------------------------------------- */
-/** \name Extract HQ Loop Normal
- * \{ */
-
-typedef struct gpuHQNor {
- short x, y, z, w;
-} gpuHQNor;
-
-static void extract_lnor_hq_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_alias_add(&format, "lnor");
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- *(gpuHQNor **)tls_data = GPU_vertbuf_get_data(vbo);
-}
-
-static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *data)
-{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- if (mr->loop_normals) {
- normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]);
- }
- else {
- if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
- normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v));
- }
- else {
- normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_face_no_get(mr, f));
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *data)
-{
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index];
- if (mr->loop_normals) {
- normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
- }
- else if (mp->flag & ME_SMOOTH) {
- copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no);
- }
- else {
- normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]);
- }
-
- /* Flag for paint mode overlay.
- * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
- * In paint mode it will use the un-mapped data to draw the wire-frame. */
- if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
- (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
- lnor_data->w = -1;
- }
- else if (mp->flag & ME_FACE_SEL) {
- lnor_data->w = 1;
- }
- else {
- lnor_data->w = 0;
- }
- }
-}
-
-const MeshExtract extract_lnor_hq = {
- .init = extract_lnor_hq_init,
- .iter_poly_bm = extract_lnor_hq_iter_poly_bm,
- .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh,
- .data_type = MR_DATA_LOOP_NOR,
- .data_size = sizeof(gpuHQNor *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor),
-};
-
-/** \} */
-/* ---------------------------------------------------------------------- */
-/** \name Extract Loop Normal
- * \{ */
-
-static void extract_lnor_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_alias_add(&format, "lnor");
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- *(GPUPackedNormal **)tls_data = GPU_vertbuf_get_data(vbo);
-}
-
-static void extract_lnor_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *data)
-{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- if (mr->loop_normals) {
- (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]);
- }
- else {
- if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
- (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(
- bm_vert_no_get(mr, l_iter->v));
- }
- else {
- (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f));
- }
- }
- (*(GPUPackedNormal **)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *data)
-{
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index];
- if (mr->loop_normals) {
- *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
- }
- else if (mp->flag & ME_SMOOTH) {
- *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no);
- }
- else {
- *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]);
- }
-
- /* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
- * In paint mode it will use the un-mapped data to draw the wire-frame. */
- if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
- (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
- lnor_data->w = -1;
- }
- else if (mp->flag & ME_FACE_SEL) {
- lnor_data->w = 1;
- }
- else {
- lnor_data->w = 0;
- }
- }
-}
-
-const MeshExtract extract_lnor = {
- .init = extract_lnor_init,
- .iter_poly_bm = extract_lnor_iter_poly_bm,
- .iter_poly_mesh = extract_lnor_iter_poly_mesh,
- .data_type = MR_DATA_LOOP_NOR,
- .data_size = sizeof(GPUPackedNormal *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract UV layers
- * \{ */
-
-static void extract_uv_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- GPUVertFormat format = {0};
- GPU_vertformat_deinterleave(&format);
-
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
- uint32_t uv_layers = cache->cd_used.uv;
- /* HACK to fix T68857 */
- if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
- int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
- if (layer != -1) {
- uv_layers |= (1 << layer);
- }
- }
-
- for (int i = 0; i < MAX_MTFACE; i++) {
- if (uv_layers & (1 << i)) {
- char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
-
- GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
- /* UV layer name. */
- BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- /* Auto layer name. */
- BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
- GPU_vertformat_alias_add(&format, attr_name);
- /* Active render layer name. */
- if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "u");
- }
- /* Active display layer name. */
- if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "au");
- /* Alias to `pos` for edit uvs. */
- GPU_vertformat_alias_add(&format, "pos");
- }
- /* Stencil mask uv layer name. */
- if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "mu");
- }
- }
- }
-
- int v_len = mr->loop_len;
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- /* VBO will not be used, only allocate minimum of memory. */
- v_len = 1;
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, v_len);
-
- float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo);
- for (int i = 0; i < MAX_MTFACE; i++) {
- if (uv_layers & (1 << i)) {
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i);
- BMIter f_iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
- memcpy(uv_data, luv->uv, sizeof(*uv_data));
- uv_data++;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- else {
- MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
- memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
- }
- }
- }
- }
-}
-
-const MeshExtract extract_uv = {
- .init = extract_uv_init,
- .data_type = 0,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Tangent layers
- * \{ */
-
-static void extract_tan_ex_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- GPUVertBuf *vbo,
- const bool do_hq)
-{
- GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10;
- GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT;
-
- GPUVertFormat format = {0};
- GPU_vertformat_deinterleave(&format);
-
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
- CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
- uint32_t tan_layers = cache->cd_used.tan;
- float(*orco)[3] = CustomData_get_layer(cd_vdata, CD_ORCO);
- bool orco_allocated = false;
- const bool use_orco_tan = cache->cd_used.tan_orco != 0;
-
- int tan_len = 0;
- char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME];
-
- for (int i = 0; i < MAX_MTFACE; i++) {
- if (tan_layers & (1 << i)) {
- char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
- GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
- /* Tangent layer name. */
- BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
- /* Active render layer name. */
- if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "t");
- }
- /* Active display layer name. */
- if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "at");
- }
-
- BLI_strncpy(tangent_names[tan_len++], layer_name, MAX_CUSTOMDATA_LAYER_NAME);
- }
- }
- if (use_orco_tan && orco == NULL) {
- /* If `orco` is not available compute it ourselves */
- orco_allocated = true;
- orco = MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMesh *bm = mr->bm;
- for (int v = 0; v < mr->vert_len; v++) {
- const BMVert *eve = BM_vert_at_index(bm, v);
- /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords.
- * not the distorted ones. */
- copy_v3_v3(orco[v], eve->co);
- }
- }
- else {
- const MVert *mv = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mv++) {
- copy_v3_v3(orco[v], mv->co);
- }
- }
- BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0);
- }
-
- /* Start Fresh */
- CustomData loop_data;
- CustomData_reset(&loop_data);
- if (tan_len != 0 || use_orco_tan) {
- short tangent_mask = 0;
- bool calc_active_tangent = false;
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BKE_editmesh_loop_tangent_calc(mr->edit_bmesh,
- calc_active_tangent,
- tangent_names,
- tan_len,
- mr->poly_normals,
- mr->loop_normals,
- orco,
- &loop_data,
- mr->loop_len,
- &tangent_mask);
- }
- else {
- BKE_mesh_calc_loop_tangent_ex(mr->mvert,
- mr->mpoly,
- mr->poly_len,
- mr->mloop,
- mr->mlooptri,
- mr->tri_len,
- cd_ldata,
- calc_active_tangent,
- tangent_names,
- tan_len,
- mr->poly_normals,
- mr->loop_normals,
- orco,
- &loop_data,
- mr->loop_len,
- &tangent_mask);
- }
- }
-
- if (use_orco_tan) {
- char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *layer_name = CustomData_get_layer_name(&loop_data, CD_TANGENT, 0);
- GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
- BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
- GPU_vertformat_alias_add(&format, "t");
- GPU_vertformat_alias_add(&format, "at");
- }
-
- if (orco_allocated) {
- MEM_SAFE_FREE(orco);
- }
-
- int v_len = mr->loop_len;
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- /* VBO will not be used, only allocate minimum of memory. */
- v_len = 1;
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, v_len);
-
- if (do_hq) {
- short(*tan_data)[4] = (short(*)[4])GPU_vertbuf_get_data(vbo);
- for (int i = 0; i < tan_len; i++) {
- const char *name = tangent_names[i];
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(
- &loop_data, CD_TANGENT, name);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
- normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
- (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
- tan_data++;
- }
- }
- if (use_orco_tan) {
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
- normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
- (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
- tan_data++;
- }
- }
- }
- else {
- GPUPackedNormal *tan_data = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo);
- for (int i = 0; i < tan_len; i++) {
- const char *name = tangent_names[i];
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(
- &loop_data, CD_TANGENT, name);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
- *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
- tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
- tan_data++;
- }
- }
- if (use_orco_tan) {
- float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
- *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
- tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
- tan_data++;
- }
- }
- }
-
- CustomData_free(&loop_data, mr->loop_len);
-}
-
-static void extract_tan_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(tls_data))
-{
- extract_tan_ex_init(mr, cache, buf, false);
-}
-
-const MeshExtract extract_tan = {
- .init = extract_tan_init,
- .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract HQ Tangent layers
- * \{ */
-
-static void extract_tan_hq_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(tls_data))
-{
- extract_tan_ex_init(mr, cache, buf, true);
-}
-
-const MeshExtract extract_tan_hq = {
- .init = extract_tan_hq_init,
- .data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Sculpt Data
+/** \name Extract Edit Flag Utils
* \{ */
-static void extract_sculpt_data_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- GPUVertFormat format = {0};
-
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
- CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
- CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata;
-
- float *cd_mask = CustomData_get_layer(cd_vdata, CD_PAINT_MASK);
- int *cd_face_set = CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS);
-
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- typedef struct gpuSculptData {
- uint8_t face_set_color[4];
- float mask;
- } gpuSculptData;
-
- gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo);
- MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- int cd_mask_ofs = CustomData_get_offset(cd_vdata, CD_PAINT_MASK);
- int cd_face_set_ofs = CustomData_get_offset(cd_pdata, CD_SCULPT_FACE_SETS);
- BMIter f_iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- float v_mask = 0.0f;
- if (cd_mask) {
- v_mask = BM_ELEM_CD_GET_FLOAT(l_iter->v, cd_mask_ofs);
- }
- vbo_data->mask = v_mask;
- uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- if (cd_face_set) {
- const int face_set_id = BM_ELEM_CD_GET_INT(l_iter->f, cd_face_set_ofs);
- if (face_set_id != mr->me->face_sets_color_default) {
- BKE_paint_face_set_overlay_color_get(
- face_set_id, mr->me->face_sets_color_seed, face_set_color);
- }
- }
- copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color);
- vbo_data++;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- else {
- int mp_loop = 0;
- for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
- const MPoly *p = &mr->mpoly[mp_index];
- for (int l = 0; l < p->totloop; l++) {
- float v_mask = 0.0f;
- if (cd_mask) {
- v_mask = cd_mask[loops[mp_loop].v];
- }
- vbo_data->mask = v_mask;
-
- uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- if (cd_face_set) {
- const int face_set_id = cd_face_set[mp_index];
- /* Skip for the default color Face Set to render it white. */
- if (face_set_id != mr->me->face_sets_color_default) {
- BKE_paint_face_set_overlay_color_get(
- face_set_id, mr->me->face_sets_color_seed, face_set_color);
- }
- }
- copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color);
- mp_loop++;
- vbo_data++;
- }
- }
- }
-}
-
-const MeshExtract extract_sculpt_data = {
- .init = extract_sculpt_data_init,
- .data_type = 0,
- .data_size = 0,
- /* TODO: enable threading. */
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract VCol
- * \{ */
-
-static void extract_vcol_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- GPUVertFormat format = {0};
- GPU_vertformat_deinterleave(&format);
-
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
- CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
- uint32_t vcol_layers = cache->cd_used.vcol;
- uint32_t svcol_layers = cache->cd_used.sculpt_vcol;
-
- for (int i = 0; i < MAX_MCOL; i++) {
- if (vcol_layers & (1 << i)) {
- char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
- GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
-
- BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) {
- GPU_vertformat_alias_add(&format, "c");
- }
- if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) {
- GPU_vertformat_alias_add(&format, "ac");
- }
-
- /* Gather number of auto layers. */
- /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */
- if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 &&
- CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) {
- BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
- GPU_vertformat_alias_add(&format, attr_name);
- }
- }
- }
-
- /* Sculpt Vertex Colors */
- if (U.experimental.use_sculpt_vertex_colors) {
- for (int i = 0; i < 8; i++) {
- if (svcol_layers & (1 << i)) {
- char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i);
- GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
-
- BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
-
- if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) {
- GPU_vertformat_alias_add(&format, "c");
- }
- if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) {
- GPU_vertformat_alias_add(&format, "ac");
- }
- /* Gather number of auto layers. */
- /* We only do `vcols` that are not overridden by `uvs`. */
- if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
- BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
- GPU_vertformat_alias_add(&format, attr_name);
- }
- }
- }
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- typedef struct gpuMeshVcol {
- ushort r, g, b, a;
- } gpuMeshVcol;
-
- gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo);
- MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP);
-
- for (int i = 0; i < MAX_MCOL; i++) {
- if (vcol_layers & (1 << i)) {
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
- BMIter f_iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
- vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
- vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
- vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
- vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
- vcol_data++;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- else {
- const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) {
- vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
- vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
- vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
- vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
- }
- }
- }
-
- if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) {
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i);
- BMIter f_iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- const MPropCol *prop_col = BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs);
- vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]);
- vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]);
- vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]);
- vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]);
- vcol_data++;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- else {
- MPropCol *vcol = CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) {
- vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]);
- vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]);
- vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]);
- vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]);
- }
- }
- }
- }
-}
-
-const MeshExtract extract_vcol = {
- .init = extract_vcol_init,
- .data_type = 0,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Orco
- * \{ */
-
-typedef struct MeshExtract_Orco_Data {
- float (*vbo_data)[4];
- float (*orco)[3];
-} MeshExtract_Orco_Data;
-
-static void extract_orco_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
- * attributes. This is a substantial waste of video-ram and should be done another way.
- * Unfortunately, at the time of writing, I did not found any other "non disruptive"
- * alternative. */
- GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- CustomData *cd_vdata = &mr->me->vdata;
-
- MeshExtract_Orco_Data *data = tls_data;
- data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo);
- data->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
- /* Make sure `orco` layer was requested only if needed! */
- BLI_assert(data->orco);
-}
-
-static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *f,
- const int UNUSED(f_index),
- void *data)
-{
- MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- float *loop_orco = orco_data->vbo_data[l_index];
- copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(l_iter->v)]);
- loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_orco_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *data)
-{
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
- float *loop_orco = orco_data->vbo_data[ml_index];
- copy_v3_v3(loop_orco, orco_data->orco[ml->v]);
- loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
- }
-}
-
-const MeshExtract extract_orco = {
- .init = extract_orco_init,
- .iter_poly_bm = extract_orco_iter_poly_bm,
- .iter_poly_mesh = extract_orco_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_Orco_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Edge Factor
- * Defines how much an edge is visible.
- * \{ */
-
-typedef struct MeshExtract_EdgeFac_Data {
- uchar *vbo_data;
- bool use_edge_render;
- /* Number of loop per edge. */
- uchar *edge_loop_count;
-} MeshExtract_EdgeFac_Data;
-
-static float loop_edge_factor_get(const float f_no[3],
- const float v_co[3],
- const float v_no[3],
- const float v_next_co[3])
-{
- float enor[3], evec[3];
- sub_v3_v3v3(evec, v_next_co, v_co);
- cross_v3_v3v3(enor, v_no, evec);
- normalize_v3(enor);
- float d = fabsf(dot_v3v3(enor, f_no));
- /* Re-scale to the slider range. */
- d *= (1.0f / 0.065f);
- CLAMP(d, 0.0f, 1.0f);
- return d;
-}
-
-static void extract_edge_fac_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
-
- MeshExtract_EdgeFac_Data *data = tls_data;
-
- if (mr->extract_type == MR_EXTRACT_MESH) {
- data->edge_loop_count = MEM_callocN(sizeof(uint32_t) * mr->edge_len, __func__);
-
- /* HACK(fclem) Detecting the need for edge render.
- * We could have a flag in the mesh instead or check the modifier stack. */
- const MEdge *med = mr->medge;
- for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) {
- if ((med->flag & ME_EDGERENDER) == 0) {
- data->use_edge_render = true;
- break;
- }
- }
- }
- else {
- /* HACK to bypass non-manifold check in mesh_edge_fac_finish(). */
- data->use_edge_render = true;
- }
-
- data->vbo_data = GPU_vertbuf_get_data(vbo);
-}
-
-static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_EdgeFac_Data *data = _data;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
-
- if (BM_edge_is_manifold(l_iter->e)) {
- float ratio = loop_edge_factor_get(bm_face_no_get(mr, f),
- bm_vert_co_get(mr, l_iter->v),
- bm_vert_no_get(mr, l_iter->v),
- bm_vert_co_get(mr, l_iter->next->v));
- data->vbo_data[l_index] = ratio * 253 + 1;
- }
- else {
- data->vbo_data[l_index] = 255;
- }
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *_data)
-{
- MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
-
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
-
- if (data->use_edge_render) {
- const MEdge *med = &mr->medge[ml->e];
- data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0;
- }
- else {
-
- /* Count loop per edge to detect non-manifold. */
- if (data->edge_loop_count[ml->e] < 3) {
- data->edge_loop_count[ml->e]++;
- }
- if (data->edge_loop_count[ml->e] == 2) {
- /* Manifold */
- const int ml_index_last = mp->totloop + mp->loopstart - 1;
- const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
- const MLoop *ml_next = &mr->mloop[ml_index_other];
- const MVert *v1 = &mr->mvert[ml->v];
- const MVert *v2 = &mr->mvert[ml_next->v];
- float vnor_f[3];
- normal_short_to_float_v3(vnor_f, v1->no);
- float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co);
- data->vbo_data[ml_index] = ratio * 253 + 1;
- }
- else {
- /* Non-manifold */
- data->vbo_data[ml_index] = 255;
- }
- }
- }
-}
-
-static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr,
- const BMEdge *UNUSED(eed),
- const int ledge_index,
- void *_data)
-{
- MeshExtract_EdgeFac_Data *data = _data;
- data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255;
- data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255;
-}
-
-static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr,
- const MEdge *UNUSED(med),
- const int ledge_index,
- void *_data)
-{
- MeshExtract_EdgeFac_Data *data = _data;
-
- data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255;
- data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255;
-}
-
-static void extract_edge_fac_finish(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *_data)
-{
- GPUVertBuf *vbo = buf;
- MeshExtract_EdgeFac_Data *data = _data;
-
- if (GPU_crappy_amd_driver()) {
- /* Some AMD drivers strangely crash with VBO's with a one byte format.
- * To workaround we reinitialize the VBO with another format and convert
- * all bytes to floats. */
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
- /* We keep the data reference in data->vbo_data. */
- data->vbo_data = GPU_vertbuf_steal_data(vbo);
- GPU_vertbuf_clear(vbo);
-
- int buf_len = mr->loop_len + mr->loop_loose_len;
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, buf_len);
-
- float *fdata = (float *)GPU_vertbuf_get_data(vbo);
- for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) {
- *fdata = data->vbo_data[ml_index] / 255.0f;
- }
- /* Free old byte data. */
- MEM_freeN(data->vbo_data);
- }
- MEM_SAFE_FREE(data->edge_loop_count);
-}
-
-const MeshExtract extract_edge_fac = {
- .init = extract_edge_fac_init,
- .iter_poly_bm = extract_edge_fac_iter_poly_bm,
- .iter_poly_mesh = extract_edge_fac_iter_poly_mesh,
- .iter_ledge_bm = extract_edge_fac_iter_ledge_bm,
- .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh,
- .finish = extract_edge_fac_finish,
- .data_type = MR_DATA_POLY_NOR,
- .data_size = sizeof(MeshExtract_EdgeFac_Data),
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac)};
-
-/** \} */
-/* ---------------------------------------------------------------------- */
-/** \name Extract Vertex Weight
- * \{ */
-
-typedef struct MeshExtract_Weight_Data {
- float *vbo_data;
- const DRW_MeshWeightState *wstate;
- const MDeformVert *dvert; /* For #Mesh. */
- int cd_ofs; /* For #BMesh. */
-} MeshExtract_Weight_Data;
-
-static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
-{
- /* Error state. */
- if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) {
- return -2.0f;
- }
- if (dvert == NULL) {
- return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f;
- }
-
- float input = 0.0f;
- if (wstate->flags & DRW_MESH_WEIGHT_STATE_MULTIPAINT) {
- /* Multi-Paint feature */
- bool is_normalized = (wstate->flags & (DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE |
- DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE));
- input = BKE_defvert_multipaint_collective_weight(dvert,
- wstate->defgroup_len,
- wstate->defgroup_sel,
- wstate->defgroup_sel_count,
- is_normalized);
- /* make it black if the selected groups have no weight on a vertex */
- if (input == 0.0f) {
- return -1.0f;
- }
- }
- else {
- /* default, non tricky behavior */
- input = BKE_defvert_find_weight(dvert, wstate->defgroup_active);
-
- if (input == 0.0f) {
- switch (wstate->alert_mode) {
- case OB_DRAW_GROUPUSER_ACTIVE:
- return -1.0f;
- break;
- case OB_DRAW_GROUPUSER_ALL:
- if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) {
- return -1.0f;
- }
- break;
- }
- }
- }
-
- /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */
- if (wstate->flags & DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE) {
- input = BKE_defvert_lock_relative_weight(
- input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked);
- }
-
- CLAMP(input, 0.0f, 1.0f);
- return input;
-}
-
-static void extract_weights_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
-
- MeshExtract_Weight_Data *data = tls_data;
- data->vbo_data = (float *)GPU_vertbuf_get_data(vbo);
- data->wstate = &cache->weight_state;
-
- if (data->wstate->defgroup_active == -1) {
- /* Nothing to show. */
- data->dvert = NULL;
- data->cd_ofs = -1;
- }
- else if (mr->extract_type == MR_EXTRACT_BMESH) {
- data->dvert = NULL;
- data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT);
- }
- else {
- data->dvert = CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT);
- data->cd_ofs = -1;
- }
-}
-
-static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_Weight_Data *data = _data;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- if (data->cd_ofs != -1) {
- const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(l_iter->v, data->cd_ofs);
- data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate);
- }
- else {
- data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate);
- }
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *_data)
-{
- MeshExtract_Weight_Data *data = _data;
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- if (data->dvert != NULL) {
- const MDeformVert *dvert = &data->dvert[ml->v];
- data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
- }
- else {
- const MDeformVert *dvert = NULL;
- data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
- }
- }
-}
-
-const MeshExtract extract_weights = {
- .init = extract_weights_init,
- .iter_poly_bm = extract_weights_iter_poly_bm,
- .iter_poly_mesh = extract_weights_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_Weight_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights),
-};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Edit Mode Data / Flags
- * \{ */
-
-typedef struct EditLoopData {
- uchar v_flag;
- uchar e_flag;
- uchar crease;
- uchar bweight;
-} EditLoopData;
-
-static void mesh_render_data_face_flag(const MeshRenderData *mr,
- const BMFace *efa,
- const int cd_ofs,
- EditLoopData *eattr)
+void mesh_render_data_face_flag(const MeshRenderData *mr,
+ const BMFace *efa,
+ const int cd_ofs,
+ EditLoopData *eattr)
{
if (efa == mr->efa_act) {
eattr->v_flag |= VFLAG_FACE_ACTIVE;
@@ -1708,7 +125,8 @@ static void mesh_render_data_face_flag(const MeshRenderData *mr,
#ifdef WITH_FREESTYLE
if (mr->freestyle_face_ofs != -1) {
- const FreestyleFace *ffa = BM_ELEM_CD_GET_VOID_P(efa, mr->freestyle_face_ofs);
+ const FreestyleFace *ffa = (const FreestyleFace *)BM_ELEM_CD_GET_VOID_P(
+ efa, mr->freestyle_face_ofs);
if (ffa->flag & FREESTYLE_FACE_MARK) {
eattr->v_flag |= VFLAG_FACE_FREESTYLE;
}
@@ -1716,78 +134,15 @@ static void mesh_render_data_face_flag(const MeshRenderData *mr,
#endif
}
-static void mesh_render_data_edge_flag(const MeshRenderData *mr,
- const BMEdge *eed,
- EditLoopData *eattr)
-{
- const ToolSettings *ts = mr->toolsettings;
- const bool is_vertex_select_mode = (ts != NULL) && (ts->selectmode & SCE_SELECT_VERTEX) != 0;
- const bool is_face_only_select_mode = (ts != NULL) && (ts->selectmode == SCE_SELECT_FACE);
-
- if (eed == mr->eed_act) {
- eattr->e_flag |= VFLAG_EDGE_ACTIVE;
- }
- if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- eattr->e_flag |= VFLAG_EDGE_SELECTED;
- }
- if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) {
- eattr->e_flag |= VFLAG_EDGE_SELECTED;
- eattr->e_flag |= VFLAG_VERT_SELECTED;
- }
- if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
- eattr->e_flag |= VFLAG_EDGE_SEAM;
- }
- if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) {
- eattr->e_flag |= VFLAG_EDGE_SHARP;
- }
-
- /* Use active edge color for active face edges because
- * specular highlights make it hard to see T55456#510873.
- *
- * This isn't ideal since it can't be used when mixing edge/face modes
- * but it's still better than not being able to see the active face. */
- if (is_face_only_select_mode) {
- if (mr->efa_act != NULL) {
- if (BM_edge_in_face(eed, mr->efa_act)) {
- eattr->e_flag |= VFLAG_EDGE_ACTIVE;
- }
- }
- }
-
- /* Use a byte for value range */
- if (mr->crease_ofs != -1) {
- float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs);
- if (crease > 0) {
- eattr->crease = (uchar)(crease * 255.0f);
- }
- }
- /* Use a byte for value range */
- if (mr->bweight_ofs != -1) {
- float bweight = BM_ELEM_CD_GET_FLOAT(eed, mr->bweight_ofs);
- if (bweight > 0) {
- eattr->bweight = (uchar)(bweight * 255.0f);
- }
- }
-#ifdef WITH_FREESTYLE
- if (mr->freestyle_edge_ofs != -1) {
- const FreestyleEdge *fed = BM_ELEM_CD_GET_VOID_P(eed, mr->freestyle_edge_ofs);
- if (fed->flag & FREESTYLE_EDGE_MARK) {
- eattr->e_flag |= VFLAG_EDGE_FREESTYLE;
- }
- }
-#endif
-}
-
-static void mesh_render_data_loop_flag(const MeshRenderData *mr,
- BMLoop *l,
- const int cd_ofs,
- EditLoopData *eattr)
+void mesh_render_data_loop_flag(const MeshRenderData *mr,
+ BMLoop *l,
+ const int cd_ofs,
+ EditLoopData *eattr)
{
if (cd_ofs == -1) {
return;
}
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_ofs);
+ MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_ofs);
if (luv != NULL && (luv->flag & MLOOPUV_PINNED)) {
eattr->v_flag |= VFLAG_VERT_UV_PINNED;
}
@@ -1796,10 +151,10 @@ static void mesh_render_data_loop_flag(const MeshRenderData *mr,
}
}
-static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
- BMLoop *l,
- const int cd_ofs,
- EditLoopData *eattr)
+void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
+ BMLoop *l,
+ const int cd_ofs,
+ EditLoopData *eattr)
{
if (cd_ofs == -1) {
return;
@@ -1810,1879 +165,4 @@ static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
}
}
-static void mesh_render_data_vert_flag(const MeshRenderData *mr,
- const BMVert *eve,
- EditLoopData *eattr)
-{
- if (eve == mr->eve_act) {
- eattr->e_flag |= VFLAG_VERT_ACTIVE;
- }
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- eattr->e_flag |= VFLAG_VERT_SELECTED;
- }
-}
-
-static void extract_edit_data_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* WARNING: Adjust #EditLoopData struct accordingly. */
- GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
- GPU_vertformat_alias_add(&format, "flag");
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
- EditLoopData *vbo_data = GPU_vertbuf_get_data(vbo);
- *(EditLoopData **)tls_data = vbo_data;
-}
-
-static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- EditLoopData *vbo_data = *(EditLoopData **)_data;
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
-
- EditLoopData *data = vbo_data + l_index;
- memset(data, 0x0, sizeof(*data));
- mesh_render_data_face_flag(mr, f, -1, data);
- mesh_render_data_edge_flag(mr, l_iter->e, data);
- mesh_render_data_vert_flag(mr, l_iter->v, data);
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *_data)
-{
- EditLoopData *vbo_data = *(EditLoopData **)_data;
-
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- EditLoopData *data = vbo_data + ml_index;
- memset(data, 0x0, sizeof(*data));
- BMFace *efa = bm_original_face_get(mr, mp_index);
- BMEdge *eed = bm_original_edge_get(mr, ml->e);
- BMVert *eve = bm_original_vert_get(mr, ml->v);
- if (efa) {
- mesh_render_data_face_flag(mr, efa, -1, data);
- }
- if (eed) {
- mesh_render_data_edge_flag(mr, eed, data);
- }
- if (eve) {
- mesh_render_data_vert_flag(mr, eve, data);
- }
- }
-}
-
-static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr,
- const BMEdge *eed,
- const int ledge_index,
- void *_data)
-{
- EditLoopData *vbo_data = *(EditLoopData **)_data;
- EditLoopData *data = vbo_data + mr->loop_len + (ledge_index * 2);
- memset(data, 0x0, sizeof(*data) * 2);
- mesh_render_data_edge_flag(mr, eed, &data[0]);
- data[1] = data[0];
- mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
- mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
-}
-
-static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr,
- const MEdge *med,
- const int ledge_index,
- void *_data)
-{
- EditLoopData *vbo_data = *(EditLoopData **)_data;
- EditLoopData *data = vbo_data + mr->loop_len + ledge_index * 2;
- memset(data, 0x0, sizeof(*data) * 2);
- const int e_index = mr->ledges[ledge_index];
- BMEdge *eed = bm_original_edge_get(mr, e_index);
- BMVert *eve1 = bm_original_vert_get(mr, med->v1);
- BMVert *eve2 = bm_original_vert_get(mr, med->v2);
- if (eed) {
- mesh_render_data_edge_flag(mr, eed, &data[0]);
- data[1] = data[0];
- }
- if (eve1) {
- mesh_render_data_vert_flag(mr, eve1, &data[0]);
- }
- if (eve2) {
- mesh_render_data_vert_flag(mr, eve2, &data[1]);
- }
-}
-
-static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr,
- const BMVert *eve,
- const int lvert_index,
- void *_data)
-{
- EditLoopData *vbo_data = *(EditLoopData **)_data;
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
- EditLoopData *data = vbo_data + offset + lvert_index;
- memset(data, 0x0, sizeof(*data));
- mesh_render_data_vert_flag(mr, eve, data);
-}
-
-static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
- const MVert *UNUSED(mv),
- const int lvert_index,
- void *_data)
-{
- EditLoopData *vbo_data = *(EditLoopData **)_data;
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- EditLoopData *data = vbo_data + offset + lvert_index;
- memset(data, 0x0, sizeof(*data));
- const int v_index = mr->lverts[lvert_index];
- BMVert *eve = bm_original_vert_get(mr, v_index);
- if (eve) {
- mesh_render_data_vert_flag(mr, eve, data);
- }
-}
-
-const MeshExtract extract_edit_data = {
- .init = extract_edit_data_init,
- .iter_poly_bm = extract_edit_data_iter_poly_bm,
- .iter_poly_mesh = extract_edit_data_iter_poly_mesh,
- .iter_ledge_bm = extract_edit_data_iter_ledge_bm,
- .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh,
- .iter_lvert_bm = extract_edit_data_iter_lvert_bm,
- .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh,
- .data_type = 0,
- .data_size = sizeof(EditLoopData *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data)};
-
/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Edit UV Data / Flags
- * \{ */
-
-typedef struct MeshExtract_EditUVData_Data {
- EditLoopData *vbo_data;
- int cd_ofs;
-} MeshExtract_EditUVData_Data;
-
-static void extract_edituv_data_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* WARNING: Adjust #EditLoopData struct accordingly. */
- GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
- GPU_vertformat_alias_add(&format, "flag");
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
-
- MeshExtract_EditUVData_Data *data = tls_data;
- data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
- data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
-}
-
-static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- MeshExtract_EditUVData_Data *data = _data;
- EditLoopData *eldata = &data->vbo_data[l_index];
- memset(eldata, 0x0, sizeof(*eldata));
- mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata);
- mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
- mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata);
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *_data)
-{
- MeshExtract_EditUVData_Data *data = _data;
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
-
- EditLoopData *eldata = &data->vbo_data[ml_index];
- memset(eldata, 0x0, sizeof(*eldata));
- BMFace *efa = bm_original_face_get(mr, mp_index);
- if (efa) {
- BMEdge *eed = bm_original_edge_get(mr, ml->e);
- BMVert *eve = bm_original_vert_get(mr, ml->v);
- if (eed && eve) {
- /* Loop on an edge endpoint. */
- BMLoop *l = BM_face_edge_share_loop(efa, eed);
- mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
- mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
- }
- else {
- if (eed == NULL) {
- /* Find if the loop's vert is not part of an edit edge.
- * For this, we check if the previous loop was on an edge. */
- const int ml_index_last = mp->loopstart + mp->totloop - 1;
- const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1);
- const MLoop *ml_prev = &mr->mloop[l_prev];
- eed = bm_original_edge_get(mr, ml_prev->e);
- }
- if (eed) {
- /* Mapped points on an edge between two edit verts. */
- BMLoop *l = BM_face_edge_share_loop(efa, eed);
- mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
- }
- }
- }
- }
-}
-
-const MeshExtract extract_edituv_data = {
- .init = extract_edituv_data_init,
- .iter_poly_bm = extract_edituv_data_iter_poly_bm,
- .iter_poly_mesh = extract_edituv_data_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_EditUVData_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Edit UV area stretch
- * \{ */
-
-static void extract_edituv_stretch_area_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-}
-
-BLI_INLINE float area_ratio_get(float area, float uvarea)
-{
- if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) {
- /* Tag inversion by using the sign. */
- return (area > uvarea) ? (uvarea / area) : -(area / uvarea);
- }
- return 0.0f;
-}
-
-BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio)
-{
- ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio;
- return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
-}
-
-static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(data))
-{
- GPUVertBuf *vbo = buf;
- float tot_area = 0.0f, tot_uv_area = 0.0f;
- float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- CustomData *cd_ldata = &mr->bm->ldata;
- int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
-
- BMFace *efa;
- BMIter f_iter;
- int f;
- BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
- float area = BM_face_calc_area(efa);
- float uvarea = BM_face_calc_area_uv(efa, uv_ofs);
- tot_area += area;
- tot_uv_area += uvarea;
- area_ratio[f] = area_ratio_get(area, uvarea);
- }
- }
- else {
- BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
- const MLoopUV *uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
- const MPoly *mp = mr->mpoly;
- for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
- float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert);
- float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
- tot_area += area;
- tot_uv_area += uvarea;
- area_ratio[mp_index] = area_ratio_get(area, uvarea);
- }
- }
-
- cache->tot_area = tot_area;
- cache->tot_uv_area = tot_uv_area;
-
- /* Convert in place to avoid an extra allocation */
- uint16_t *poly_stretch = (uint16_t *)area_ratio;
- for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
- poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX;
- }
-
- /* Copy face data for each loop. */
- uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMFace *efa;
- BMIter f_iter;
- int f, l_index = 0;
- BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
- for (int i = 0; i < efa->len; i++, l_index++) {
- loop_stretch[l_index] = poly_stretch[f];
- }
- }
- }
- else {
- BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
- const MPoly *mp = mr->mpoly;
- for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
- for (int i = 0; i < mp->totloop; i++, l_index++) {
- loop_stretch[l_index] = poly_stretch[mp_index];
- }
- }
- }
-
- MEM_freeN(area_ratio);
-}
-
-const MeshExtract extract_edituv_stretch_area = {
- .init = extract_edituv_stretch_area_init,
- .finish = extract_edituv_stretch_area_finish,
- .data_type = 0,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Edit UV angle stretch
- * \{ */
-
-typedef struct UVStretchAngle {
- int16_t angle;
- int16_t uv_angles[2];
-} UVStretchAngle;
-
-typedef struct MeshExtract_StretchAngle_Data {
- UVStretchAngle *vbo_data;
- MLoopUV *luv;
- float auv[2][2], last_auv[2];
- float av[2][3], last_av[3];
- int cd_ofs;
-} MeshExtract_StretchAngle_Data;
-
-static void compute_normalize_edge_vectors(float auv[2][2],
- float av[2][3],
- const float uv[2],
- const float uv_prev[2],
- const float co[3],
- const float co_prev[3])
-{
- /* Move previous edge. */
- copy_v2_v2(auv[0], auv[1]);
- copy_v3_v3(av[0], av[1]);
- /* 2d edge */
- sub_v2_v2v2(auv[1], uv_prev, uv);
- normalize_v2(auv[1]);
- /* 3d edge */
- sub_v3_v3v3(av[1], co_prev, co);
- normalize_v3(av[1]);
-}
-
-static short v2_to_short_angle(const float v[2])
-{
- return atan2f(v[1], v[0]) * (float)M_1_PI * SHRT_MAX;
-}
-
-static void edituv_get_edituv_stretch_angle(float auv[2][2],
- const float av[2][3],
- UVStretchAngle *r_stretch)
-{
- /* Send UV's to the shader and let it compute the aspect corrected angle. */
- r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]);
- r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]);
- /* Compute 3D angle here. */
- r_stretch->angle = angle_normalized_v3v3(av[0], av[1]) * (float)M_1_PI * SHRT_MAX;
-
-#if 0 /* here for reference, this is done in shader now. */
- float uvang = angle_normalized_v2v2(auv0, auv1);
- float ang = angle_normalized_v3v3(av0, av1);
- float stretch = fabsf(uvang - ang) / (float)M_PI;
- return 1.0f - pow2f(1.0f - stretch);
-#endif
-}
-
-static void extract_edituv_stretch_angle_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* Waning: adjust #UVStretchAngle struct accordingly. */
- GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-
- MeshExtract_StretchAngle_Data *data = tls_data;
- data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo);
-
- /* Special iterator needed to save about half of the computing cost. */
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
- }
- else {
- BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
- data->luv = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
- }
-}
-
-static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_StretchAngle_Data *data = _data;
- float(*auv)[2] = data->auv, *last_auv = data->last_auv;
- float(*av)[3] = data->av, *last_av = data->last_av;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
-
- const MLoopUV *luv, *luv_next;
- BMLoop *l_next = l_iter->next;
- if (l_iter == BM_FACE_FIRST_LOOP(f)) {
- /* First loop in face. */
- BMLoop *l_tmp = l_iter->prev;
- BMLoop *l_next_tmp = l_iter;
- luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
- luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
- compute_normalize_edge_vectors(auv,
- av,
- luv->uv,
- luv_next->uv,
- bm_vert_co_get(mr, l_tmp->v),
- bm_vert_co_get(mr, l_next_tmp->v));
- /* Save last edge. */
- copy_v2_v2(last_auv, auv[1]);
- copy_v3_v3(last_av, av[1]);
- }
- if (l_next == BM_FACE_FIRST_LOOP(f)) {
- /* Move previous edge. */
- copy_v2_v2(auv[0], auv[1]);
- copy_v3_v3(av[0], av[1]);
- /* Copy already calculated last edge. */
- copy_v2_v2(auv[1], last_auv);
- copy_v3_v3(av[1], last_av);
- }
- else {
- luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
- luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
- compute_normalize_edge_vectors(auv,
- av,
- luv->uv,
- luv_next->uv,
- bm_vert_co_get(mr, l_iter->v),
- bm_vert_co_get(mr, l_next->v));
- }
- edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]);
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *_data)
-{
- MeshExtract_StretchAngle_Data *data = _data;
-
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- float(*auv)[2] = data->auv, *last_auv = data->last_auv;
- float(*av)[3] = data->av, *last_av = data->last_av;
- int l_next = ml_index + 1;
- const MVert *v, *v_next;
- if (ml_index == mp->loopstart) {
- /* First loop in face. */
- const int ml_index_last = ml_index_end - 1;
- const int l_next_tmp = mp->loopstart;
- v = &mr->mvert[mr->mloop[ml_index_last].v];
- v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
- compute_normalize_edge_vectors(
- auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
- /* Save last edge. */
- copy_v2_v2(last_auv, auv[1]);
- copy_v3_v3(last_av, av[1]);
- }
- if (l_next == ml_index_end) {
- l_next = mp->loopstart;
- /* Move previous edge. */
- copy_v2_v2(auv[0], auv[1]);
- copy_v3_v3(av[0], av[1]);
- /* Copy already calculated last edge. */
- copy_v2_v2(auv[1], last_auv);
- copy_v3_v3(av[1], last_av);
- }
- else {
- v = &mr->mvert[mr->mloop[ml_index].v];
- v_next = &mr->mvert[mr->mloop[l_next].v];
- compute_normalize_edge_vectors(
- auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co);
- }
- edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]);
- }
-}
-
-const MeshExtract extract_edituv_stretch_angle = {
- .init = extract_edituv_stretch_angle_init,
- .iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm,
- .iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_StretchAngle_Data),
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Edit Mesh Analysis Colors
- * \{ */
-
-static void extract_mesh_analysis_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
-}
-
-static void axis_from_enum_v3(float v[3], const char axis)
-{
- zero_v3(v);
- if (axis < 3) {
- v[axis] = 1.0f;
- }
- else {
- v[axis - 3] = -1.0f;
- }
-}
-
-BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
-{
- if (fac < min) {
- fac = 1.0f;
- }
- else if (fac > max) {
- fac = -1.0f;
- }
- else {
- fac = (fac - min) * minmax_irange;
- fac = 1.0f - fac;
- CLAMP(fac, 0.0f, 1.0f);
- }
- return fac;
-}
-
-static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
-{
- const MeshStatVis *statvis = &mr->toolsettings->statvis;
- const float min = statvis->overhang_min / (float)M_PI;
- const float max = statvis->overhang_max / (float)M_PI;
- const char axis = statvis->overhang_axis;
- BMEditMesh *em = mr->edit_bmesh;
- BMIter iter;
- BMesh *bm = em->bm;
- BMFace *f;
- float dir[3];
- const float minmax_irange = 1.0f / (max - min);
-
- BLI_assert(min <= max);
-
- axis_from_enum_v3(dir, axis);
-
- /* now convert into global space */
- mul_transposed_mat3_m4_v3(mr->obmat, dir);
- normalize_v3(dir);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- int l_index = 0;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
- fac = overhang_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < f->len; i++, l_index++) {
- r_overhang[l_index] = fac;
- }
- }
- }
- else {
- const MPoly *mp = mr->mpoly;
- for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
- float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI;
- fac = overhang_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < mp->totloop; i++, l_index++) {
- r_overhang[l_index] = fac;
- }
- }
- }
-}
-
-/**
- * Needed so we can use jitter values for face interpolation.
- */
-static void uv_from_jitter_v2(float uv[2])
-{
- uv[0] += 0.5f;
- uv[1] += 0.5f;
- if (uv[0] + uv[1] > 1.0f) {
- uv[0] = 1.0f - uv[0];
- uv[1] = 1.0f - uv[1];
- }
-
- clamp_v2(uv, 0.0f, 1.0f);
-}
-
-BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
-{
- /* important not '<=' */
- if (fac < max) {
- fac = (fac - min) * minmax_irange;
- fac = 1.0f - fac;
- CLAMP(fac, 0.0f, 1.0f);
- }
- else {
- fac = -1.0f;
- }
- return fac;
-}
-
-static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
-{
- const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
- /* cheating to avoid another allocation */
- float *face_dists = r_thickness + (mr->loop_len - mr->poly_len);
- BMEditMesh *em = mr->edit_bmesh;
- const float scale = 1.0f / mat4_to_scale(mr->obmat);
- const MeshStatVis *statvis = &mr->toolsettings->statvis;
- const float min = statvis->thickness_min * scale;
- const float max = statvis->thickness_max * scale;
- const float minmax_irange = 1.0f / (max - min);
- const int samples = statvis->thickness_samples;
- float jit_ofs[32][2];
- BLI_assert(samples <= 32);
- BLI_assert(min <= max);
-
- copy_vn_fl(face_dists, mr->poly_len, max);
-
- BLI_jitter_init(jit_ofs, samples);
- for (int j = 0; j < samples; j++) {
- uv_from_jitter_v2(jit_ofs[j]);
- }
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMesh *bm = em->bm;
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, NULL, false);
- struct BMLoop *(*looptris)[3] = em->looptris;
- for (int i = 0; i < mr->tri_len; i++) {
- BMLoop **ltri = looptris[i];
- const int index = BM_elem_index_get(ltri[0]->f);
- const float *cos[3] = {
- bm_vert_co_get(mr, ltri[0]->v),
- bm_vert_co_get(mr, ltri[1]->v),
- bm_vert_co_get(mr, ltri[2]->v),
- };
- float ray_co[3];
- float ray_no[3];
-
- normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
-
- for (int j = 0; j < samples; j++) {
- float dist = face_dists[index];
- interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
- madd_v3_v3fl(ray_co, ray_no, eps_offset);
-
- BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, NULL, NULL);
- if (f_hit && dist < face_dists[index]) {
- float angle_fac = fabsf(
- dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit)));
- angle_fac = 1.0f - angle_fac;
- angle_fac = angle_fac * angle_fac * angle_fac;
- angle_fac = 1.0f - angle_fac;
- dist /= angle_fac;
- if (dist < face_dists[index]) {
- face_dists[index] = dist;
- }
- }
- }
- }
- BKE_bmbvh_free(bmtree);
-
- BMIter iter;
- BMFace *f;
- int l_index = 0;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- float fac = face_dists[BM_elem_index_get(f)];
- fac = thickness_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < f->len; i++, l_index++) {
- r_thickness[l_index] = fac;
- }
- }
- }
- else {
- BVHTreeFromMesh treeData = {NULL};
-
- BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
- const MLoopTri *mlooptri = mr->mlooptri;
- for (int i = 0; i < mr->tri_len; i++, mlooptri++) {
- const int index = mlooptri->poly;
- const float *cos[3] = {mr->mvert[mr->mloop[mlooptri->tri[0]].v].co,
- mr->mvert[mr->mloop[mlooptri->tri[1]].v].co,
- mr->mvert[mr->mloop[mlooptri->tri[2]].v].co};
- float ray_co[3];
- float ray_no[3];
-
- normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
-
- for (int j = 0; j < samples; j++) {
- interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
- madd_v3_v3fl(ray_co, ray_no, eps_offset);
-
- BVHTreeRayHit hit;
- hit.index = -1;
- hit.dist = face_dists[index];
- if ((BLI_bvhtree_ray_cast(
- tree, ray_co, ray_no, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) &&
- hit.dist < face_dists[index]) {
- float angle_fac = fabsf(dot_v3v3(mr->poly_normals[index], hit.no));
- angle_fac = 1.0f - angle_fac;
- angle_fac = angle_fac * angle_fac * angle_fac;
- angle_fac = 1.0f - angle_fac;
- hit.dist /= angle_fac;
- if (hit.dist < face_dists[index]) {
- face_dists[index] = hit.dist;
- }
- }
- }
- }
-
- const MPoly *mp = mr->mpoly;
- for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
- float fac = face_dists[mp_index];
- fac = thickness_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < mp->totloop; i++, l_index++) {
- r_thickness[l_index] = fac;
- }
- }
- }
-}
-
-struct BVHTree_OverlapData {
- const Mesh *me;
- const MLoopTri *mlooptri;
- float epsilon;
-};
-
-static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
-{
- struct BVHTree_OverlapData *data = userdata;
- const Mesh *me = data->me;
-
- const MLoopTri *tri_a = &data->mlooptri[index_a];
- const MLoopTri *tri_b = &data->mlooptri[index_b];
-
- if (UNLIKELY(tri_a->poly == tri_b->poly)) {
- return false;
- }
-
- const float *tri_a_co[3] = {me->mvert[me->mloop[tri_a->tri[0]].v].co,
- me->mvert[me->mloop[tri_a->tri[1]].v].co,
- me->mvert[me->mloop[tri_a->tri[2]].v].co};
- const float *tri_b_co[3] = {me->mvert[me->mloop[tri_b->tri[0]].v].co,
- me->mvert[me->mloop[tri_b->tri[1]].v].co,
- me->mvert[me->mloop[tri_b->tri[2]].v].co};
- float ix_pair[2][3];
- int verts_shared = 0;
-
- verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
- ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
-
- /* if 2 points are shared, bail out */
- if (verts_shared >= 2) {
- return false;
- }
-
- return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) &&
- /* if we share a vertex, check the intersection isn't a 'point' */
- ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
-}
-
-static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
-{
- BMEditMesh *em = mr->edit_bmesh;
-
- for (int l_index = 0; l_index < mr->loop_len; l_index++) {
- r_intersect[l_index] = -1.0f;
- }
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- uint overlap_len;
- BMesh *bm = em->bm;
-
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, NULL, false);
- BVHTreeOverlap *overlap = BKE_bmbvh_overlap_self(bmtree, &overlap_len);
-
- if (overlap) {
- for (int i = 0; i < overlap_len; i++) {
- BMFace *f_hit_pair[2] = {
- em->looptris[overlap[i].indexA][0]->f,
- em->looptris[overlap[i].indexB][0]->f,
- };
- for (int j = 0; j < 2; j++) {
- BMFace *f_hit = f_hit_pair[j];
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit);
- int l_index = BM_elem_index_get(l_first);
- for (int k = 0; k < f_hit->len; k++, l_index++) {
- r_intersect[l_index] = 1.0f;
- }
- }
- }
- MEM_freeN(overlap);
- }
-
- BKE_bmbvh_free(bmtree);
- }
- else {
- uint overlap_len;
- BVHTreeFromMesh treeData = {NULL};
-
- BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
-
- struct BVHTree_OverlapData data = {
- .me = mr->me, .mlooptri = mr->mlooptri, .epsilon = BLI_bvhtree_get_epsilon(tree)};
-
- BVHTreeOverlap *overlap = BLI_bvhtree_overlap(tree, tree, &overlap_len, bvh_overlap_cb, &data);
- if (overlap) {
- for (int i = 0; i < overlap_len; i++) {
- const MPoly *f_hit_pair[2] = {
- &mr->mpoly[mr->mlooptri[overlap[i].indexA].poly],
- &mr->mpoly[mr->mlooptri[overlap[i].indexB].poly],
- };
- for (int j = 0; j < 2; j++) {
- const MPoly *f_hit = f_hit_pair[j];
- int l_index = f_hit->loopstart;
- for (int k = 0; k < f_hit->totloop; k++, l_index++) {
- r_intersect[l_index] = 1.0f;
- }
- }
- }
- MEM_freeN(overlap);
- }
- }
-}
-
-BLI_INLINE float distort_remap(float fac, float min, float UNUSED(max), float minmax_irange)
-{
- if (fac >= min) {
- fac = (fac - min) * minmax_irange;
- CLAMP(fac, 0.0f, 1.0f);
- }
- else {
- /* fallback */
- fac = -1.0f;
- }
- return fac;
-}
-
-static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
-{
- BMEditMesh *em = mr->edit_bmesh;
- const MeshStatVis *statvis = &mr->toolsettings->statvis;
- const float min = statvis->distort_min;
- const float max = statvis->distort_max;
- const float minmax_irange = 1.0f / (max - min);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMIter iter;
- BMesh *bm = em->bm;
- BMFace *f;
-
- if (mr->bm_vert_coords != NULL) {
- BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data);
-
- /* Most likely this is already valid, ensure just in case.
- * Needed for #BM_loop_calc_face_normal_safe_vcos. */
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- }
-
- int l_index = 0;
- int f_index = 0;
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) {
- float fac = -1.0f;
-
- if (f->len > 3) {
- BMLoop *l_iter, *l_first;
-
- fac = 0.0f;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const float *no_face;
- float no_corner[3];
- if (mr->bm_vert_coords != NULL) {
- no_face = mr->bm_poly_normals[f_index];
- BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
- }
- else {
- no_face = f->no;
- BM_loop_calc_face_normal_safe(l_iter, no_corner);
- }
-
- /* simple way to detect (what is most likely) concave */
- if (dot_v3v3(no_face, no_corner) < 0.0f) {
- negate_v3(no_corner);
- }
- fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner));
-
- } while ((l_iter = l_iter->next) != l_first);
- fac *= 2.0f;
- }
-
- fac = distort_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < f->len; i++, l_index++) {
- r_distort[l_index] = fac;
- }
- }
- }
- else {
- const MPoly *mp = mr->mpoly;
- for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
- float fac = -1.0f;
-
- if (mp->totloop > 3) {
- float *f_no = mr->poly_normals[mp_index];
- fac = 0.0f;
-
- for (int i = 1; i <= mp->totloop; i++) {
- const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop];
- const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
- const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
- float no_corner[3];
- normal_tri_v3(no_corner,
- mr->mvert[l_prev->v].co,
- mr->mvert[l_curr->v].co,
- mr->mvert[l_next->v].co);
- /* simple way to detect (what is most likely) concave */
- if (dot_v3v3(f_no, no_corner) < 0.0f) {
- negate_v3(no_corner);
- }
- fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
- }
- fac *= 2.0f;
- }
-
- fac = distort_remap(fac, min, max, minmax_irange);
- for (int i = 0; i < mp->totloop; i++, l_index++) {
- r_distort[l_index] = fac;
- }
- }
- }
-}
-
-BLI_INLINE float sharp_remap(float fac, float min, float UNUSED(max), float minmax_irange)
-{
- /* important not '>=' */
- if (fac > min) {
- fac = (fac - min) * minmax_irange;
- CLAMP(fac, 0.0f, 1.0f);
- }
- else {
- /* fallback */
- fac = -1.0f;
- }
- return fac;
-}
-
-static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
-{
- BMEditMesh *em = mr->edit_bmesh;
- const MeshStatVis *statvis = &mr->toolsettings->statvis;
- const float min = statvis->sharp_min;
- const float max = statvis->sharp_max;
- const float minmax_irange = 1.0f / (max - min);
-
- /* Can we avoid this extra allocation? */
- float *vert_angles = MEM_mallocN(sizeof(float) * mr->vert_len, __func__);
- copy_vn_fl(vert_angles, mr->vert_len, -M_PI);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMIter iter;
- BMesh *bm = em->bm;
- BMFace *efa;
- BMEdge *e;
- /* first assign float values to verts */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- float angle = BM_edge_calc_face_angle_signed(e);
- float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
- float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
- *col1 = max_ff(*col1, angle);
- *col2 = max_ff(*col2, angle);
- }
- /* Copy vert value to loops. */
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- int l_index = BM_elem_index_get(l_iter);
- int v_index = BM_elem_index_get(l_iter->v);
- r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- else {
- /* first assign float values to verts */
- const MPoly *mp = mr->mpoly;
-
- EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len);
-
- for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
- for (int i = 0; i < mp->totloop; i++) {
- const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
- const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
- const MVert *v_curr = &mr->mvert[l_curr->v];
- const MVert *v_next = &mr->mvert[l_next->v];
- float angle;
- void **pval;
- bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
- if (!value_is_init) {
- *pval = mr->poly_normals[mp_index];
- /* non-manifold edge, yet... */
- continue;
- }
- if (*pval != NULL) {
- const float *f1_no = mr->poly_normals[mp_index];
- const float *f2_no = *pval;
- angle = angle_normalized_v3v3(f1_no, f2_no);
- angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle;
- /* Tag as manifold. */
- *pval = NULL;
- }
- else {
- /* non-manifold edge */
- angle = DEG2RADF(90.0f);
- }
- float *col1 = &vert_angles[l_curr->v];
- float *col2 = &vert_angles[l_next->v];
- *col1 = max_ff(*col1, angle);
- *col2 = max_ff(*col2, angle);
- }
- }
- /* Remaining non manifold edges. */
- EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- if (BLI_edgehashIterator_getValue(ehi) != NULL) {
- uint v1, v2;
- const float angle = DEG2RADF(90.0f);
- BLI_edgehashIterator_getKey(ehi, &v1, &v2);
- float *col1 = &vert_angles[v1];
- float *col2 = &vert_angles[v2];
- *col1 = max_ff(*col1, angle);
- *col2 = max_ff(*col2, angle);
- }
- }
- BLI_edgehashIterator_free(ehi);
- BLI_edgehash_free(eh, NULL);
-
- const MLoop *ml = mr->mloop;
- for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) {
- r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange);
- }
- }
-
- MEM_freeN(vert_angles);
-}
-
-static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(data))
-{
- GPUVertBuf *vbo = buf;
- BLI_assert(mr->edit_bmesh);
-
- float *l_weight = (float *)GPU_vertbuf_get_data(vbo);
-
- switch (mr->toolsettings->statvis.type) {
- case SCE_STATVIS_OVERHANG:
- statvis_calc_overhang(mr, l_weight);
- break;
- case SCE_STATVIS_THICKNESS:
- statvis_calc_thickness(mr, l_weight);
- break;
- case SCE_STATVIS_INTERSECT:
- statvis_calc_intersect(mr, l_weight);
- break;
- case SCE_STATVIS_DISTORT:
- statvis_calc_distort(mr, l_weight);
- break;
- case SCE_STATVIS_SHARP:
- statvis_calc_sharp(mr, l_weight);
- break;
- }
-}
-
-const MeshExtract extract_mesh_analysis = {
- .init = extract_mesh_analysis_init,
- .finish = extract_analysis_iter_finish_mesh,
- /* This is not needed for all visualization types.
- * * Maybe split into different extract. */
- .data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Face-dots positions
- * \{ */
-
-static void extract_fdots_pos_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->poly_len);
- *(float(**)[3])tls_data = GPU_vertbuf_get_data(vbo);
-}
-
-static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int f_index,
- void *data)
-{
- float(*center)[3] = *(float(**)[3])data;
-
- float *co = center[f_index];
- zero_v3(co);
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- add_v3_v3(co, bm_vert_co_get(mr, l_iter->v));
- } while ((l_iter = l_iter->next) != l_first);
- mul_v3_fl(co, 1.0f / (float)f->len);
-}
-
-static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *data)
-{
- float(*center)[3] = *(float(**)[3])data;
- float *co = center[mp_index];
- zero_v3(co);
-
- const MVert *mvert = mr->mvert;
- const MLoop *mloop = mr->mloop;
-
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- if (mr->use_subsurf_fdots) {
- const MVert *mv = &mr->mvert[ml->v];
- if (mv->flag & ME_VERT_FACEDOT) {
- copy_v3_v3(center[mp_index], mv->co);
- break;
- }
- }
- else {
- const MVert *mv = &mvert[ml->v];
- add_v3_v3(center[mp_index], mv->co);
- }
- }
-
- if (!mr->use_subsurf_fdots) {
- mul_v3_fl(co, 1.0f / (float)mp->totloop);
- }
-}
-
-const MeshExtract extract_fdots_pos = {
- .init = extract_fdots_pos_init,
- .iter_poly_bm = extract_fdots_pos_iter_poly_bm,
- .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(float (*)[3]),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Face-dots Normal and edit flag
- * \{ */
-#define NOR_AND_FLAG_DEFAULT 0
-#define NOR_AND_FLAG_SELECT 1
-#define NOR_AND_FLAG_ACTIVE -1
-#define NOR_AND_FLAG_HIDDEN -2
-
-static void extract_fdots_nor_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->poly_len);
-}
-
-static void extract_fdots_nor_finish(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(data))
-{
- GPUVertBuf *vbo = buf;
- static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
- GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo);
- BMFace *efa;
-
- /* Quicker than doing it for each loop. */
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- for (int f = 0; f < mr->poly_len; f++) {
- efa = BM_face_at_index(mr->bm, f);
- const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
- if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
- mr->p_origindex[f] == ORIGINDEX_NONE)) {
- nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
- nor[f].w = NOR_AND_FLAG_HIDDEN;
- }
- else {
- nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
- /* Select / Active Flag. */
- nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
- ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
- NOR_AND_FLAG_DEFAULT);
- }
- }
- }
- else {
- for (int f = 0; f < mr->poly_len; f++) {
- efa = bm_original_face_get(mr, f);
- const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
- if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
- mr->p_origindex[f] == ORIGINDEX_NONE)) {
- nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
- nor[f].w = NOR_AND_FLAG_HIDDEN;
- }
- else {
- nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
- /* Select / Active Flag. */
- nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
- ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
- NOR_AND_FLAG_DEFAULT);
- }
- }
- }
-}
-
-const MeshExtract extract_fdots_nor = {
- .init = extract_fdots_nor_init,
- .finish = extract_fdots_nor_finish,
- .data_type = MR_DATA_POLY_NOR,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Face-dots High Quality Normal and edit flag
- * \{ */
-static void extract_fdots_nor_hq_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->poly_len);
-}
-
-static void extract_fdots_nor_hq_finish(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(data))
-{
- GPUVertBuf *vbo = buf;
- static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
- short *nor = (short *)GPU_vertbuf_get_data(vbo);
- BMFace *efa;
-
- /* Quicker than doing it for each loop. */
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- for (int f = 0; f < mr->poly_len; f++) {
- efa = BM_face_at_index(mr->bm, f);
- const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
- if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
- mr->p_origindex[f] == ORIGINDEX_NONE)) {
- normal_float_to_short_v3(&nor[f * 4], invalid_normal);
- nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN;
- }
- else {
- normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa));
- /* Select / Active Flag. */
- nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
- ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
- NOR_AND_FLAG_DEFAULT);
- }
- }
- }
- else {
- for (int f = 0; f < mr->poly_len; f++) {
- efa = bm_original_face_get(mr, f);
- const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
- if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
- mr->p_origindex[f] == ORIGINDEX_NONE)) {
- normal_float_to_short_v3(&nor[f * 4], invalid_normal);
- nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN;
- }
- else {
- normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa));
- /* Select / Active Flag. */
- nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
- ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
- NOR_AND_FLAG_DEFAULT);
- }
- }
- }
-}
-
-const MeshExtract extract_fdots_nor_hq = {
- .init = extract_fdots_nor_hq_init,
- .finish = extract_fdots_nor_hq_finish,
- .data_type = MR_DATA_POLY_NOR,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Face-dots UV
- * \{ */
-
-typedef struct MeshExtract_FdotUV_Data {
- float (*vbo_data)[2];
- MLoopUV *uv_data;
- int cd_ofs;
-} MeshExtract_FdotUV_Data;
-
-static void extract_fdots_uv_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_vertformat_alias_add(&format, "au");
- GPU_vertformat_alias_add(&format, "pos");
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->poly_len);
-
- if (!mr->use_subsurf_fdots) {
- /* Clear so we can accumulate on it. */
- memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride);
- }
-
- MeshExtract_FdotUV_Data *data = tls_data;
- data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo);
-
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
- }
- else {
- data->uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
- }
-}
-
-static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_FdotUV_Data *data = _data;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- float w = 1.0f / (float)f->len;
- const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
- madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w);
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *_data)
-{
- MeshExtract_FdotUV_Data *data = _data;
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- if (mr->use_subsurf_fdots) {
- const MVert *mv = &mr->mvert[ml->v];
- if (mv->flag & ME_VERT_FACEDOT) {
- copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv);
- }
- }
- else {
- float w = 1.0f / (float)mp->totloop;
- madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w);
- }
- }
-}
-
-const MeshExtract extract_fdots_uv = {
- .init = extract_fdots_uv_init,
- .iter_poly_bm = extract_fdots_uv_iter_poly_bm,
- .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_FdotUV_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Face-dots Edit UV flag
- * \{ */
-
-typedef struct MeshExtract_EditUVFdotData_Data {
- EditLoopData *vbo_data;
- int cd_ofs;
-} MeshExtract_EditUVFdotData_Data;
-
-static void extract_fdots_edituv_data_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->poly_len);
-
- MeshExtract_EditUVFdotData_Data *data = tls_data;
- data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
- data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
-}
-
-static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
- const BMFace *f,
- const int UNUSED(f_index),
- void *_data)
-{
- MeshExtract_EditUVFdotData_Data *data = _data;
- EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)];
- memset(eldata, 0x0, sizeof(*eldata));
- mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
-}
-
-static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *UNUSED(mp),
- const int mp_index,
- void *_data)
-{
- MeshExtract_EditUVFdotData_Data *data = _data;
- EditLoopData *eldata = &data->vbo_data[mp_index];
- memset(eldata, 0x0, sizeof(*eldata));
- BMFace *efa = bm_original_face_get(mr, mp_index);
- if (efa) {
- mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
- }
-}
-
-const MeshExtract extract_fdots_edituv_data = {
- .init = extract_fdots_edituv_data_init,
- .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm,
- .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(MeshExtract_EditUVFdotData_Data),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Skin Modifier Roots
- * \{ */
-
-typedef struct SkinRootData {
- float size;
- float local_pos[3];
-} SkinRootData;
-
-static void extract_skin_roots_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *UNUSED(tls_data))
-{
- GPUVertBuf *vbo = buf;
- /* Exclusively for edit mode. */
- BLI_assert(mr->bm);
-
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->bm->totvert);
-
- SkinRootData *vbo_data = (SkinRootData *)GPU_vertbuf_get_data(vbo);
-
- int root_len = 0;
- int cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MVERT_SKIN);
-
- BMIter iter;
- BMVert *eve;
- BM_ITER_MESH (eve, &iter, mr->bm, BM_VERTS_OF_MESH) {
- const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_ofs);
- if (vs->flag & MVERT_SKIN_ROOT) {
- vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f;
- copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve));
- vbo_data++;
- root_len++;
- }
- }
-
- /* It's really unlikely that all verts will be roots. Resize to avoid losing VRAM. */
- GPU_vertbuf_data_len_set(vbo, root_len);
-}
-
-const MeshExtract extract_skin_roots = {
- .init = extract_skin_roots_init,
- .data_type = 0,
- .data_size = 0,
- .use_threading = false,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots)};
-
-/** \} */
-
-/* ---------------------------------------------------------------------- */
-/** \name Extract Selection Index
- * \{ */
-
-static void extract_select_idx_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* TODO rename "color" to something more descriptive. */
- GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
- }
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
- *(uint32_t **)tls_data = GPU_vertbuf_get_data(vbo);
-}
-
-/* TODO Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
- * select element associated with this loop ID. This would remove the need for this separate
- * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
- * shader to output original index. */
-
-static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *f,
- const int f_index,
- void *data)
-{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- (*(uint32_t **)data)[l_index] = f_index;
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *f,
- const int UNUSED(f_index),
- void *data)
-{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->e);
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *f,
- const int UNUSED(f_index),
- void *data)
-{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->v);
- } while ((l_iter = l_iter->next) != l_first);
-}
-
-static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr,
- const BMEdge *eed,
- const int ledge_index,
- void *data)
-{
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed);
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed);
-}
-
-static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr,
- const BMEdge *eed,
- const int ledge_index,
- void *data)
-{
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1);
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2);
-}
-
-static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr,
- const BMVert *eve,
- const int lvert_index,
- void *data)
-{
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- (*(uint32_t **)data)[offset + lvert_index] = BM_elem_index_get(eve);
-}
-
-static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int mp_index,
- void *data)
-{
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- (*(uint32_t **)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index;
- }
-}
-
-static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *data)
-{
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- (*(uint32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e;
- }
-}
-
-static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *mp,
- const int UNUSED(mp_index),
- void *data)
-{
- const MLoop *mloop = mr->mloop;
- const int ml_index_end = mp->loopstart + mp->totloop;
- for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
- const MLoop *ml = &mloop[ml_index];
- (*(uint32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v;
- }
-}
-
-static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr,
- const MEdge *UNUSED(med),
- const int ledge_index,
- void *data)
-{
- const int e_index = mr->ledges[ledge_index];
- const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index;
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig;
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig;
-}
-
-static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr,
- const MEdge *med,
- const int ledge_index,
- void *data)
-{
- int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1;
- int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2;
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig;
- (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig;
-}
-
-static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr,
- const MVert *UNUSED(mv),
- const int lvert_index,
- void *data)
-{
- const int offset = mr->loop_len + (mr->edge_loose_len * 2);
-
- const int v_index = mr->lverts[lvert_index];
- const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index;
- (*(uint32_t **)data)[offset + lvert_index] = v_orig;
-}
-
-const MeshExtract extract_poly_idx = {
- .init = extract_select_idx_init,
- .iter_poly_bm = extract_poly_idx_iter_poly_bm,
- .iter_poly_mesh = extract_poly_idx_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(uint32_t *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx)};
-
-const MeshExtract extract_edge_idx = {
- .init = extract_select_idx_init,
- .iter_poly_bm = extract_edge_idx_iter_poly_bm,
- .iter_poly_mesh = extract_edge_idx_iter_poly_mesh,
- .iter_ledge_bm = extract_edge_idx_iter_ledge_bm,
- .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh,
- .data_type = 0,
- .data_size = sizeof(uint32_t *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx)};
-
-const MeshExtract extract_vert_idx = {
- .init = extract_select_idx_init,
- .iter_poly_bm = extract_vert_idx_iter_poly_bm,
- .iter_poly_mesh = extract_vert_idx_iter_poly_mesh,
- .iter_ledge_bm = extract_vert_idx_iter_ledge_bm,
- .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh,
- .iter_lvert_bm = extract_vert_idx_iter_lvert_bm,
- .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh,
- .data_type = 0,
- .data_size = sizeof(uint32_t *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx)};
-
-static void extract_fdot_idx_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
-{
- GPUVertBuf *vbo = buf;
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* TODO rename "color" to something more descriptive. */
- GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->poly_len);
- *(uint32_t **)tls_data = GPU_vertbuf_get_data(vbo);
-}
-
-static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
- const BMFace *UNUSED(f),
- const int f_index,
- void *data)
-{
- (*(uint32_t **)data)[f_index] = f_index;
-}
-
-static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr,
- const MPoly *UNUSED(mp),
- const int mp_index,
- void *data)
-{
- if (mr->p_origindex != NULL) {
- (*(uint32_t **)data)[mp_index] = mr->p_origindex[mp_index];
- }
- else {
- (*(uint32_t **)data)[mp_index] = mp_index;
- }
-}
-
-const MeshExtract extract_fdot_idx = {
- .init = extract_fdot_idx_init,
- .iter_poly_bm = extract_fdot_idx_iter_poly_bm,
- .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh,
- .data_type = 0,
- .data_size = sizeof(uint32_t *),
- .use_threading = true,
- .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)};
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_private.h b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
index 1b4521335ec..5f670bdc5ec 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_private.h
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_private.h
@@ -30,6 +30,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "draw_cache_extract.h"
@@ -258,11 +259,30 @@ void mesh_render_data_update_looptris(MeshRenderData *mr,
const eMRDataType data_flag);
/* draw_cache_extract_mesh_extractors.c */
+typedef struct EditLoopData {
+ uchar v_flag;
+ uchar e_flag;
+ uchar crease;
+ uchar bweight;
+} EditLoopData;
+
void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc);
eMRIterType mesh_extract_iter_type(const MeshExtract *ext);
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
const bool do_hq_normals,
const bool do_single_mat);
+void mesh_render_data_face_flag(const MeshRenderData *mr,
+ const BMFace *efa,
+ const int cd_ofs,
+ EditLoopData *eattr);
+void mesh_render_data_loop_flag(const MeshRenderData *mr,
+ BMLoop *l,
+ const int cd_ofs,
+ EditLoopData *eattr);
+void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
+ BMLoop *l,
+ const int cd_ofs,
+ EditLoopData *eattr);
extern const MeshExtract extract_tris;
extern const MeshExtract extract_tris_single_mat;
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 5743f39f7da..220a7f37c3d 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -219,7 +219,7 @@ struct GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(struct Mesh *me);
struct GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu);
struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(struct Object *ob);
-int DRW_mesh_material_count_get(struct Mesh *me);
+int DRW_mesh_material_count_get(const struct Mesh *me);
/* See 'common_globals_lib.glsl' for duplicate defines. */
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc
index c4cd547ef43..51bd4c535cd 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curve.cc
@@ -363,7 +363,7 @@ static void curve_cd_calc_used_gpu_layers(CustomDataMask *cd_layers,
int type = gpu_attr->type;
/* Curves cannot have named layers.
- * Note: We could relax this assumption later. */
+ * NOTE: We could relax this assumption later. */
if (name[0] != '\0') {
continue;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 1d4f411c94d..1fed5d79697 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -365,7 +365,7 @@ static void surf_uv_quad(const DispList *dl, const uint quad[4], float r_uv[4][2
}
for (int i = 0; i < 4; i++) {
- /* Note: For some reason the shading U and V are swapped compared to the
+ /* NOTE: For some reason the shading U and V are swapped compared to the
* one described in the surface format. */
/* find uv based on vertex index into grid array */
r_uv[i][0] = (quad[i] / dl->nr) / (float)orco_sizev;
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index bea9ba1122b..336ccd40d5c 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -301,7 +301,7 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts,
int v,
bool is_endpoint)
{
- /* Note: we use the sign of strength and thickness to pass cap flag. */
+ /* NOTE: we use the sign of strength and thickness to pass cap flag. */
const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND);
const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND);
gpStrokeVert *vert = &verts[v];
@@ -422,7 +422,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.tri_len = 0,
.curve_len = 0,
};
- BKE_gpencil_visible_stroke_iter(
+ BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra);
/* Create VBOs. */
@@ -439,7 +439,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_advanced_iter(
+ NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
/* Mark last 2 verts as invalid. */
for (int i = 0; i < 2; i++) {
@@ -514,7 +515,7 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
/* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
bool do_onion = true;
- BKE_gpencil_visible_stroke_iter(
+ BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_lines_indices_cb, &iter, do_onion, cfra);
GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo);
@@ -843,8 +844,8 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
int vert_len = GPU_vertbuf_get_vertex_len(cache->vbo);
gpEditIterData iter;
- iter.vgindex = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, iter.vgindex)) {
+ iter.vgindex = gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gpd->vertex_group_names, iter.vgindex)) {
iter.vgindex = -1;
}
@@ -856,7 +857,7 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
iter.verts = (gpEditVert *)GPU_vertbuf_get_data(cache->edit_vbo);
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(
+ BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
/* Create the batches */
@@ -883,7 +884,7 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
cache->edit_curve_vbo = GPU_vertbuf_create_with_format(format);
/* Count data. */
- BKE_gpencil_visible_stroke_iter(
+ BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra);
gpEditCurveIterData iter;
@@ -894,7 +895,7 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
iter.verts = (gpEditCurveVert *)GPU_vertbuf_get_data(cache->edit_curve_vbo);
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(
+ BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra);
cache->edit_curve_handles_batch = GPU_batch_create(
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
index eabef49fa22..0a1c7d9581a 100644
--- a/source/blender/draw/intern/draw_cache_impl_lattice.c
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -84,7 +84,7 @@ static int lattice_render_verts_len_get(Lattice *lt)
return vert_len_calc(u, v, w);
}
- /* TODO remove internal coords */
+ /* TODO: remove internal coords. */
return vert_len_calc(u, v, w);
}
@@ -102,7 +102,7 @@ static int lattice_render_edges_len_get(Lattice *lt)
return edge_len_calc(u, v, w);
}
- /* TODO remove internal coords */
+ /* TODO: remove internal coords. */
return edge_len_calc(u, v, w);
}
@@ -305,7 +305,7 @@ void DRW_lattice_batch_cache_dirty_tag(Lattice *lt, int mode)
cache->is_dirty = true;
break;
case BKE_LATTICE_BATCH_DIRTY_SELECT:
- /* TODO Separate Flag vbo */
+ /* TODO: Separate Flag VBO. */
GPU_BATCH_DISCARD_SAFE(cache->overlay_verts);
break;
default:
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 33f8ec38a54..0c002ff09f2 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -544,8 +544,8 @@ static void drw_mesh_weight_state_extract(Object *ob,
/* Extract complete vertex weight group selection state and mode flags. */
memset(wstate, 0, sizeof(*wstate));
- wstate->defgroup_active = ob->actdef - 1;
- wstate->defgroup_len = BLI_listbase_count(&ob->defbase);
+ wstate->defgroup_active = me->vertex_group_active_index - 1;
+ wstate->defgroup_len = BLI_listbase_count(&me->vertex_group_names);
wstate->alert_mode = ts->weightuser;
@@ -821,6 +821,17 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
mesh_batch_cache_discard_shaded_tri(cache);
mesh_batch_cache_discard_uvedit(cache);
break;
+ case BKE_MESH_BATCH_DIRTY_DEFORM:
+ FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor);
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor);
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_pos);
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_nor);
+ GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.tris);
+ }
+ batch_map = MDEPS_CREATE_MAP(vbo.pos_nor, vbo.lnor, vbo.fdots_pos, vbo.fdots_nor, ibo.tris);
+ mesh_batch_cache_discard_batch(cache, batch_map);
+ break;
case BKE_MESH_BATCH_DIRTY_UVEDIT_ALL:
mesh_batch_cache_discard_uvedit(cache);
break;
@@ -1052,7 +1063,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me)
return cache->batch.surface;
}
-int DRW_mesh_material_count_get(Mesh *me)
+int DRW_mesh_material_count_get(const Mesh *me)
{
return mesh_render_mat_len_get(me);
}
@@ -1278,7 +1289,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Mesh *me)
* \{ */
/* Thread safety need to be assured by caller. Don't call this during drawing.
- * Note: For now this only free the shading batches / vbo if any cd layers is
+ * NOTE: For now this only free the shading batches / vbo if any cd layers is
* not needed anymore. */
void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
{
@@ -1305,7 +1316,7 @@ static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, M
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
/* Make sure all requested batches have been setup. */
- /* Note: The next line creates a different scheduling than during release builds what can lead to
+ /* NOTE: The next line creates a different scheduling than during release builds what can lead to
* some issues (See T77867 where we needed to disable this function in order to debug what was
* happening in release builds). */
BLI_task_graph_work_and_wait(task_graph);
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index ff969f920da..4d3a990ec72 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -140,7 +140,7 @@ static void metaball_batch_cache_clear(MetaBall *mb)
GPU_BATCH_DISCARD_SAFE(cache->edge_detection);
GPU_VERTBUF_DISCARD_SAFE(cache->pos_nor_in_order);
GPU_INDEXBUF_DISCARD_SAFE(cache->edges_adj_lines);
- /* Note: shaded_triangles[0] is already freed by cache->batch */
+ /* NOTE: shaded_triangles[0] is already freed by `cache->batch`. */
MEM_SAFE_FREE(cache->shaded_triangles);
cache->mat_len = 0;
cache->is_manifold = false;
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index a9febcedbf9..5c51f24a435 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -181,7 +181,7 @@ static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
{
- /* TODO more granular update tagging. */
+ /* TODO: more granular update tagging. */
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex);
@@ -560,7 +560,7 @@ static int particle_batch_cache_fill_segments(ParticleSystem *psys,
(is_simple && is_child) ? (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]);
}
for (int k = 0; k < num_col_layers; k++) {
- /* TODO Put the conversion outside the loop */
+ /* TODO: Put the conversion outside the loop. */
ushort scol[4];
particle_pack_mcol(
(is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
@@ -587,7 +587,7 @@ static int particle_batch_cache_fill_segments(ParticleSystem *psys,
uv[k]);
}
for (int k = 0; k < num_col_layers; k++) {
- /* TODO Put the conversion outside the loop */
+ /* TODO: Put the conversion outside the loop. */
ushort scol[4];
particle_pack_mcol((is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] :
&mcol[k],
@@ -1500,7 +1500,7 @@ static void particle_batch_cache_ensure_edit_pos_and_seg(PTCacheEdit *edit,
edit, particle, edit->pathcache, 0, edit->totcached, &elb, &data_step);
}
else {
- BLI_assert(!"Hairs are not in edit mode!");
+ BLI_assert_msg(0, "Hairs are not in edit mode!");
}
hair_cache->indices = GPU_indexbuf_build(&elb);
}
diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h
index 6e537a3bffa..b977d0cdda2 100644
--- a/source/blender/draw/intern/draw_cache_inline.h
+++ b/source/blender/draw/intern/draw_cache_inline.h
@@ -74,7 +74,7 @@ BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo)
{
- /* TODO do not rely on data uploaded. This prevents multithreading.
+ /* TODO: do not rely on data uploaded. This prevents multithreading.
* (need access to a gl context) */
return (ibo != NULL && !GPU_indexbuf_is_init(ibo));
}
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index d3a90ccfbd0..62d715460bb 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -192,7 +192,7 @@ void DRW_globals_update(void)
(max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f));
gb->sizeVertexGpencil = U.pixelsize * UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
gb->sizeFaceDot = U.pixelsize * UI_GetThemeValuef(TH_FACEDOT_SIZE);
- gb->sizeEdge = U.pixelsize * (1.0f / 2.0f); /* TODO Theme */
+ gb->sizeEdge = U.pixelsize * (1.0f / 2.0f); /* TODO: Theme. */
gb->sizeEdgeFix = U.pixelsize * (0.5f + 2.0f * (2.0f * (gb->sizeEdge * (float)M_SQRT1_2)));
const float(*screen_vecs)[3] = (float(*)[3])DRW_viewport_screenvecs_get();
@@ -210,7 +210,7 @@ void DRW_globals_update(void)
{
float *color = gb->UBO_FIRST_COLOR;
do {
- /* TODO more accurate transform. */
+ /* TODO: more accurate transform. */
srgb_to_linearrgb_v4(color, color);
color += 4;
} while (color <= gb->UBO_LAST_COLOR);
@@ -291,7 +291,7 @@ DRWView *DRW_view_create_with_zoffset(const DRWView *parent_view,
/* ******************************************** COLOR UTILS ************************************ */
-/* TODO FINISH */
+/* TODO: FINISH. */
/**
* Get the wire color theme_id of an object based on its state
* \a r_color is a way to get a pointer to the static color var associated
@@ -304,7 +304,7 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color
/* confusing logic here, there are 2 methods of setting the color
* 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
*
- * note: no theme yet for 'colindex' */
+ * NOTE: no theme yet for 'colindex'. */
int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
if (is_edit) {
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 7e6e1f03f8a..1eaf2bee236 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -35,7 +35,7 @@ struct ViewLayer;
/* Used as ubo but colors can be directly referenced as well */
/* Keep in sync with: common_globals_lib.glsl (globalsBlock) */
-/* NOTE! Also keep all color as vec4 and between UBO_FIRST_COLOR and UBO_LAST_COLOR */
+/* NOTE: Also keep all color as vec4 and between #UBO_FIRST_COLOR and #UBO_LAST_COLOR. */
typedef struct GlobalsUboStorage {
/* UBOs data needs to be 16 byte aligned (size of vec4) */
float colorWire[4];
@@ -141,7 +141,7 @@ typedef struct GlobalsUboStorage {
float colorUVShadow[4];
- /* NOTE! Put all color before UBO_LAST_COLOR */
+ /* NOTE: Put all color before #UBO_LAST_COLOR. */
float screenVecs[2][4]; /* Padded as vec4. */
float sizeViewport[2], sizeViewportInv[2]; /* Packed as vec4 in GLSL. */
diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c
index a21402e6392..9cfdbf7c688 100644
--- a/source/blender/draw/intern/draw_fluid.c
+++ b/source/blender/draw/intern/draw_fluid.c
@@ -589,7 +589,7 @@ void DRW_fluid_ensure_range_field(FluidModifierData *fmd)
#endif /* WITH_FLUID */
}
-/* TODO Unify with the other GPU_free_smoke. */
+/* TODO: Unify with the other #GPU_free_smoke. */
void DRW_smoke_free_velocity(FluidModifierData *fmd)
{
if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index d101df737ff..c2e25389091 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -197,7 +197,7 @@ static ParticleHairCache *drw_hair_particle_cache_get(
return cache;
}
-/* Note: Only valid after DRW_hair_update(). */
+/* NOTE: Only valid after DRW_hair_update(). */
GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -262,7 +262,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
- /* TODO optimize this. Only bind the ones GPUMaterial needs. */
+ /* TODO: optimize this. Only bind the ones GPUMaterial needs. */
for (int i = 0; i < hair_cache->num_uv_layers; i++) {
for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; n++) {
DRW_shgroup_uniform_texture(shgrp, hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index db64c7deb63..6f5e041fa79 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1645,7 +1645,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_draw_scene();
- /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
+ /* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See T56996, T61474) */
GPU_flush();
DRW_stats_reset();
@@ -2315,7 +2315,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) {
if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) {
- /* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */
+ /* NOTE: don't use "BKE_object_pose_armature_get" here, it breaks selection. */
Object *obpose = OBPOSE_FROM_OBACT(obact);
if (obpose == NULL) {
Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact);
@@ -3147,7 +3147,7 @@ void DRW_opengl_render_context_enable(void *re_gl_context)
/* If thread is main you should use DRW_opengl_context_enable(). */
BLI_assert(!BLI_thread_is_main());
- /* TODO get rid of the blocking. Only here because of the static global DST. */
+ /* TODO: get rid of the blocking. Only here because of the static global DST. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
WM_opengl_context_activate(re_gl_context);
}
@@ -3155,7 +3155,7 @@ void DRW_opengl_render_context_enable(void *re_gl_context)
void DRW_opengl_render_context_disable(void *re_gl_context)
{
WM_opengl_context_release(re_gl_context);
- /* TODO get rid of the blocking. */
+ /* TODO: get rid of the blocking. */
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
}
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 373b51a67e0..c4e8d0a980d 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -467,7 +467,7 @@ typedef struct DRWCommandSmallChunk {
uint32_t command_len;
uint32_t command_used;
/* 4bits for each command. */
- /* TODO reduce size of command_type. */
+ /* TODO: reduce size of command_type. */
uint64_t command_type[6];
DRWCommand commands[6];
} DRWCommandSmallChunk;
@@ -498,7 +498,7 @@ typedef struct DRWDebugSphere {
#define STENCIL_UNDEFINED 256
#define DRW_DRAWLIST_LEN 256
typedef struct DRWManager {
- /* TODO clean up this struct a bit */
+ /* TODO: clean up this struct a bit. */
/* Cache generation */
ViewportMemoryPool *vmempool;
DRWInstanceDataList *idatalist;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 5eedca4507e..0a0e1ba9ac3 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -94,7 +94,7 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
int ubo_len = 1 + chunk_id - ((elem_id == 0) ? 1 : 0);
size_t list_size = sizeof(GPUUniformBuf *) * ubo_len;
- /* TODO find a better system. currently a lot of obinfos UBO are going to be unused
+ /* TODO: find a better system. currently a lot of obinfos UBO are going to be unused
* if not rendering with Eevee. */
if (vmempool->matrices_ubo == NULL) {
@@ -782,7 +782,7 @@ static void drw_command_set_mutable_state(DRWShadingGroup *shgroup,
DRWState enable,
DRWState disable)
{
- /* TODO Restrict what state can be changed. */
+ /* TODO: Restrict what state can be changed. */
DRWCommandSetMutableState *cmd = drw_command_create(shgroup, DRW_CMD_DRWSTATE);
cmd->enable = enable;
cmd->disable = disable;
@@ -1263,7 +1263,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1);
}
else {
- /* Note: This is only here to support old hardware fallback where uniform buffer is still
+ /* NOTE: This is only here to support old hardware fallback where uniform buffer is still
* too slow or buggy. */
int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
@@ -1456,7 +1456,7 @@ void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
drw_command_set_stencil_mask(shgroup, write_mask, reference, compare_mask);
}
-/* TODO remove this function. */
+/* TODO: remove this function. */
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
{
drw_command_set_stencil_mask(shgroup, 0xFF, mask, 0xFF);
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index f29caebeb84..7f7696d485c 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -225,7 +225,7 @@ void drw_state_set(DRWState state)
GPU_shadow_offset(false);
}
- /* TODO this should be part of shader state. */
+ /* TODO: this should be part of shader state. */
if (state & DRW_STATE_CLIP_PLANES) {
GPU_clip_distances(DST.view_active->clip_planes_len);
}
@@ -383,10 +383,10 @@ static bool draw_culling_sphere_test(const BoundSphere *frustum_bsphere,
if (center_dist_sq > square_f(radius_sum)) {
return false;
}
- /* TODO we could test against the inscribed sphere of the frustum to early out positively. */
+ /* TODO: we could test against the inscribed sphere of the frustum to early out positively. */
/* Test against the 6 frustum planes. */
- /* TODO order planes with sides first then far then near clip. Should be better culling
+ /* TODO: order planes with sides first then far then near clip. Should be better culling
* heuristic when sculpting. */
for (int p = 0; p < 6; p++) {
float dist = plane_point_side_v3(frustum_planes[p], bsphere->center);
@@ -701,7 +701,7 @@ BLI_INLINE void draw_select_buffer(DRWShadingGroup *shgroup,
int count = 1;
int tot = is_instancing ? GPU_vertbuf_get_vertex_len(batch->inst[0]) :
GPU_vertbuf_get_vertex_len(batch->verts[0]);
- /* Hack : get "vbo" data without actually drawing. */
+ /* HACK: get VBO data without actually drawing. */
int *select_id = (void *)GPU_vertbuf_get_data(state->select_buf);
/* Batching */
@@ -818,7 +818,7 @@ static void draw_call_single_do(DRWShadingGroup *shgroup,
draw_call_resource_bind(state, &handle);
- /* TODO This is Legacy. Need to be removed. */
+ /* TODO: This is Legacy. Need to be removed. */
if (state->obmats_loc == -1 && (state->obmat_loc != -1 || state->obinv_loc != -1)) {
draw_legacy_matrix_update(shgroup, &handle, state->obmat_loc, state->obinv_loc);
}
@@ -1076,7 +1076,7 @@ static void drw_update_view(void)
/* TODO(fclem): update a big UBO and only bind ranges here. */
GPU_uniformbuf_update(G_draw.view_ubo, &DST.view_active->storage);
- /* TODO get rid of this. */
+ /* TODO: get rid of this. */
DST.view_storage_cpy = DST.view_active->storage;
draw_compute_culling(DST.view_active);
diff --git a/source/blender/draw/intern/draw_shader.c b/source/blender/draw/intern/draw_shader.c
index 9c756065353..121a0acd059 100644
--- a/source/blender/draw/intern/draw_shader.c
+++ b/source/blender/draw/intern/draw_shader.c
@@ -104,7 +104,7 @@ GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
sh = hair_refine_shader_transform_feedback_workaround_create(refinement);
break;
default:
- BLI_assert(!"Incorrect shader type");
+ BLI_assert_msg(0, "Incorrect shader type");
}
e_data.hair_refine_sh[refinement] = sh;
}
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 2fb44d0030b..ae2c66881ff 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -266,7 +266,7 @@ void DRW_draw_gizmo_3d(void)
ARegion *region = draw_ctx->region;
/* draw depth culled gizmos - gizmos need to be updated *after* view matrix was set up */
- /* TODO depth culling gizmos is not yet supported, just drawing _3D here, should
+ /* TODO: depth culling gizmos is not yet supported, just drawing _3D here, should
* later become _IN_SCENE (and draw _3D separate) */
WM_gizmomap_draw(region->gizmo_map, draw_ctx->evil_C, WM_GIZMOMAP_DRAWSTEP_3D);
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
index 43ad28c2618..bdb9af1faf3 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
@@ -89,7 +89,7 @@ BLI_INLINE void lines_adjacency_triangle(
*pval = POINTER_FROM_INT(NO_EDGE);
bool inv_opposite = (v_data < 0);
uint l_opposite = (uint)abs(v_data) - 1;
- /* TODO Make this part thread-safe. */
+ /* TODO: Make this part thread-safe. */
if (inv_opposite == inv_indices) {
/* Don't share edge if triangles have non matching winding. */
GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1);
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
new file mode 100644
index 00000000000..1bc4c7e330f
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
@@ -0,0 +1,241 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_capabilities.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edge Factor
+ * Defines how much an edge is visible.
+ * \{ */
+
+struct MeshExtract_EdgeFac_Data {
+ uchar *vbo_data;
+ bool use_edge_render;
+ /* Number of loop per edge. */
+ uchar *edge_loop_count;
+};
+
+static float loop_edge_factor_get(const float f_no[3],
+ const float v_co[3],
+ const float v_no[3],
+ const float v_next_co[3])
+{
+ float enor[3], evec[3];
+ sub_v3_v3v3(evec, v_next_co, v_co);
+ cross_v3_v3v3(enor, v_no, evec);
+ normalize_v3(enor);
+ float d = fabsf(dot_v3v3(enor, f_no));
+ /* Re-scale to the slider range. */
+ d *= (1.0f / 0.065f);
+ CLAMP(d, 0.0f, 1.0f);
+ return d;
+}
+
+static void extract_edge_fac_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
+
+ MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(tls_data);
+
+ if (mr->extract_type == MR_EXTRACT_MESH) {
+ data->edge_loop_count = static_cast<uchar *>(
+ MEM_callocN(sizeof(uint32_t) * mr->edge_len, __func__));
+
+ /* HACK(fclem) Detecting the need for edge render.
+ * We could have a flag in the mesh instead or check the modifier stack. */
+ const MEdge *med = mr->medge;
+ for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) {
+ if ((med->flag & ME_EDGERENDER) == 0) {
+ data->use_edge_render = true;
+ break;
+ }
+ }
+ }
+ else {
+ /* HACK to bypass non-manifold check in mesh_edge_fac_finish(). */
+ data->use_edge_render = true;
+ }
+
+ data->vbo_data = static_cast<uchar *>(GPU_vertbuf_get_data(vbo));
+}
+
+static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
+ if (BM_edge_is_manifold(l_iter->e)) {
+ float ratio = loop_edge_factor_get(bm_face_no_get(mr, f),
+ bm_vert_co_get(mr, l_iter->v),
+ bm_vert_no_get(mr, l_iter->v),
+ bm_vert_co_get(mr, l_iter->next->v));
+ data->vbo_data[l_index] = ratio * 253 + 1;
+ }
+ else {
+ data->vbo_data[l_index] = 255;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *_data)
+{
+ MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data);
+
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
+ if (data->use_edge_render) {
+ const MEdge *med = &mr->medge[ml->e];
+ data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0;
+ }
+ else {
+
+ /* Count loop per edge to detect non-manifold. */
+ if (data->edge_loop_count[ml->e] < 3) {
+ data->edge_loop_count[ml->e]++;
+ }
+ if (data->edge_loop_count[ml->e] == 2) {
+ /* Manifold */
+ const int ml_index_last = mp->totloop + mp->loopstart - 1;
+ const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
+ const MLoop *ml_next = &mr->mloop[ml_index_other];
+ const MVert *v1 = &mr->mvert[ml->v];
+ const MVert *v2 = &mr->mvert[ml_next->v];
+ float vnor_f[3];
+ normal_short_to_float_v3(vnor_f, v1->no);
+ float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co);
+ data->vbo_data[ml_index] = ratio * 253 + 1;
+ }
+ else {
+ /* Non-manifold */
+ data->vbo_data[ml_index] = 255;
+ }
+ }
+ }
+}
+
+static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr,
+ const BMEdge *UNUSED(eed),
+ const int ledge_index,
+ void *_data)
+{
+ MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data);
+ data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255;
+ data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255;
+}
+
+static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr,
+ const MEdge *UNUSED(med),
+ const int ledge_index,
+ void *_data)
+{
+ MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data);
+
+ data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255;
+ data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255;
+}
+
+static void extract_edge_fac_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data);
+
+ if (GPU_crappy_amd_driver()) {
+ /* Some AMD drivers strangely crash with VBO's with a one byte format.
+ * To workaround we reinitialize the VBO with another format and convert
+ * all bytes to floats. */
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+ /* We keep the data reference in data->vbo_data. */
+ data->vbo_data = static_cast<uchar *>(GPU_vertbuf_steal_data(vbo));
+ GPU_vertbuf_clear(vbo);
+
+ int buf_len = mr->loop_len + mr->loop_loose_len;
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, buf_len);
+
+ float *fdata = (float *)GPU_vertbuf_get_data(vbo);
+ for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) {
+ *fdata = data->vbo_data[ml_index] / 255.0f;
+ }
+ /* Free old byte data. */
+ MEM_freeN(data->vbo_data);
+ }
+ MEM_SAFE_FREE(data->edge_loop_count);
+}
+
+constexpr MeshExtract create_extractor_edge_fac()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_edge_fac_init;
+ extractor.iter_poly_bm = extract_edge_fac_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_edge_fac_iter_poly_mesh;
+ extractor.iter_ledge_bm = extract_edge_fac_iter_ledge_bm;
+ extractor.iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh;
+ extractor.finish = extract_edge_fac_finish;
+ extractor.data_type = MR_DATA_POLY_NOR;
+ extractor.data_size = sizeof(MeshExtract_EdgeFac_Data);
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_edge_fac = blender::draw::create_extractor_edge_fac();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
new file mode 100644
index 00000000000..ff250a30ec4
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
@@ -0,0 +1,265 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+#include "draw_cache_impl.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edit Mode Data / Flags
+ * \{ */
+
+static void mesh_render_data_edge_flag(const MeshRenderData *mr,
+ const BMEdge *eed,
+ EditLoopData *eattr)
+{
+ const ToolSettings *ts = mr->toolsettings;
+ const bool is_vertex_select_mode = (ts != nullptr) && (ts->selectmode & SCE_SELECT_VERTEX) != 0;
+ const bool is_face_only_select_mode = (ts != nullptr) && (ts->selectmode == SCE_SELECT_FACE);
+
+ if (eed == mr->eed_act) {
+ eattr->e_flag |= VFLAG_EDGE_ACTIVE;
+ }
+ if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ eattr->e_flag |= VFLAG_EDGE_SELECTED;
+ }
+ if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) {
+ eattr->e_flag |= VFLAG_EDGE_SELECTED;
+ eattr->e_flag |= VFLAG_VERT_SELECTED;
+ }
+ if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
+ eattr->e_flag |= VFLAG_EDGE_SEAM;
+ }
+ if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) {
+ eattr->e_flag |= VFLAG_EDGE_SHARP;
+ }
+
+ /* Use active edge color for active face edges because
+ * specular highlights make it hard to see T55456#510873.
+ *
+ * This isn't ideal since it can't be used when mixing edge/face modes
+ * but it's still better than not being able to see the active face. */
+ if (is_face_only_select_mode) {
+ if (mr->efa_act != nullptr) {
+ if (BM_edge_in_face(eed, mr->efa_act)) {
+ eattr->e_flag |= VFLAG_EDGE_ACTIVE;
+ }
+ }
+ }
+
+ /* Use a byte for value range */
+ if (mr->crease_ofs != -1) {
+ float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs);
+ if (crease > 0) {
+ eattr->crease = (uchar)(crease * 255.0f);
+ }
+ }
+ /* Use a byte for value range */
+ if (mr->bweight_ofs != -1) {
+ float bweight = BM_ELEM_CD_GET_FLOAT(eed, mr->bweight_ofs);
+ if (bweight > 0) {
+ eattr->bweight = (uchar)(bweight * 255.0f);
+ }
+ }
+#ifdef WITH_FREESTYLE
+ if (mr->freestyle_edge_ofs != -1) {
+ const FreestyleEdge *fed = (const FreestyleEdge *)BM_ELEM_CD_GET_VOID_P(
+ eed, mr->freestyle_edge_ofs);
+ if (fed->flag & FREESTYLE_EDGE_MARK) {
+ eattr->e_flag |= VFLAG_EDGE_FREESTYLE;
+ }
+ }
+#endif
+}
+
+static void mesh_render_data_vert_flag(const MeshRenderData *mr,
+ const BMVert *eve,
+ EditLoopData *eattr)
+{
+ if (eve == mr->eve_act) {
+ eattr->e_flag |= VFLAG_VERT_ACTIVE;
+ }
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ eattr->e_flag |= VFLAG_VERT_SELECTED;
+ }
+}
+
+static void extract_edit_data_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* WARNING: Adjust #EditLoopData struct accordingly. */
+ GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
+ GPU_vertformat_alias_add(&format, "flag");
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
+ EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
+ *(EditLoopData **)tls_data = vbo_data;
+}
+
+static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
+ EditLoopData *data = vbo_data + l_index;
+ memset(data, 0x0, sizeof(*data));
+ mesh_render_data_face_flag(mr, f, -1, data);
+ mesh_render_data_edge_flag(mr, l_iter->e, data);
+ mesh_render_data_vert_flag(mr, l_iter->v, data);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *_data)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ EditLoopData *data = vbo_data + ml_index;
+ memset(data, 0x0, sizeof(*data));
+ BMFace *efa = bm_original_face_get(mr, mp_index);
+ BMEdge *eed = bm_original_edge_get(mr, ml->e);
+ BMVert *eve = bm_original_vert_get(mr, ml->v);
+ if (efa) {
+ mesh_render_data_face_flag(mr, efa, -1, data);
+ }
+ if (eed) {
+ mesh_render_data_edge_flag(mr, eed, data);
+ }
+ if (eve) {
+ mesh_render_data_vert_flag(mr, eve, data);
+ }
+ }
+}
+
+static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr,
+ const BMEdge *eed,
+ const int ledge_index,
+ void *_data)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+ EditLoopData *data = vbo_data + mr->loop_len + (ledge_index * 2);
+ memset(data, 0x0, sizeof(*data) * 2);
+ mesh_render_data_edge_flag(mr, eed, &data[0]);
+ data[1] = data[0];
+ mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
+ mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
+}
+
+static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr,
+ const MEdge *med,
+ const int ledge_index,
+ void *_data)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+ EditLoopData *data = vbo_data + mr->loop_len + ledge_index * 2;
+ memset(data, 0x0, sizeof(*data) * 2);
+ const int e_index = mr->ledges[ledge_index];
+ BMEdge *eed = bm_original_edge_get(mr, e_index);
+ BMVert *eve1 = bm_original_vert_get(mr, med->v1);
+ BMVert *eve2 = bm_original_vert_get(mr, med->v2);
+ if (eed) {
+ mesh_render_data_edge_flag(mr, eed, &data[0]);
+ data[1] = data[0];
+ }
+ if (eve1) {
+ mesh_render_data_vert_flag(mr, eve1, &data[0]);
+ }
+ if (eve2) {
+ mesh_render_data_vert_flag(mr, eve2, &data[1]);
+ }
+}
+
+static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr,
+ const BMVert *eve,
+ const int lvert_index,
+ void *_data)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+ EditLoopData *data = vbo_data + offset + lvert_index;
+ memset(data, 0x0, sizeof(*data));
+ mesh_render_data_vert_flag(mr, eve, data);
+}
+
+static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
+ const MVert *UNUSED(mv),
+ const int lvert_index,
+ void *_data)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ EditLoopData *data = vbo_data + offset + lvert_index;
+ memset(data, 0x0, sizeof(*data));
+ const int v_index = mr->lverts[lvert_index];
+ BMVert *eve = bm_original_vert_get(mr, v_index);
+ if (eve) {
+ mesh_render_data_vert_flag(mr, eve, data);
+ }
+}
+
+constexpr MeshExtract create_extractor_edit_data()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_edit_data_init;
+ extractor.iter_poly_bm = extract_edit_data_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_edit_data_iter_poly_mesh;
+ extractor.iter_ledge_bm = extract_edit_data_iter_ledge_bm;
+ extractor.iter_ledge_mesh = extract_edit_data_iter_ledge_mesh;
+ extractor.iter_lvert_bm = extract_edit_data_iter_lvert_bm;
+ extractor.iter_lvert_mesh = extract_edit_data_iter_lvert_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(EditLoopData *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_edit_data = blender::draw::create_extractor_edit_data();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
new file mode 100644
index 00000000000..aa58266d56b
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
@@ -0,0 +1,140 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+#include "draw_cache_impl.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edit UV Data / Flags
+ * \{ */
+
+struct MeshExtract_EditUVData_Data {
+ EditLoopData *vbo_data;
+ int cd_ofs;
+};
+
+static void extract_edituv_data_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* WARNING: Adjust #EditLoopData struct accordingly. */
+ GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
+ GPU_vertformat_alias_add(&format, "flag");
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+
+ MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data);
+ data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
+ data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
+}
+
+static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
+ EditLoopData *eldata = &data->vbo_data[l_index];
+ memset(eldata, 0x0, sizeof(*eldata));
+ mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata);
+ mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
+ mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *_data)
+{
+ MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
+ EditLoopData *eldata = &data->vbo_data[ml_index];
+ memset(eldata, 0x0, sizeof(*eldata));
+ BMFace *efa = bm_original_face_get(mr, mp_index);
+ if (efa) {
+ BMEdge *eed = bm_original_edge_get(mr, ml->e);
+ BMVert *eve = bm_original_vert_get(mr, ml->v);
+ if (eed && eve) {
+ /* Loop on an edge endpoint. */
+ BMLoop *l = BM_face_edge_share_loop(efa, eed);
+ mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
+ mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
+ }
+ else {
+ if (eed == nullptr) {
+ /* Find if the loop's vert is not part of an edit edge.
+ * For this, we check if the previous loop was on an edge. */
+ const int ml_index_last = mp->loopstart + mp->totloop - 1;
+ const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1);
+ const MLoop *ml_prev = &mr->mloop[l_prev];
+ eed = bm_original_edge_get(mr, ml_prev->e);
+ }
+ if (eed) {
+ /* Mapped points on an edge between two edit verts. */
+ BMLoop *l = BM_face_edge_share_loop(efa, eed);
+ mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
+ }
+ }
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_edituv_data()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_edituv_data_init;
+ extractor.iter_poly_bm = extract_edituv_data_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_edituv_data_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_EditUVData_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_edituv_data = blender::draw::create_extractor_edituv_data();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
new file mode 100644
index 00000000000..1d62637d172
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
@@ -0,0 +1,236 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_mesh.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edit UV angle stretch
+ * \{ */
+
+struct UVStretchAngle {
+ int16_t angle;
+ int16_t uv_angles[2];
+};
+
+struct MeshExtract_StretchAngle_Data {
+ UVStretchAngle *vbo_data;
+ MLoopUV *luv;
+ float auv[2][2], last_auv[2];
+ float av[2][3], last_av[3];
+ int cd_ofs;
+};
+
+static void compute_normalize_edge_vectors(float auv[2][2],
+ float av[2][3],
+ const float uv[2],
+ const float uv_prev[2],
+ const float co[3],
+ const float co_prev[3])
+{
+ /* Move previous edge. */
+ copy_v2_v2(auv[0], auv[1]);
+ copy_v3_v3(av[0], av[1]);
+ /* 2d edge */
+ sub_v2_v2v2(auv[1], uv_prev, uv);
+ normalize_v2(auv[1]);
+ /* 3d edge */
+ sub_v3_v3v3(av[1], co_prev, co);
+ normalize_v3(av[1]);
+}
+
+static short v2_to_short_angle(const float v[2])
+{
+ return atan2f(v[1], v[0]) * (float)M_1_PI * SHRT_MAX;
+}
+
+static void edituv_get_edituv_stretch_angle(float auv[2][2],
+ const float av[2][3],
+ UVStretchAngle *r_stretch)
+{
+ /* Send UV's to the shader and let it compute the aspect corrected angle. */
+ r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]);
+ r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]);
+ /* Compute 3D angle here. */
+ r_stretch->angle = angle_normalized_v3v3(av[0], av[1]) * (float)M_1_PI * SHRT_MAX;
+
+#if 0 /* here for reference, this is done in shader now. */
+ float uvang = angle_normalized_v2v2(auv0, auv1);
+ float ang = angle_normalized_v3v3(av0, av1);
+ float stretch = fabsf(uvang - ang) / (float)M_PI;
+ return 1.0f - pow2f(1.0f - stretch);
+#endif
+}
+
+static void extract_edituv_stretch_angle_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* Waning: adjust #UVStretchAngle struct accordingly. */
+ GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ MeshExtract_StretchAngle_Data *data = static_cast<MeshExtract_StretchAngle_Data *>(tls_data);
+ data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo);
+
+ /* Special iterator needed to save about half of the computing cost. */
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
+ }
+ else {
+ BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
+ data->luv = (MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
+ }
+}
+
+static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_StretchAngle_Data *data = static_cast<MeshExtract_StretchAngle_Data *>(_data);
+ float(*auv)[2] = data->auv, *last_auv = data->last_auv;
+ float(*av)[3] = data->av, *last_av = data->last_av;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+
+ const MLoopUV *luv, *luv_next;
+ BMLoop *l_next = l_iter->next;
+ if (l_iter == BM_FACE_FIRST_LOOP(f)) {
+ /* First loop in face. */
+ BMLoop *l_tmp = l_iter->prev;
+ BMLoop *l_next_tmp = l_iter;
+ luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
+ luv_next = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, l_tmp->v),
+ bm_vert_co_get(mr, l_next_tmp->v));
+ /* Save last edge. */
+ copy_v2_v2(last_auv, auv[1]);
+ copy_v3_v3(last_av, av[1]);
+ }
+ if (l_next == BM_FACE_FIRST_LOOP(f)) {
+ /* Move previous edge. */
+ copy_v2_v2(auv[0], auv[1]);
+ copy_v3_v3(av[0], av[1]);
+ /* Copy already calculated last edge. */
+ copy_v2_v2(auv[1], last_auv);
+ copy_v3_v3(av[1], last_av);
+ }
+ else {
+ luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
+ luv_next = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, l_iter->v),
+ bm_vert_co_get(mr, l_next->v));
+ }
+ edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *_data)
+{
+ MeshExtract_StretchAngle_Data *data = static_cast<MeshExtract_StretchAngle_Data *>(_data);
+
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ float(*auv)[2] = data->auv, *last_auv = data->last_auv;
+ float(*av)[3] = data->av, *last_av = data->last_av;
+ int l_next = ml_index + 1;
+ const MVert *v, *v_next;
+ if (ml_index == mp->loopstart) {
+ /* First loop in face. */
+ const int ml_index_last = ml_index_end - 1;
+ const int l_next_tmp = mp->loopstart;
+ v = &mr->mvert[mr->mloop[ml_index_last].v];
+ v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
+ compute_normalize_edge_vectors(
+ auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
+ /* Save last edge. */
+ copy_v2_v2(last_auv, auv[1]);
+ copy_v3_v3(last_av, av[1]);
+ }
+ if (l_next == ml_index_end) {
+ l_next = mp->loopstart;
+ /* Move previous edge. */
+ copy_v2_v2(auv[0], auv[1]);
+ copy_v3_v3(av[0], av[1]);
+ /* Copy already calculated last edge. */
+ copy_v2_v2(auv[1], last_auv);
+ copy_v3_v3(av[1], last_av);
+ }
+ else {
+ v = &mr->mvert[mr->mloop[ml_index].v];
+ v_next = &mr->mvert[mr->mloop[l_next].v];
+ compute_normalize_edge_vectors(
+ auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co);
+ }
+ edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]);
+ }
+}
+
+constexpr MeshExtract create_extractor_edituv_edituv_stretch_angle()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_edituv_stretch_angle_init;
+ extractor.iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_StretchAngle_Data);
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_edituv_stretch_angle =
+ blender::draw::create_extractor_edituv_edituv_stretch_angle();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
new file mode 100644
index 00000000000..16814653408
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
@@ -0,0 +1,157 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_mesh.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edit UV area stretch
+ * \{ */
+
+static void extract_edituv_stretch_area_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+}
+
+BLI_INLINE float area_ratio_get(float area, float uvarea)
+{
+ if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) {
+ /* Tag inversion by using the sign. */
+ return (area > uvarea) ? (uvarea / area) : -(area / uvarea);
+ }
+ return 0.0f;
+}
+
+BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio)
+{
+ ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio;
+ return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
+}
+
+static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ float tot_area = 0.0f, tot_uv_area = 0.0f;
+ float *area_ratio = static_cast<float *>(MEM_mallocN(sizeof(float) * mr->poly_len, __func__));
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ CustomData *cd_ldata = &mr->bm->ldata;
+ int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
+
+ BMFace *efa;
+ BMIter f_iter;
+ int f;
+ BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
+ float area = BM_face_calc_area(efa);
+ float uvarea = BM_face_calc_area_uv(efa, uv_ofs);
+ tot_area += area;
+ tot_uv_area += uvarea;
+ area_ratio[f] = area_ratio_get(area, uvarea);
+ }
+ }
+ else {
+ BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
+ const MLoopUV *uv_data = (const MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert);
+ float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
+ tot_area += area;
+ tot_uv_area += uvarea;
+ area_ratio[mp_index] = area_ratio_get(area, uvarea);
+ }
+ }
+
+ cache->tot_area = tot_area;
+ cache->tot_uv_area = tot_uv_area;
+
+ /* Convert in place to avoid an extra allocation */
+ uint16_t *poly_stretch = (uint16_t *)area_ratio;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
+ poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX;
+ }
+
+ /* Copy face data for each loop. */
+ uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMFace *efa;
+ BMIter f_iter;
+ int f, l_index = 0;
+ BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
+ for (int i = 0; i < efa->len; i++, l_index++) {
+ loop_stretch[l_index] = poly_stretch[f];
+ }
+ }
+ }
+ else {
+ BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH));
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ loop_stretch[l_index] = poly_stretch[mp_index];
+ }
+ }
+ }
+
+ MEM_freeN(area_ratio);
+}
+
+constexpr MeshExtract create_extractor_edituv_stretch_area()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_edituv_stretch_area_init;
+ extractor.finish = extract_edituv_stretch_area_finish;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_edituv_stretch_area =
+ blender::draw::create_extractor_edituv_stretch_area();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
new file mode 100644
index 00000000000..5a988c73a7e
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc
@@ -0,0 +1,101 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+#include "draw_cache_impl.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Face-dots Edit UV flag
+ * \{ */
+
+struct MeshExtract_EditUVFdotData_Data {
+ EditLoopData *vbo_data;
+ int cd_ofs;
+};
+
+static void extract_fdots_edituv_data_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->poly_len);
+
+ MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(tls_data);
+ data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
+ data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
+}
+
+static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(_data);
+ EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)];
+ memset(eldata, 0x0, sizeof(*eldata));
+ mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
+}
+
+static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *UNUSED(mp),
+ const int mp_index,
+ void *_data)
+{
+ MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(_data);
+ EditLoopData *eldata = &data->vbo_data[mp_index];
+ memset(eldata, 0x0, sizeof(*eldata));
+ BMFace *efa = bm_original_face_get(mr, mp_index);
+ if (efa) {
+ mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
+ }
+}
+
+constexpr MeshExtract create_extractor_fdots_edituv_data()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_fdots_edituv_data_init;
+ extractor.iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_EditUVFdotData_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_fdots_edituv_data = blender::draw::create_extractor_fdots_edituv_data();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
new file mode 100644
index 00000000000..fb9d34e7733
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
@@ -0,0 +1,200 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Face-dots Normal and edit flag
+ * \{ */
+#define NOR_AND_FLAG_DEFAULT 0
+#define NOR_AND_FLAG_SELECT 1
+#define NOR_AND_FLAG_ACTIVE -1
+#define NOR_AND_FLAG_HIDDEN -2
+
+static void extract_fdots_nor_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->poly_len);
+}
+
+static void extract_fdots_nor_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
+ GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo);
+ BMFace *efa;
+
+ /* Quicker than doing it for each loop. */
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ for (int f = 0; f < mr->poly_len; f++) {
+ efa = BM_face_at_index(mr->bm, f);
+ const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
+ if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+ mr->p_origindex[f] == ORIGINDEX_NONE)) {
+ nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
+ nor[f].w = NOR_AND_FLAG_HIDDEN;
+ }
+ else {
+ nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
+ /* Select / Active Flag. */
+ nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
+ ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
+ NOR_AND_FLAG_DEFAULT);
+ }
+ }
+ }
+ else {
+ for (int f = 0; f < mr->poly_len; f++) {
+ efa = bm_original_face_get(mr, f);
+ const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
+ if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+ mr->p_origindex[f] == ORIGINDEX_NONE)) {
+ nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
+ nor[f].w = NOR_AND_FLAG_HIDDEN;
+ }
+ else {
+ nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
+ /* Select / Active Flag. */
+ nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
+ ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
+ NOR_AND_FLAG_DEFAULT);
+ }
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_fdots_nor()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_fdots_nor_init;
+ extractor.finish = extract_fdots_nor_finish;
+ extractor.data_type = MR_DATA_LOOP_NOR;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor);
+ return extractor;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Face-dots High Quality Normal and edit flag
+ * \{ */
+static void extract_fdots_nor_hq_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->poly_len);
+}
+
+static void extract_fdots_nor_hq_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
+ short *nor = (short *)GPU_vertbuf_get_data(vbo);
+ BMFace *efa;
+
+ /* Quicker than doing it for each loop. */
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ for (int f = 0; f < mr->poly_len; f++) {
+ efa = BM_face_at_index(mr->bm, f);
+ const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
+ if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+ mr->p_origindex[f] == ORIGINDEX_NONE)) {
+ normal_float_to_short_v3(&nor[f * 4], invalid_normal);
+ nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN;
+ }
+ else {
+ normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa));
+ /* Select / Active Flag. */
+ nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
+ ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
+ NOR_AND_FLAG_DEFAULT);
+ }
+ }
+ }
+ else {
+ for (int f = 0; f < mr->poly_len; f++) {
+ efa = bm_original_face_get(mr, f);
+ const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
+ if (is_face_hidden || (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
+ mr->p_origindex[f] == ORIGINDEX_NONE)) {
+ normal_float_to_short_v3(&nor[f * 4], invalid_normal);
+ nor[f * 4 + 3] = NOR_AND_FLAG_HIDDEN;
+ }
+ else {
+ normal_float_to_short_v3(&nor[f * 4], bm_face_no_get(mr, efa));
+ /* Select / Active Flag. */
+ nor[f * 4 + 3] = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
+ ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
+ NOR_AND_FLAG_DEFAULT);
+ }
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_fdots_nor_hq()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_fdots_nor_hq_init;
+ extractor.finish = extract_fdots_nor_hq_finish;
+ extractor.data_type = MR_DATA_LOOP_NOR;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_fdots_nor = blender::draw::create_extractor_fdots_nor();
+const MeshExtract extract_fdots_nor_hq = blender::draw::create_extractor_fdots_nor_hq();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
new file mode 100644
index 00000000000..c4706c412c6
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
@@ -0,0 +1,119 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Face-dots positions
+ * \{ */
+
+static void extract_fdots_pos_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->poly_len);
+ void *vbo_data = GPU_vertbuf_get_data(vbo);
+ *(float(**)[3])tls_data = static_cast<float(*)[3]>(vbo_data);
+}
+
+static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int f_index,
+ void *data)
+{
+ float(*center)[3] = *static_cast<float(**)[3]>(data);
+
+ float *co = center[f_index];
+ zero_v3(co);
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ add_v3_v3(co, bm_vert_co_get(mr, l_iter->v));
+ } while ((l_iter = l_iter->next) != l_first);
+ mul_v3_fl(co, 1.0f / (float)f->len);
+}
+
+static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *data)
+{
+ float(*center)[3] = *static_cast<float(**)[3]>(data);
+ float *co = center[mp_index];
+ zero_v3(co);
+
+ const MVert *mvert = mr->mvert;
+ const MLoop *mloop = mr->mloop;
+
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ if (mr->use_subsurf_fdots) {
+ const MVert *mv = &mr->mvert[ml->v];
+ if (mv->flag & ME_VERT_FACEDOT) {
+ copy_v3_v3(center[mp_index], mv->co);
+ break;
+ }
+ }
+ else {
+ const MVert *mv = &mvert[ml->v];
+ add_v3_v3(center[mp_index], mv->co);
+ }
+ }
+
+ if (!mr->use_subsurf_fdots) {
+ mul_v3_fl(co, 1.0f / (float)mp->totloop);
+ }
+}
+
+constexpr MeshExtract create_extractor_fdots_pos()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_fdots_pos_init;
+ extractor.iter_poly_bm = extract_fdots_pos_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_fdots_pos_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(float(*)[3]);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_fdots_pos = blender::draw::create_extractor_fdots_pos();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc
new file mode 100644
index 00000000000..0289fd63a30
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc
@@ -0,0 +1,127 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Face-dots UV
+ * \{ */
+
+struct MeshExtract_FdotUV_Data {
+ float (*vbo_data)[2];
+ MLoopUV *uv_data;
+ int cd_ofs;
+};
+
+static void extract_fdots_uv_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "au");
+ GPU_vertformat_alias_add(&format, "pos");
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->poly_len);
+
+ if (!mr->use_subsurf_fdots) {
+ /* Clear so we can accumulate on it. */
+ memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride);
+ }
+
+ MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(tls_data);
+ data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
+ }
+ else {
+ data->uv_data = (MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
+ }
+}
+
+static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(_data);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ float w = 1.0f / (float)f->len;
+ const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
+ madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *_data)
+{
+ MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(_data);
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ if (mr->use_subsurf_fdots) {
+ const MVert *mv = &mr->mvert[ml->v];
+ if (mv->flag & ME_VERT_FACEDOT) {
+ copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv);
+ }
+ }
+ else {
+ float w = 1.0f / (float)mp->totloop;
+ madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w);
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_fdots_uv()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_fdots_uv_init;
+ extractor.iter_poly_bm = extract_fdots_uv_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_fdots_uv_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_FdotUV_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_fdots_uv = blender::draw::create_extractor_fdots_uv();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
new file mode 100644
index 00000000000..b942068352b
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
@@ -0,0 +1,228 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loop Normal
+ * \{ */
+
+static void extract_lnor_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_alias_add(&format, "lnor");
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ *(GPUPackedNormal **)tls_data = static_cast<GPUPackedNormal *>(GPU_vertbuf_get_data(vbo));
+}
+
+static void extract_lnor_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *data)
+{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ if (mr->loop_normals) {
+ (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]);
+ }
+ else {
+ if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
+ (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(
+ bm_vert_no_get(mr, l_iter->v));
+ }
+ else {
+ (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, f));
+ }
+ }
+ (*(GPUPackedNormal **)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *data)
+{
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index];
+ if (mr->loop_normals) {
+ *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
+ }
+ else if (mp->flag & ME_SMOOTH) {
+ *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no);
+ }
+ else {
+ *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]);
+ }
+
+ /* Flag for paint mode overlay.
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
+ * In paint mode it will use the un-mapped data to draw the wire-frame. */
+ if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
+ (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
+ lnor_data->w = -1;
+ }
+ else if (mp->flag & ME_FACE_SEL) {
+ lnor_data->w = 1;
+ }
+ else {
+ lnor_data->w = 0;
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_lnor()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_lnor_init;
+ extractor.iter_poly_bm = extract_lnor_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_lnor_iter_poly_mesh;
+ extractor.data_type = MR_DATA_LOOP_NOR;
+ extractor.data_size = sizeof(GPUPackedNormal *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor);
+ return extractor;
+}
+
+/** \} */
+/* ---------------------------------------------------------------------- */
+/** \name Extract HQ Loop Normal
+ * \{ */
+
+struct gpuHQNor {
+ short x, y, z, w;
+};
+
+static void extract_lnor_hq_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_alias_add(&format, "lnor");
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ *(gpuHQNor **)tls_data = static_cast<gpuHQNor *>(GPU_vertbuf_get_data(vbo));
+}
+
+static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *data)
+{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ if (mr->loop_normals) {
+ normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]);
+ }
+ else {
+ if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
+ normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_vert_no_get(mr, l_iter->v));
+ }
+ else {
+ normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, bm_face_no_get(mr, f));
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *data)
+{
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index];
+ if (mr->loop_normals) {
+ normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
+ }
+ else if (mp->flag & ME_SMOOTH) {
+ copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no);
+ }
+ else {
+ normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]);
+ }
+
+ /* Flag for paint mode overlay.
+ * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
+ * In paint mode it will use the un-mapped data to draw the wire-frame. */
+ if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED &&
+ (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) {
+ lnor_data->w = -1;
+ }
+ else if (mp->flag & ME_FACE_SEL) {
+ lnor_data->w = 1;
+ }
+ else {
+ lnor_data->w = 0;
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_lnor_hq()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_lnor_hq_init;
+ extractor.iter_poly_bm = extract_lnor_hq_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_lnor_hq_iter_poly_mesh;
+ extractor.data_type = MR_DATA_LOOP_NOR;
+ extractor.data_size = sizeof(gpuHQNor *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_lnor = blender::draw::create_extractor_lnor();
+const MeshExtract extract_lnor_hq = blender::draw::create_extractor_lnor_hq();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
new file mode 100644
index 00000000000..b734061b76a
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
@@ -0,0 +1,654 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_edgehash.h"
+#include "BLI_jitter_2d.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_editmesh_bvh.h"
+#include "BKE_editmesh_cache.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Edit Mesh Analysis Colors
+ * \{ */
+
+static void extract_mesh_analysis_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+}
+
+static void axis_from_enum_v3(float v[3], const char axis)
+{
+ zero_v3(v);
+ if (axis < 3) {
+ v[axis] = 1.0f;
+ }
+ else {
+ v[axis - 3] = -1.0f;
+ }
+}
+
+BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
+{
+ if (fac < min) {
+ fac = 1.0f;
+ }
+ else if (fac > max) {
+ fac = -1.0f;
+ }
+ else {
+ fac = (fac - min) * minmax_irange;
+ fac = 1.0f - fac;
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+ return fac;
+}
+
+static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
+{
+ const MeshStatVis *statvis = &mr->toolsettings->statvis;
+ const float min = statvis->overhang_min / (float)M_PI;
+ const float max = statvis->overhang_max / (float)M_PI;
+ const char axis = statvis->overhang_axis;
+ BMEditMesh *em = mr->edit_bmesh;
+ BMIter iter;
+ BMesh *bm = em->bm;
+ BMFace *f;
+ float dir[3];
+ const float minmax_irange = 1.0f / (max - min);
+
+ BLI_assert(min <= max);
+
+ axis_from_enum_v3(dir, axis);
+
+ /* now convert into global space */
+ mul_transposed_mat3_m4_v3(mr->obmat, dir);
+ normalize_v3(dir);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int l_index = 0;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
+ fac = overhang_remap(fac, min, max, minmax_irange);
+ for (int i = 0; i < f->len; i++, l_index++) {
+ r_overhang[l_index] = fac;
+ }
+ }
+ }
+ else {
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI;
+ fac = overhang_remap(fac, min, max, minmax_irange);
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ r_overhang[l_index] = fac;
+ }
+ }
+ }
+}
+
+/**
+ * Needed so we can use jitter values for face interpolation.
+ */
+static void uv_from_jitter_v2(float uv[2])
+{
+ uv[0] += 0.5f;
+ uv[1] += 0.5f;
+ if (uv[0] + uv[1] > 1.0f) {
+ uv[0] = 1.0f - uv[0];
+ uv[1] = 1.0f - uv[1];
+ }
+
+ clamp_v2(uv, 0.0f, 1.0f);
+}
+
+BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
+{
+ /* important not '<=' */
+ if (fac < max) {
+ fac = (fac - min) * minmax_irange;
+ fac = 1.0f - fac;
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+ else {
+ fac = -1.0f;
+ }
+ return fac;
+}
+
+static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
+{
+ const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
+ /* cheating to avoid another allocation */
+ float *face_dists = r_thickness + (mr->loop_len - mr->poly_len);
+ BMEditMesh *em = mr->edit_bmesh;
+ const float scale = 1.0f / mat4_to_scale(mr->obmat);
+ const MeshStatVis *statvis = &mr->toolsettings->statvis;
+ const float min = statvis->thickness_min * scale;
+ const float max = statvis->thickness_max * scale;
+ const float minmax_irange = 1.0f / (max - min);
+ const int samples = statvis->thickness_samples;
+ float jit_ofs[32][2];
+ BLI_assert(samples <= 32);
+ BLI_assert(min <= max);
+
+ copy_vn_fl(face_dists, mr->poly_len, max);
+
+ BLI_jitter_init(jit_ofs, samples);
+ for (int j = 0; j < samples; j++) {
+ uv_from_jitter_v2(jit_ofs[j]);
+ }
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMesh *bm = em->bm;
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false);
+ struct BMLoop *(*looptris)[3] = em->looptris;
+ for (int i = 0; i < mr->tri_len; i++) {
+ BMLoop **ltri = looptris[i];
+ const int index = BM_elem_index_get(ltri[0]->f);
+ const float *cos[3] = {
+ bm_vert_co_get(mr, ltri[0]->v),
+ bm_vert_co_get(mr, ltri[1]->v),
+ bm_vert_co_get(mr, ltri[2]->v),
+ };
+ float ray_co[3];
+ float ray_no[3];
+
+ normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
+
+ for (int j = 0; j < samples; j++) {
+ float dist = face_dists[index];
+ interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
+ madd_v3_v3fl(ray_co, ray_no, eps_offset);
+
+ BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, nullptr, nullptr);
+ if (f_hit && dist < face_dists[index]) {
+ float angle_fac = fabsf(
+ dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit)));
+ angle_fac = 1.0f - angle_fac;
+ angle_fac = angle_fac * angle_fac * angle_fac;
+ angle_fac = 1.0f - angle_fac;
+ dist /= angle_fac;
+ if (dist < face_dists[index]) {
+ face_dists[index] = dist;
+ }
+ }
+ }
+ }
+ BKE_bmbvh_free(bmtree);
+
+ BMIter iter;
+ BMFace *f;
+ int l_index = 0;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ float fac = face_dists[BM_elem_index_get(f)];
+ fac = thickness_remap(fac, min, max, minmax_irange);
+ for (int i = 0; i < f->len; i++, l_index++) {
+ r_thickness[l_index] = fac;
+ }
+ }
+ }
+ else {
+ BVHTreeFromMesh treeData = {nullptr};
+
+ BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
+ const MLoopTri *mlooptri = mr->mlooptri;
+ for (int i = 0; i < mr->tri_len; i++, mlooptri++) {
+ const int index = mlooptri->poly;
+ const float *cos[3] = {mr->mvert[mr->mloop[mlooptri->tri[0]].v].co,
+ mr->mvert[mr->mloop[mlooptri->tri[1]].v].co,
+ mr->mvert[mr->mloop[mlooptri->tri[2]].v].co};
+ float ray_co[3];
+ float ray_no[3];
+
+ normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
+
+ for (int j = 0; j < samples; j++) {
+ interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
+ madd_v3_v3fl(ray_co, ray_no, eps_offset);
+
+ BVHTreeRayHit hit;
+ hit.index = -1;
+ hit.dist = face_dists[index];
+ if ((BLI_bvhtree_ray_cast(
+ tree, ray_co, ray_no, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) &&
+ hit.dist < face_dists[index]) {
+ float angle_fac = fabsf(dot_v3v3(mr->poly_normals[index], hit.no));
+ angle_fac = 1.0f - angle_fac;
+ angle_fac = angle_fac * angle_fac * angle_fac;
+ angle_fac = 1.0f - angle_fac;
+ hit.dist /= angle_fac;
+ if (hit.dist < face_dists[index]) {
+ face_dists[index] = hit.dist;
+ }
+ }
+ }
+ }
+
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float fac = face_dists[mp_index];
+ fac = thickness_remap(fac, min, max, minmax_irange);
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ r_thickness[l_index] = fac;
+ }
+ }
+ }
+}
+
+struct BVHTree_OverlapData {
+ const Mesh *me;
+ const MLoopTri *mlooptri;
+ float epsilon;
+};
+
+static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
+{
+ struct BVHTree_OverlapData *data = static_cast<struct BVHTree_OverlapData *>(userdata);
+ const Mesh *me = data->me;
+
+ const MLoopTri *tri_a = &data->mlooptri[index_a];
+ const MLoopTri *tri_b = &data->mlooptri[index_b];
+
+ if (UNLIKELY(tri_a->poly == tri_b->poly)) {
+ return false;
+ }
+
+ const float *tri_a_co[3] = {me->mvert[me->mloop[tri_a->tri[0]].v].co,
+ me->mvert[me->mloop[tri_a->tri[1]].v].co,
+ me->mvert[me->mloop[tri_a->tri[2]].v].co};
+ const float *tri_b_co[3] = {me->mvert[me->mloop[tri_b->tri[0]].v].co,
+ me->mvert[me->mloop[tri_b->tri[1]].v].co,
+ me->mvert[me->mloop[tri_b->tri[2]].v].co};
+ float ix_pair[2][3];
+ int verts_shared = 0;
+
+ verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
+ ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
+
+ /* if 2 points are shared, bail out */
+ if (verts_shared >= 2) {
+ return false;
+ }
+
+ return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) &&
+ /* if we share a vertex, check the intersection isn't a 'point' */
+ ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
+}
+
+static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
+{
+ BMEditMesh *em = mr->edit_bmesh;
+
+ for (int l_index = 0; l_index < mr->loop_len; l_index++) {
+ r_intersect[l_index] = -1.0f;
+ }
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ uint overlap_len;
+ BMesh *bm = em->bm;
+
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false);
+ BVHTreeOverlap *overlap = BKE_bmbvh_overlap_self(bmtree, &overlap_len);
+
+ if (overlap) {
+ for (int i = 0; i < overlap_len; i++) {
+ BMFace *f_hit_pair[2] = {
+ em->looptris[overlap[i].indexA][0]->f,
+ em->looptris[overlap[i].indexB][0]->f,
+ };
+ for (int j = 0; j < 2; j++) {
+ BMFace *f_hit = f_hit_pair[j];
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit);
+ int l_index = BM_elem_index_get(l_first);
+ for (int k = 0; k < f_hit->len; k++, l_index++) {
+ r_intersect[l_index] = 1.0f;
+ }
+ }
+ }
+ MEM_freeN(overlap);
+ }
+
+ BKE_bmbvh_free(bmtree);
+ }
+ else {
+ uint overlap_len;
+ BVHTreeFromMesh treeData = {nullptr};
+
+ BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
+
+ struct BVHTree_OverlapData data = {nullptr};
+ data.me = mr->me;
+ data.mlooptri = mr->mlooptri;
+ data.epsilon = BLI_bvhtree_get_epsilon(tree);
+
+ BVHTreeOverlap *overlap = BLI_bvhtree_overlap(tree, tree, &overlap_len, bvh_overlap_cb, &data);
+ if (overlap) {
+ for (int i = 0; i < overlap_len; i++) {
+ const MPoly *f_hit_pair[2] = {
+ &mr->mpoly[mr->mlooptri[overlap[i].indexA].poly],
+ &mr->mpoly[mr->mlooptri[overlap[i].indexB].poly],
+ };
+ for (int j = 0; j < 2; j++) {
+ const MPoly *f_hit = f_hit_pair[j];
+ int l_index = f_hit->loopstart;
+ for (int k = 0; k < f_hit->totloop; k++, l_index++) {
+ r_intersect[l_index] = 1.0f;
+ }
+ }
+ }
+ MEM_freeN(overlap);
+ }
+ }
+}
+
+BLI_INLINE float distort_remap(float fac, float min, float UNUSED(max), float minmax_irange)
+{
+ if (fac >= min) {
+ fac = (fac - min) * minmax_irange;
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+ else {
+ /* fallback */
+ fac = -1.0f;
+ }
+ return fac;
+}
+
+static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
+{
+ BMEditMesh *em = mr->edit_bmesh;
+ const MeshStatVis *statvis = &mr->toolsettings->statvis;
+ const float min = statvis->distort_min;
+ const float max = statvis->distort_max;
+ const float minmax_irange = 1.0f / (max - min);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMIter iter;
+ BMesh *bm = em->bm;
+ BMFace *f;
+
+ if (mr->bm_vert_coords != nullptr) {
+ BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data);
+
+ /* Most likely this is already valid, ensure just in case.
+ * Needed for #BM_loop_calc_face_normal_safe_vcos. */
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ }
+
+ int l_index = 0;
+ int f_index = 0;
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) {
+ float fac = -1.0f;
+
+ if (f->len > 3) {
+ BMLoop *l_iter, *l_first;
+
+ fac = 0.0f;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const float *no_face;
+ float no_corner[3];
+ if (mr->bm_vert_coords != nullptr) {
+ no_face = mr->bm_poly_normals[f_index];
+ BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
+ }
+ else {
+ no_face = f->no;
+ BM_loop_calc_face_normal_safe(l_iter, no_corner);
+ }
+
+ /* simple way to detect (what is most likely) concave */
+ if (dot_v3v3(no_face, no_corner) < 0.0f) {
+ negate_v3(no_corner);
+ }
+ fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner));
+
+ } while ((l_iter = l_iter->next) != l_first);
+ fac *= 2.0f;
+ }
+
+ fac = distort_remap(fac, min, max, minmax_irange);
+ for (int i = 0; i < f->len; i++, l_index++) {
+ r_distort[l_index] = fac;
+ }
+ }
+ }
+ else {
+ const MPoly *mp = mr->mpoly;
+ for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ float fac = -1.0f;
+
+ if (mp->totloop > 3) {
+ float *f_no = mr->poly_normals[mp_index];
+ fac = 0.0f;
+
+ for (int i = 1; i <= mp->totloop; i++) {
+ const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop];
+ const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
+ const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
+ float no_corner[3];
+ normal_tri_v3(no_corner,
+ mr->mvert[l_prev->v].co,
+ mr->mvert[l_curr->v].co,
+ mr->mvert[l_next->v].co);
+ /* simple way to detect (what is most likely) concave */
+ if (dot_v3v3(f_no, no_corner) < 0.0f) {
+ negate_v3(no_corner);
+ }
+ fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
+ }
+ fac *= 2.0f;
+ }
+
+ fac = distort_remap(fac, min, max, minmax_irange);
+ for (int i = 0; i < mp->totloop; i++, l_index++) {
+ r_distort[l_index] = fac;
+ }
+ }
+ }
+}
+
+BLI_INLINE float sharp_remap(float fac, float min, float UNUSED(max), float minmax_irange)
+{
+ /* important not '>=' */
+ if (fac > min) {
+ fac = (fac - min) * minmax_irange;
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+ else {
+ /* fallback */
+ fac = -1.0f;
+ }
+ return fac;
+}
+
+static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
+{
+ BMEditMesh *em = mr->edit_bmesh;
+ const MeshStatVis *statvis = &mr->toolsettings->statvis;
+ const float min = statvis->sharp_min;
+ const float max = statvis->sharp_max;
+ const float minmax_irange = 1.0f / (max - min);
+
+ /* Can we avoid this extra allocation? */
+ float *vert_angles = (float *)MEM_mallocN(sizeof(float) * mr->vert_len, __func__);
+ copy_vn_fl(vert_angles, mr->vert_len, -M_PI);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMIter iter;
+ BMesh *bm = em->bm;
+ BMFace *efa;
+ BMEdge *e;
+ /* first assign float values to verts */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ float angle = BM_edge_calc_face_angle_signed(e);
+ float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
+ float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
+ *col1 = max_ff(*col1, angle);
+ *col2 = max_ff(*col2, angle);
+ }
+ /* Copy vert value to loops. */
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ int l_index = BM_elem_index_get(l_iter);
+ int v_index = BM_elem_index_get(l_iter->v);
+ r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ else {
+ /* first assign float values to verts */
+ const MPoly *mp = mr->mpoly;
+
+ EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len);
+
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
+ for (int i = 0; i < mp->totloop; i++) {
+ const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
+ const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
+ const MVert *v_curr = &mr->mvert[l_curr->v];
+ const MVert *v_next = &mr->mvert[l_next->v];
+ float angle;
+ void **pval;
+ bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
+ if (!value_is_init) {
+ *pval = mr->poly_normals[mp_index];
+ /* non-manifold edge, yet... */
+ continue;
+ }
+ if (*pval != nullptr) {
+ const float *f1_no = mr->poly_normals[mp_index];
+ const float *f2_no = static_cast<const float *>(*pval);
+ angle = angle_normalized_v3v3(f1_no, f2_no);
+ angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle;
+ /* Tag as manifold. */
+ *pval = nullptr;
+ }
+ else {
+ /* non-manifold edge */
+ angle = DEG2RADF(90.0f);
+ }
+ float *col1 = &vert_angles[l_curr->v];
+ float *col2 = &vert_angles[l_next->v];
+ *col1 = max_ff(*col1, angle);
+ *col2 = max_ff(*col2, angle);
+ }
+ }
+ /* Remaining non manifold edges. */
+ EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh);
+ for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ if (BLI_edgehashIterator_getValue(ehi) != nullptr) {
+ uint v1, v2;
+ const float angle = DEG2RADF(90.0f);
+ BLI_edgehashIterator_getKey(ehi, &v1, &v2);
+ float *col1 = &vert_angles[v1];
+ float *col2 = &vert_angles[v2];
+ *col1 = max_ff(*col1, angle);
+ *col2 = max_ff(*col2, angle);
+ }
+ }
+ BLI_edgehashIterator_free(ehi);
+ BLI_edgehash_free(eh, nullptr);
+
+ const MLoop *ml = mr->mloop;
+ for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) {
+ r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange);
+ }
+ }
+
+ MEM_freeN(vert_angles);
+}
+
+static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ BLI_assert(mr->edit_bmesh);
+
+ float *l_weight = (float *)GPU_vertbuf_get_data(vbo);
+
+ switch (mr->toolsettings->statvis.type) {
+ case SCE_STATVIS_OVERHANG:
+ statvis_calc_overhang(mr, l_weight);
+ break;
+ case SCE_STATVIS_THICKNESS:
+ statvis_calc_thickness(mr, l_weight);
+ break;
+ case SCE_STATVIS_INTERSECT:
+ statvis_calc_intersect(mr, l_weight);
+ break;
+ case SCE_STATVIS_DISTORT:
+ statvis_calc_distort(mr, l_weight);
+ break;
+ case SCE_STATVIS_SHARP:
+ statvis_calc_sharp(mr, l_weight);
+ break;
+ }
+}
+
+constexpr MeshExtract create_extractor_mesh_analysis()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_mesh_analysis_init;
+ extractor.finish = extract_analysis_iter_finish_mesh;
+ /* This is not needed for all visualization types.
+ * Maybe split into different extract. */
+ extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_mesh_analysis = blender::draw::create_extractor_mesh_analysis();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
new file mode 100644
index 00000000000..80b73cac678
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
@@ -0,0 +1,115 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Orco
+ * \{ */
+
+struct MeshExtract_Orco_Data {
+ float (*vbo_data)[4];
+ float (*orco)[3];
+};
+
+static void extract_orco_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
+ * attributes. This is a substantial waste of video-ram and should be done another way.
+ * Unfortunately, at the time of writing, I did not found any other "non disruptive"
+ * alternative. */
+ GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ CustomData *cd_vdata = &mr->me->vdata;
+
+ MeshExtract_Orco_Data *data = static_cast<MeshExtract_Orco_Data *>(tls_data);
+ data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo);
+ data->orco = static_cast<float(*)[3]>(CustomData_get_layer(cd_vdata, CD_ORCO));
+ /* Make sure `orco` layer was requested only if needed! */
+ BLI_assert(data->orco);
+}
+
+static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *data)
+{
+ MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ float *loop_orco = orco_data->vbo_data[l_index];
+ copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(l_iter->v)]);
+ loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_orco_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *data)
+{
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
+ float *loop_orco = orco_data->vbo_data[ml_index];
+ copy_v3_v3(loop_orco, orco_data->orco[ml->v]);
+ loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
+ }
+}
+
+constexpr MeshExtract create_extractor_orco()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_orco_init;
+ extractor.iter_poly_bm = extract_orco_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_orco_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_Orco_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_orco = blender::draw::create_extractor_orco();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
new file mode 100644
index 00000000000..2ac926dd257
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
@@ -0,0 +1,415 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Position and Vertex Normal
+ * \{ */
+
+struct PosNorLoop {
+ float pos[3];
+ GPUPackedNormal nor;
+};
+
+struct MeshExtract_PosNor_Data {
+ PosNorLoop *vbo_data;
+ GPUNormal *normals;
+};
+
+static void extract_pos_nor_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* WARNING Adjust #PosNorLoop struct accordingly. */
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_alias_add(&format, "vnor");
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
+
+ /* Pack normals per vert, reduce amount of computation. */
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(tls_data);
+ data->vbo_data = static_cast<PosNorLoop *>(GPU_vertbuf_get_data(vbo));
+ data->normals = (GPUNormal *)MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__);
+
+ /* Quicker than doing it for each loop. */
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMIter iter;
+ BMVert *eve;
+ int v;
+ BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
+ data->normals[v].low = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve));
+ }
+ }
+ else {
+ const MVert *mv = mr->mvert;
+ for (int v = 0; v < mr->vert_len; v++, mv++) {
+ data->normals[v].low = GPU_normal_convert_i10_s3(mv->no);
+ }
+ }
+}
+
+static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ PosNorLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
+ vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low;
+ vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
+ PosNorLoop *vert = &data->vbo_data[ml_index];
+ const MVert *mv = &mr->mvert[ml->v];
+ copy_v3_v3(vert->pos, mv->co);
+ vert->nor = data->normals[ml->v].low;
+ /* Flag for paint mode overlay. */
+ if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
+ (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
+ vert->nor.w = -1;
+ }
+ else if (mv->flag & SELECT) {
+ vert->nor.w = 1;
+ }
+ else {
+ vert->nor.w = 0;
+ }
+ }
+}
+
+static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr,
+ const BMEdge *eed,
+ const int ledge_index,
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+
+ int l_index = mr->loop_len + ledge_index * 2;
+ PosNorLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
+ copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
+ vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low;
+ vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low;
+}
+
+static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr,
+ const MEdge *med,
+ const int ledge_index,
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+ const int ml_index = mr->loop_len + ledge_index * 2;
+ PosNorLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co);
+ copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co);
+ vert[0].nor = data->normals[med->v1].low;
+ vert[1].nor = data->normals[med->v2].low;
+}
+
+static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr,
+ const BMVert *eve,
+ const int lvert_index,
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ const int l_index = offset + lvert_index;
+ PosNorLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
+ vert->nor = data->normals[BM_elem_index_get(eve)].low;
+}
+
+static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr,
+ const MVert *mv,
+ const int lvert_index,
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ const int ml_index = offset + lvert_index;
+ const int v_index = mr->lverts[lvert_index];
+ PosNorLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert->pos, mv->co);
+ vert->nor = data->normals[v_index].low;
+}
+
+static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *_data)
+{
+ MeshExtract_PosNor_Data *data = static_cast<MeshExtract_PosNor_Data *>(_data);
+ MEM_freeN(data->normals);
+}
+
+constexpr MeshExtract create_extractor_pos_nor()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_pos_nor_init;
+ extractor.iter_poly_bm = extract_pos_nor_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_pos_nor_iter_poly_mesh;
+ extractor.iter_ledge_bm = extract_pos_nor_iter_ledge_bm;
+ extractor.iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh;
+ extractor.iter_lvert_bm = extract_pos_nor_iter_lvert_bm;
+ extractor.iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh;
+ extractor.finish = extract_pos_nor_finish;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_PosNor_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor);
+ return extractor;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Position and High Quality Vertex Normal
+ * \{ */
+
+struct PosNorHQLoop {
+ float pos[3];
+ short nor[4];
+};
+
+struct MeshExtract_PosNorHQ_Data {
+ PosNorHQLoop *vbo_data;
+ GPUNormal *normals;
+};
+
+static void extract_pos_nor_hq_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* WARNING Adjust #PosNorHQLoop struct accordingly. */
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_alias_add(&format, "vnor");
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
+
+ /* Pack normals per vert, reduce amount of computation. */
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(tls_data);
+ data->vbo_data = static_cast<PosNorHQLoop *>(GPU_vertbuf_get_data(vbo));
+ data->normals = (GPUNormal *)MEM_mallocN(sizeof(GPUNormal) * mr->vert_len, __func__);
+
+ /* Quicker than doing it for each loop. */
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMIter iter;
+ BMVert *eve;
+ int v;
+ BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
+ normal_float_to_short_v3(data->normals[v].high, bm_vert_no_get(mr, eve));
+ }
+ }
+ else {
+ const MVert *mv = mr->mvert;
+ for (int v = 0; v < mr->vert_len; v++, mv++) {
+ copy_v3_v3_short(data->normals[v].high, mv->no);
+ }
+ }
+}
+
+static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr,
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ PosNorHQLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v));
+ copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high);
+
+ vert->nor[3] = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0;
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+
+ PosNorHQLoop *vert = &data->vbo_data[ml_index];
+ const MVert *mv = &mr->mvert[ml->v];
+ copy_v3_v3(vert->pos, mv->co);
+ copy_v3_v3_short(vert->nor, data->normals[ml->v].high);
+
+ /* Flag for paint mode overlay. */
+ if (mp->flag & ME_HIDE || mv->flag & ME_HIDE ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
+ (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) {
+ vert->nor[3] = -1;
+ }
+ else if (mv->flag & SELECT) {
+ vert->nor[3] = 1;
+ }
+ else {
+ vert->nor[3] = 0;
+ }
+ }
+}
+
+static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr,
+ const BMEdge *eed,
+ const int ledge_index,
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ int l_index = mr->loop_len + ledge_index * 2;
+ PosNorHQLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
+ copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
+ copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high);
+ vert[0].nor[3] = 0;
+ copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high);
+ vert[1].nor[3] = 0;
+}
+
+static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr,
+ const MEdge *med,
+ const int ledge_index,
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ const int ml_index = mr->loop_len + ledge_index * 2;
+ PosNorHQLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co);
+ copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co);
+ copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high);
+ vert[0].nor[3] = 0;
+ copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high);
+ vert[1].nor[3] = 0;
+}
+
+static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr,
+ const BMVert *eve,
+ const int lvert_index,
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ const int l_index = offset + lvert_index;
+ PosNorHQLoop *vert = &data->vbo_data[l_index];
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
+ copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high);
+ vert->nor[3] = 0;
+}
+
+static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr,
+ const MVert *mv,
+ const int lvert_index,
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ const int ml_index = offset + lvert_index;
+ const int v_index = mr->lverts[lvert_index];
+ PosNorHQLoop *vert = &data->vbo_data[ml_index];
+ copy_v3_v3(vert->pos, mv->co);
+ copy_v3_v3_short(vert->nor, data->normals[v_index].high);
+ vert->nor[3] = 0;
+}
+
+static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *_data)
+{
+ MeshExtract_PosNorHQ_Data *data = static_cast<MeshExtract_PosNorHQ_Data *>(_data);
+ MEM_freeN(data->normals);
+}
+
+constexpr MeshExtract create_extractor_pos_nor_hq()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_pos_nor_hq_init;
+ extractor.iter_poly_bm = extract_pos_nor_hq_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh;
+ extractor.iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm;
+ extractor.iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh;
+ extractor.iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm;
+ extractor.iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh;
+ extractor.finish = extract_pos_nor_hq_finish;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_PosNorHQ_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_pos_nor = blender::draw::create_extractor_pos_nor();
+const MeshExtract extract_pos_nor_hq = blender::draw::create_extractor_pos_nor_hq();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
new file mode 100644
index 00000000000..7b36a009419
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+
+#include "BKE_paint.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Sculpt Data
+ * \{ */
+
+static void extract_sculpt_data_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat format = {0};
+
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
+ CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata;
+
+ float *cd_mask = (float *)CustomData_get_layer(cd_vdata, CD_PAINT_MASK);
+ int *cd_face_set = (int *)CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS);
+
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ struct gpuSculptData {
+ uint8_t face_set_color[4];
+ float mask;
+ };
+
+ gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo);
+ MLoop *loops = (MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_mask_ofs = CustomData_get_offset(cd_vdata, CD_PAINT_MASK);
+ int cd_face_set_ofs = CustomData_get_offset(cd_pdata, CD_SCULPT_FACE_SETS);
+ BMIter f_iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ float v_mask = 0.0f;
+ if (cd_mask) {
+ v_mask = BM_ELEM_CD_GET_FLOAT(l_iter->v, cd_mask_ofs);
+ }
+ vbo_data->mask = v_mask;
+ uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+ if (cd_face_set) {
+ const int face_set_id = BM_ELEM_CD_GET_INT(l_iter->f, cd_face_set_ofs);
+ if (face_set_id != mr->me->face_sets_color_default) {
+ BKE_paint_face_set_overlay_color_get(
+ face_set_id, mr->me->face_sets_color_seed, face_set_color);
+ }
+ }
+ copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color);
+ vbo_data++;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ else {
+ int mp_loop = 0;
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
+ const MPoly *p = &mr->mpoly[mp_index];
+ for (int l = 0; l < p->totloop; l++) {
+ float v_mask = 0.0f;
+ if (cd_mask) {
+ v_mask = cd_mask[loops[mp_loop].v];
+ }
+ vbo_data->mask = v_mask;
+
+ uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+ if (cd_face_set) {
+ const int face_set_id = cd_face_set[mp_index];
+ /* Skip for the default color Face Set to render it white. */
+ if (face_set_id != mr->me->face_sets_color_default) {
+ BKE_paint_face_set_overlay_color_get(
+ face_set_id, mr->me->face_sets_color_seed, face_set_color);
+ }
+ }
+ copy_v3_v3_uchar(vbo_data->face_set_color, face_set_color);
+ mp_loop++;
+ vbo_data++;
+ }
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_sculpt_data()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_sculpt_data_init;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_sculpt_data = blender::draw::create_extractor_sculpt_data();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
new file mode 100644
index 00000000000..ac44e97f229
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
@@ -0,0 +1,295 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Selection Index
+ * \{ */
+
+static void extract_select_idx_init_impl(const MeshRenderData *UNUSED(mr),
+ const int len,
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* TODO: rename "color" to something more descriptive. */
+ GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, len);
+ *(uint32_t **)tls_data = (uint32_t *)GPU_vertbuf_get_data(vbo);
+}
+
+static void extract_select_idx_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ extract_select_idx_init_impl(mr, mr->loop_len + mr->loop_loose_len, buf, tls_data);
+}
+
+/* TODO: Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
+ * select element associated with this loop ID. This would remove the need for this separate
+ * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
+ * shader to output original index. */
+
+static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *f,
+ const int f_index,
+ void *data)
+{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ (*(uint32_t **)data)[l_index] = f_index;
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *data)
+{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->e);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *data)
+{
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ (*(uint32_t **)data)[l_index] = BM_elem_index_get(l_iter->v);
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr,
+ const BMEdge *eed,
+ const int ledge_index,
+ void *data)
+{
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed);
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed);
+}
+
+static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr,
+ const BMEdge *eed,
+ const int ledge_index,
+ void *data)
+{
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1);
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2);
+}
+
+static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr,
+ const BMVert *eve,
+ const int lvert_index,
+ void *data)
+{
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ (*(uint32_t **)data)[offset + lvert_index] = BM_elem_index_get(eve);
+}
+
+static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int mp_index,
+ void *data)
+{
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ (*(uint32_t **)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index;
+ }
+}
+
+static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *data)
+{
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ (*(uint32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e;
+ }
+}
+
+static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *data)
+{
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ (*(uint32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v;
+ }
+}
+
+static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr,
+ const MEdge *UNUSED(med),
+ const int ledge_index,
+ void *data)
+{
+ const int e_index = mr->ledges[ledge_index];
+ const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index;
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig;
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig;
+}
+
+static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr,
+ const MEdge *med,
+ const int ledge_index,
+ void *data)
+{
+ int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1;
+ int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2;
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig;
+ (*(uint32_t **)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig;
+}
+
+static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr,
+ const MVert *UNUSED(mv),
+ const int lvert_index,
+ void *data)
+{
+ const int offset = mr->loop_len + (mr->edge_loose_len * 2);
+
+ const int v_index = mr->lverts[lvert_index];
+ const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index;
+ (*(uint32_t **)data)[offset + lvert_index] = v_orig;
+}
+
+constexpr MeshExtract create_extractor_poly_idx()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_select_idx_init;
+ extractor.iter_poly_bm = extract_poly_idx_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_poly_idx_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(uint32_t *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx);
+ return extractor;
+}
+
+constexpr MeshExtract create_extractor_edge_idx()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_select_idx_init;
+ extractor.iter_poly_bm = extract_edge_idx_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_edge_idx_iter_poly_mesh;
+ extractor.iter_ledge_bm = extract_edge_idx_iter_ledge_bm;
+ extractor.iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(uint32_t *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx);
+ return extractor;
+}
+
+constexpr MeshExtract create_extractor_vert_idx()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_select_idx_init;
+ extractor.iter_poly_bm = extract_vert_idx_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_vert_idx_iter_poly_mesh;
+ extractor.iter_ledge_bm = extract_vert_idx_iter_ledge_bm;
+ extractor.iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh;
+ extractor.iter_lvert_bm = extract_vert_idx_iter_lvert_bm;
+ extractor.iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(uint32_t *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx);
+ return extractor;
+}
+
+static void extract_fdot_idx_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ extract_select_idx_init_impl(mr, mr->poly_len, buf, tls_data);
+}
+
+static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *UNUSED(f),
+ const int f_index,
+ void *data)
+{
+ (*(uint32_t **)data)[f_index] = f_index;
+}
+
+static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *UNUSED(mp),
+ const int mp_index,
+ void *data)
+{
+ if (mr->p_origindex != nullptr) {
+ (*(uint32_t **)data)[mp_index] = mr->p_origindex[mp_index];
+ }
+ else {
+ (*(uint32_t **)data)[mp_index] = mp_index;
+ }
+}
+
+constexpr MeshExtract create_extractor_fdot_idx()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_fdot_idx_init;
+ extractor.iter_poly_bm = extract_fdot_idx_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_fdot_idx_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(uint32_t *);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_poly_idx = blender::draw::create_extractor_poly_idx();
+const MeshExtract extract_edge_idx = blender::draw::create_extractor_edge_idx();
+const MeshExtract extract_vert_idx = blender::draw::create_extractor_vert_idx();
+const MeshExtract extract_fdot_idx = blender::draw::create_extractor_fdot_idx();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
new file mode 100644
index 00000000000..d7a01ee607f
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
@@ -0,0 +1,93 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Skin Modifier Roots
+ * \{ */
+
+struct SkinRootData {
+ float size;
+ float local_pos[3];
+};
+
+static void extract_skin_roots_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ /* Exclusively for edit mode. */
+ BLI_assert(mr->bm);
+
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->bm->totvert);
+
+ SkinRootData *vbo_data = (SkinRootData *)GPU_vertbuf_get_data(vbo);
+
+ int root_len = 0;
+ int cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MVERT_SKIN);
+
+ BMIter iter;
+ BMVert *eve;
+ BM_ITER_MESH (eve, &iter, mr->bm, BM_VERTS_OF_MESH) {
+ const MVertSkin *vs = (const MVertSkin *)BM_ELEM_CD_GET_VOID_P(eve, cd_ofs);
+ if (vs->flag & MVERT_SKIN_ROOT) {
+ vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f;
+ copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve));
+ vbo_data++;
+ root_len++;
+ }
+ }
+
+ /* It's really unlikely that all verts will be roots. Resize to avoid losing VRAM. */
+ GPU_vertbuf_data_len_set(vbo, root_len);
+}
+
+constexpr MeshExtract create_extractor_skin_roots()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_skin_roots_init;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_skin_roots = blender::draw::create_extractor_skin_roots();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
new file mode 100644
index 00000000000..f251141c442
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
@@ -0,0 +1,266 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_tangent.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Tangent layers
+ * \{ */
+
+static void extract_tan_ex_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ GPUVertBuf *vbo,
+ const bool do_hq)
+{
+ GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10;
+ GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT;
+
+ GPUVertFormat format = {0};
+ GPU_vertformat_deinterleave(&format);
+
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
+ uint32_t tan_layers = cache->cd_used.tan;
+ float(*orco)[3] = (float(*)[3])CustomData_get_layer(cd_vdata, CD_ORCO);
+ bool orco_allocated = false;
+ const bool use_orco_tan = cache->cd_used.tan_orco != 0;
+
+ int tan_len = 0;
+ char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME];
+
+ for (int i = 0; i < MAX_MTFACE; i++) {
+ if (tan_layers & (1 << i)) {
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+ /* Tangent layer name. */
+ BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name);
+ GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
+ /* Active render layer name. */
+ if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
+ GPU_vertformat_alias_add(&format, "t");
+ }
+ /* Active display layer name. */
+ if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
+ GPU_vertformat_alias_add(&format, "at");
+ }
+
+ BLI_strncpy(tangent_names[tan_len++], layer_name, MAX_CUSTOMDATA_LAYER_NAME);
+ }
+ }
+ if (use_orco_tan && orco == nullptr) {
+ /* If `orco` is not available compute it ourselves */
+ orco_allocated = true;
+ orco = (float(*)[3])MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__);
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMesh *bm = mr->bm;
+ for (int v = 0; v < mr->vert_len; v++) {
+ const BMVert *eve = BM_vert_at_index(bm, v);
+ /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords.
+ * not the distorted ones. */
+ copy_v3_v3(orco[v], eve->co);
+ }
+ }
+ else {
+ const MVert *mv = mr->mvert;
+ for (int v = 0; v < mr->vert_len; v++, mv++) {
+ copy_v3_v3(orco[v], mv->co);
+ }
+ }
+ BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0);
+ }
+
+ /* Start Fresh */
+ CustomData loop_data;
+ CustomData_reset(&loop_data);
+ if (tan_len != 0 || use_orco_tan) {
+ short tangent_mask = 0;
+ bool calc_active_tangent = false;
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BKE_editmesh_loop_tangent_calc(mr->edit_bmesh,
+ calc_active_tangent,
+ tangent_names,
+ tan_len,
+ mr->poly_normals,
+ mr->loop_normals,
+ orco,
+ &loop_data,
+ mr->loop_len,
+ &tangent_mask);
+ }
+ else {
+ BKE_mesh_calc_loop_tangent_ex(mr->mvert,
+ mr->mpoly,
+ mr->poly_len,
+ mr->mloop,
+ mr->mlooptri,
+ mr->tri_len,
+ cd_ldata,
+ calc_active_tangent,
+ tangent_names,
+ tan_len,
+ mr->poly_normals,
+ mr->loop_normals,
+ orco,
+ &loop_data,
+ mr->loop_len,
+ &tangent_mask);
+ }
+ }
+
+ if (use_orco_tan) {
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(&loop_data, CD_TANGENT, 0);
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+ BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name);
+ GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
+ GPU_vertformat_alias_add(&format, "t");
+ GPU_vertformat_alias_add(&format, "at");
+ }
+
+ if (orco_allocated) {
+ MEM_SAFE_FREE(orco);
+ }
+
+ int v_len = mr->loop_len;
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ /* VBO will not be used, only allocate minimum of memory. */
+ v_len = 1;
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, v_len);
+
+ if (do_hq) {
+ short(*tan_data)[4] = (short(*)[4])GPU_vertbuf_get_data(vbo);
+ for (int i = 0; i < tan_len; i++) {
+ const char *name = tangent_names[i];
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(
+ &loop_data, CD_TANGENT, name);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
+ (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
+ tan_data++;
+ }
+ }
+ if (use_orco_tan) {
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
+ (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
+ tan_data++;
+ }
+ }
+ }
+ else {
+ GPUPackedNormal *tan_data = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo);
+ for (int i = 0; i < tan_len; i++) {
+ const char *name = tangent_names[i];
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(
+ &loop_data, CD_TANGENT, name);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
+ tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
+ tan_data++;
+ }
+ }
+ if (use_orco_tan) {
+ float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
+ *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
+ tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
+ tan_data++;
+ }
+ }
+ }
+
+ CustomData_free(&loop_data, mr->loop_len);
+}
+
+static void extract_tan_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ extract_tan_ex_init(mr, cache, vbo, false);
+}
+
+constexpr MeshExtract create_extractor_tan()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_tan_init;
+ extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan);
+ return extractor;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract HQ Tangent layers
+ * \{ */
+
+static void extract_tan_hq_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ extract_tan_ex_init(mr, cache, vbo, true);
+}
+
+constexpr MeshExtract create_extractor_tan_hq()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_tan_hq_init;
+ extractor.data_type = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_tan = blender::draw::create_extractor_tan();
+const MeshExtract extract_tan_hq = blender::draw::create_extractor_tan_hq();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
new file mode 100644
index 00000000000..0f3c2483296
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
@@ -0,0 +1,136 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "BLI_string.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract UV layers
+ * \{ */
+
+static void extract_uv_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat format = {0};
+ GPU_vertformat_deinterleave(&format);
+
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ uint32_t uv_layers = cache->cd_used.uv;
+ /* HACK to fix T68857 */
+ if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
+ int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ if (layer != -1) {
+ uv_layers |= (1 << layer);
+ }
+ }
+
+ for (int i = 0; i < MAX_MTFACE; i++) {
+ if (uv_layers & (1 << i)) {
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
+
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+ /* UV layer name. */
+ BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name);
+ GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ /* Auto layer name. */
+ BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
+ GPU_vertformat_alias_add(&format, attr_name);
+ /* Active render layer name. */
+ if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
+ GPU_vertformat_alias_add(&format, "u");
+ }
+ /* Active display layer name. */
+ if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
+ GPU_vertformat_alias_add(&format, "au");
+ /* Alias to `pos` for edit uvs. */
+ GPU_vertformat_alias_add(&format, "pos");
+ }
+ /* Stencil mask uv layer name. */
+ if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) {
+ GPU_vertformat_alias_add(&format, "mu");
+ }
+ }
+ }
+
+ int v_len = mr->loop_len;
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ /* VBO will not be used, only allocate minimum of memory. */
+ v_len = 1;
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, v_len);
+
+ float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo);
+ for (int i = 0; i < MAX_MTFACE; i++) {
+ if (uv_layers & (1 << i)) {
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i);
+ BMIter f_iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
+ memcpy(uv_data, luv->uv, sizeof(*uv_data));
+ uv_data++;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ else {
+ MLoopUV *layer_data = (MLoopUV *)CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
+ memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
+ }
+ }
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_uv()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_uv_init;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_uv = blender::draw::create_extractor_uv();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
new file mode 100644
index 00000000000..2f1cff08796
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
@@ -0,0 +1,191 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract VCol
+ * \{ */
+
+static void extract_vcol_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat format = {0};
+ GPU_vertformat_deinterleave(&format);
+
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
+ uint32_t vcol_layers = cache->cd_used.vcol;
+ uint32_t svcol_layers = cache->cd_used.sculpt_vcol;
+
+ for (int i = 0; i < MAX_MCOL; i++) {
+ if (vcol_layers & (1 << i)) {
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+
+ BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
+ GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) {
+ GPU_vertformat_alias_add(&format, "c");
+ }
+ if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) {
+ GPU_vertformat_alias_add(&format, "ac");
+ }
+
+ /* Gather number of auto layers. */
+ /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 &&
+ CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) {
+ BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
+ GPU_vertformat_alias_add(&format, attr_name);
+ }
+ }
+ }
+
+ /* Sculpt Vertex Colors */
+ if (U.experimental.use_sculpt_vertex_colors) {
+ for (int i = 0; i < 8; i++) {
+ if (svcol_layers & (1 << i)) {
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i);
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+
+ BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
+ GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) {
+ GPU_vertformat_alias_add(&format, "c");
+ }
+ if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) {
+ GPU_vertformat_alias_add(&format, "ac");
+ }
+ /* Gather number of auto layers. */
+ /* We only do `vcols` that are not overridden by `uvs`. */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
+ BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
+ GPU_vertformat_alias_add(&format, attr_name);
+ }
+ }
+ }
+ }
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+
+ using gpuMeshVcol = struct gpuMeshVcol {
+ ushort r, g, b, a;
+ };
+
+ gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo);
+ MLoop *loops = (MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP);
+
+ for (int i = 0; i < MAX_MCOL; i++) {
+ if (vcol_layers & (1 << i)) {
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
+ BMIter f_iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const MLoopCol *mloopcol = (const MLoopCol *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ vcol_data++;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ else {
+ const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) {
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ }
+ }
+ }
+
+ if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) {
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i);
+ BMIter f_iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const MPropCol *prop_col = (const MPropCol *)BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs);
+ vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]);
+ vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]);
+ vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]);
+ vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]);
+ vcol_data++;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ else {
+ MPropCol *vcol = (MPropCol *)CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i);
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) {
+ vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]);
+ vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]);
+ vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]);
+ vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]);
+ }
+ }
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_vcol()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_vcol_init;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_vcol = blender::draw::create_extractor_vcol();
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
new file mode 100644
index 00000000000..aae266eadce
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
@@ -0,0 +1,189 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_deform.h"
+
+#include "draw_cache_extract_mesh_private.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Vertex Weight
+ * \{ */
+
+struct MeshExtract_Weight_Data {
+ float *vbo_data;
+ const DRW_MeshWeightState *wstate;
+ const MDeformVert *dvert; /* For #Mesh. */
+ int cd_ofs; /* For #BMesh. */
+};
+
+static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
+{
+ /* Error state. */
+ if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) {
+ return -2.0f;
+ }
+ if (dvert == nullptr) {
+ return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f;
+ }
+
+ float input = 0.0f;
+ if (wstate->flags & DRW_MESH_WEIGHT_STATE_MULTIPAINT) {
+ /* Multi-Paint feature */
+ bool is_normalized = (wstate->flags & (DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE |
+ DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE));
+ input = BKE_defvert_multipaint_collective_weight(dvert,
+ wstate->defgroup_len,
+ wstate->defgroup_sel,
+ wstate->defgroup_sel_count,
+ is_normalized);
+ /* make it black if the selected groups have no weight on a vertex */
+ if (input == 0.0f) {
+ return -1.0f;
+ }
+ }
+ else {
+ /* default, non tricky behavior */
+ input = BKE_defvert_find_weight(dvert, wstate->defgroup_active);
+
+ if (input == 0.0f) {
+ switch (wstate->alert_mode) {
+ case OB_DRAW_GROUPUSER_ACTIVE:
+ return -1.0f;
+ break;
+ case OB_DRAW_GROUPUSER_ALL:
+ if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) {
+ return -1.0f;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */
+ if (wstate->flags & DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE) {
+ input = BKE_defvert_lock_relative_weight(
+ input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked);
+ }
+
+ CLAMP(input, 0.0f, 1.0f);
+ return input;
+}
+
+static void extract_weights_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
+
+ MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(tls_data);
+ data->vbo_data = (float *)GPU_vertbuf_get_data(vbo);
+ data->wstate = &cache->weight_state;
+
+ if (data->wstate->defgroup_active == -1) {
+ /* Nothing to show. */
+ data->dvert = nullptr;
+ data->cd_ofs = -1;
+ }
+ else if (mr->extract_type == MR_EXTRACT_BMESH) {
+ data->dvert = nullptr;
+ data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT);
+ }
+ else {
+ data->dvert = (const MDeformVert *)CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT);
+ data->cd_ofs = -1;
+ }
+}
+
+static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr),
+ const BMFace *f,
+ const int UNUSED(f_index),
+ void *_data)
+{
+ MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(_data);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const int l_index = BM_elem_index_get(l_iter);
+ if (data->cd_ofs != -1) {
+ const MDeformVert *dvert = (const MDeformVert *)BM_ELEM_CD_GET_VOID_P(l_iter->v,
+ data->cd_ofs);
+ data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate);
+ }
+ else {
+ data->vbo_data[l_index] = evaluate_vertex_weight(nullptr, data->wstate);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+}
+
+static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
+ const MPoly *mp,
+ const int UNUSED(mp_index),
+ void *_data)
+{
+ MeshExtract_Weight_Data *data = static_cast<MeshExtract_Weight_Data *>(_data);
+ const MLoop *mloop = mr->mloop;
+ const int ml_index_end = mp->loopstart + mp->totloop;
+ for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
+ const MLoop *ml = &mloop[ml_index];
+ if (data->dvert != nullptr) {
+ const MDeformVert *dvert = &data->dvert[ml->v];
+ data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
+ }
+ else {
+ const MDeformVert *dvert = nullptr;
+ data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate);
+ }
+ }
+}
+
+constexpr MeshExtract create_extractor_weights()
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = extract_weights_init;
+ extractor.iter_poly_bm = extract_weights_iter_poly_bm;
+ extractor.iter_poly_mesh = extract_weights_iter_poly_mesh;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = sizeof(MeshExtract_Weight_Data);
+ extractor.use_threading = true;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+const MeshExtract extract_weights = blender::draw::create_extractor_weights();
+}
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl
index 4012de4f95b..a980b87821a 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -18,7 +18,7 @@ layout(std140) uniform viewBlock
* Fourth components are near and far values. */
vec4 ViewVecs[2];
- /* TODO move it elsewhere. */
+ /* TODO: move it elsewhere. */
vec4 CameraTexCoFactors;
};
@@ -45,7 +45,7 @@ float mul_project_m4_v3_zfac(in vec3 co)
#endif
/* Not the right place but need to be common to all overlay's.
- * TODO Split to an overlay lib. */
+ * TODO: Split to an overlay lib. */
mat4 extract_matrix_packed_data(mat4 mat, out vec4 dataA, out vec4 dataB)
{
const float div = 1.0 / 255.0;
@@ -61,7 +61,7 @@ mat4 extract_matrix_packed_data(mat4 mat, out vec4 dataA, out vec4 dataB)
}
/* Same here, Not the right place but need to be common to all overlay's.
- * TODO Split to an overlay lib. */
+ * TODO: Split to an overlay lib. */
/* edge_start and edge_pos needs to be in the range [0..sizeViewport]. */
vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos)
{
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index f69830fc015..87688ee343c 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -4025,7 +4025,7 @@ static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac),
/* conditionally supported */
case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* this should only appear in tweakmode */
+ /* This should only appear in tweak-mode. */
return true;
}
else {
@@ -5176,7 +5176,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
}
/* step 3) draw special toggles .................................
- * - in Graph Editor, checkboxes for visibility in curves area
+ * - in Graph Editor, check-boxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
* - in Grease Pencil mode, color swatches for layer color
*/
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 136cdefd2ec..8f8c1c067d4 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -747,7 +747,7 @@ static bool animedit_poll_channels_active(bContext *C)
return 1;
}
-/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */
+/* Poll callback for Animation Editor channels list region + not in NLA-tweak-mode for NLA. */
static bool animedit_poll_channels_nla_tweakmode_off(bContext *C)
{
ScrArea *area = CTX_wm_area(C);
@@ -763,7 +763,7 @@ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C)
return 0;
}
- /* NLA TweakMode test */
+ /* NLA tweak-mode test. */
if (area->spacetype == SPACE_NLA) {
if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) {
return 0;
@@ -1283,6 +1283,9 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp)
else {
group_fcurves_last->next->prev = group_fcurves_first->prev;
}
+
+ /* Clear links pointing outside the per-group list. */
+ group_fcurves_first->prev = group_fcurves_last->next = NULL;
}
/* Initialize memory for temp-group */
@@ -1337,24 +1340,12 @@ static void join_groups_action_temp(bAction *act)
if (agrp->flag & AGRP_TEMP) {
LISTBASE_FOREACH (FCurve *, fcu, &agrp->channels) {
fcu->grp = NULL;
- if (fcu == agrp->channels.last) {
- break;
- }
}
BLI_remlink(&act->groups, agrp);
break;
}
}
-
- /* BLI_movelisttolist() doesn't touch first->prev and last->next pointers in its "dst" list.
- * Ensure that after the reshuffling the list is properly terminated. */
- if (!BLI_listbase_is_empty(&act->curves)) {
- FCurve *act_fcurves_first = act->curves.first;
- act_fcurves_first->prev = NULL;
- FCurve *act_fcurves_last = act->curves.last;
- act_fcurves_last->next = NULL;
- }
}
/* Change the order of anim-channels within action
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 745b869228a..2fcd59a1bbe 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -89,7 +89,7 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
/* *************************************************** */
/* PREVIEW RANGE 'CURTAINS' */
-/* Note: 'Preview Range' tools are defined in anim_ops.c */
+/* NOTE: 'Preview Range' tools are defined in `anim_ops.c`. */
/* Draw preview range 'curtains' for highlighting where the animation data is */
void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index f04fa556dad..b2d387ea898 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -32,7 +32,7 @@
* are being edited. Likewise, the NLA Editor also uses this for its channel list and in
* its operators.
*
- * Note: much of the original system this was based on was built before the creation of the RNA
+ * NOTE: much of the original system this was based on was built before the creation of the RNA
* system. In future, it would be interesting to replace some parts of this code with RNA queries,
* however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this
* system, so if any such work does occur, it should only be used for the internals used here...
@@ -131,7 +131,7 @@ static void animedit_get_yscale_factor(bAnimContext *ac)
/* ----------- Private Stuff - Action Editor ------------- */
/* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
-/* Note: there's a similar function in key.c (BKE_key_from_object) */
+/* NOTE: there's a similar function in key.c #BKE_key_from_object. */
static Key *actedit_get_shapekeys(bAnimContext *ac)
{
ViewLayer *view_layer = ac->view_layer;
@@ -222,9 +222,9 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
ac->mode = saction->mode;
return true;
- case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
+ case SACTCONT_MASK: /* Mask */ /* XXX: review how this mode is handled. */
{
- /* TODO, other methods to get the mask */
+ /* TODO: other methods to get the mask. */
#if 0
Sequence *seq = SEQ_select_active_get(ac->scene);
MovieClip *clip = ac->scene->clip;
@@ -454,7 +454,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
* keep expander channels with no sub-data out, as those cases should get
* dealt with by the recursive detection idiom in place.
*
- * Implementation Note:
+ * Implementation NOTE:
* YES the _doSubChannels variable is NOT read anywhere. BUT, this is NOT an excuse
* to go steamrolling the logic into a single-line expression as from experience,
* those are notoriously difficult to read + debug when extending later on. The code
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 7adddf8f4ae..9d998326b4d 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -687,7 +687,7 @@ static int ed_marker_add_exec(bContext *C, wmOperator *UNUSED(op))
marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
marker->flag = SELECT;
marker->frame = frame;
- BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); /* XXX - temp code only */
+ BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); /* XXX: temp code only. */
BLI_addtail(markers, marker);
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
@@ -897,7 +897,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_CANCELLED;
}
-/* note, init has to be called successfully */
+/* NOTE: init has to be called successfully. */
static void ed_marker_move_apply(bContext *C, wmOperator *op)
{
#ifdef DURIAN_CAMERA_SWITCH
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index aac2465d43a..51a897600e1 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -355,7 +355,7 @@ static void motionpath_free_free_tree_data(ListBase *targets)
/* Perform baking of the given object's and/or its bones' transforms to motion paths
* - scene: current scene
- * - ob: object whose flagged motionpaths should get calculated
+ * - ob: object whose flagged motion-paths should get calculated
* - recalc: whether we need to
*/
/* TODO: include reports pointer? */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 72d9bff545a..6f3277397c5 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -51,8 +51,10 @@
#include "DEG_depsgraph.h"
+#include "SEQ_iterator.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
+#include "SEQ_transform.h"
#include "anim_intern.h"
@@ -81,6 +83,49 @@ static bool change_frame_poll(bContext *C)
return false;
}
+static int seq_snap_threshold_get_frame_distance(bContext *C)
+{
+ const int snap_distance = SEQ_tool_settings_snap_distance_get(CTX_data_scene(C));
+ const ARegion *region = CTX_wm_region(C);
+ return round_fl_to_int(UI_view2d_region_to_view_x(&region->v2d, snap_distance) -
+ UI_view2d_region_to_view_x(&region->v2d, 0));
+}
+
+static void seq_frame_snap_update_best(const int position,
+ const int timeline_frame,
+ int *r_best_frame,
+ int *r_best_distance)
+{
+ if (abs(position - timeline_frame) < *r_best_distance) {
+ *r_best_distance = abs(position - timeline_frame);
+ *r_best_frame = position;
+ }
+}
+
+static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_frame)
+{
+
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene, false));
+ SeqCollection *strips = SEQ_query_all_strips(seqbase);
+
+ int best_frame = 0;
+ int best_distance = MAXFRAME;
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ seq_frame_snap_update_best(
+ SEQ_transform_get_left_handle_frame(seq), timeline_frame, &best_frame, &best_distance);
+ seq_frame_snap_update_best(
+ SEQ_transform_get_right_handle_frame(seq), timeline_frame, &best_frame, &best_distance);
+ }
+ SEQ_collection_free(strips);
+
+ if (best_distance < seq_snap_threshold_get_frame_distance(C)) {
+ return best_frame;
+ }
+
+ return timeline_frame;
+}
+
/* Set the new frame number */
static void change_frame_apply(bContext *C, wmOperator *op)
{
@@ -90,7 +135,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
if (do_snap) {
if (CTX_wm_space_seq(C)) {
- frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+ frame = seq_frame_apply_snap(C, scene, frame);
}
else {
frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame);
@@ -181,6 +226,18 @@ static void change_frame_seq_preview_end(bContext *C)
}
}
+static bool use_sequencer_snapping(bContext *C)
+{
+ if (!CTX_wm_space_seq(C)) {
+ return false;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ short snap_flag = SEQ_tool_settings_snap_flag_get(scene);
+ return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) &&
+ (snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS);
+}
+
/* Modal Operator init */
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -190,6 +247,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
*/
RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
+ if (use_sequencer_snapping(C)) {
+ RNA_boolean_set(op->ptr, "snap", true);
+ }
+
change_frame_seq_preview_begin(C, event);
change_frame_apply(C, op);
@@ -231,11 +292,22 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EVT_LEFTCTRLKEY:
case EVT_RIGHTCTRLKEY:
- if (event->val == KM_RELEASE) {
- RNA_boolean_set(op->ptr, "snap", false);
+ /* Use Ctrl key to invert snapping in sequencer. */
+ if (use_sequencer_snapping(C)) {
+ if (event->val == KM_RELEASE) {
+ RNA_boolean_set(op->ptr, "snap", true);
+ }
+ else if (event->val == KM_PRESS) {
+ RNA_boolean_set(op->ptr, "snap", false);
+ }
}
- else if (event->val == KM_PRESS) {
- RNA_boolean_set(op->ptr, "snap", true);
+ else {
+ if (event->val == KM_RELEASE) {
+ RNA_boolean_set(op->ptr, "snap", false);
+ }
+ else if (event->val == KM_PRESS) {
+ RNA_boolean_set(op->ptr, "snap", true);
+ }
}
break;
}
@@ -465,7 +537,7 @@ static void ANIM_OT_previewrange_set(wmOperatorType *ot)
/* rna */
/* used to define frame range.
*
- * note: border Y values are not used,
+ * NOTE: border Y values are not used,
* but are needed by box_select gesture operator stuff */
WM_operator_properties_border(ot);
}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index dae2138e481..bfaa76b3bf9 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -80,7 +80,7 @@ FCurve *verify_driver_fcurve(ID *id,
/* init animdata if none available yet */
adt = BKE_animdata_from_id(id);
if (adt == NULL && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) {
- adt = BKE_animdata_add_id(id);
+ adt = BKE_animdata_ensure_id(id);
}
if (adt == NULL) {
/* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
@@ -581,7 +581,7 @@ bool ANIM_remove_driver(ReportList *UNUSED(reports),
}
else {
/* find the matching driver and remove it only
- * Note: here is one of the places where we don't want new F-Curve + Driver added!
+ * NOTE: here is one of the places where we don't want new F-Curve + Driver added!
* so 'add' var must be 0
*/
fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_LOOKUP_ONLY);
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index aeead9350e9..0923d490110 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -1024,7 +1024,7 @@ static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
return 0;
}
-/* Note: for markers and 'value', the values to use must be supplied as the first float value */
+/* NOTE: for markers and 'value', the values to use must be supplied as the first float value. */
/* calchandles_fcurve */
KeyframeEditFunc ANIM_editkeyframes_mirror(short mode)
{
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index aeddd03f3c1..eb91afa5c84 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -932,7 +932,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(Main *bmain,
int len_id = strlen(identifier);
int len_path = strlen(fcu->rna_path);
if (len_id <= len_path) {
- /* note, paths which end with "] will fail with this test - Animated ID Props */
+ /* NOTE: paths which end with "] will fail with this test - Animated ID Props. */
if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
if ((from_single) || (aci->array_index == fcu->array_index)) {
break;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 9364be41543..0a499232ba9 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -85,6 +85,8 @@ static KeyingSet *keyingset_get_from_op_with_error(wmOperator *op,
PropertyRNA *prop,
Scene *scene);
+static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks);
+
/* ************************************************** */
/* Keyframing Setting Wrangling */
@@ -140,7 +142,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id)
/* init animdata if none available yet */
adt = BKE_animdata_from_id(id);
if (adt == NULL) {
- adt = BKE_animdata_add_id(id);
+ adt = BKE_animdata_ensure_id(id);
}
if (adt == NULL) {
/* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
@@ -1672,7 +1674,7 @@ int delete_keyframe(Main *bmain,
}
/* get F-Curve
- * Note: here is one of the places where we don't want new Action + F-Curve added!
+ * NOTE: here is one of the places where we don't want new Action + F-Curve added!
* so 'add' var must be 0
*/
if (act == NULL) {
@@ -1779,7 +1781,7 @@ static int clear_keyframe(Main *bmain,
}
/* get F-Curve
- * Note: here is one of the places where we don't want new Action + F-Curve added!
+ * NOTE: here is one of the places where we don't want new Action + F-Curve added!
* so 'add' var must be 0
*/
if (act == NULL) {
@@ -2079,42 +2081,19 @@ void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
static int delete_key_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */
- int num_channels;
-
KeyingSet *ks = keyingset_get_from_op_with_error(op, op->type->prop, scene);
if (ks == NULL) {
return OPERATOR_CANCELLED;
}
- const int prop_type = RNA_property_type(op->type->prop);
- if (prop_type == PROP_ENUM) {
- int type = RNA_property_enum_get(op->ptr, op->type->prop);
- ks = ANIM_keyingset_get_from_enum_type(scene, type);
- if (ks == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
- return OPERATOR_CANCELLED;
- }
- }
- else if (prop_type == PROP_STRING) {
- char type_id[MAX_ID_NAME - 2];
- RNA_property_string_get(op->ptr, op->type->prop, type_id);
- ks = ANIM_keyingset_get_from_idname(scene, type_id);
-
- if (ks == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Active Keying Set '%s' not found", type_id);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- BLI_assert(0);
- }
+ return delete_key_using_keying_set(C, op, ks);
+}
- /* report failure */
- if (ks == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
- return OPERATOR_CANCELLED;
- }
+static int delete_key_using_keying_set(bContext *C, wmOperator *op, KeyingSet *ks)
+{
+ Scene *scene = CTX_data_scene(C);
+ float cfra = (float)CFRA; /* XXX for now, don't bother about all the yucky offset crap */
+ int num_channels;
/* try to delete keyframes for the channels specified by KeyingSet */
num_channels = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
@@ -2130,7 +2109,8 @@ static int delete_key_exec(bContext *C, wmOperator *op)
if (num_channels > 0) {
/* if the appropriate properties have been set, make a note that we've inserted something */
- if (RNA_boolean_get(op->ptr, "confirm_success")) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "confirm_success");
+ if (prop != NULL && RNA_property_boolean_get(op->ptr, prop)) {
BKE_reportf(op->reports,
RPT_INFO,
"Successfully removed %d keyframes for keying set '%s'",
@@ -2301,7 +2281,7 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int delete_key_v3d_exec(bContext *C, wmOperator *op)
+static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
float cfra = (float)CFRA;
@@ -2408,6 +2388,18 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int delete_key_v3d_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks = ANIM_scene_get_active_keyingset(scene);
+
+ if (ks == NULL) {
+ return delete_key_v3d_without_keying_set(C, op);
+ }
+
+ return delete_key_using_keying_set(C, op, ks);
+}
+
void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
{
/* identifiers */
@@ -2931,7 +2923,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
}
/* 2. test for time */
- /* TODO... yet to be implemented (this feature may evolve before then anyway) */
+ /* TODO: yet to be implemented (this feature may evolve before then anyway). */
}
/* try materials */
@@ -3101,7 +3093,7 @@ bool ED_autokeyframe_property(
ToolSettings *ts = scene->toolsettings;
const eInsertKeyFlags flag = ANIM_get_keyframing_flags(scene, true);
- /* Note: We use rnaindex instead of fcu->array_index,
+ /* NOTE: We use rnaindex instead of fcu->array_index,
* because a button may control all items of an array at once.
* E.g., color wheels (see T42567). */
BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1));
diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c
index 034378399b9..6af033f3cf2 100644
--- a/source/blender/editors/animation/time_scrub_ui.c
+++ b/source/blender/editors/animation/time_scrub_ui.c
@@ -109,7 +109,7 @@ static void draw_current_frame(const Scene *scene,
if (draw_line) {
/* Draw vertical line to from the bottom of the current frame box to the bottom of the screen.
*/
- const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_frame_get(scene));
+ const float subframe_x = UI_view2d_view_to_region_x(v2d, BKE_scene_ctime_get(scene));
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 0030e78002b..e942bcf2902 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -20,6 +20,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blenloader
../../blentranslation
../../depsgraph
../../gpu
@@ -43,9 +44,11 @@ set(SRC
armature_utils.c
editarmature_undo.c
meshlaplacian.c
+ pose_backup.c
pose_edit.c
pose_group.c
pose_lib.c
+ pose_lib_2.c
pose_select.c
pose_slide.c
pose_transform.c
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 0ee11a6ef55..45bf18fe1bb 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -225,7 +225,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* TODO most of this code is copied from set3dcursor_invoke,
+ /* TODO: most of this code is copied from set3dcursor_invoke,
* it would be better to reuse code in set3dcursor_invoke */
/* temporarily change 3d cursor position */
@@ -438,17 +438,15 @@ static void updateDuplicateSubtarget(EditBone *dup_bone,
}
}
-static void updateDuplicateActionConstraintSettings(EditBone *dup_bone,
- EditBone *orig_bone,
- Object *ob,
- bConstraint *curcon)
+static void updateDuplicateActionConstraintSettings(
+ EditBone *dup_bone, EditBone *orig_bone, Object *ob, bPoseChannel *pchan, bConstraint *curcon)
{
bActionConstraint *act_con = (bActionConstraint *)curcon->data;
bAction *act = (bAction *)act_con->act;
float mat[4][4];
- bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = NULL};
+ bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan};
BKE_constraint_custom_object_space_get(cob.space_obj_world_matrix, curcon);
unit_m4(mat);
@@ -832,7 +830,7 @@ static void updateDuplicateConstraintSettings(EditBone *dup_bone, EditBone *orig
for (curcon = conlist->first; curcon; curcon = curcon->next) {
switch (curcon->type) {
case CONSTRAINT_TYPE_ACTION:
- updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, curcon);
+ updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, pchan, curcon);
break;
case CONSTRAINT_TYPE_KINEMATIC:
updateDuplicateKinematicConstraintSettings(curcon);
@@ -1603,7 +1601,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
ED_armature_edit_refresh_layer_used(obedit->data);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT);
ED_outliner_select_sync_from_edit_bone_tag(C);
@@ -1694,7 +1692,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
DEG_id_tag_update(&obedit->id, ID_RECALC_SELECT);
ED_outliner_select_sync_from_edit_bone_tag(C);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 48b487c29fd..ea6c71fd33f 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -228,7 +228,7 @@ float ED_armature_ebone_roll_to_vector(const EditBone *bone,
return roll;
}
-/* note, ranges arithmetic is used below */
+/* NOTE: ranges arithmetic is used below. */
typedef enum eCalcRollTypes {
/* pos */
CALC_ROLL_POS_X = 0,
@@ -449,7 +449,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
}
if (changed) {
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
}
@@ -519,7 +519,7 @@ static int armature_roll_clear_exec(bContext *C, wmOperator *op)
}
if (changed) {
- /* Note, notifier might evolve. */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
}
@@ -577,7 +577,7 @@ static void chains_find_tips(ListBase *edbo, ListBase *list)
EditBone *curBone, *ebo;
LinkData *ld;
- /* note: this is potentially very slow ... there's got to be a better way */
+ /* NOTE: this is potentially very slow ... there's got to be a better way. */
for (curBone = edbo->first; curBone; curBone = curBone->next) {
short stop = 0;
@@ -1000,7 +1000,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
armature_clear_swap_done_flags(arm);
armature_tag_unselect(arm);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
}
@@ -1151,7 +1151,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
}
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index d429e51061b..f9950d27e97 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -203,6 +203,10 @@ void POSELIB_OT_pose_move(struct wmOperatorType *ot);
void POSELIB_OT_browse_interactive(struct wmOperatorType *ot);
void POSELIB_OT_apply_pose(struct wmOperatorType *ot);
+/* pose_lib_2.c */
+void POSELIB_OT_apply_pose_asset(struct wmOperatorType *ot);
+void POSELIB_OT_blend_pose_asset(struct wmOperatorType *ot);
+
/* ******************************************************* */
/* Pose Sliding Tools */
/* pose_slide.c */
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 70154695dcd..35bd30377c8 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -69,7 +69,7 @@
/** \name Unique Bone Name Utility (Edit Mode)
* \{ */
-/* note: there's a ed_armature_bone_unique_name() too! */
+/* NOTE: there's a ed_armature_bone_unique_name() too! */
static bool editbone_unique_check(void *arg, const char *name)
{
struct {
@@ -589,7 +589,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op)
/* Since we renamed stuff... */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* Note, notifier might evolve. */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
MEM_freeN(objects);
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index a0face26bae..fbd89106de5 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -131,6 +131,8 @@ void ED_operatortypes_armature(void)
/* POSELIB */
WM_operatortype_append(POSELIB_OT_browse_interactive);
WM_operatortype_append(POSELIB_OT_apply_pose);
+ WM_operatortype_append(POSELIB_OT_apply_pose_asset);
+ WM_operatortype_append(POSELIB_OT_blend_pose_asset);
WM_operatortype_append(POSELIB_OT_pose_add);
WM_operatortype_append(POSELIB_OT_pose_remove);
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index c447138f00c..32fd1c9ad41 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -703,7 +703,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ok = true;
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob_old);
}
MEM_freeN(bases);
@@ -893,7 +893,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
}
}
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
DEG_id_tag_update(&ob->id, ID_RECALC_SELECT);
@@ -1004,7 +1004,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
ED_armature_edit_sync_selection(arm->edbo);
- /* Note, notifier might evolve. */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
}
MEM_freeN(objects);
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 65f30c3729f..bd799c00373 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -1426,7 +1426,7 @@ static void armature_select_more_less(Object *ob, bool more)
bArmature *arm = (bArmature *)ob->data;
EditBone *ebone;
- /* XXX, eventually we shouldn't need this - campbell */
+ /* XXX(campbell): eventually we shouldn't need this. */
ED_armature_edit_sync_selection(arm->edbo);
/* count bones & store selection state */
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index fc9191967f8..ec5c665402b 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -478,7 +478,7 @@ void ED_object_vgroup_calc_from_armature(ReportList *reports,
bArmature *arm = par->data;
if (mode == ARM_GROUPS_NAME) {
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const int defbase_tot = BKE_object_defgroup_count(ob);
int defbase_add;
/* Traverse the bone list, trying to create empty vertex
* groups corresponding to the bone.
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index bc6d0687654..874f1b49451 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -391,7 +391,7 @@ void armature_tag_unselect(bArmature *arm)
void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select)
{
- /* TODO When this function is called by property updates,
+ /* TODO: When this function is called by property updates,
* canceling the value change will not restore mirrored bone correctly. */
/* Currently check_select==true when this function is called from a transform operator,
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index 725945f8edc..832e75b2a8b 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -206,7 +206,7 @@ static void armature_undosys_step_decode(struct bContext *C,
}
undoarm_to_editarm(&elem->data, arm);
arm->needs_flush_to_id = 1;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&arm->id, ID_RECALC_GEOMETRY);
}
/* The first element is always active */
diff --git a/source/blender/editors/armature/pose_backup.c b/source/blender/editors/armature/pose_backup.c
new file mode 100644
index 00000000000..dffcd9bdc5a
--- /dev/null
+++ b/source/blender/editors/armature/pose_backup.c
@@ -0,0 +1,139 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edarmature
+ */
+
+#include "ED_armature.h"
+
+#include <string.h>
+
+#include "BLI_listbase.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_idprop.h"
+
+/* simple struct for storing backup info for one pose channel */
+typedef struct PoseChannelBackup {
+ struct PoseChannelBackup *next, *prev;
+
+ struct bPoseChannel *pchan; /* Pose channel this backup is for. */
+
+ struct bPoseChannel olddata; /* Backup of pose channel. */
+ struct IDProperty *oldprops; /* Backup copy (needs freeing) of pose channel's ID properties. */
+} PoseChannelBackup;
+
+typedef struct PoseBackup {
+ bool is_bone_selection_relevant;
+ ListBase /* PoseChannelBackup* */ backups;
+} PoseBackup;
+
+static PoseBackup *pose_backup_create(const Object *ob,
+ const bAction *action,
+ const bool is_bone_selection_relevant)
+{
+ ListBase backups = {NULL, NULL};
+ const bArmature *armature = ob->data;
+
+ /* TODO(Sybren): reuse same approach as in `armature_pose.cc` in this function, as that doesn't
+ * have the assumption that action group names are bone names. */
+ LISTBASE_FOREACH (bActionGroup *, agrp, &action->groups) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+ if (pchan == NULL) {
+ continue;
+ }
+
+ if (is_bone_selection_relevant && !PBONE_SELECTED(armature, pchan->bone)) {
+ continue;
+ }
+
+ PoseChannelBackup *chan_bak = MEM_callocN(sizeof(*chan_bak), "PoseChannelBackup");
+ chan_bak->pchan = pchan;
+ memcpy(&chan_bak->olddata, chan_bak->pchan, sizeof(chan_bak->olddata));
+
+ if (pchan->prop) {
+ chan_bak->oldprops = IDP_CopyProperty(pchan->prop);
+ }
+
+ BLI_addtail(&backups, chan_bak);
+ }
+
+ /* PoseBackup is constructed late, so that the above loop can use stack variables. */
+ PoseBackup *pose_backup = MEM_callocN(sizeof(*pose_backup), __func__);
+ pose_backup->is_bone_selection_relevant = is_bone_selection_relevant;
+ pose_backup->backups = backups;
+ return pose_backup;
+}
+
+PoseBackup *ED_pose_backup_create_all_bones(const Object *ob, const bAction *action)
+{
+ return pose_backup_create(ob, action, false);
+}
+
+PoseBackup *ED_pose_backup_create_selected_bones(const Object *ob, const bAction *action)
+{
+ /* See if bone selection is relevant. */
+ bool all_bones_selected = true;
+ bool no_bones_selected = true;
+ const bArmature *armature = ob->data;
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ const bool is_selected = PBONE_SELECTED(armature, pchan->bone);
+ all_bones_selected &= is_selected;
+ no_bones_selected &= !is_selected;
+ }
+
+ /* If no bones are selected, act as if all are. */
+ const bool is_bone_selection_relevant = !all_bones_selected && !no_bones_selected;
+ return pose_backup_create(ob, action, is_bone_selection_relevant);
+}
+
+bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup)
+{
+ return pose_backup->is_bone_selection_relevant;
+}
+
+void ED_pose_backup_restore(const PoseBackup *pbd)
+{
+ LISTBASE_FOREACH (PoseChannelBackup *, chan_bak, &pbd->backups) {
+ memcpy(chan_bak->pchan, &chan_bak->olddata, sizeof(chan_bak->olddata));
+
+ if (chan_bak->oldprops) {
+ IDP_SyncGroupValues(chan_bak->pchan->prop, chan_bak->oldprops);
+ }
+
+ /* TODO: constraints settings aren't restored yet,
+ * even though these could change (though not that likely) */
+ }
+}
+
+void ED_pose_backup_free(PoseBackup *pbd)
+{
+ LISTBASE_FOREACH_MUTABLE (PoseChannelBackup *, chan_bak, &pbd->backups) {
+ if (chan_bak->oldprops) {
+ IDP_FreeProperty(chan_bak->oldprops);
+ }
+ BLI_freelinkN(&pbd->backups, chan_bak);
+ }
+ MEM_freeN(pbd);
+}
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index f86cc1159d5..20d7baa39ed 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -318,7 +318,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
TIMEIT_START(recalc_pose_paths);
#endif
- /* calculate the bones that now have motionpaths... */
+ /* Calculate the bones that now have motionpaths. */
/* TODO: only make for the selected bones? */
ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL);
@@ -396,7 +396,7 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- /* calculate the bones that now have motionpaths... */
+ /* Calculate the bones that now have motion-paths. */
/* TODO: only make for the selected bones? */
ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL);
@@ -567,7 +567,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *op)
/* since we renamed stuff... */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -618,7 +618,7 @@ static int pose_autoside_names_exec(bContext *C, wmOperator *op)
/* since we renamed stuff... */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
ob_prev = ob;
}
@@ -760,7 +760,7 @@ static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op)
RNA_boolean_set_array(&ptr, "layers", layers);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
@@ -833,7 +833,7 @@ static int armature_layers_exec(bContext *C, wmOperator *op)
RNA_id_pointer_create((ID *)arm, &ptr);
RNA_boolean_set_array(&ptr, "layers", layers);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
@@ -919,7 +919,7 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op)
RNA_boolean_set_array(&ptr, "layers", layers);
if (prev_ob != ob) {
- /* Note, notifier might evolve. */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE);
prev_ob = ob;
@@ -998,7 +998,7 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op)
ED_armature_edit_refresh_layer_used(ob->data);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/armature/pose_lib_2.c b/source/blender/editors/armature/pose_lib_2.c
new file mode 100644
index 00000000000..eb091296282
--- /dev/null
+++ b/source/blender/editors/armature/pose_lib_2.c
@@ -0,0 +1,638 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021, Blender Foundation
+ */
+
+/** \file
+ * \ingroup edarmature
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_armature_types.h"
+
+#include "BKE_action.h"
+#include "BKE_anim_data.h"
+#include "BKE_animsys.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_lib_id.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+
+#include "ED_armature.h"
+#include "ED_asset.h"
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+
+#include "armature_intern.h"
+
+typedef enum ePoseBlendState {
+ POSE_BLEND_INIT,
+ POSE_BLEND_BLENDING,
+ POSE_BLEND_ORIGINAL,
+ POSE_BLEND_CONFIRM,
+ POSE_BLEND_CANCEL,
+} ePoseBlendState;
+
+typedef struct PoseBlendData {
+ ePoseBlendState state;
+ bool needs_redraw;
+
+ struct {
+ bool use_release_confirm;
+ int drag_start_xy[2];
+ int init_event_type;
+
+ bool cursor_wrap_enabled;
+ } release_confirm_info;
+
+ /* For temp-loading the Action from the pose library. */
+ AssetTempIDConsumer *temp_id_consumer;
+
+ /* Blend factor, interval [0, 1] for interpolating between current and given pose. */
+ float blend_factor;
+ struct PoseBackup *pose_backup;
+
+ Object *ob; /* Object to work on. */
+ bAction *act; /* Pose to blend into the current pose. */
+ bool free_action;
+
+ Scene *scene; /* For auto-keying. */
+ ScrArea *area; /* For drawing status text. */
+
+ /** Info-text to print in header. */
+ char headerstr[UI_MAX_DRAW_STR];
+} PoseBlendData;
+
+/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
+static void poselib_backup_posecopy(PoseBlendData *pbd)
+{
+ pbd->pose_backup = ED_pose_backup_create_selected_bones(pbd->ob, pbd->act);
+
+ if (pbd->state == POSE_BLEND_INIT) {
+ /* Ready for blending now. */
+ pbd->state = POSE_BLEND_BLENDING;
+ }
+}
+
+/* ---------------------------- */
+
+/* Auto-key/tag bones affected by the pose Action. */
+static void poselib_keytag_pose(bContext *C, Scene *scene, PoseBlendData *pbd)
+{
+ if (!autokeyframe_cfra_can_key(scene, &pbd->ob->id)) {
+ return;
+ }
+
+ AnimData *adt = BKE_animdata_from_id(&pbd->ob->id);
+ if (adt != NULL && adt->action != NULL && ID_IS_LINKED(&adt->action->id)) {
+ /* Changes to linked-in Actions are not allowed. */
+ return;
+ }
+
+ bPose *pose = pbd->ob->pose;
+ bAction *act = pbd->act;
+
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+ ListBase dsources = {NULL, NULL};
+
+ /* start tagging/keying */
+ const bArmature *armature = pbd->ob->data;
+ LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
+ /* only for selected bones unless there aren't any selected, in which case all are included */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, agrp->name);
+ if (pchan == NULL) {
+ continue;
+ }
+
+ if (ED_pose_backup_is_selection_relevant(pbd->pose_backup) &&
+ !PBONE_SELECTED(armature, pchan->bone)) {
+ continue;
+ }
+
+ /* Add data-source override for the PoseChannel, to be used later. */
+ ANIM_relative_keyingset_add_source(&dsources, &pbd->ob->id, &RNA_PoseBone, pchan);
+ }
+
+ /* Perform actual auto-keying. */
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
+
+ /* send notifiers for this */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+}
+
+/* Apply the relevant changes to the pose */
+static void poselib_blend_apply(bContext *C, wmOperator *op)
+{
+ PoseBlendData *pbd = (PoseBlendData *)op->customdata;
+
+ if (pbd->state == POSE_BLEND_BLENDING) {
+ BLI_snprintf(pbd->headerstr,
+ sizeof(pbd->headerstr),
+ TIP_("PoseLib blending: \"%s\" at %3.0f%%"),
+ pbd->act->id.name + 2,
+ pbd->blend_factor * 100);
+ ED_area_status_text(pbd->area, pbd->headerstr);
+
+ ED_workspace_status_text(
+ C, TIP_("Tab: show original pose; Horizontal mouse movement: change blend percentage"));
+ }
+ else {
+ ED_area_status_text(pbd->area, TIP_("PoseLib showing original pose"));
+ ED_workspace_status_text(C, TIP_("Tab: show blended pose"));
+ }
+
+ if (!pbd->needs_redraw) {
+ return;
+ }
+ pbd->needs_redraw = false;
+
+ ED_pose_backup_restore(pbd->pose_backup);
+
+ /* The pose needs updating, whether it's for restoring the original pose or for showing the
+ * result of the blend. */
+ DEG_id_tag_update(&pbd->ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pbd->ob);
+
+ if (pbd->state != POSE_BLEND_BLENDING) {
+ return;
+ }
+
+ /* Perform the actual blending. */
+ struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, 0.0f);
+ BKE_pose_apply_action_blend(pbd->ob, pbd->act, &anim_eval_context, pbd->blend_factor);
+}
+
+/* ---------------------------- */
+
+static void poselib_blend_set_factor(PoseBlendData *pbd, const float new_factor)
+{
+ pbd->blend_factor = CLAMPIS(new_factor, 0.0f, 1.0f);
+ pbd->needs_redraw = true;
+}
+
+static void poselib_slide_mouse_update_blendfactor(PoseBlendData *pbd, const wmEvent *event)
+{
+ if (pbd->release_confirm_info.use_release_confirm) {
+ /* Release confirm calculates factor based on where the dragging was started from. */
+ const float range = 300 * U.pixelsize;
+ const float new_factor = (event->x - pbd->release_confirm_info.drag_start_xy[0]) / range;
+ poselib_blend_set_factor(pbd, new_factor);
+ }
+ else {
+ const float new_factor = (event->x - pbd->area->v1->vec.x) / ((float)pbd->area->winx);
+ poselib_blend_set_factor(pbd, new_factor);
+ }
+}
+
+/* Return operator return value. */
+static int poselib_blend_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event)
+{
+ PoseBlendData *pbd = op->customdata;
+
+ if (event->type == MOUSEMOVE) {
+ poselib_slide_mouse_update_blendfactor(pbd, event);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* Handle the release confirm event directly, it has priority over others. */
+ if (pbd->release_confirm_info.use_release_confirm &&
+ (event->type == pbd->release_confirm_info.init_event_type) && (event->val == KM_RELEASE)) {
+ pbd->state = POSE_BLEND_CONFIRM;
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* only accept 'press' event, and ignore 'release', so that we don't get double actions */
+ if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* NORMAL EVENT HANDLING... */
+ /* searching takes priority over normal activity */
+ switch (event->type) {
+ /* Exit - cancel. */
+ case EVT_ESCKEY:
+ case RIGHTMOUSE:
+ pbd->state = POSE_BLEND_CANCEL;
+ break;
+
+ /* Exit - confirm. */
+ case LEFTMOUSE:
+ case EVT_RETKEY:
+ case EVT_PADENTER:
+ case EVT_SPACEKEY:
+ pbd->state = POSE_BLEND_CONFIRM;
+ break;
+
+ /* TODO(Sybren): toggle between original pose and poselib pose. */
+ case EVT_TABKEY:
+ pbd->state = pbd->state == POSE_BLEND_BLENDING ? POSE_BLEND_ORIGINAL : POSE_BLEND_BLENDING;
+ pbd->needs_redraw = true;
+ break;
+
+ /* TODO(Sybren): use better UI for slider. */
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void poselib_blend_cursor_update(bContext *C, wmOperator *op)
+{
+ PoseBlendData *pbd = op->customdata;
+
+ /* Ensure cursor-grab (continuous grabbing) is enabled when using release-confirm. */
+ if (pbd->release_confirm_info.use_release_confirm &&
+ !pbd->release_confirm_info.cursor_wrap_enabled) {
+ WM_cursor_grab_enable(CTX_wm_window(C), WM_CURSOR_WRAP_XY, true, NULL);
+ pbd->release_confirm_info.cursor_wrap_enabled = true;
+ }
+}
+
+/* ---------------------------- */
+
+static Object *get_poselib_object(bContext *C)
+{
+ if (C == NULL) {
+ return NULL;
+ }
+ return BKE_object_pose_armature_get(CTX_data_active_object(C));
+}
+
+static void poselib_tempload_exit(PoseBlendData *pbd)
+{
+ ED_asset_temp_id_consumer_free(&pbd->temp_id_consumer);
+}
+
+static bAction *poselib_blend_init_get_action(bContext *C, wmOperator *op)
+{
+ bool asset_handle_valid;
+ const AssetLibraryReference *asset_library = CTX_wm_asset_library(C);
+ const AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid);
+ /* Poll callback should check. */
+ BLI_assert((asset_library != NULL) && asset_handle_valid);
+
+ PoseBlendData *pbd = op->customdata;
+
+ pbd->temp_id_consumer = ED_asset_temp_id_consumer_create(&asset_handle);
+ return (bAction *)ED_asset_temp_id_consumer_ensure_local_id(
+ pbd->temp_id_consumer, C, asset_library, ID_AC, CTX_data_main(C), op->reports);
+}
+
+static bAction *flip_pose(bContext *C, Object *ob, bAction *action)
+{
+ bAction *action_copy = (bAction *)BKE_id_copy_ex(NULL, &action->id, NULL, LIB_ID_COPY_LOCALIZE);
+
+ /* Lock the window manager while flipping the pose. Flipping requires temporarily modifying the
+ * pose, which can cause unwanted visual glitches. */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ const bool interface_was_locked = CTX_wm_interface_locked(C);
+ WM_set_locked_interface(wm, true);
+
+ BKE_action_flip_with_pose(action_copy, ob);
+
+ WM_set_locked_interface(wm, interface_was_locked);
+ return action_copy;
+}
+
+/* Return true on success, false if the context isn't suitable. */
+static bool poselib_blend_init_data(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ op->customdata = NULL;
+
+ /* check if valid poselib */
+ Object *ob = get_poselib_object(C);
+ if (ELEM(NULL, ob, ob->pose, ob->data)) {
+ BKE_report(op->reports, RPT_ERROR, TIP_("Pose lib is only for armatures in pose mode"));
+ return false;
+ }
+
+ /* Set up blend state info. */
+ PoseBlendData *pbd;
+ op->customdata = pbd = MEM_callocN(sizeof(PoseBlendData), "PoseLib Preview Data");
+
+ bAction *action = poselib_blend_init_get_action(C, op);
+ if (action == NULL) {
+ return false;
+ }
+
+ /* Maybe flip the Action. */
+ const bool apply_flipped = RNA_boolean_get(op->ptr, "flipped");
+ if (apply_flipped) {
+ action = flip_pose(C, ob, action);
+ pbd->free_action = true;
+ }
+ pbd->act = action;
+
+ /* Get the basic data. */
+ pbd->ob = ob;
+ pbd->ob->pose = ob->pose;
+
+ pbd->scene = CTX_data_scene(C);
+ pbd->area = CTX_wm_area(C);
+
+ pbd->state = POSE_BLEND_INIT;
+ pbd->needs_redraw = true;
+ pbd->blend_factor = RNA_float_get(op->ptr, "blend_factor");
+ /* Just to avoid a clang-analyzer warning (false positive), it's set properly below. */
+ pbd->release_confirm_info.use_release_confirm = false;
+
+ /* Release confirm data. Only available if there's an event to work with. */
+ if (event != NULL) {
+ PropertyRNA *release_confirm_prop = RNA_struct_find_property(op->ptr, "release_confirm");
+ pbd->release_confirm_info.use_release_confirm = (release_confirm_prop != NULL) &&
+ RNA_property_boolean_get(op->ptr,
+ release_confirm_prop);
+ }
+
+ if (pbd->release_confirm_info.use_release_confirm) {
+ BLI_assert(event != NULL);
+ pbd->release_confirm_info.drag_start_xy[0] = event->x;
+ pbd->release_confirm_info.drag_start_xy[1] = event->y;
+ pbd->release_confirm_info.init_event_type = WM_userdef_event_type_from_keymap_type(
+ event->type);
+ }
+
+ /* Make backups for blending and restoring the pose. */
+ poselib_backup_posecopy(pbd);
+
+ /* Set pose flags to ensure the depsgraph evaluation doesn't overwrite it. */
+ pbd->ob->pose->flag &= ~POSE_DO_UNLOCK;
+ pbd->ob->pose->flag |= POSE_LOCKED;
+
+ return true;
+}
+
+static void poselib_blend_cleanup(bContext *C, wmOperator *op)
+{
+ PoseBlendData *pbd = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+
+ /* Redraw the header so that it doesn't show any of our stuff anymore. */
+ ED_area_status_text(pbd->area, NULL);
+ ED_workspace_status_text(C, NULL);
+
+ /* This signals the depsgraph to unlock and reevaluate the pose on the next evaluation. */
+ bPose *pose = pbd->ob->pose;
+ pose->flag |= POSE_DO_UNLOCK;
+
+ switch (pbd->state) {
+ case POSE_BLEND_CONFIRM: {
+ Scene *scene = pbd->scene;
+ poselib_keytag_pose(C, scene, pbd);
+
+ /* Ensure the redo panel has the actually-used value, instead of the initial value. */
+ RNA_float_set(op->ptr, "blend_factor", pbd->blend_factor);
+ break;
+ }
+
+ case POSE_BLEND_INIT:
+ case POSE_BLEND_BLENDING:
+ case POSE_BLEND_ORIGINAL:
+ /* Cleanup should not be called directly from these states. */
+ BLI_assert(!"poselib_blend_cleanup: unexpected pose blend state");
+ BKE_report(op->reports, RPT_ERROR, "Internal pose library error, cancelling operator");
+ ATTR_FALLTHROUGH;
+ case POSE_BLEND_CANCEL:
+ ED_pose_backup_restore(pbd->pose_backup);
+ break;
+ }
+
+ if (pbd->release_confirm_info.cursor_wrap_enabled) {
+ WM_cursor_grab_disable(win, pbd->release_confirm_info.drag_start_xy);
+ pbd->release_confirm_info.cursor_wrap_enabled = false;
+ }
+
+ DEG_id_tag_update(&pbd->ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pbd->ob);
+ /* Update mouse-hover highlights. */
+ WM_event_add_mousemove(win);
+}
+
+static void poselib_blend_free(wmOperator *op)
+{
+ PoseBlendData *pbd = op->customdata;
+ if (pbd == NULL) {
+ return;
+ }
+
+ if (pbd->free_action) {
+ /* Run before #poselib_tempload_exit to avoid any problems from indirectly
+ * referenced ID pointers. */
+ BKE_id_free(NULL, pbd->act);
+ }
+ poselib_tempload_exit(pbd);
+
+ /* Must have been dealt with before! */
+ BLI_assert(pbd->release_confirm_info.cursor_wrap_enabled == false);
+
+ /* Free temp data for operator */
+ ED_pose_backup_free(pbd->pose_backup);
+ pbd->pose_backup = NULL;
+
+ MEM_SAFE_FREE(op->customdata);
+}
+
+static int poselib_blend_exit(bContext *C, wmOperator *op)
+{
+ PoseBlendData *pbd = op->customdata;
+ const ePoseBlendState exit_state = pbd->state;
+
+ poselib_blend_cleanup(C, op);
+ poselib_blend_free(op);
+
+ if (exit_state == POSE_BLEND_CANCEL) {
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_FINISHED;
+}
+
+/* Cancel previewing operation (called when exiting Blender) */
+static void poselib_blend_cancel(bContext *C, wmOperator *op)
+{
+ PoseBlendData *pbd = op->customdata;
+ pbd->state = POSE_BLEND_CANCEL;
+ poselib_blend_exit(C, op);
+}
+
+/* Main modal status check. */
+static int poselib_blend_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const int operator_result = poselib_blend_handle_event(C, op, event);
+
+ poselib_blend_cursor_update(C, op);
+
+ const PoseBlendData *pbd = op->customdata;
+ if (ELEM(pbd->state, POSE_BLEND_CONFIRM, POSE_BLEND_CANCEL)) {
+ return poselib_blend_exit(C, op);
+ }
+
+ if (pbd->needs_redraw) {
+ poselib_blend_apply(C, op);
+ }
+
+ return operator_result;
+}
+
+/* Modal Operator init. */
+static int poselib_blend_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (!poselib_blend_init_data(C, op, event)) {
+ poselib_blend_free(op);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Do initial apply to have something to look at. */
+ poselib_blend_apply(C, op);
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Single-shot apply. */
+static int poselib_blend_exec(bContext *C, wmOperator *op)
+{
+ if (!poselib_blend_init_data(C, op, NULL)) {
+ poselib_blend_free(op);
+ return OPERATOR_CANCELLED;
+ }
+
+ poselib_blend_apply(C, op);
+
+ PoseBlendData *pbd = op->customdata;
+ pbd->state = POSE_BLEND_CONFIRM;
+ return poselib_blend_exit(C, op);
+}
+
+static bool poselib_asset_in_context(bContext *C)
+{
+ bool asset_handle_valid;
+ /* Check whether the context provides the asset data needed to add a pose. */
+ const AssetLibraryReference *asset_library = CTX_wm_asset_library(C);
+ AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid);
+
+ return (asset_library != NULL) && asset_handle_valid &&
+ (asset_handle.file_data->blentype == ID_AC);
+}
+
+/* Poll callback for operators that require existing PoseLib data (with poses) to work. */
+static bool poselib_blend_poll(bContext *C)
+{
+ Object *ob = get_poselib_object(C);
+ if (ELEM(NULL, ob, ob->pose, ob->data)) {
+ /* Pose lib is only for armatures in pose mode. */
+ return false;
+ }
+
+ return poselib_asset_in_context(C);
+}
+
+void POSELIB_OT_apply_pose_asset(wmOperatorType *ot)
+{
+ /* Identifiers: */
+ ot->name = "Apply Pose Library Pose";
+ ot->idname = "POSELIB_OT_apply_pose_asset";
+ ot->description = "Apply the given Pose Action to the rig";
+
+ /* Callbacks: */
+ ot->exec = poselib_blend_exec;
+ ot->poll = poselib_blend_poll;
+
+ /* Flags: */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties: */
+ RNA_def_float_factor(ot->srna,
+ "blend_factor",
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ "Blend Factor",
+ "Amount that the pose is applied on top of the existing poses",
+ 0.0f,
+ 1.0f);
+ RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Apply Flipped",
+ "When enabled, applies the pose flipped over the X-axis");
+}
+
+void POSELIB_OT_blend_pose_asset(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* Identifiers: */
+ ot->name = "Blend Pose Library Pose";
+ ot->idname = "POSELIB_OT_blend_pose_asset";
+ ot->description = "Blend the given Pose Action to the rig";
+
+ /* Callbacks: */
+ ot->invoke = poselib_blend_invoke;
+ ot->modal = poselib_blend_modal;
+ ot->cancel = poselib_blend_cancel;
+ ot->exec = poselib_blend_exec;
+ ot->poll = poselib_blend_poll;
+
+ /* Flags: */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* Properties: */
+ prop = RNA_def_float_factor(ot->srna,
+ "blend_factor",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Blend Factor",
+ "Amount that the pose is applied on top of the existing poses",
+ 0.0f,
+ 1.0f);
+ /* Blending should always start at 0%, and not at whatever percentage was last used. This RNA
+ * property just exists for symmetry with the Apply operator (and thus simplicity of the rest of
+ * the code, which can assume this property exists). */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Apply Flipped",
+ "When enabled, applies the pose flipped over the X-axis");
+ prop = RNA_def_boolean(ot->srna,
+ "release_confirm",
+ false,
+ "Confirm on Release",
+ "Always confirm operation when releasing button");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 8fc06a5f962..c39fcb790dd 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -69,7 +69,7 @@
/* ***************** Pose Select Utilities ********************* */
-/* Note: SEL_TOGGLE is assumed to have already been handled! */
+/* NOTE: SEL_TOGGLE is assumed to have already been handled! */
static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
{
/* select pchan only if selectable, but deselect works always */
@@ -161,9 +161,9 @@ void ED_armature_pose_select_pick_bone(ViewLayer *view_layer,
/* Since we do unified select, we don't shift+select a bone if the
* armature object was not active yet.
- * Note, special exception for armature mode so we can do multi-select
+ * NOTE(campbell): special exception for armature mode so we can do multi-select
* we could check for multi-select explicitly but think its fine to
- * always give predictable behavior in weight paint mode - campbell */
+ * always give predictable behavior in weight paint mode. */
if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) == 0)) {
/* When we are entering into posemode via toggle-select,
* from another active object - always select the bone. */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 9b1de742332..1a1685e4a01 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -833,7 +833,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
float prevFrameF, nextFrameF;
if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) {
- BLI_assert(!"Invalid pfl data");
+ BLI_assert_msg(0, "Invalid pfl data");
return;
}
@@ -1005,14 +1005,14 @@ static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso)
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
/* Bbone properties - they all start a "bbone_" prefix. */
- /* TODO Not implemented */
+ /* TODO: Not implemented. */
// pose_slide_apply_props(pso, pfl, "bbone_");
}
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
/* Not strictly a transform, but custom properties contribute
* to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
- /* TODO Not implemented */
+ /* TODO: Not implemented. */
// pose_slide_apply_props(pso, pfl, "[\"");
}
}
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index e597fd46106..1118e84ef4f 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -457,7 +457,7 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
/* For the affected bones, reset specific constraints that are now known to be invalid. */
applyarmature_reset_constraints(pose, use_selected);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
@@ -557,7 +557,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
@@ -1228,7 +1228,7 @@ static int pose_clear_transform_generic_exec(bContext *C,
DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
- /* note, notifier might evolve */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
}
}
diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt
index 8c5f91561b7..a27975bc37b 100644
--- a/source/blender/editors/asset/CMakeLists.txt
+++ b/source/blender/editors/asset/CMakeLists.txt
@@ -19,6 +19,7 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../blenloader
../../makesdna
../../makesrna
../../windowmanager
@@ -30,10 +31,14 @@ set(INC_SYS
set(SRC
asset_edit.cc
+ asset_list.cc
asset_ops.cc
+ asset_temp_id_consumer.cc
)
set(LIB
+ bf_blenloader
+ bf_blenkernel
)
blender_add_lib(bf_editor_asset "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/asset/asset_edit.cc b/source/blender/editors/asset/asset_edit.cc
index d20de4141cb..f4860737193 100644
--- a/source/blender/editors/asset/asset_edit.cc
+++ b/source/blender/editors/asset/asset_edit.cc
@@ -18,11 +18,18 @@
* \ingroup edasset
*/
+#include <memory>
+#include <string>
+
#include "BKE_asset.h"
#include "BKE_context.h"
#include "BKE_lib_id.h"
+#include "BLO_readfile.h"
+
#include "DNA_ID.h"
+#include "DNA_asset_types.h"
+#include "DNA_space_types.h"
#include "UI_interface_icons.h"
@@ -30,6 +37,8 @@
#include "ED_asset.h"
+using namespace blender;
+
bool ED_asset_mark_id(const bContext *C, ID *id)
{
if (id->asset_data) {
@@ -45,6 +54,9 @@ bool ED_asset_mark_id(const bContext *C, ID *id)
UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true);
+ /* Important for asset storage to update properly! */
+ ED_assetlist_storage_tag_main_data_dirty();
+
return true;
}
@@ -57,6 +69,9 @@ bool ED_asset_clear_id(ID *id)
/* Don't clear fake user here, there's no guarantee that it was actually set by
* #ED_asset_mark_id(), it might have been something/someone else. */
+ /* Important for asset storage to update properly! */
+ ED_assetlist_storage_tag_main_data_dirty();
+
return true;
}
@@ -65,3 +80,76 @@ bool ED_asset_can_make_single_from_context(const bContext *C)
/* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */
return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != nullptr;
}
+
+/* TODO better place? */
+/* TODO What about the setter and the `itemf` callback? */
+#include "BKE_preferences.h"
+#include "DNA_asset_types.h"
+#include "DNA_userdef_types.h"
+int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library)
+{
+ /* Simple case: Predefined repository, just set the value. */
+ if (library->type < ASSET_LIBRARY_CUSTOM) {
+ return library->type;
+ }
+
+ /* Note that the path isn't checked for validity here. If an invalid library path is used, the
+ * Asset Browser can give a nice hint on what's wrong. */
+ const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
+ &U, library->custom_library_index);
+ if (user_library) {
+ return ASSET_LIBRARY_CUSTOM + library->custom_library_index;
+ }
+
+ BLI_assert(0);
+ return ASSET_LIBRARY_LOCAL;
+}
+
+AssetLibraryReference ED_asset_library_reference_from_enum_value(int value)
+{
+ AssetLibraryReference library;
+
+ /* Simple case: Predefined repository, just set the value. */
+ if (value < ASSET_LIBRARY_CUSTOM) {
+ library.type = value;
+ library.custom_library_index = -1;
+ BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL));
+ return library;
+ }
+
+ const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
+ &U, value - ASSET_LIBRARY_CUSTOM);
+
+ /* Note that the path isn't checked for validity here. If an invalid library path is used, the
+ * Asset Browser can give a nice hint on what's wrong. */
+ const bool is_valid = (user_library->name[0] && user_library->path[0]);
+ if (!user_library) {
+ library.type = ASSET_LIBRARY_LOCAL;
+ library.custom_library_index = -1;
+ }
+ else if (user_library && is_valid) {
+ library.custom_library_index = value - ASSET_LIBRARY_CUSTOM;
+ library.type = ASSET_LIBRARY_CUSTOM;
+ }
+ return library;
+}
+
+const char *ED_asset_handle_get_name(const AssetHandle *asset)
+{
+ return asset->file_data->name;
+}
+
+void ED_asset_handle_get_full_library_path(const bContext *C,
+ const AssetLibraryReference *asset_library,
+ const AssetHandle *asset,
+ char r_full_lib_path[FILE_MAX_LIBEXTRA])
+{
+ *r_full_lib_path = '\0';
+
+ std::string asset_path = ED_assetlist_asset_filepath_get(C, *asset_library, *asset);
+ if (asset_path.empty()) {
+ return;
+ }
+
+ BLO_library_path_explode(asset_path.c_str(), r_full_lib_path, nullptr, nullptr);
+}
diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc
new file mode 100644
index 00000000000..dd1c5f360a0
--- /dev/null
+++ b/source/blender/editors/asset/asset_list.cc
@@ -0,0 +1,637 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edasset
+ *
+ * Abstractions to manage runtime asset lists with a global cache for multiple UI elements to
+ * access.
+ * Internally this uses the #FileList API and structures from `filelist.c`. This is just because it
+ * contains most necessary logic already and there's not much time for a more long-term solution.
+ */
+
+#include <optional>
+#include <string>
+
+#include "BKE_asset.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "BLI_function_ref.hh"
+#include "BLI_hash.hh"
+#include "BLI_map.hh"
+#include "BLI_path_util.h"
+#include "BLI_utility_mixins.hh"
+
+#include "DNA_asset_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_preferences.h"
+
+#include "ED_asset.h"
+#include "ED_fileselect.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* XXX uses private header of file-space. */
+#include "../space_file/filelist.h"
+
+using namespace blender;
+
+/**
+ * Wrapper to add logic to the AssetLibraryReference DNA struct.
+ */
+class AssetLibraryReferenceWrapper {
+ const AssetLibraryReference reference_;
+
+ public:
+ /* Intentionally not `explicit`, allow implicit conversion for convenience. Might have to be
+ * NOLINT */
+ AssetLibraryReferenceWrapper(const AssetLibraryReference &reference);
+ ~AssetLibraryReferenceWrapper() = default;
+
+ friend bool operator==(const AssetLibraryReferenceWrapper &a,
+ const AssetLibraryReferenceWrapper &b);
+ uint64_t hash() const;
+};
+
+AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryReference &reference)
+ : reference_(reference)
+{
+}
+
+bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b)
+{
+ return (a.reference_.type == b.reference_.type) && (a.reference_.type == ASSET_LIBRARY_CUSTOM) ?
+ (a.reference_.custom_library_index == b.reference_.custom_library_index) :
+ true;
+}
+
+uint64_t AssetLibraryReferenceWrapper::hash() const
+{
+ uint64_t hash1 = DefaultHash<decltype(reference_.type)>{}(reference_.type);
+ if (reference_.type != ASSET_LIBRARY_CUSTOM) {
+ return hash1;
+ }
+
+ uint64_t hash2 = DefaultHash<decltype(reference_.custom_library_index)>{}(
+ reference_.custom_library_index);
+ return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Asset list API
+ *
+ * Internally re-uses #FileList from the File Browser. It does all the heavy lifting already.
+ * \{ */
+
+/**
+ * RAII wrapper for `FileList`
+ */
+class FileListWrapper {
+ static void filelist_free_fn(FileList *list)
+ {
+ filelist_free(list);
+ MEM_freeN(list);
+ }
+
+ std::unique_ptr<FileList, decltype(&filelist_free_fn)> file_list_;
+
+ public:
+ explicit FileListWrapper(eFileSelectType filesel_type)
+ : file_list_(filelist_new(filesel_type), filelist_free_fn)
+ {
+ }
+ FileListWrapper(FileListWrapper &&other) = default;
+ FileListWrapper &operator=(FileListWrapper &&other) = default;
+ ~FileListWrapper()
+ {
+ /* Destructs the owned pointer. */
+ file_list_ = nullptr;
+ }
+
+ operator FileList *() const
+ {
+ return file_list_.get();
+ }
+};
+
+class PreviewTimer {
+ /* Non-owning! The Window-Manager registers and owns this. */
+ wmTimer *timer_ = nullptr;
+
+ public:
+ void ensureRunning(const bContext *C)
+ {
+ if (!timer_) {
+ timer_ = WM_event_add_timer_notifier(
+ CTX_wm_manager(C), CTX_wm_window(C), NC_ASSET | ND_ASSET_LIST_PREVIEW, 0.01);
+ }
+ }
+
+ void stop(const bContext *C)
+ {
+ if (timer_) {
+ WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), timer_);
+ timer_ = nullptr;
+ }
+ }
+};
+
+class AssetList : NonCopyable {
+ FileListWrapper filelist_;
+ AssetLibraryReference library_ref_;
+ PreviewTimer previews_timer_;
+
+ public:
+ AssetList() = delete;
+ AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref);
+ AssetList(AssetList &&other) = default;
+ ~AssetList() = default;
+
+ void setup(const AssetFilterSettings *filter_settings = nullptr);
+ void fetch(const bContext &C);
+ void ensurePreviewsJob(bContext *C);
+ void clear(bContext *C);
+
+ bool needsRefetch() const;
+ void iterate(AssetListIterFn fn) const;
+ bool listen(const wmNotifier &notifier) const;
+ int size() const;
+ void tagMainDataDirty() const;
+ void remapID(ID *id_old, ID *id_new) const;
+ StringRef filepath() const;
+};
+
+AssetList::AssetList(eFileSelectType filesel_type, const AssetLibraryReference &asset_library_ref)
+ : filelist_(filesel_type), library_ref_(asset_library_ref)
+{
+}
+
+void AssetList::setup(const AssetFilterSettings *filter_settings)
+{
+ FileList *files = filelist_;
+
+ /* TODO there should only be one (FileSelectAssetLibraryUID vs. AssetLibraryReference). */
+ FileSelectAssetLibraryUID file_asset_lib_ref;
+ file_asset_lib_ref.type = library_ref_.type;
+ file_asset_lib_ref.custom_library_index = library_ref_.custom_library_index;
+
+ bUserAssetLibrary *user_library = nullptr;
+
+ /* Ensure valid repository, or fall-back to local one. */
+ if (library_ref_.type == ASSET_LIBRARY_CUSTOM) {
+ BLI_assert(library_ref_.custom_library_index >= 0);
+
+ user_library = BKE_preferences_asset_library_find_from_index(
+ &U, library_ref_.custom_library_index);
+ }
+
+ /* Relevant bits from file_refresh(). */
+ /* TODO pass options properly. */
+ filelist_setrecursion(files, 1);
+ filelist_setsorting(files, FILE_SORT_ALPHA, false);
+ filelist_setlibrary(files, &file_asset_lib_ref);
+ /* TODO different filtering settings require the list to be reread. That's a no-go for when we
+ * want to allow showing the same asset library with different filter settings (as in,
+ * different ID types). The filelist needs to be made smarter somehow, maybe goes together with
+ * the plan to separate the view (preview caching, filtering, etc. ) from the data. */
+ filelist_setfilter_options(
+ files,
+ filter_settings != nullptr,
+ true,
+ true, /* Just always hide parent, prefer to not add an extra user option for this. */
+ FILE_TYPE_BLENDERLIB,
+ filter_settings ? filter_settings->id_types : FILTER_ID_ALL,
+ true,
+ "",
+ "");
+
+ char path[FILE_MAXDIR] = "";
+ if (user_library) {
+ BLI_strncpy(path, user_library->path, sizeof(path));
+ filelist_setdir(files, path);
+ }
+ else {
+ filelist_setdir(files, path);
+ }
+}
+
+void AssetList::fetch(const bContext &C)
+{
+ FileList *files = filelist_;
+
+ if (filelist_needs_force_reset(files)) {
+ filelist_readjob_stop(files, CTX_wm_manager(&C));
+ filelist_clear(files);
+ }
+
+ if (filelist_needs_reading(files)) {
+ if (!filelist_pending(files)) {
+ filelist_readjob_start(files, NC_ASSET | ND_ASSET_LIST_READING, &C);
+ }
+ }
+ filelist_sort(files);
+ filelist_filter(files);
+}
+
+bool AssetList::needsRefetch() const
+{
+ return filelist_needs_force_reset(filelist_) || filelist_needs_reading(filelist_);
+}
+
+void AssetList::iterate(AssetListIterFn fn) const
+{
+ FileList *files = filelist_;
+ int numfiles = filelist_files_ensure(files);
+
+ for (int i = 0; i < numfiles; i++) {
+ FileDirEntry *file = filelist_file(files, i);
+ if (!fn(*file)) {
+ break;
+ }
+ }
+}
+
+void AssetList::ensurePreviewsJob(bContext *C)
+{
+ FileList *files = filelist_;
+ int numfiles = filelist_files_ensure(files);
+
+ filelist_cache_previews_set(files, true);
+ filelist_file_cache_slidingwindow_set(files, 256);
+ /* TODO fetch all previews for now. */
+ filelist_file_cache_block(files, numfiles / 2);
+ filelist_cache_previews_update(files);
+
+ {
+ const bool previews_running = filelist_cache_previews_running(files) &&
+ !filelist_cache_previews_done(files);
+ if (previews_running) {
+ previews_timer_.ensureRunning(C);
+ }
+ else {
+ /* Preview is not running, no need to keep generating update events! */
+ previews_timer_.stop(C);
+ }
+ }
+}
+
+void AssetList::clear(bContext *C)
+{
+ /* Based on #ED_fileselect_clear() */
+
+ FileList *files = filelist_;
+ filelist_readjob_stop(files, CTX_wm_manager(C));
+ filelist_freelib(files);
+ filelist_clear(files);
+
+ WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr);
+}
+
+/**
+ * \return True if the asset-list needs a UI redraw.
+ */
+bool AssetList::listen(const wmNotifier &notifier) const
+{
+ switch (notifier.category) {
+ case NC_ID: {
+ if (ELEM(notifier.action, NA_RENAME)) {
+ return true;
+ }
+ break;
+ }
+ case NC_ASSET:
+ if (ELEM(notifier.data, ND_ASSET_LIST, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
+ return true;
+ }
+ if (ELEM(notifier.action, NA_ADDED, NA_REMOVED, NA_EDITED)) {
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+/**
+ * \return The number of assets in the list.
+ */
+int AssetList::size() const
+{
+ return filelist_files_ensure(filelist_);
+}
+
+void AssetList::tagMainDataDirty() const
+{
+ if (filelist_needs_reset_on_main_changes(filelist_)) {
+ /* Full refresh of the file list if local asset data was changed. Refreshing this view
+ * is cheap and users expect this to be updated immediately. */
+ filelist_tag_force_reset(filelist_);
+ }
+}
+
+void AssetList::remapID(ID * /*id_old*/, ID * /*id_new*/) const
+{
+ /* Trigger full re-fetch of the file list if main data was changed, don't even attempt remap
+ * pointers. We could give file list types a id-remap callback, but it's probably not worth it.
+ * Refreshing local file lists is relatively cheap. */
+ tagMainDataDirty();
+}
+
+StringRef AssetList::filepath() const
+{
+ return filelist_dir(filelist_);
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Runtime asset list cache
+ * \{ */
+
+/**
+ * Class managing a global asset list map, each entry being a list for a specific asset library.
+ */
+class AssetListStorage {
+ using AssetListMap = Map<AssetLibraryReferenceWrapper, AssetList>;
+
+ public:
+ /* Purely static class, can't instantiate this. */
+ AssetListStorage() = delete;
+
+ static void fetch_library(const AssetLibraryReference &library_reference,
+ const bContext &C,
+ const AssetFilterSettings *filter_settings = nullptr);
+ static void destruct();
+ static AssetList *lookup_list(const AssetLibraryReference &library_ref);
+ static void tagMainDataDirty();
+ static void remapID(ID *id_new, ID *id_old);
+
+ private:
+ static std::optional<eFileSelectType> asset_library_reference_to_fileselect_type(
+ const AssetLibraryReference &library_reference);
+
+ using is_new_t = bool;
+ static std::tuple<AssetList &, is_new_t> ensure_list_storage(
+ const AssetLibraryReference &library_reference, eFileSelectType filesel_type);
+
+ static AssetListMap &global_storage();
+};
+
+void AssetListStorage::fetch_library(const AssetLibraryReference &library_reference,
+ const bContext &C,
+ const AssetFilterSettings *filter_settings)
+{
+ std::optional filesel_type = asset_library_reference_to_fileselect_type(library_reference);
+ if (!filesel_type) {
+ return;
+ }
+
+ auto [list, is_new] = ensure_list_storage(library_reference, *filesel_type);
+ if (is_new || list.needsRefetch()) {
+ list.setup(filter_settings);
+ list.fetch(C);
+ }
+}
+
+void AssetListStorage::destruct()
+{
+ global_storage().~AssetListMap();
+}
+
+AssetList *AssetListStorage::lookup_list(const AssetLibraryReference &library_ref)
+{
+ return global_storage().lookup_ptr(library_ref);
+}
+
+void AssetListStorage::tagMainDataDirty()
+{
+ for (AssetList &list : global_storage().values()) {
+ list.tagMainDataDirty();
+ }
+}
+
+void AssetListStorage::remapID(ID *id_new, ID *id_old)
+{
+ for (AssetList &list : global_storage().values()) {
+ list.remapID(id_new, id_old);
+ }
+}
+
+std::optional<eFileSelectType> AssetListStorage::asset_library_reference_to_fileselect_type(
+ const AssetLibraryReference &library_reference)
+{
+ switch (library_reference.type) {
+ case ASSET_LIBRARY_CUSTOM:
+ return FILE_LOADLIB;
+ case ASSET_LIBRARY_LOCAL:
+ return FILE_MAIN_ASSET;
+ }
+
+ return std::nullopt;
+}
+
+std::tuple<AssetList &, AssetListStorage::is_new_t> AssetListStorage::ensure_list_storage(
+ const AssetLibraryReference &library_reference, eFileSelectType filesel_type)
+{
+ AssetListMap &storage = global_storage();
+
+ if (AssetList *list = storage.lookup_ptr(library_reference)) {
+ return {*list, false};
+ }
+ storage.add(library_reference, AssetList(filesel_type, library_reference));
+ return {storage.lookup(library_reference), true};
+}
+
+/**
+ * Wrapper for Construct on First Use idiom, to avoid the Static Initialization Fiasco.
+ */
+AssetListStorage::AssetListMap &AssetListStorage::global_storage()
+{
+ static AssetListMap global_storage_;
+ return global_storage_;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name C-API
+ * \{ */
+
+/**
+ * Invoke asset list reading, potentially in a parallel job. Won't wait until the job is done,
+ * and may return earlier.
+ */
+void ED_assetlist_storage_fetch(const AssetLibraryReference *library_reference,
+ const AssetFilterSettings *filter_settings,
+ const bContext *C)
+{
+ AssetListStorage::fetch_library(*library_reference, *C, filter_settings);
+}
+
+void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference, bContext *C)
+{
+
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ list->ensurePreviewsJob(C);
+ }
+}
+
+void ED_assetlist_clear(const AssetLibraryReference *library_reference, bContext *C)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ list->clear(C);
+ }
+}
+
+bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *library_reference)
+{
+ return AssetListStorage::lookup_list(*library_reference) != nullptr;
+}
+
+/* TODO expose AssetList with an iterator? */
+void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ list->iterate(fn);
+ }
+}
+
+/* TODO hack to use the File Browser path, so we can keep all the import logic handled by the asset
+ * API. Get rid of this once the File Browser is integrated better with the asset list. */
+static const char *assetlist_library_path_from_sfile_get_hack(const bContext *C)
+{
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ if (!sfile || !ED_fileselect_is_asset_browser(sfile)) {
+ return nullptr;
+ }
+
+ FileAssetSelectParams *asset_select_params = ED_fileselect_get_asset_params(sfile);
+ if (!asset_select_params) {
+ return nullptr;
+ }
+
+ return filelist_dir(sfile->files);
+}
+
+std::string ED_assetlist_asset_filepath_get(const bContext *C,
+ const AssetLibraryReference &library_reference,
+ const AssetHandle &asset_handle)
+{
+ if (asset_handle.file_data->id || !asset_handle.file_data->asset_data) {
+ return {};
+ }
+ const char *library_path = ED_assetlist_library_path(&library_reference);
+ if (!library_path) {
+ library_path = assetlist_library_path_from_sfile_get_hack(C);
+ }
+ if (!library_path) {
+ return {};
+ }
+ const char *asset_relpath = asset_handle.file_data->relpath;
+
+ char path[FILE_MAX_LIBEXTRA];
+ BLI_join_dirfile(path, sizeof(path), library_path, asset_relpath);
+
+ return path;
+}
+
+ID *ED_assetlist_asset_local_id_get(const AssetHandle *asset_handle)
+{
+ return asset_handle->file_data->asset_data ? asset_handle->file_data->id : nullptr;
+}
+
+ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
+{
+ ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
+ if (imbuf) {
+ return imbuf;
+ }
+
+ return filelist_geticon_image_ex(asset_handle->file_data);
+}
+
+const char *ED_assetlist_library_path(const AssetLibraryReference *library_reference)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ return list->filepath().data();
+ }
+ return nullptr;
+}
+
+/**
+ * \return True if the region needs a UI redraw.
+ */
+bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
+ const wmNotifier *notifier)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ return list->listen(*notifier);
+ }
+ return false;
+}
+
+/**
+ * \return The number of assets stored in the asset list for \a library_reference, or -1 if there
+ * is no list fetched for it.
+ */
+int ED_assetlist_size(const AssetLibraryReference *library_reference)
+{
+ AssetList *list = AssetListStorage::lookup_list(*library_reference);
+ if (list) {
+ return list->size();
+ }
+ return -1;
+}
+
+/**
+ * Tag all asset lists in the storage that show main data as needing an update (re-fetch).
+ *
+ * This only tags the data. If the asset list is visible on screen, the space is still responsible
+ * for ensuring the necessary redraw. It can use #ED_assetlist_listen() to check if the asset-list
+ * needs a redraw for a given notifier.
+ */
+void ED_assetlist_storage_tag_main_data_dirty()
+{
+ AssetListStorage::tagMainDataDirty();
+}
+
+/**
+ * Remapping of ID pointers within the asset lists. Typically called when an ID is deleted to clear
+ * all references to it (\a id_new is null then).
+ */
+void ED_assetlist_storage_id_remap(ID *id_old, ID *id_new)
+{
+ AssetListStorage::remapID(id_old, id_new);
+}
+
+/**
+ * Can't wait for static deallocation to run. There's nested data allocated with our guarded
+ * allocator, it will complain about unfreed memory on exit.
+ */
+void ED_assetlist_storage_exit()
+{
+ AssetListStorage::destruct();
+}
+
+/** \} */
diff --git a/source/blender/editors/asset/asset_ops.cc b/source/blender/editors/asset/asset_ops.cc
index 8ca1b488a1d..79edd1f8a6a 100644
--- a/source/blender/editors/asset/asset_ops.cc
+++ b/source/blender/editors/asset/asset_ops.cc
@@ -252,8 +252,41 @@ static void ASSET_OT_clear(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
+static bool asset_list_refresh_poll(bContext *C)
+{
+ const AssetLibraryReference *library = CTX_wm_asset_library(C);
+ if (!library) {
+ return false;
+ }
+
+ return ED_assetlist_storage_has_list_for_library(library);
+}
+
+static int asset_list_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
+{
+ const AssetLibraryReference *library = CTX_wm_asset_library(C);
+ ED_assetlist_clear(library, C);
+ return OPERATOR_FINISHED;
+}
+
+static void ASSET_OT_list_refresh(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Refresh Asset List";
+ ot->description = "Trigger a reread of the assets";
+ ot->idname = "ASSET_OT_list_refresh";
+
+ /* api callbacks */
+ ot->exec = asset_list_refresh_exec;
+ ot->poll = asset_list_refresh_poll;
+}
+
+/* -------------------------------------------------------------------- */
+
void ED_operatortypes_asset(void)
{
WM_operatortype_append(ASSET_OT_mark);
WM_operatortype_append(ASSET_OT_clear);
+
+ WM_operatortype_append(ASSET_OT_list_refresh);
}
diff --git a/source/blender/editors/asset/asset_temp_id_consumer.cc b/source/blender/editors/asset/asset_temp_id_consumer.cc
new file mode 100644
index 00000000000..24e1fc86fef
--- /dev/null
+++ b/source/blender/editors/asset/asset_temp_id_consumer.cc
@@ -0,0 +1,113 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edasset
+ *
+ * API for temporary loading of asset IDs.
+ * Uses the `BLO_library_temp_xxx()` API internally.
+ */
+
+#include "DNA_asset_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_report.h"
+
+#include "BLI_utility_mixins.hh"
+
+#include "BLO_readfile.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "ED_asset.h"
+
+using namespace blender;
+
+class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
+ const AssetHandle &handle_;
+ TempLibraryContext *temp_lib_context_ = nullptr;
+
+ public:
+ AssetTemporaryIDConsumer(const AssetHandle &handle) : handle_(handle)
+ {
+ }
+ ~AssetTemporaryIDConsumer()
+ {
+ if (temp_lib_context_) {
+ BLO_library_temp_free(temp_lib_context_);
+ }
+ }
+
+ ID *get_local_id()
+ {
+ return ED_assetlist_asset_local_id_get(&handle_);
+ }
+
+ ID *import_id(const bContext *C,
+ const AssetLibraryReference &asset_library,
+ ID_Type id_type,
+ Main &bmain,
+ ReportList &reports)
+ {
+ const char *asset_name = ED_asset_handle_get_name(&handle_);
+ char blend_file_path[FILE_MAX_LIBEXTRA];
+ ED_asset_handle_get_full_library_path(C, &asset_library, &handle_, blend_file_path);
+
+ temp_lib_context_ = BLO_library_temp_load_id(
+ &bmain, blend_file_path, id_type, asset_name, &reports);
+
+ if (temp_lib_context_ == nullptr || temp_lib_context_->temp_id == nullptr) {
+ BKE_reportf(&reports, RPT_ERROR, "Unable to load %s from %s", asset_name, blend_file_path);
+ return nullptr;
+ }
+
+ BLI_assert(GS(temp_lib_context_->temp_id->name) == id_type);
+ return temp_lib_context_->temp_id;
+ }
+};
+
+AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle)
+{
+ if (!handle) {
+ return nullptr;
+ }
+ BLI_assert(handle->file_data->asset_data != nullptr);
+ return reinterpret_cast<AssetTempIDConsumer *>(
+ OBJECT_GUARDED_NEW(AssetTemporaryIDConsumer, *handle));
+}
+
+void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer)
+{
+ OBJECT_GUARDED_SAFE_DELETE(*consumer, AssetTemporaryIDConsumer);
+}
+
+ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_,
+ const bContext *C,
+ const AssetLibraryReference *asset_library,
+ ID_Type id_type,
+ Main *bmain,
+ ReportList *reports)
+{
+ if (!(consumer_ && asset_library && bmain && reports)) {
+ return nullptr;
+ }
+ AssetTemporaryIDConsumer *consumer = reinterpret_cast<AssetTemporaryIDConsumer *>(consumer_);
+
+ if (ID *local_id = consumer->get_local_id()) {
+ return local_id;
+ }
+ return consumer->import_id(C, *asset_library, id_type, *bmain, *reports);
+}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 58cd69781a7..e7d97ce343c 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1929,7 +1929,7 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d)
}
/* Never allow the order to exceed the number of points
- * - note, this is ok but changes unselected nurbs, disable for now */
+ * NOTE: this is ok but changes unselected nurbs, disable for now. */
#if 0
if ((nu != NULL) && (nu->type == CU_NURBS)) {
clamp_nurb_order_u(nu);
@@ -1988,7 +1988,7 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d)
nu->bp = bp1;
/* Never allow the order to exceed the number of points
- * - note, this is ok but changes unselected nurbs, disable for now */
+ * NOTE: this is ok but changes unselected nurbs, disable for now. */
#if 0
if (nu->type == CU_NURBS) {
clamp_nurb_order_u(nu);
@@ -6877,7 +6877,7 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
Nurb *newnu = BKE_nurb_duplicate(nu);
- if (ob_active->totcol) { /* TODO, merge material lists */
+ if (ob_active->totcol) { /* TODO: merge material lists. */
CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1);
}
else {
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 065763764c1..2be55accd3a 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -485,7 +485,7 @@ Nurb *ED_curve_add_nurbs_primitive(
break;
default: /* should never happen */
- BLI_assert(!"invalid nurbs type");
+ BLI_assert_msg(0, "invalid nurbs type");
return NULL;
}
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index febcf83116b..26906b0ddcd 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -698,7 +698,7 @@ static void curve_draw_exec_precalc(wmOperator *op)
}
if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) {
- /* note, we could try to de-duplicate the length calculations above */
+ /* NOTE: we could try to de-duplicate the length calculations above. */
const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool);
BLI_mempool_iter iter;
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index 88f6398567d..210411c6eb5 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -267,7 +267,7 @@ static void curve_undosys_step_decode(struct bContext *C,
}
undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr);
cu->editnurb->needs_flush_to_id = 1;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY);
}
/* The first element is always active */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 95970cff4ef..e43e4194c51 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -656,7 +656,7 @@ static void txt_add_object(bContext *C,
obedit = BKE_object_add(bmain, view_layer, OB_FONT, NULL);
base = view_layer->basact;
- /* seems to assume view align ? TODO - look into this, could be an operator option */
+ /* seems to assume view align ? TODO: look into this, could be an operator option. */
ED_object_base_init_transform_on_add(base->object, NULL, rot);
BKE_object_where_is_calc(depsgraph, scene, obedit);
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index a305a997d50..6eaf8971eb0 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -341,7 +341,7 @@ static Object *editfont_object_from_context(bContext *C)
typedef struct FontUndoStep {
UndoStep step;
- /* note: will split out into list for multi-object-editmode. */
+ /* NOTE: will split out into list for multi-object-editmode. */
UndoRefID_Object obedit_ref;
UndoFont data;
} FontUndoStep;
@@ -379,7 +379,7 @@ static void font_undosys_step_decode(struct bContext *C,
Curve *cu = obedit->data;
undofont_to_editfont(&us->data, cu);
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY);
ED_undo_object_set_active_or_warn(
CTX_data_scene(C), CTX_data_view_layer(C), obedit, us_p->name, &LOG);
diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
index 2896aa25930..2ec287a62e9 100644
--- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c
@@ -51,7 +51,7 @@ void wm_gizmo_geometryinfo_draw(const GizmoGeomInfo *info,
const bool UNUSED(select),
const float color[4])
{
- /* TODO store the Batches inside the GizmoGeomInfo and updated it when geom changes
+ /* TODO: store the Batches inside the GizmoGeomInfo and updated it when geom changes
* So we don't need to re-created and discard it every time */
GPUVertBuf *vbo;
diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c
index 4e56ceb9fd4..f842c20b74f 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_presets.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c
@@ -41,7 +41,7 @@
#include "ED_gizmo_library.h" /* own include */
#include "gizmo_library_intern.h" /* own include */
-/* TODO, this is to be used by RNA. might move to ED_gizmo_library */
+/* TODO: this is to be used by RNA. might move to ED_gizmo_library. */
/**
* Given a single axis, orient the matrix to a different direction.
diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c
index 77c65cd1bb8..7d0ae5afb9b 100644
--- a/source/blender/editors/gizmo_library/gizmo_library_utils.c
+++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c
@@ -237,7 +237,7 @@ bool gizmo_window_project_3d(
if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
- /* Note: we might want a custom reference point passed in,
+ /* NOTE: we might want a custom reference point passed in,
* instead of the gizmo center. */
ED_view3d_win_to_3d(v3d, region, mat[3], mval, r_co);
invert_m4(mat);
diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
index d99ce25451c..f286d3930e2 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c
@@ -82,7 +82,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz,
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- /* TODO, other draw styles */
+ /* TODO: other draw styles. */
if (color[3] == 1.0 && fill_alpha == 1.0 && select == false) {
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(color);
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
index deb89319f4f..6fd06b47656 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -774,7 +774,7 @@ static int gizmo_cage2d_get_cursor(wmGizmo *gz)
case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y:
return WM_CURSOR_Y_MOVE;
- /* TODO diagonal cursor */
+ /* TODO: diagonal cursor. */
case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y:
case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y:
return WM_CURSOR_NSEW_SCROLL;
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
index 3131ec70fb0..196fb88ea55 100644
--- a/source/blender/editors/gpencil/annotate_draw.c
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -348,7 +348,7 @@ static void annotation_draw_stroke_3d(
/* If there was a significant pressure change, stop the curve,
* change the thickness of the stroke, and continue drawing again
* (since line-width cannot change in middle of GL_LINE_STRIP)
- * Note: we want more visible levels of pressures when thickness is bigger.
+ * NOTE: we want more visible levels of pressures when thickness is bigger.
*/
if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
/* if the pressure changes before get at least 2 vertices,
@@ -901,7 +901,7 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
}
/* draw annotations sketches to specified 3d-view assuming that matrices are already set
- * correctly Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
+ * correctly NOTE: this gets called twice - first time with only3d=true to draw 3d-strokes,
* second time with only3d=false for screen-aligned strokes */
void ED_annotation_draw_view3d(
Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 7b995c545ba..4b0c5ccd285 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -708,7 +708,7 @@ static void annotation_stroke_arrow_init_conv_point(bGPDspoint *pt, const float
static void annotation_stroke_arrow_init_point(
tGPsdata *p, tGPspoint *ptc, bGPDspoint *pt, const float co[8], const int co_idx)
{
- /* Note: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */
+ /* NOTE: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */
const float real_co[2] = {co[co_idx], co[co_idx + 1]};
copy_v2_v2(&ptc->x, real_co);
annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
@@ -1141,7 +1141,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p,
/* Clear Tags
*
- * Note: It's better this way, as we are sure that
+ * NOTE: It's better this way, as we are sure that
* we don't miss anything, though things will be
* slightly slower as a result
*/
@@ -1172,7 +1172,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p,
((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
/* Check if point segment of stroke had anything to do with
* eraser region (either within stroke painted, or on its lines)
- * - this assumes that linewidth is irrelevant
+ * - this assumes that line-width is irrelevant.
*/
if (gpencil_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
if ((annotation_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) ||
@@ -2478,18 +2478,15 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve
/* default exit state - pass through to support MMB view nav, etc. */
int estate = OPERATOR_PASS_THROUGH;
- /* if (event->type == NDOF_MOTION)
- * return OPERATOR_PASS_THROUGH;
- * -------------------------------
- * [mce] Not quite what I was looking
- * for, but a good start! GP continues to
- * draw on the screen while the 3D mouse
- * moves the viewpoint. Problem is that
- * the stroke is converted to 3D only after
- * it is finished. This approach should work
- * better in tools that immediately apply
- * in 3D space.
- */
+ /* NOTE(mike erwin): Not quite what I was looking for, but a good start!
+ * grease-pencil continues to draw on the screen while the 3D mouse moves the viewpoint.
+ * Problem is that the stroke is converted to 3D only after it is finished.
+ * This approach should work better in tools that immediately apply in 3D space. */
+#if 0
+ if (event->type == NDOF_MOTION) {
+ return OPERATOR_PASS_THROUGH;
+ }
+#endif
if (p->status == GP_STATUS_IDLING) {
ARegion *region = CTX_wm_region(C);
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index 6e6d94a2909..fbdb7c8e520 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -513,7 +513,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
static bool gpencil_frame_snap_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene))
{
-#if 0 /* note: gpf->framenum is already an int! */
+#if 0 /* NOTE: gpf->framenum is already an int! */
if (gpf->flag & GP_FRAME_SELECT) {
gpf->framenum = (int)(floor(gpf->framenum + 0.5));
}
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index d8734c4ae6b..8d60ef3ed12 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -39,6 +39,32 @@
#include "ED_gpencil.h"
+/**
+ * Populate stroke with point data from data buffers.
+ * \param gps: Grease pencil stroke
+ * \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values.
+ * \param totpoints: Total of points
+ * \param mat: 4x4 transform matrix to transform points into the right coordinate space.
+ */
+void ED_gpencil_stroke_init_data(bGPDstroke *gps,
+ const float *array,
+ const int totpoints,
+ const float mat[4][4])
+{
+ for (int i = 0; i < totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ const int x = GP_PRIM_DATABUF_SIZE * i;
+
+ pt->x = array[x];
+ pt->y = array[x + 1];
+ pt->z = array[x + 2];
+ mul_m4_v3(mat, &pt->x);
+
+ pt->pressure = array[x + 3];
+ pt->strength = array[x + 4];
+ }
+}
+
/* Definition of the most important info from a color */
typedef struct ColorTemplate {
const char *name;
@@ -847,115 +873,115 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
/* generate strokes */
gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false);
- BKE_gpencil_stroke_add_points(gps, data0, 270, mat);
+ ED_gpencil_stroke_init_data(gps, data0, 270, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data1, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data1, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false);
- BKE_gpencil_stroke_add_points(gps, data2, 18, mat);
+ ED_gpencil_stroke_init_data(gps, data2, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
- BKE_gpencil_stroke_add_points(gps, data3, 64, mat);
+ ED_gpencil_stroke_init_data(gps, data3, 64, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data4, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data4, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
- BKE_gpencil_stroke_add_points(gps, data5, 64, mat);
+ ED_gpencil_stroke_init_data(gps, data5, 64, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data6, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data6, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false);
- BKE_gpencil_stroke_add_points(gps, data7, 18, mat);
+ ED_gpencil_stroke_init_data(gps, data7, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
- BKE_gpencil_stroke_add_points(gps, data8, 49, mat);
+ ED_gpencil_stroke_init_data(gps, data8, 49, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data9, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data9, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
- BKE_gpencil_stroke_add_points(gps, data10, 49, mat);
+ ED_gpencil_stroke_init_data(gps, data10, 49, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
- BKE_gpencil_stroke_add_points(gps, data11, 18, mat);
+ ED_gpencil_stroke_init_data(gps, data11, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
- BKE_gpencil_stroke_add_points(gps, data12, 18, mat);
+ ED_gpencil_stroke_init_data(gps, data12, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data13, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data13, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data14, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data14, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false);
- BKE_gpencil_stroke_add_points(gps, data15, 65, mat);
+ ED_gpencil_stroke_init_data(gps, data15, 65, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false);
- BKE_gpencil_stroke_add_points(gps, data16, 34, mat);
+ ED_gpencil_stroke_init_data(gps, data16, 34, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data17, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data17, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false);
- BKE_gpencil_stroke_add_points(gps, data18, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data18, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false);
- BKE_gpencil_stroke_add_points(gps, data19, 34, mat);
+ ED_gpencil_stroke_init_data(gps, data19, 34, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data20, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data20, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false);
- BKE_gpencil_stroke_add_points(gps, data21, 64, mat);
+ ED_gpencil_stroke_init_data(gps, data21, 64, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
- BKE_gpencil_stroke_add_points(gps, data22, 26, mat);
+ ED_gpencil_stroke_init_data(gps, data22, 26, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
- BKE_gpencil_stroke_add_points(gps, data23, 26, mat);
+ ED_gpencil_stroke_init_data(gps, data23, 26, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data24, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data24, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
- BKE_gpencil_stroke_add_points(gps, data25, 18, mat);
+ ED_gpencil_stroke_init_data(gps, data25, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
- BKE_gpencil_stroke_add_points(gps, data26, 18, mat);
+ ED_gpencil_stroke_init_data(gps, data26, 18, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
- BKE_gpencil_stroke_add_points(gps, data27, 33, mat);
+ ED_gpencil_stroke_init_data(gps, data27, 33, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* update depsgraph */
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index e95496b51ee..73c4e64dd9a 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -235,7 +235,7 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
/* generate stroke */
gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false);
- BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
+ ED_gpencil_stroke_init_data(gps, data0, 175, mat);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* update depsgraph */
diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c
index 24fb0873a86..c800851bb08 100644
--- a/source/blender/editors/gpencil/gpencil_armature.c
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -384,7 +384,7 @@ static void gpencil_add_verts_to_dgroups(
/* loop groups and assign weight */
for (j = 0; j < numbones; j++) {
- int def_nr = BLI_findindex(&ob->defbase, dgrouplist[j]);
+ int def_nr = BLI_findindex(&gpd->vertex_group_names, dgrouplist[j]);
if (def_nr < 0) {
continue;
}
@@ -454,7 +454,7 @@ static void gpencil_object_vgroup_calc_from_armature(const bContext *C,
bArmature *arm = ob_arm->data;
/* always create groups */
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const int defbase_tot = BKE_object_defgroup_count(ob);
int defbase_add;
/* Traverse the bone list, trying to create empty vertex
* groups corresponding to the bone.
diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.c b/source/blender/editors/gpencil/gpencil_bake_animation.c
index 1a5e2950e09..2d299230124 100644
--- a/source/blender/editors/gpencil/gpencil_bake_animation.c
+++ b/source/blender/editors/gpencil/gpencil_bake_animation.c
@@ -38,6 +38,7 @@
#include "BKE_duplilist.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -303,8 +304,12 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
float matrix[4][4];
BKE_gpencil_layer_transform_matrix_get(depsgraph, elem->ob, gpl_src, matrix);
+ /* Apply time modifier. */
+ int remap_cfra = BKE_gpencil_time_modifier_cfra(
+ depsgraph, scene, elem->ob, gpl_src, CFRA, false);
/* Duplicate frame. */
- bGPDframe *gpf_src = BKE_gpencil_layer_frame_get(gpl_src, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf_src = BKE_gpencil_layer_frame_get(
+ gpl_src, remap_cfra, GP_GETFRAME_USE_PREV);
if (gpf_src == NULL) {
continue;
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 9bea1868895..ee3536c2f3f 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -230,7 +230,7 @@ typedef struct tGpTimingData {
float tot_dist;
/* Times */
- float *times; /* Note: Gap times will be negative! */
+ float *times; /* NOTE: Gap times will be negative! */
float tot_time, gap_tot_time;
double inittime;
@@ -1409,7 +1409,7 @@ static void gpencil_layer_to_curve(bContext *C,
gtd);
break;
default:
- BLI_assert(!"invalid mode");
+ BLI_assert_msg(0, "invalid mode");
break;
}
prev_gps = gps;
@@ -1806,7 +1806,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot)
0,
100);
- /* Note: Internal use, this one will always be hidden by UI code... */
+ /* NOTE: Internal use, this one will always be hidden by UI code... */
prop = RNA_def_boolean(
ot->srna,
"use_timing_data",
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index e272f46d13d..b1e57079d28 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -2165,7 +2165,9 @@ static bool gpencil_vertex_group_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if ((ob) && (ob->type == OB_GPENCIL)) {
- if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
+ const bGPdata *gpd = (const bGPdata *)ob->data;
+ if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) &&
+ !BLI_listbase_is_empty(&gpd->vertex_group_names)) {
if (ELEM(ob->mode, OB_MODE_EDIT_GPENCIL, OB_MODE_SCULPT_GPENCIL)) {
return true;
}
@@ -2180,7 +2182,9 @@ static bool gpencil_vertex_group_weight_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if ((ob) && (ob->type == OB_GPENCIL)) {
- if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
+ const bGPdata *gpd = (const bGPdata *)ob->data;
+ if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) &&
+ !BLI_listbase_is_empty(&gpd->vertex_group_names)) {
if (ob->mode == OB_MODE_WEIGHT_GPENCIL) {
return true;
}
@@ -2333,6 +2337,7 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ob->data;
/* sanity checks */
if (ELEM(NULL, ts, ob, ob->data)) {
@@ -2340,8 +2345,9 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op)
}
MDeformVert *dvert;
- const int def_nr = ob->actdef - 1;
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
+ const int def_nr = gpd->vertex_group_active_index - 1;
+
+ bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr);
if (defgroup == NULL) {
return OPERATOR_CANCELLED;
}
@@ -2373,7 +2379,6 @@ static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers */
- bGPdata *gpd = ob->data;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
@@ -2403,14 +2408,15 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ob->data;
/* sanity checks */
if (ELEM(NULL, ts, ob, ob->data)) {
return OPERATOR_CANCELLED;
}
- const int def_nr = ob->actdef - 1;
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr);
if (defgroup == NULL) {
return OPERATOR_CANCELLED;
}
@@ -2470,7 +2476,6 @@ static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers */
- bGPdata *gpd = ob->data;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
@@ -2500,6 +2505,7 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ob->data;
/* sanity checks */
if (ELEM(NULL, ts, ob, ob->data)) {
@@ -2508,8 +2514,8 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
MDeformVert *dvert = NULL;
MDeformWeight *dw = NULL;
- const int def_nr = ob->actdef - 1;
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, def_nr);
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr);
if (defgroup == NULL) {
return OPERATOR_CANCELLED;
}
@@ -2548,7 +2554,6 @@ static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers */
- bGPdata *gpd = ob->data;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
@@ -2576,6 +2581,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
+ bGPdata *gpd = ob->data;
/* sanity checks */
if (ELEM(NULL, ts, ob, ob->data)) {
@@ -2585,8 +2591,8 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
bDeformGroup *defgroup = NULL;
MDeformVert *dvert = NULL;
MDeformWeight *dw = NULL;
- const int def_nr = ob->actdef - 1;
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ const int defbase_tot = BLI_listbase_count(&gpd->vertex_group_names);
if (defbase_tot == 0) {
return OPERATOR_CANCELLED;
}
@@ -2603,7 +2609,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
for (int i = 0; i < gps->totpoints; i++) {
dvert = &gps->dvert[i];
for (int v = 0; v < defbase_tot; v++) {
- defgroup = BLI_findlink(&ob->defbase, v);
+ defgroup = BLI_findlink(&gpd->vertex_group_names, v);
/* skip NULL or locked groups */
if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
continue;
@@ -2629,7 +2635,7 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
dvert = &gps->dvert[i];
for (int v = 0; v < defbase_tot; v++) {
- defgroup = BLI_findlink(&ob->defbase, v);
+ defgroup = BLI_findlink(&gpd->vertex_group_names, v);
/* skip NULL or locked groups */
if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
continue;
@@ -2653,7 +2659,6 @@ static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers */
- bGPdata *gpd = ob->data;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
@@ -2769,7 +2774,6 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob_active = CTX_data_active_object(C);
- bGPdata *gpd_dst = NULL;
bool ok = false;
/* Ensure we're in right mode and that the active object is correct */
@@ -2807,7 +2811,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- gpd_dst = ob_active->data;
+ bGPdata *gpd_dst = ob_active->data;
Object *ob_dst = ob_active;
/* loop and join all data */
@@ -2828,11 +2832,11 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
/* copy vertex groups to the base one's */
int old_idx = 0;
- LISTBASE_FOREACH (bDeformGroup *, dg, &ob_iter->defbase) {
+ LISTBASE_FOREACH (bDeformGroup *, dg, &gpd_src->vertex_group_names) {
bDeformGroup *vgroup = MEM_dupallocN(dg);
- int idx = BLI_listbase_count(&ob_active->defbase);
+ int idx = BLI_listbase_count(&gpd_dst->vertex_group_names);
BKE_object_defgroup_unique_name(vgroup, ob_active);
- BLI_addtail(&ob_active->defbase, vgroup);
+ BLI_addtail(&gpd_dst->vertex_group_names, vgroup);
/* update vertex groups in strokes in original data */
LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) {
@@ -2852,8 +2856,9 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
}
old_idx++;
}
- if (ob_active->defbase.first && ob_active->actdef == 0) {
- ob_active->actdef = 1;
+ if (!BLI_listbase_is_empty(&gpd_dst->vertex_group_names) &&
+ gpd_dst->vertex_group_active_index == 0) {
+ gpd_dst->vertex_group_active_index = 1;
}
/* add missing materials reading source materials and checking in destination object */
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 4419833a99c..67e1bd5294b 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -1522,8 +1522,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
pt = gps->points;
point2D = (tGPspoint *)tgpf->sbuffer;
- const int def_nr = tgpf->ob->actdef - 1;
- const bool have_weight = (bool)BLI_findlink(&tgpf->ob->defbase, def_nr);
+ const int def_nr = tgpf->gpd->vertex_group_active_index - 1;
+ const bool have_weight = (bool)BLI_findlink(&tgpf->gpd->vertex_group_names, def_nr);
if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
BKE_gpencil_dvert_ensure(gps);
@@ -1625,7 +1625,7 @@ static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgp
static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), void *arg)
{
tGPDfill *tgpf = (tGPDfill *)arg;
- /* draw only in the region that originated operator. This is required for multiwindow */
+ /* Draw only in the region that originated operator. This is required for multi-window. */
ARegion *region = CTX_wm_region(C);
if (region != tgpf->region) {
return;
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 0062e363cdf..8640ffa67cf 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -278,7 +278,7 @@ static void gpencil_stroke_pair_table(bContext *C,
tGPDinterpolate_layer *tgpil)
{
bGPdata *gpd = tgpi->gpd;
- const bool only_selected = ((GPENCIL_EDIT_MODE(gpd)) &&
+ const bool only_selected = (GPENCIL_EDIT_MODE(gpd) &&
((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) != 0));
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
@@ -291,8 +291,7 @@ static void gpencil_stroke_pair_table(bContext *C,
LISTBASE_FOREACH (bGPDstroke *, gps_from, &tgpil->prevFrame->strokes) {
bGPDstroke *gps_to = NULL;
/* only selected */
- if ((GPENCIL_EDIT_MODE(gpd)) && (only_selected) &&
- ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ if (GPENCIL_EDIT_MODE(gpd) && (only_selected) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
continue;
}
/* skip strokes that are invalid for current view */
@@ -712,7 +711,7 @@ static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGP
tgpi->flag, (RNA_enum_get(op->ptr, "layers") == 1), GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS);
SET_FLAG_FROM_TEST(
tgpi->flag,
- ((GPENCIL_EDIT_MODE(tgpi->gpd)) && (RNA_boolean_get(op->ptr, "interpolate_selected_only"))),
+ (GPENCIL_EDIT_MODE(tgpi->gpd) && (RNA_boolean_get(op->ptr, "interpolate_selected_only"))),
GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED);
tgpi->flipmode = RNA_enum_get(op->ptr, "flip");
@@ -1249,7 +1248,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
const int step = RNA_int_get(op->ptr, "step");
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool all_layers = (bool)(RNA_enum_get(op->ptr, "layers") == 1);
- const bool only_selected = ((GPENCIL_EDIT_MODE(gpd)) &&
+ const bool only_selected = (GPENCIL_EDIT_MODE(gpd) &&
(RNA_boolean_get(op->ptr, "interpolate_selected_only") != 0));
eGP_InterpolateFlipMode flipmode = RNA_enum_get(op->ptr, "flip");
@@ -1309,7 +1308,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
LISTBASE_FOREACH (bGPDstroke *, gps_from, &prevFrame->strokes) {
bGPDstroke *gps_to = NULL;
/* Only selected. */
- if ((GPENCIL_EDIT_MODE(gpd)) && (only_selected) &&
+ if (GPENCIL_EDIT_MODE(gpd) && (only_selected) &&
((gps_from->flag & GP_STROKE_SELECT) == 0)) {
continue;
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 409d10996d0..d6f6dbb2b10 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -938,8 +938,8 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
Depsgraph *depsgraph = p->depsgraph;
Object *obact = (Object *)p->ownerPtr.data;
RegionView3D *rv3d = p->region->regiondata;
- const int def_nr = obact->actdef - 1;
- const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr);
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ const bool have_weight = (bool)BLI_findlink(&gpd->vertex_group_names, def_nr);
const char align_flag = ts->gpencil_v3d_align;
const bool is_depth = (bool)(align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
const bool is_lock_axis_view = (bool)(ts->gp_sculpt.lock_axis == 0);
@@ -1526,7 +1526,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
/* Clear Tags
*
- * Note: It's better this way, as we are sure that
+ * NOTE: It's better this way, as we are sure that
* we don't miss anything, though things will be
* slightly slower as a result
*/
@@ -1579,7 +1579,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
/* Check if point segment of stroke had anything to do with
* eraser region (either within stroke painted, or on its lines)
- * - this assumes that linewidth is irrelevant
+ * - this assumes that line-width is irrelevant.
*/
if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) {
@@ -2174,7 +2174,7 @@ static void gpencil_paint_initstroke(tGPsdata *p,
/* Add a new frame if needed (and based off the active frame,
* as we need some existing strokes to erase)
*
- * Note: We don't add a new frame if there's nothing there now, so
+ * NOTE: We don't add a new frame if there's nothing there now, so
* -> If there are no frames at all, don't add one
* -> If there are no strokes in that frame, don't add a new empty frame
*/
@@ -3602,18 +3602,15 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* default exit state - pass through to support MMB view nav, etc. */
int estate = OPERATOR_PASS_THROUGH;
- /* if (event->type == NDOF_MOTION)
- * return OPERATOR_PASS_THROUGH;
- * -------------------------------
- * [mce] Not quite what I was looking
- * for, but a good start! GP continues to
- * draw on the screen while the 3D mouse
- * moves the viewpoint. Problem is that
- * the stroke is converted to 3D only after
- * it is finished. This approach should work
- * better in tools that immediately apply
- * in 3D space.
- */
+ /* NOTE(mike erwin): Not quite what I was looking for, but a good start!
+ * grease-pencil continues to draw on the screen while the 3D mouse moves the viewpoint.
+ * Problem is that the stroke is converted to 3D only after it is finished.
+ * This approach should work better in tools that immediately apply in 3D space. */
+#if 0
+ if (event->type == NDOF_MOTION) {
+ return OPERATOR_PASS_THROUGH;
+ }
+#endif
if (p->status == GP_STATUS_IDLING) {
ARegion *region = CTX_wm_region(C);
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index a2b4e5dee64..cf49aefe2ea 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -1315,8 +1315,8 @@ static void gpencil_primitive_interaction_end(bContext *C,
Brush *brush = tgpi->brush;
BrushGpencilSettings *brush_settings = brush->gpencil_settings;
- const int def_nr = tgpi->ob->actdef - 1;
- const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr);
+ const int def_nr = tgpi->gpd->vertex_group_active_index - 1;
+ const bool have_weight = BLI_findlink(&tgpi->gpd->vertex_group_names, def_nr) != NULL;
/* return to normal cursor and header status */
ED_workspace_status_text(C, NULL);
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 0226558b4a0..14caf0c08a7 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -1096,7 +1096,7 @@ static void gpencil_brush_clone_adjust(tGP_BrushEditData *gso)
}
}
-/* Entrypoint for applying "clone" brush */
+/* Entry-point for applying "clone" brush. */
static bool gpencil_sculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
{
/* Which "mode" are we operating in? */
@@ -1177,8 +1177,8 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->object = ob;
if (ob) {
invert_m4_m4(gso->inv_mat, ob->obmat);
- gso->vrgroup = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, gso->vrgroup)) {
+ gso->vrgroup = gso->gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup)) {
gso->vrgroup = -1;
}
/* Check if some modifier can transform the stroke. */
@@ -1352,7 +1352,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso
* - This is useful when animating as it saves that "uh-oh" moment when you realize you've
* spent too much time editing the wrong frame.
*/
- if ((IS_AUTOKEY_ON(scene)) && (gpf->framenum != cfra)) {
+ if (IS_AUTOKEY_ON(scene) && (gpf->framenum != cfra)) {
BKE_gpencil_frame_addcopy(gpl, cfra);
/* Need tag to recalculate evaluated data to avoid crashes. */
DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -1377,7 +1377,7 @@ static float gpencil_sculpt_rotation_eval_get(tGP_BrushEditData *gso,
int idx_eval)
{
/* If multiframe or no modifiers, return 0. */
- if ((GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd)) || (!gso->is_transformed)) {
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd) || (!gso->is_transformed)) {
return 0.0f;
}
@@ -1500,7 +1500,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso,
((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
/* Check if point segment of stroke had anything to do with
* brush region (either within stroke painted, or on its lines)
- * - this assumes that linewidth is irrelevant
+ * - this assumes that line-width is irrelevant.
*/
if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
/* Apply operation to these points */
@@ -1513,8 +1513,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso,
}
pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* If masked and the point is not selected, skip it. */
- if ((GPENCIL_ANY_SCULPT_MASK(gso->mask)) &&
- ((pt_active->flag & GP_SPOINT_SELECT) == 0)) {
+ if (GPENCIL_ANY_SCULPT_MASK(gso->mask) && ((pt_active->flag & GP_SPOINT_SELECT) == 0)) {
continue;
}
index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index c33b43247fd..69734fa1ba8 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -689,7 +689,7 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op)
break;
default:
- BLI_assert(!"unhandled select grouped gpencil mode");
+ BLI_assert_msg(0, "unhandled select grouped gpencil mode");
break;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 54672743439..ba3d3b584d7 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1227,7 +1227,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
float xy[2];
/* 3D to Screen-space */
- /* Note: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space
+ /* NOTE: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space
* coordinates, resulting in lost precision, which in turn causes stair-stepping
* artifacts in the final points. */
@@ -1600,8 +1600,8 @@ void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
@@ -1654,8 +1654,8 @@ void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
@@ -1707,8 +1707,8 @@ void ED_gpencil_vgroup_select(bContext *C, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
@@ -1762,8 +1762,8 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const int def_nr = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const int def_nr = gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gpd->vertex_group_names, def_nr)) {
return;
}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index 7ec64b2afd6..633e371cbd1 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -910,7 +910,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
/* Check if point segment of stroke had anything to do with
* brush region (either within stroke painted, or on its lines)
- * - this assumes that linewidth is irrelevant
+ * - this assumes that line-width is irrelevant.
*/
if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
@@ -919,7 +919,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
pt_active = pt->runtime.pt_orig;
if (pt_active != NULL) {
/* If masked and the point is not selected, skip it. */
- if ((GPENCIL_ANY_VERTEX_MASK(gso->mask)) &&
+ if (GPENCIL_ANY_VERTEX_MASK(gso->mask) &&
((pt_active->flag & GP_SPOINT_SELECT) == 0)) {
continue;
}
diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c
index 56eed187d87..d14322e12b5 100644
--- a/source/blender/editors/gpencil/gpencil_weight_paint.c
+++ b/source/blender/editors/gpencil/gpencil_weight_paint.c
@@ -252,7 +252,7 @@ static bool brush_draw_apply(tGP_BrushWeightpaintData *gso,
}
}
else {
- bDeformGroup *defgroup = BLI_findlink(&gso->object->defbase, gso->vrgroup);
+ bDeformGroup *defgroup = BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup);
if (defgroup->flag & DG_LOCK_WEIGHT) {
return false;
}
@@ -308,8 +308,8 @@ static bool gpencil_weightpaint_brush_init(bContext *C, wmOperator *op)
gso->scene = scene;
gso->object = ob;
if (ob) {
- gso->vrgroup = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, gso->vrgroup)) {
+ gso->vrgroup = gso->gpd->vertex_group_active_index - 1;
+ if (!BLI_findlink(&gso->gpd->vertex_group_names, gso->vrgroup)) {
gso->vrgroup = -1;
}
}
@@ -448,7 +448,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1]))) {
/* Check if point segment of stroke had anything to do with
* brush region (either within stroke painted, or on its lines)
- * - this assumes that linewidth is irrelevant
+ * - this assumes that line-width is irrelevant.
*/
if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 4b440aa7367..50e53acb376 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -34,9 +34,9 @@ struct ListBase;
struct ARegion;
struct ARegionType;
+struct FModifier;
struct Main;
struct NlaStrip;
-struct FModifier;
struct PanelType;
struct ReportList;
struct ScrArea;
@@ -177,9 +177,9 @@ typedef struct bAnimListElem {
* action's ID. But if this is a f-curve which is a driver, then the owner
* is set to, for example, object.
*
- * Note, that this is different from id above. The id above will be set to
- * an object if the f-curve is coming from action associated with that
- * object. */
+ * NOTE: this is different from id above. The id above will be set to
+ * an object if the f-curve is coming from action associated with that object.
+ */
struct ID *fcurve_owner_id;
/**
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 85563b76f38..868235c36e5 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -23,6 +23,10 @@
#pragma once
+#include <stdbool.h>
+
+#include "BLI_listbase.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -41,6 +45,7 @@ struct Scene;
struct UndoType;
struct View3D;
struct ViewLayer;
+struct bAction;
struct bArmature;
struct bContext;
struct bPoseChannel;
@@ -242,6 +247,17 @@ void ED_mesh_deform_bind_callback(struct MeshDeformModifierData *mmd,
int totvert,
float cagemat[4][4]);
+/* Pose backups, pose_backup.c */
+struct PoseBackup;
+/* Create a backup of those bones that are animated in the given action. */
+struct PoseBackup *ED_pose_backup_create_selected_bones(
+ const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
+struct PoseBackup *ED_pose_backup_create_all_bones(
+ const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
+bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup);
+void ED_pose_backup_restore(const struct PoseBackup *pbd);
+void ED_pose_backup_free(struct PoseBackup *pbd);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h
index dd505167fe5..0058c0615c3 100644
--- a/source/blender/editors/include/ED_asset.h
+++ b/source/blender/editors/include/ED_asset.h
@@ -20,17 +20,80 @@
#pragma once
+#include "DNA_ID_enums.h"
+
#ifdef __cplusplus
extern "C" {
#endif
+struct AssetFilterSettings;
+struct AssetLibraryReference;
+struct Main;
+struct ReportList;
+struct bContext;
+struct wmNotifier;
+
+typedef struct AssetTempIDConsumer AssetTempIDConsumer;
+
bool ED_asset_mark_id(const struct bContext *C, struct ID *id);
bool ED_asset_clear_id(struct ID *id);
bool ED_asset_can_make_single_from_context(const struct bContext *C);
+int ED_asset_library_reference_to_enum_value(const struct AssetLibraryReference *library);
+struct AssetLibraryReference ED_asset_library_reference_from_enum_value(int value);
+
+const char *ED_asset_handle_get_name(const AssetHandle *asset);
+void ED_asset_handle_get_full_library_path(const struct bContext *C,
+ const AssetLibraryReference *asset_library,
+ const AssetHandle *asset,
+ char r_full_lib_path[]);
+
+AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle);
+void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer);
+struct ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer,
+ const struct bContext *C,
+ const AssetLibraryReference *asset_library,
+ ID_Type id_type,
+ struct Main *bmain,
+ struct ReportList *reports);
+
+void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference,
+ const struct AssetFilterSettings *filter_settings,
+ const struct bContext *C);
+void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference,
+ struct bContext *C);
+void ED_assetlist_clear(const struct AssetLibraryReference *library_reference, struct bContext *C);
+bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *library_reference);
+void ED_assetlist_storage_tag_main_data_dirty(void);
+void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
+void ED_assetlist_storage_exit(void);
+
+ID *ED_assetlist_asset_local_id_get(const AssetHandle *asset_handle);
+struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
+const char *ED_assetlist_library_path(const struct AssetLibraryReference *library_reference);
+
+bool ED_assetlist_listen(const struct AssetLibraryReference *library_reference,
+ const struct wmNotifier *notifier);
+int ED_assetlist_size(const struct AssetLibraryReference *library_reference);
+
void ED_operatortypes_asset(void);
#ifdef __cplusplus
}
#endif
+
+/* TODO move to C++ asset-list header? */
+#ifdef __cplusplus
+
+# include <string>
+
+std::string ED_assetlist_asset_filepath_get(const bContext *C,
+ const AssetLibraryReference &library_reference,
+ const AssetHandle &asset_handle);
+
+# include "BLI_function_ref.hh"
+/* Can return false to stop iterating. */
+using AssetListIterFn = blender::FunctionRef<bool(FileDirEntry &)>;
+void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn);
+#endif
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 8118e3c6c69..e57e2316d93 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -66,7 +66,7 @@ typedef struct FileAttributeColumn {
} FileAttributeColumn;
typedef struct FileLayout {
- /* view settings - XXX - move into own struct */
+ /* view settings - XXX: move into own struct. */
int offset_top;
/* Height of the header for the different FileAttributeColumn's. */
int attribute_column_header_h;
@@ -136,13 +136,9 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);
-void ED_fileselect_clear(struct wmWindowManager *wm,
- struct Scene *owner_scene,
- struct SpaceFile *sfile);
+void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile);
-void ED_fileselect_exit(struct wmWindowManager *wm,
- struct Scene *owner_scene,
- struct SpaceFile *sfile);
+void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile);
bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile);
struct ID *ED_fileselect_active_asset_get(const struct SpaceFile *sfile);
@@ -166,7 +162,7 @@ int ED_file_icon(const struct FileDirEntry *file);
void ED_file_read_bookmarks(void);
-void ED_file_change_dir_ex(struct bContext *C, struct bScreen *screen, struct ScrArea *area);
+void ED_file_change_dir_ex(struct bContext *C, struct ScrArea *area);
void ED_file_change_dir(struct bContext *C);
void ED_file_path_button(struct bScreen *screen,
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 59b5a1abaa6..8a8d91a570c 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -251,6 +251,13 @@ void ED_gpencil_brush_draw_eraser(struct Brush *brush, int x, int y);
/* ----------- Add Primitive Utilities -------------- */
+/* Number of values defining each point in the built-in data buffers for primitives. */
+#define GP_PRIM_DATABUF_SIZE 5
+void ED_gpencil_stroke_init_data(struct bGPDstroke *gps,
+ const float *array,
+ const int totpoints,
+ const float mat[4][4]);
+
void ED_gpencil_create_blank(struct bContext *C, struct Object *ob, float mat[4][4]);
void ED_gpencil_create_monkey(struct bContext *C, struct Object *ob, float mat[4][4]);
void ED_gpencil_create_stroke(struct bContext *C, struct Object *ob, float mat[4][4]);
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 0493832c06f..673f629d6ef 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -468,7 +468,7 @@ bool fcurve_is_changed(struct PointerRNA ptr,
* Checks whether a keyframe exists for the given ID-block one the given frame.
* - It is recommended to call this method over the other keyframe-checkers directly,
* in case some detail of the implementation changes...
- * - frame: the value of this is quite often result of #BKE_scene_frame_get()
+ * - frame: the value of this is quite often result of #BKE_scene_ctime_get()
*/
bool id_frame_has_keyframe(struct ID *id, float frame, short filter);
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 7fcae2349db..2b73194afb2 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -27,6 +27,8 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
struct ARegion;
struct BMBVHTree;
struct BMEdge;
@@ -84,7 +86,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em);
void EDBM_selectmode_to_scene(struct bContext *C);
void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index);
-void EDBM_mesh_free(struct BMEditMesh *em);
+void EDBM_mesh_free_data(struct BMEditMesh *em);
void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data);
void EDBM_mesh_load(struct Main *bmain, struct Object *ob);
@@ -455,12 +457,14 @@ typedef struct BMBackup {
struct BMesh *bmcopy;
} BMBackup;
-/* save a copy of the bmesh for restoring later */
struct BMBackup EDBM_redo_state_store(struct BMEditMesh *em);
/* restore a bmesh from backup */
-void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalctess);
-/* delete the backup, optionally flushing it to an editmesh */
-void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess);
+void EDBM_redo_state_restore(struct BMBackup *backup, struct BMEditMesh *em, bool recalc_looptri)
+ ATTR_NONNULL(1, 2);
+void EDBM_redo_state_restore_and_free(struct BMBackup *backup,
+ struct BMEditMesh *em,
+ bool recalc_looptri) ATTR_NONNULL(1, 2);
+void EDBM_redo_state_free(struct BMBackup *backup) ATTR_NONNULL(1);
/* *** meshtools.c *** */
int ED_mesh_join_objects_exec(struct bContext *C, struct wmOperator *op);
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 9d36a2c7fc1..66e08ed1cb7 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -31,6 +31,7 @@ struct ID;
struct Main;
struct Scene;
struct ScrArea;
+struct SpaceNode;
struct Tex;
struct View2D;
struct bContext;
@@ -115,6 +116,7 @@ bool ED_node_select_check(const ListBase *lb);
void ED_node_select_all(ListBase *lb, int action);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain,
+ struct SpaceNode *snode,
struct bNodeTree *ntree,
struct bNode *node,
bool *r_active_texture_changed);
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 6d0172e724a..5318c653b6d 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -34,9 +34,9 @@ struct ParticleSystem;
struct Scene;
struct UndoType;
struct ViewLayer;
-struct wmGenericUserData;
struct bContext;
struct rcti;
+struct wmGenericUserData;
/* particle edit mode */
void PE_free_ptcache_edit(struct PTCacheEdit *edit);
diff --git a/source/blender/editors/include/ED_spreadsheet.h b/source/blender/editors/include/ED_spreadsheet.h
index 88bc4738c0b..dfa8aa7bfbc 100644
--- a/source/blender/editors/include/ED_spreadsheet.h
+++ b/source/blender/editors/include/ED_spreadsheet.h
@@ -16,10 +16,13 @@
#pragma once
-struct SpreadsheetContext;
-struct SpaceSpreadsheet;
-struct SpaceNode;
struct ID;
+struct Main;
+struct Object;
+struct SpaceNode;
+struct SpaceSpreadsheet;
+struct SpreadsheetContext;
+struct bContext;
struct bNode;
#ifdef __cplusplus
@@ -29,14 +32,25 @@ extern "C" {
struct SpreadsheetContext *ED_spreadsheet_context_new(int type);
void ED_spreadsheet_context_free(struct SpreadsheetContext *context);
void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet);
-void ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet);
+bool ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet);
uint64_t ED_spreadsheet_context_path_hash(const struct SpaceSpreadsheet *sspreadsheet);
struct ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet);
-void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet,
- struct SpaceNode *snode,
- struct bNode *node);
+void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet,
+ struct SpaceNode *snode,
+ struct bNode *node);
+void ED_spreadsheet_context_paths_set_geometry_node(struct Main *bmain,
+ struct SpaceNode *snode,
+ struct bNode *node);
+void ED_spreadsheet_context_path_set_evaluated_object(struct SpaceSpreadsheet *sspreadsheet,
+ struct Object *object);
+
+void ED_spreadsheet_context_path_guess(const struct bContext *C,
+ struct SpaceSpreadsheet *sspreadsheet);
+bool ED_spreadsheet_context_path_is_active(const struct bContext *C,
+ struct SpaceSpreadsheet *sspreadsheet);
+bool ED_spreadsheet_context_path_exists(struct Main *bmain, struct SpaceSpreadsheet *sspreadsheet);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 484e083c111..7ccdc49d291 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -21,7 +21,7 @@
* \ingroup editorui
*/
-/* Note: this is included multiple times with different #defines for DEF_ICON. */
+/* NOTE: this is included multiple times with different #defines for DEF_ICON. */
/* Auto define more specific types for places that do not need the distinction. */
#ifndef DEF_ICON_SCENE
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 47e3dc84503..a25aac5803c 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -25,6 +25,7 @@
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h" /* size_t */
+#include "BLI_utildefines.h"
#include "UI_interface_icons.h"
#ifdef __cplusplus
@@ -34,6 +35,7 @@ extern "C" {
/* Struct Declarations */
struct ARegion;
+struct AssetFilterSettings;
struct AutoComplete;
struct EnumPropertyItem;
struct FileSelectParams;
@@ -58,6 +60,7 @@ struct bNodeTree;
struct bScreen;
struct rctf;
struct rcti;
+struct uiBlockInteraction_Handle;
struct uiButSearch;
struct uiFontStyle;
struct uiList;
@@ -129,12 +132,6 @@ enum {
UI_DIR_ALL = UI_DIR_UP | UI_DIR_DOWN | UI_DIR_LEFT | UI_DIR_RIGHT,
};
-#if 0
-/* uiBlock->autofill (not yet used) */
-# define UI_BLOCK_COLLUMNS 1
-# define UI_BLOCK_ROWS 2
-#endif
-
/** #uiBlock.flag (controls) */
enum {
UI_BLOCK_LOOP = 1 << 0,
@@ -251,7 +248,7 @@ enum {
#define UI_PANEL_BOX_STYLE_MARGIN (U.widget_unit * 0.2f)
/* but->drawflag - these flags should only affect how the button is drawn. */
-/* Note: currently, these flags _are not passed_ to the widget's state() or draw() functions
+/* NOTE: currently, these flags *are not passed* to the widget's state() or draw() functions
* (except for the 'align' ones)!
*/
enum {
@@ -371,6 +368,9 @@ typedef enum {
/** Buttons with value >= #UI_BTYPE_SEARCH_MENU don't get undo pushes. */
UI_BTYPE_SEARCH_MENU = 41 << 9,
UI_BTYPE_EXTRA = 42 << 9,
+ /** A preview image (#PreviewImage), with text under it. Typically bigger than normal buttons and
+ * laid out in a grid, e.g. like the File Browser in thumbnail display mode. */
+ UI_BTYPE_PREVIEW_TILE = 43 << 9,
UI_BTYPE_HOTKEY_EVENT = 46 << 9,
/** Non-interactive image, used for splash screen */
UI_BTYPE_IMAGE = 47 << 9,
@@ -520,6 +520,54 @@ typedef int (*uiButPushedStateFunc)(struct uiBut *but, const void *arg);
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
+/* -------------------------------------------------------------------- */
+/** \name Custom Interaction
+ *
+ * Sometimes it's useful to create data that remains available
+ * while the user interacts with a button.
+ *
+ * A common case is dragging a number button or slider
+ * however this could be used in other cases too.
+ * \{ */
+
+struct uiBlockInteraction_Params {
+ /**
+ * When true, this interaction is not modal
+ * (user clicking on a number button arrows or pasting a value for example).
+ */
+ bool is_click;
+ /**
+ * Array of unique event ID's (values from #uiBut.retval).
+ * There may be more than one for multi-button editing (see #UI_BUT_DRAG_MULTI).
+ */
+ int *unique_retval_ids;
+ uint unique_retval_ids_len;
+};
+
+/** Returns 'user_data', freed by #uiBlockInteractionEndFn. */
+typedef void *(*uiBlockInteractionBeginFn)(struct bContext *C,
+ const struct uiBlockInteraction_Params *params,
+ void *arg1);
+typedef void (*uiBlockInteractionEndFn)(struct bContext *C,
+ const struct uiBlockInteraction_Params *params,
+ void *arg1,
+ void *user_data);
+typedef void (*uiBlockInteractionUpdateFn)(struct bContext *C,
+ const struct uiBlockInteraction_Params *params,
+ void *arg1,
+ void *user_data);
+
+typedef struct uiBlockInteraction_CallbackData {
+ uiBlockInteractionBeginFn begin_fn;
+ uiBlockInteractionEndFn end_fn;
+ uiBlockInteractionUpdateFn update_fn;
+ void *arg1;
+} uiBlockInteraction_CallbackData;
+
+void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks);
+
+/** \} */
+
/* Menu Callbacks */
typedef void (*uiMenuCreateFunc)(struct bContext *C, struct uiLayout *layout, void *arg1);
@@ -544,6 +592,8 @@ bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title);
bool UI_block_is_empty(const uiBlock *block);
bool UI_block_can_add_separator(const uiBlock *block);
+struct uiList *UI_list_find_mouse_over(const struct ARegion *region, const struct wmEvent *event);
+
/* interface_region_menu_popup.c */
/**
* Popup Menus
@@ -661,6 +711,7 @@ void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2],
void UI_block_end(const struct bContext *C, uiBlock *block);
void UI_block_draw(const struct bContext *C, struct uiBlock *block);
void UI_blocklist_update_window_matrix(const struct bContext *C, const struct ListBase *lb);
+void UI_blocklist_update_view_for_buttons(const struct bContext *C, const struct ListBase *lb);
void UI_blocklist_draw(const struct bContext *C, const struct ListBase *lb);
void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block);
@@ -669,7 +720,7 @@ enum {
UI_BLOCK_THEME_STYLE_POPUP = 1,
};
void UI_block_theme_style_set(uiBlock *block, char theme_style);
-char UI_block_emboss_get(uiBlock *block);
+eUIEmbossType UI_block_emboss_get(uiBlock *block);
void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss);
bool UI_block_is_search_only(const uiBlock *block);
void UI_block_set_search_only(uiBlock *block, bool search_only);
@@ -684,7 +735,7 @@ void UI_block_region_set(uiBlock *block, struct ARegion *region);
void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr);
void UI_block_lock_clear(uiBlock *block);
-/* automatic aligning, horiz or verical */
+/* Automatic aligning, horizontal or vertical. */
void UI_block_align_begin(uiBlock *block);
void UI_block_align_end(uiBlock *block);
@@ -1370,7 +1421,7 @@ typedef struct uiStringInfo {
char *strinfo;
} uiStringInfo;
-/* Note: Expects pointers to uiStringInfo structs as parameters.
+/* NOTE: Expects pointers to uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
* Strings in uiStringInfo must be MEM_freeN'ed by caller. */
void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
@@ -2151,6 +2202,17 @@ void uiTemplateCacheFile(uiLayout *layout,
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
+enum uiTemplateListFlags {
+ UI_TEMPLATE_LIST_FLAG_NONE = 0,
+ UI_TEMPLATE_LIST_SORT_REVERSE = (1 << 0),
+ UI_TEMPLATE_LIST_SORT_LOCK = (1 << 1),
+ /* Don't allow resizing the list, i.e. don't add the grip button. */
+ UI_TEMPLATE_LIST_NO_GRIP = (1 << 2),
+
+ UI_TEMPLATE_LIST_FLAGS_LAST
+};
+ENUM_OPERATORS(enum uiTemplateListFlags, UI_TEMPLATE_LIST_FLAGS_LAST);
+
void uiTemplateList(uiLayout *layout,
struct bContext *C,
const char *listtype_name,
@@ -2164,8 +2226,23 @@ void uiTemplateList(uiLayout *layout,
int maxrows,
int layout_type,
int columns,
- bool sort_reverse,
- bool sort_lock);
+ enum uiTemplateListFlags flags);
+struct uiList *uiTemplateList_ex(uiLayout *layout,
+ struct bContext *C,
+ const char *listtype_name,
+ const char *list_id,
+ struct PointerRNA *dataptr,
+ const char *propname,
+ struct PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ int rows,
+ int maxrows,
+ int layout_type,
+ int columns,
+ enum uiTemplateListFlags flags,
+ void *customdata);
+
void uiTemplateNodeLink(uiLayout *layout,
struct bContext *C,
struct bNodeTree *ntree,
@@ -2211,6 +2288,27 @@ int uiTemplateRecentFiles(struct uiLayout *layout, int rows);
void uiTemplateFileSelectPath(uiLayout *layout,
struct bContext *C,
struct FileSelectParams *params);
+void uiTemplateAssetView(struct uiLayout *layout,
+ struct bContext *C,
+ const char *list_id,
+ struct PointerRNA *asset_library_dataptr,
+ const char *asset_library_propname,
+ struct PointerRNA *assets_dataptr,
+ const char *assets_propname,
+ struct PointerRNA *active_dataptr,
+ const char *active_propname,
+ const struct AssetFilterSettings *filter_settings,
+ const char *activate_opname,
+ struct PointerRNA *r_activate_op_properties,
+ const char *drag_opname,
+ struct PointerRNA *r_drag_op_properties);
+
+struct PointerRNA *UI_list_custom_activate_operator_set(struct uiList *ui_list,
+ const char *opname,
+ bool create_properties);
+struct PointerRNA *UI_list_custom_drag_operator_set(struct uiList *ui_list,
+ const char *opname,
+ bool create_properties);
/* items */
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname);
@@ -2475,6 +2573,7 @@ typedef struct uiDragColorHandle {
void ED_operatortypes_ui(void);
void ED_keymap_ui(struct wmKeyConfig *keyconf);
+void ED_uilisttypes_ui(void);
void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
bool UI_drop_color_poll(struct bContext *C,
@@ -2575,6 +2674,8 @@ bool UI_editsource_enable_check(void);
void UI_editsource_active_but_test(uiBut *but);
void UI_editsource_but_replace(const uiBut *old_but, uiBut *new_but);
+void UI_but_ensure_in_view(const struct bContext *C, struct ARegion *region, const uiBut *but);
+
/* UI_butstore_ helpers */
typedef struct uiButStore uiButStore;
typedef struct uiButStoreElem uiButStoreElem;
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 266a538b6c3..37cf7229ffb 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -105,7 +105,10 @@ int UI_iconfile_get_index(const char *filename);
struct PreviewImage *UI_icon_to_preview(int icon_id);
-int UI_icon_from_rnaptr(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
+int UI_icon_from_rnaptr(const struct bContext *C,
+ struct PointerRNA *ptr,
+ int rnaicon,
+ const bool big);
int UI_icon_from_idcode(const int idcode);
int UI_icon_from_library(const struct ID *id);
int UI_icon_from_object_mode(const int mode);
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 16729873b4e..8191a9a9062 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -51,7 +51,7 @@ enum eView2D_CommonViewTypes {
V2D_COMMONVIEW_STANDARD,
/* listview (i.e. Outliner) */
V2D_COMMONVIEW_LIST,
- /* stackview (this is basically a list where new items are added at the top) */
+ /* Stack-view (this is basically a list where new items are added at the top). */
V2D_COMMONVIEW_STACK,
/* headers (this is basically the same as listview, but no y-panning) */
V2D_COMMONVIEW_HEADER,
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 5011a50ed73..39dd6143eb9 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -66,6 +66,8 @@ set(SRC
interface_region_tooltip.c
interface_regions.c
interface_style.c
+ interface_template_asset_view.cc
+ interface_template_list.cc
interface_template_search_menu.c
interface_template_search_operator.c
interface_templates.c
@@ -102,7 +104,7 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WIN32)
+if(WIN32 OR APPLE)
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 6f341edf11b..ddde4f5a9dc 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -131,12 +131,10 @@ static bool ui_but_is_unit_radians(const uiBut *but)
/* ************* window matrix ************** */
-void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
+void ui_block_to_region_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
{
const int getsizex = BLI_rcti_size_x(&region->winrct) + 1;
const int getsizey = BLI_rcti_size_y(&region->winrct) + 1;
- const int sx = region->winrct.xmin;
- const int sy = region->winrct.ymin;
float gx = *r_x;
float gy = *r_y;
@@ -146,14 +144,19 @@ void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, fl
gy += block->panel->ofsy;
}
- *r_x = ((float)sx) +
- ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
+ *r_x = ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] +
block->winmat[3][0]));
- *r_y = ((float)sy) +
- ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
+ *r_y = ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] +
block->winmat[3][1]));
}
+void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
+{
+ ui_block_to_region_fl(region, block, r_x, r_y);
+ *r_x += region->winrct.xmin;
+ *r_y += region->winrct.ymin;
+}
+
void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_y)
{
float fx = *r_x;
@@ -165,6 +168,16 @@ void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_
*r_y = (int)(fy + 0.5f);
}
+void ui_block_to_region_rctf(const ARegion *region,
+ uiBlock *block,
+ rctf *rct_dst,
+ const rctf *rct_src)
+{
+ *rct_dst = *rct_src;
+ ui_block_to_region_fl(region, block, &rct_dst->xmin, &rct_dst->ymin);
+ ui_block_to_region_fl(region, block, &rct_dst->xmax, &rct_dst->ymax);
+}
+
void ui_block_to_window_rctf(const ARegion *region,
uiBlock *block,
rctf *rct_dst,
@@ -249,6 +262,14 @@ void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti
rect_dst->ymax = rct_src->ymax - region->winrct.ymin;
}
+void ui_window_to_region_rctf(const ARegion *region, rctf *rect_dst, const rctf *rct_src)
+{
+ rect_dst->xmin = rct_src->xmin - region->winrct.xmin;
+ rect_dst->xmax = rct_src->xmax - region->winrct.xmin;
+ rect_dst->ymin = rct_src->ymin - region->winrct.ymin;
+ rect_dst->ymax = rct_src->ymax - region->winrct.ymin;
+}
+
void ui_region_to_window(const ARegion *region, int *r_x, int *r_y)
{
*r_x += region->winrct.xmin;
@@ -476,7 +497,7 @@ void ui_block_bounds_calc(uiBlock *block)
static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
{
- /* note: this is used for the splash where window bounds event has not been
+ /* NOTE: this is used for the splash where window bounds event has not been
* updated by ghost, get the window bounds from ghost directly */
const int xmax = WM_window_pixels_x(window);
@@ -587,7 +608,7 @@ void UI_block_bounds_set_normal(uiBlock *block, int addval)
block->bounds_type = UI_BLOCK_BOUNDS;
}
-/* used for pulldowns */
+/* Used for pull-downs. */
void UI_block_bounds_set_text(uiBlock *block, int addval)
{
block->bounds = addval;
@@ -862,7 +883,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but)
SWAP(void *, but->dragpoin, oldbut->dragpoin);
}
- /* note: if layout hasn't been applied yet, it uses old button pointers... */
+ /* NOTE: if layout hasn't been applied yet, it uses old button pointers... */
}
/**
@@ -1382,11 +1403,11 @@ static bool ui_but_event_property_operator_string(const bContext *C,
else {
/* special exceptions for common nested data in editors... */
if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) {
- /* dopesheet filtering options... */
+ /* Dope-sheet filtering options. */
data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop));
}
else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) {
- /* Filebrowser options... */
+ /* File-browser options. */
data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop));
}
}
@@ -1945,8 +1966,8 @@ void ui_fontscale(short *points, float aspect)
if (aspect < 0.9f || aspect > 1.1f) {
float pointsf = *points;
- /* for some reason scaling fonts goes too fast compared to widget size */
- /* XXX not true anymore? (ton) */
+ /* For some reason scaling fonts goes too fast compared to widget size. */
+ /* XXX(ton): not true anymore? */
// aspect = sqrt(aspect);
pointsf /= aspect;
@@ -2432,7 +2453,7 @@ bool ui_but_is_rna_valid(uiBut *but)
*/
bool ui_but_supports_cycling(const uiBut *but)
{
- return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) ||
+ return (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX) ||
(but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) ||
(but->type == UI_BTYPE_COLOR && ((uiButColor *)but)->is_pallete_color) ||
(but->menu_step_func != NULL));
@@ -3140,7 +3161,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
return true;
}
else if (str[0] == '#') {
- /* shortcut to create new driver expression (versus immediate Py-execution) */
+ /* Shortcut to create new driver expression (versus immediate Python-execution). */
return ui_but_anim_expression_create(but, str + 1);
}
else {
@@ -3223,7 +3244,7 @@ void ui_but_range_set_hard(uiBut *but)
}
}
-/* note: this could be split up into functions which handle arrays and not */
+/* NOTE: this could be split up into functions which handle arrays and not. */
void ui_but_range_set_soft(uiBut *but)
{
/* Ideally we would not limit this, but practically it's more than
@@ -3440,6 +3461,15 @@ void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
}
}
+void UI_blocklist_update_view_for_buttons(const bContext *C, const ListBase *lb)
+{
+ LISTBASE_FOREACH (uiBlock *, block, lb) {
+ if (block->active) {
+ ui_but_update_view_for_active(C, block);
+ }
+ }
+}
+
void UI_blocklist_draw(const bContext *C, const ListBase *lb)
{
LISTBASE_FOREACH (uiBlock *, block, lb) {
@@ -3542,7 +3572,7 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eU
return block;
}
-char UI_block_emboss_get(uiBlock *block)
+eUIEmbossType UI_block_emboss_get(uiBlock *block)
{
return block->emboss;
}
@@ -4106,7 +4136,6 @@ static uiBut *ui_def_but(uiBlock *block,
UI_BTYPE_BLOCK,
UI_BTYPE_BUT_MENU,
UI_BTYPE_SEARCH_MENU,
- UI_BTYPE_PROGRESS_BAR,
UI_BTYPE_DATASETROW,
UI_BTYPE_POPOVER)) {
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
@@ -4247,7 +4276,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
uiItemS(layout);
}
- /* note, item_array[...] is reversed on access */
+ /* NOTE: `item_array[...]` is reversed on access. */
/* create items */
uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
@@ -4550,7 +4579,7 @@ static uiBut *ui_def_but_rna(uiBlock *block,
else if (proptype == PROP_STRING) {
min = 0;
max = RNA_property_string_maxlength(prop);
- /* note, 'max' may be zero (code for dynamically resized array) */
+ /* NOTE: 'max' may be zero (code for dynamically resized array). */
}
}
@@ -6757,7 +6786,7 @@ static void operator_enum_search_update_fn(const struct bContext *C,
for (int i = 0; i < filtered_amount; i++) {
const EnumPropertyItem *item = filtered_items[i];
- /* note: need to give the index rather than the
+ /* NOTE: need to give the index rather than the
* identifier because the enum can be freed */
if (!UI_search_item_add(
items, item->name, POINTER_FROM_INT(item->value), item->icon, 0, 0)) {
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 775e3923edc..3049e2bd7b8 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -417,7 +417,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
&um->items, drawstr, but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext);
}
else if (but->rnaprop) {
- /* Note: 'member_id' may be a path. */
+ /* NOTE: 'member_id' may be a path. */
const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
const char *member_id_data_path = member_id;
@@ -425,7 +425,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
}
const char *prop_id = RNA_property_identifier(but->rnaprop);
- /* Note, ignore 'drawstr', use property idname always. */
+ /* NOTE: ignore 'drawstr', use property idname always. */
ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex);
if (data_path) {
MEM_freeN((void *)data_path);
@@ -494,7 +494,7 @@ static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, Pr
RNA_string_set(&props_ptr, "filepath", dir);
}
-bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
+bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *event)
{
/* ui_but_is_interactive() may let some buttons through that should not get a context menu - it
* doesn't make sense for them. */
@@ -560,7 +560,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0;
/* Set the (button_pointer, button_prop)
- * and pointer data for Python access to the hovered ui element. */
+ * and pointer data for Python access to the hovered UI element. */
uiLayoutSetContextFromBut(layout, but);
/* Keyframes */
@@ -1226,6 +1226,20 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
+ /* UI List item context menu. Scripts can add items to it, by default there's nothing shown. */
+ ARegion *region = CTX_wm_region(C);
+ const bool is_inside_listbox = ui_list_find_mouse_over(region, event) != NULL;
+ const bool is_inside_listrow = is_inside_listbox ?
+ ui_list_row_find_mouse_over(region, event->x, event->y) !=
+ NULL :
+ false;
+ if (is_inside_listrow) {
+ MenuType *mt = WM_menutype_find("UI_MT_list_item_context_menu", true);
+ if (mt) {
+ UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
+ }
+ }
+
MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
if (mt) {
UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 05b6fcdded1..655fdda3069 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -229,7 +229,7 @@ void ui_draw_but_TAB_outline(const rcti *rect,
{0.98, 0.805},
};
- /* mult */
+ /* Multiply. */
for (a = 0; a < 4; a++) {
mul_v2_fl(vec[a], rad);
}
@@ -592,7 +592,7 @@ static void waveform_draw_one(float *waveform, int nbr, const float col[3])
GPU_vertbuf_attr_fill(vbo, pos_id, waveform);
- /* TODO store the GPUBatch inside the scope */
+ /* TODO: store the #GPUBatch inside the scope. */
GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
@@ -2223,9 +2223,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region),
/* ****************************************************** */
-/* TODO: high quality UI drop shadows using GLSL shader and single draw call
- * would replace / modify the following 3 functions - merwin
- */
+/* TODO(merwin): high quality UI drop shadows using GLSL shader and single draw call
+ * would replace / modify the following 3 functions. */
static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize, uchar alpha)
{
@@ -2350,7 +2349,7 @@ void ui_draw_dropshadow(
true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
#endif
/* Compute final visibility to match old method result. */
- /* TODO we could just find a better fit function inside the shader instead of this. */
+ /* TODO: we could just find a better fit function inside the shader instead of this. */
visibility = visibility * (1.0f - calpha);
calpha += dalpha;
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 45609d96840..4f8bb6342f7 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -35,10 +35,12 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "BLI_array_utils.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_sort_utils.h"
#include "BLI_string.h"
#include "BLI_string_cursor_utf8.h"
#include "BLI_string_utf8.h"
@@ -170,6 +172,20 @@ static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but
static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str);
static void button_tooltip_timer_reset(bContext *C, uiBut *but);
+static void ui_block_interaction_begin_ensure(bContext *C,
+ uiBlock *block,
+ struct uiHandleButtonData *data,
+ const bool is_click);
+static struct uiBlockInteraction_Handle *ui_block_interaction_begin(struct bContext *C,
+ uiBlock *block,
+ const bool is_click);
+static void ui_block_interaction_end(struct bContext *C,
+ uiBlockInteraction_CallbackData *callbacks,
+ struct uiBlockInteraction_Handle *interaction);
+static void ui_block_interaction_update(struct bContext *C,
+ uiBlockInteraction_CallbackData *callbacks,
+ struct uiBlockInteraction_Handle *interaction);
+
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEvent *event);
@@ -225,6 +241,19 @@ typedef enum uiMenuScrollType {
MENU_SCROLL_BOTTOM,
} uiMenuScrollType;
+typedef struct uiBlockInteraction_Handle {
+ struct uiBlockInteraction_Params params;
+ void *user_data;
+ /**
+ * This is shared between #uiHandleButtonData and #uiAfterFunc,
+ * the last user runs the end callback and frees the data.
+ *
+ * This is needed as the order of freeing changes depending on
+ * accepting/canceling the operation.
+ */
+ int user_count;
+} uiBlockInteraction_Handle;
+
#ifdef USE_ALLSELECT
/* Unfortunately there's no good way handle more generally:
@@ -273,7 +302,7 @@ static void ui_selectcontext_apply(bContext *C,
/**
* how far to drag before we check for gesture direction (in pixels),
- * note: half the height of a button is about right... */
+ * NOTE: half the height of a button is about right... */
# define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4)
/**
@@ -430,6 +459,8 @@ typedef struct uiHandleButtonData {
uiSelectContextStore select_others;
#endif
+ struct uiBlockInteraction_Handle *custom_interaction_handle;
+
/* Text field undo. */
struct uiUndoStack_Text *undo_stack_text;
@@ -471,6 +502,9 @@ typedef struct uiAfterFunc {
void *search_arg;
uiFreeArgFunc search_arg_free_fn;
+ uiBlockInteraction_CallbackData custom_interaction_callbacks;
+ uiBlockInteraction_Handle *custom_interaction_handle;
+
bContextStore *context;
char undostr[BKE_UNDO_STR_MAX];
@@ -733,23 +767,34 @@ static uiAfterFunc *ui_afterfunc_new(void)
* For executing operators after the button is pressed.
* (some non operator buttons need to trigger operators), see: T37795.
*
+ * \param context_but: A button from which to get the context from (`uiBut.context`) for the
+ * operator execution.
+ *
+ * \note Ownership over \a properties is moved here. The #uiAfterFunc owns it now.
* \note Can only call while handling buttons.
*/
-PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, bool create_props)
+static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot,
+ PointerRNA **properties,
+ int opcontext,
+ const uiBut *context_but)
{
- PointerRNA *ptr = NULL;
uiAfterFunc *after = ui_afterfunc_new();
after->optype = ot;
after->opcontext = opcontext;
+ if (properties) {
+ after->opptr = *properties;
+ *properties = NULL;
+ }
- if (create_props) {
- ptr = MEM_callocN(sizeof(PointerRNA), __func__);
- WM_operator_properties_create_ptr(ptr, ot);
- after->opptr = ptr;
+ if (context_but && context_but->context) {
+ after->context = CTX_store_copy(context_but->context);
}
+}
- return ptr;
+void ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext)
+{
+ ui_handle_afterfunc_add_operator_ex(ot, NULL, opcontext, NULL);
}
static void popup_check(bContext *C, wmOperator *op)
@@ -769,72 +814,95 @@ static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but)
(block->handle && block->handle->popup_op));
}
+/**
+ * These functions are postponed and only executed after all other
+ * handling is done, i.e. menus are closed, in order to avoid conflicts
+ * with these functions removing the buttons we are working with.
+ */
static void ui_apply_but_func(bContext *C, uiBut *but)
{
uiBlock *block = but->block;
+ if (!ui_afterfunc_check(block, but)) {
+ return;
+ }
- /* these functions are postponed and only executed after all other
- * handling is done, i.e. menus are closed, in order to avoid conflicts
- * with these functions removing the buttons we are working with */
-
- if (ui_afterfunc_check(block, but)) {
- uiAfterFunc *after = ui_afterfunc_new();
+ uiAfterFunc *after = ui_afterfunc_new();
- if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) {
- /* exception, this will crash due to removed button otherwise */
- but->func(C, but->func_arg1, but->func_arg2);
- }
- else {
- after->func = but->func;
- }
+ if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) {
+ /* exception, this will crash due to removed button otherwise */
+ but->func(C, but->func_arg1, but->func_arg2);
+ }
+ else {
+ after->func = but->func;
+ }
- after->func_arg1 = but->func_arg1;
- after->func_arg2 = but->func_arg2;
+ after->func_arg1 = but->func_arg1;
+ after->func_arg2 = but->func_arg2;
- after->funcN = but->funcN;
- after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL;
+ after->funcN = but->funcN;
+ after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL;
- after->rename_func = but->rename_func;
- after->rename_arg1 = but->rename_arg1;
- after->rename_orig = but->rename_orig; /* needs free! */
+ after->rename_func = but->rename_func;
+ after->rename_arg1 = but->rename_arg1;
+ after->rename_orig = but->rename_orig; /* needs free! */
- after->handle_func = block->handle_func;
- after->handle_func_arg = block->handle_func_arg;
- after->retval = but->retval;
+ after->handle_func = block->handle_func;
+ after->handle_func_arg = block->handle_func_arg;
+ after->retval = but->retval;
- if (but->type == UI_BTYPE_BUT_MENU) {
- after->butm_func = block->butm_func;
- after->butm_func_arg = block->butm_func_arg;
- after->a2 = but->a2;
- }
+ if (but->type == UI_BTYPE_BUT_MENU) {
+ after->butm_func = block->butm_func;
+ after->butm_func_arg = block->butm_func_arg;
+ after->a2 = but->a2;
+ }
- if (block->handle) {
- after->popup_op = block->handle->popup_op;
- }
+ if (block->handle) {
+ after->popup_op = block->handle->popup_op;
+ }
- after->optype = but->optype;
- after->opcontext = but->opcontext;
- after->opptr = but->opptr;
+ after->optype = but->optype;
+ after->opcontext = but->opcontext;
+ after->opptr = but->opptr;
- after->rnapoin = but->rnapoin;
- after->rnaprop = but->rnaprop;
+ after->rnapoin = but->rnapoin;
+ after->rnaprop = but->rnaprop;
- if (but->type == UI_BTYPE_SEARCH_MENU) {
- uiButSearch *search_but = (uiButSearch *)but;
- after->search_arg_free_fn = search_but->arg_free_fn;
- after->search_arg = search_but->arg;
- search_but->arg_free_fn = NULL;
- search_but->arg = NULL;
- }
+ if (but->type == UI_BTYPE_SEARCH_MENU) {
+ uiButSearch *search_but = (uiButSearch *)but;
+ after->search_arg_free_fn = search_but->arg_free_fn;
+ after->search_arg = search_but->arg;
+ search_but->arg_free_fn = NULL;
+ search_but->arg = NULL;
+ }
- if (but->context) {
- after->context = CTX_store_copy(but->context);
+ if (but->active != NULL) {
+ uiHandleButtonData *data = but->active;
+ if (data->custom_interaction_handle != NULL) {
+ after->custom_interaction_callbacks = block->custom_interaction_callbacks;
+ after->custom_interaction_handle = data->custom_interaction_handle;
+
+ /* Ensure this callback runs once and last. */
+ uiAfterFunc *after_prev = after->prev;
+ if (after_prev &&
+ (after_prev->custom_interaction_handle == data->custom_interaction_handle)) {
+ after_prev->custom_interaction_handle = NULL;
+ memset(&after_prev->custom_interaction_callbacks,
+ 0x0,
+ sizeof(after_prev->custom_interaction_callbacks));
+ }
+ else {
+ after->custom_interaction_handle->user_count++;
+ }
}
+ }
- but->optype = NULL;
- but->opcontext = 0;
- but->opptr = NULL;
+ if (but->context) {
+ after->context = CTX_store_copy(but->context);
}
+
+ but->optype = NULL;
+ but->opcontext = 0;
+ but->opptr = NULL;
}
/* typically call ui_apply_but_undo(), ui_apply_but_autokey() */
@@ -997,6 +1065,18 @@ static void ui_apply_but_funcs_after(bContext *C)
after.search_arg_free_fn(after.search_arg);
}
+ if (after.custom_interaction_handle != NULL) {
+ after.custom_interaction_handle->user_count--;
+ BLI_assert(after.custom_interaction_handle->user_count >= 0);
+ if (after.custom_interaction_handle->user_count == 0) {
+ ui_block_interaction_update(
+ C, &after.custom_interaction_callbacks, after.custom_interaction_handle);
+ ui_block_interaction_end(
+ C, &after.custom_interaction_callbacks, after.custom_interaction_handle);
+ }
+ after.custom_interaction_handle = NULL;
+ }
+
ui_afterfunc_update_preferences_dirty(&after);
if (after.undostr[0]) {
@@ -1076,6 +1156,42 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
data->applied = true;
}
+/**
+ * \note Ownership of \a properties is moved here. The #uiAfterFunc owns it now.
+ *
+ * \param context_but: The button to use context from when calling or polling the operator.
+ *
+ * \returns true if the operator was executed, otherwise false.
+ */
+static bool ui_list_invoke_item_operator(bContext *C,
+ const uiBut *context_but,
+ wmOperatorType *ot,
+ PointerRNA **properties)
+{
+ if (!ui_but_context_poll_operator(C, ot, context_but)) {
+ return false;
+ }
+
+ /* Allow the context to be set from the hovered button, so the list item draw callback can set
+ * context for the operators. */
+ ui_handle_afterfunc_add_operator_ex(ot, properties, WM_OP_INVOKE_DEFAULT, context_but);
+ return true;
+}
+
+static void ui_apply_but_LISTROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
+{
+ uiBut *listbox = ui_list_find_from_row(data->region, but);
+ if (listbox) {
+ uiList *list = listbox->custom_data;
+ if (list && list->dyn_data->custom_activate_optype) {
+ ui_list_invoke_item_operator(
+ C, but, list->dyn_data->custom_activate_optype, &list->dyn_data->custom_activate_opptr);
+ }
+ }
+
+ ui_apply_but_ROW(C, block, but, data);
+}
+
static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
{
if (!data->str) {
@@ -1350,7 +1466,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat
}
/* edit buttons proportionally to eachother
- * note: if we mix buttons which are proportional and others which are not,
+ * NOTE: if we mix buttons which are proportional and others which are not,
* this may work a bit strangely */
if ((but_active->rnaprop && (RNA_property_flag(but_active->rnaprop) & PROP_PROPORTIONAL)) ||
ELEM(but_active->unit_type, RNA_SUBTYPE_UNIT_VALUE(PROP_UNIT_LENGTH))) {
@@ -1502,7 +1618,7 @@ static bool ui_drag_toggle_set_xy_xy(
ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]);
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
- /* Note: ctrl is always true here because (at least for now)
+ /* NOTE: ctrl is always true here because (at least for now)
* we always want to consider text control in this case, even when not embossed. */
if (ui_but_is_interactive(but, true)) {
if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
@@ -1548,7 +1664,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
*/
if (drag_info->is_xy_lock_init == false) {
/* first store the buttons original coords */
- uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true);
+ uiBut *but = ui_but_find_mouse_over_ex(region, xy_input[0], xy_input[1], true, NULL, NULL);
if (but) {
if (but->flag & UI_BUT_DRAG_LOCK) {
@@ -1619,7 +1735,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
wmWindow *win = CTX_wm_window(C);
const ARegion *region = CTX_wm_region(C);
uiBut *but = ui_but_find_mouse_over_ex(
- region, drag_info->xy_init[0], drag_info->xy_init[1], true);
+ region, drag_info->xy_init[0], drag_info->xy_init[1], true, NULL, NULL);
if (but) {
ui_apply_but_undo(but);
@@ -1686,7 +1802,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore
break;
}
uiSelectContextElem *other = &selctx_data->elems[i];
- /* TODO,. de-duplicate copy_to_selected_button */
+ /* TODO: de-duplicate copy_to_selected_button. */
if (link->ptr.data != ptr.data) {
if (use_path_from_id) {
/* Path relative to ID. */
@@ -1987,7 +2103,7 @@ static bool ui_but_drag_init(bContext *C,
bool valid = false;
uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
- /* TODO support more button pointer types */
+ /* TODO: support more button pointer types. */
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
ui_but_v3_get(but, drag_info->color);
drag_info->gamma_corrected = true;
@@ -2181,9 +2297,11 @@ static void ui_apply_but(
ui_apply_but_TOG(C, but, data);
break;
case UI_BTYPE_ROW:
- case UI_BTYPE_LISTROW:
ui_apply_but_ROW(C, block, but, data);
break;
+ case UI_BTYPE_LISTROW:
+ ui_apply_but_LISTROW(C, block, but, data);
+ break;
case UI_BTYPE_DATASETROW:
ui_apply_but_ROW(C, block, but, data);
break;
@@ -2283,6 +2401,11 @@ static void ui_apply_but(
uiButCurveProfile *but_profile = (uiButCurveProfile *)but;
but_profile->edit_profile = editprofile;
}
+
+ if (data->custom_interaction_handle != NULL) {
+ ui_block_interaction_update(
+ C, &block->custom_interaction_callbacks, data->custom_interaction_handle);
+ }
}
/** \} */
@@ -2297,7 +2420,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */
LISTBASE_FOREACH (wmDrag *, wmd, drags) {
- /* TODO asset dropping. */
+ /* TODO: asset dropping. */
if (wmd->type == WM_DRAG_ID) {
/* align these types with UI_but_active_drop_name */
if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
@@ -2428,7 +2551,7 @@ static void ui_but_paste_numeric_array(bContext *C,
static void ui_but_copy_numeric_value(uiBut *but, char *output, int output_len_max)
{
/* Get many decimal places, then strip trailing zeros.
- * note: too high values start to give strange results */
+ * NOTE: too high values start to give strange results. */
ui_but_string_get_ex(but, output, output_len_max, UI_PRECISION_FLOAT_MAX, false, NULL);
BLI_str_rstrip_float_zero(output, '\0');
}
@@ -3268,7 +3391,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
}
#ifdef WITH_INPUT_IME
-/* enable ime, and set up uibut ime data */
+/* Enable IME, and setup #uiBut IME data. */
static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but))
{
/* XXX Is this really needed? */
@@ -3284,7 +3407,7 @@ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but))
wm_window_IME_begin(win, x, y, 0, 0, true);
}
-/* disable ime, and clear uibut ime data */
+/* Disable IME, and clear #uiBut IME data. */
static void ui_textedit_ime_end(wmWindow *win, uiBut *UNUSED(but))
{
wm_window_IME_end(win);
@@ -3396,6 +3519,11 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
ui_but_update(but);
+ /* Popup blocks don't support moving after creation, so don't change the view for them. */
+ if (!data->searchbox) {
+ UI_but_ensure_in_view(C, data->region, but);
+ }
+
WM_cursor_modal_set(win, WM_CURSOR_TEXT_EDIT);
#ifdef WITH_INPUT_IME
@@ -4210,7 +4338,7 @@ static uiBut *ui_but_list_row_text_activate(bContext *C,
uiButtonActivateType activate_type)
{
ARegion *region = CTX_wm_region(C);
- uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true);
+ uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->x, event->y, true, NULL, NULL);
if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) {
/* exit listrow */
@@ -4284,7 +4412,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
button_tooltip_timer_reset(C, but);
ui_but_extra_operator_icon_apply(C, but, op_icon);
- /* Note: 'but', 'data' may now be freed, don't access. */
+ /* NOTE: 'but', 'data' may now be freed, don't access. */
return true;
}
@@ -4334,7 +4462,7 @@ static bool ui_do_but_ANY_drag_toggle(
}
}
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
- /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into
+ /* NOTE: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into
* its own function */
data->applied = false;
*r_retval = ui_do_but_EXIT(C, but, data, event);
@@ -4677,7 +4805,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- /* first handle click on icondrag type button */
+ /* First handle click on icon-drag type button. */
if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) && but->dragpoin) {
if (ui_but_contains_point_px_icon(but, data->region, event)) {
@@ -4700,10 +4828,19 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
- /* XXX (a bit ugly) Special case handling for filebrowser drag button */
+ /* XXX: (a bit ugly) Special case handling for file-browser drag button. */
if (but->dragpoin && but->imb && ui_but_contains_point_px_icon(but, data->region, event)) {
ret = WM_UI_HANDLER_CONTINUE;
}
+ /* Same special case handling for UI lists. Return CONTINUE so that a tweak or CLICK event
+ * will be sent for the list to work with. */
+ const uiBut *listbox = ui_list_find_mouse_over(data->region, event);
+ if (listbox) {
+ const uiList *ui_list = listbox->custom_data;
+ if (ui_list && ui_list->dyn_data->custom_drag_optype) {
+ ret = WM_UI_HANDLER_CONTINUE;
+ }
+ }
button_activate_state(C, but, BUTTON_STATE_EXIT);
return ret;
}
@@ -4852,6 +4989,8 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
return changed;
}
+ ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false);
+
if (ui_but_is_cursor_warp(but)) {
const float softmin = but->softmin;
const float softmax = but->softmax;
@@ -5362,6 +5501,8 @@ static bool ui_numedit_but_SLI(uiBut *but,
return changed;
}
+ ui_block_interaction_begin_ensure(but->block->evil_C, but->block, data, false);
+
const PropertyScaleType scale_type = ui_but_scale_type(but);
softmin = but->softmin;
@@ -5763,7 +5904,7 @@ static int ui_do_but_GRIP(
int retval = WM_UI_HANDLER_CONTINUE;
const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
- /* Note: Having to store org point in window space and recompute it to block "space" each time
+ /* NOTE: Having to store org point in window space and recompute it to block "space" each time
* is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which
* returns different results when the block is inside a panel or not...
* See T37739.
@@ -5836,7 +5977,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- /* first handle click on icondrag type button */
+ /* First handle click on icon-drag type button. */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
if (ui_but_contains_point_px_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
@@ -6021,7 +6162,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
uiButColor *color_but = (uiButColor *)but;
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- /* first handle click on icondrag type button */
+ /* First handle click on icon-drag type button. */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
ui_palette_set_active(color_but);
if (ui_but_contains_point_px_icon(but, data->region, event)) {
@@ -6435,7 +6576,7 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but,
CLAMP(hsv[2], hsv_but->but.softmin, hsv_but->but.softmax);
break;
default:
- BLI_assert(!"invalid hsv type");
+ BLI_assert_msg(0, "invalid hsv type");
break;
}
@@ -6951,8 +7092,8 @@ static bool ui_numedit_but_CURVE(uiBlock *block,
CurveMapPoint *cmp = cuma->curve;
bool changed = false;
- /* evtx evty and drag coords are absolute mousecoords,
- * prevents errors when editing when layout changes */
+ /* evtx evty and drag coords are absolute mouse-coords,
+ * prevents errors when editing when layout changes. */
int mx = evtx;
int my = evty;
ui_window_to_block(data->region, block, &mx, &my);
@@ -7010,7 +7151,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block,
changed = true;
#ifdef USE_CONT_MOUSE_CORRECT
- /* note: using 'cmp_last' is weak since there may be multiple points selected,
+ /* NOTE: using 'cmp_last' is weak since there may be multiple points selected,
* but in practice this isn't really an issue */
if (ui_but_is_cursor_warp(but)) {
/* OK but can go outside bounds */
@@ -7219,8 +7360,8 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block,
CurveProfilePoint *pts = profile->path;
bool changed = false;
- /* evtx evty and drag coords are absolute mousecoords,
- * prevents errors when editing when layout changes */
+ /* evtx evty and drag coords are absolute mouse-coords,
+ * prevents errors when editing when layout changes. */
int mx = evtx;
int my = evty;
ui_window_to_block(data->region, block, &mx, &my);
@@ -7281,7 +7422,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block,
data->draglasty = evty;
changed = true;
#ifdef USE_CONT_MOUSE_CORRECT
- /* note: using 'cmp_last' is weak since there may be multiple points selected,
+ /* NOTE: using 'cmp_last' is weak since there may be multiple points selected,
* but in practice this isn't really an issue */
if (ui_but_is_cursor_warp(but)) {
/* OK but can go outside bounds */
@@ -7773,7 +7914,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
(event->val == KM_PRESS)) {
/* RMB has two options now */
- if (ui_popup_context_menu_for_button(C, but)) {
+ if (ui_popup_context_menu_for_button(C, but, event)) {
return WM_UI_HANDLER_BREAK;
}
}
@@ -7853,6 +7994,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_IMAGE:
case UI_BTYPE_PROGRESS_BAR:
case UI_BTYPE_NODE_SOCKET:
+ case UI_BTYPE_PREVIEW_TILE:
retval = ui_do_but_EXIT(C, but, data, event);
break;
case UI_BTYPE_HISTOGRAM:
@@ -8239,6 +8381,16 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
but->flag &= ~UI_SELECT;
}
+ if (state == BUTTON_STATE_TEXT_EDITING) {
+ ui_block_interaction_begin_ensure(C, but->block, data, true);
+ }
+ else if (state == BUTTON_STATE_EXIT) {
+ if (data->state == BUTTON_STATE_NUM_EDITING) {
+ /* This happens on pasting values for example. */
+ ui_block_interaction_begin_ensure(C, but->block, data, true);
+ }
+ }
+
data->state = state;
if (state != BUTTON_STATE_EXIT) {
@@ -8467,6 +8619,21 @@ static void button_activate_exit(
ED_region_tag_redraw_no_rebuild(data->region);
ED_region_tag_refresh_ui(data->region);
+ if ((but->flag & UI_BUT_DRAG_MULTI) == 0) {
+ if (data->custom_interaction_handle != NULL) {
+ /* Should only set when the button is modal. */
+ BLI_assert(but->active != NULL);
+ data->custom_interaction_handle->user_count--;
+
+ BLI_assert(data->custom_interaction_handle->user_count >= 0);
+ if (data->custom_interaction_handle->user_count == 0) {
+ ui_block_interaction_end(
+ C, &but->block->custom_interaction_callbacks, data->custom_interaction_handle);
+ }
+ data->custom_interaction_handle = NULL;
+ }
+ }
+
/* clean up button */
if (but->active) {
MEM_freeN(but->active);
@@ -8614,9 +8781,9 @@ void UI_context_active_but_prop_handle(bContext *C)
{
uiBut *activebut = ui_context_rna_button_active(C);
if (activebut) {
- /* TODO, look into a better way to handle the button change
+ /* TODO(campbell): look into a better way to handle the button change
* currently this is mainly so reset defaults works for the
- * operator redo panel - campbell */
+ * operator redo panel. */
uiBlock *block = activebut->block;
if (block->handle_func) {
block->handle_func(C, block->handle_func_arg, activebut->retval);
@@ -8722,6 +8889,26 @@ void UI_context_update_anim_flag(const bContext *C)
}
}
+/**
+ * In some cases we may want to update the view (#View2D) in-between layout definition and drawing.
+ * E.g. to make sure a button is visible while editing.
+ */
+void ui_but_update_view_for_active(const bContext *C, const uiBlock *block)
+{
+ uiBut *active_but = ui_block_active_but_get(block);
+ if (!active_but || !active_but->active || !active_but->changed || active_but->block != block) {
+ return;
+ }
+ /* If there is a search popup attached to the button, don't change the view. The popups don't
+ * support updating the position to the button position nicely. */
+ uiHandleButtonData *data = active_but->active;
+ if (data->searchbox) {
+ return;
+ }
+
+ UI_but_ensure_in_view(C, active_but->active->region, active_but);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -8805,7 +8992,7 @@ void ui_but_execute_begin(struct bContext *UNUSED(C),
{
BLI_assert(region != NULL);
BLI_assert(BLI_findindex(&region->uiblocks, but->block) != -1);
- /* note: ideally we would not have to change 'but->active' however
+ /* NOTE: ideally we would not have to change 'but->active' however
* some functions we call don't use data (as they should be doing) */
uiHandleButtonData *data;
*active_back = but->active;
@@ -9174,7 +9361,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
*
* This is needed to make sure if a button was active,
* it stays active while the mouse is over it.
- * This avoids adding mousemoves, see: T33466. */
+ * This avoids adding mouse-moves, see: T33466. */
if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT, BUTTON_STATE_WAIT_DRAG)) {
if (ui_but_find_mouse_over(region, event) == but) {
button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
@@ -9186,6 +9373,149 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
return retval;
}
+/**
+ * Activate the underlying list-row button, so the row is highlighted.
+ * Early exits if \a activate_dragging is true, but the custom drag operator fails to execute.
+ * Gives the wanted behavior where the item is activated on a tweak event when the custom drag
+ * operator is executed.
+ */
+static int ui_list_activate_hovered_row(bContext *C,
+ ARegion *region,
+ const uiList *ui_list,
+ const wmEvent *event,
+ bool activate_dragging)
+{
+ const bool do_drag = activate_dragging && ui_list->dyn_data->custom_drag_optype;
+
+ if (do_drag) {
+ const uiBut *hovered_but = ui_but_find_mouse_over(region, event);
+ if (!ui_list_invoke_item_operator(C,
+ hovered_but,
+ ui_list->dyn_data->custom_drag_optype,
+ &ui_list->dyn_data->custom_drag_opptr)) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ }
+
+ const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x;
+ uiBut *listrow = ui_list_row_find_mouse_over(region, mouse_xy[0], mouse_xy[1]);
+ if (listrow) {
+ wmOperatorType *custom_activate_optype = ui_list->dyn_data->custom_activate_optype;
+
+ /* Hacky: Ensure the custom activate operator is not called when the custom drag operator
+ * was. Only one should run! */
+ if (activate_dragging && do_drag) {
+ ((uiList *)ui_list)->dyn_data->custom_activate_optype = NULL;
+ }
+
+ /* Simulate click on listrow button itself (which may be overlapped by another button). Also
+ * calls the custom activate operator (ui_list->custom_activate_opname). */
+ UI_but_execute(C, region, listrow);
+
+ ((uiList *)ui_list)->dyn_data->custom_activate_optype = custom_activate_optype;
+ }
+
+ return WM_UI_HANDLER_BREAK;
+}
+
+static bool ui_list_is_hovering_draggable_but(bContext *C,
+ const uiList *list,
+ const ARegion *region,
+ const wmEvent *event)
+{
+ /* On a tweak event, uses the coordinates from where tweaking was started. */
+ const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x;
+ const uiBut *hovered_but = ui_but_find_mouse_over_ex(
+ region, mouse_xy[0], mouse_xy[1], false, NULL, NULL);
+
+ if (list->dyn_data->custom_drag_optype) {
+ if (ui_but_context_poll_operator(C, list->dyn_data->custom_drag_optype, hovered_but)) {
+ return true;
+ }
+ }
+
+ return (hovered_but && hovered_but->dragpoin);
+}
+
+static int ui_list_handle_click_drag(bContext *C,
+ const uiList *ui_list,
+ ARegion *region,
+ const wmEvent *event)
+{
+ if (!ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) {
+ return WM_HANDLER_CONTINUE;
+ }
+
+ int retval = WM_HANDLER_CONTINUE;
+
+ const bool is_draggable = ui_list_is_hovering_draggable_but(C, ui_list, region, event);
+ bool activate = false;
+ bool activate_dragging = false;
+
+ if (event->type == EVT_TWEAK_L) {
+ if (is_draggable) {
+ activate_dragging = true;
+ activate = true;
+ }
+ }
+ /* #KM_CLICK is only sent after an uncaught release event, so the foreground button gets all
+ * regular events (including mouse presses to start dragging) and this part only kicks in if it
+ * hasn't handled the release event. Note that if there's no overlaid button, the row selects
+ * on the press event already via regular #UI_BTYPE_LISTROW handling. */
+ else if ((event->type == LEFTMOUSE) && (event->val == KM_CLICK)) {
+ activate = true;
+ }
+
+ if (activate) {
+ retval = ui_list_activate_hovered_row(C, region, ui_list, event, activate_dragging);
+ }
+
+ return retval;
+}
+
+static void ui_list_activate_row_from_index(
+ bContext *C, ARegion *region, uiBut *listbox, uiList *ui_list, int index)
+{
+ uiBut *new_active_row = ui_list_row_find_from_index(region, index, listbox);
+ if (new_active_row) {
+ /* Preferred way to update the active item, also calls the custom activate operator
+ * (#uiList.custom_activate_opname). */
+ UI_but_execute(C, region, new_active_row);
+ }
+ else {
+ /* A bit ugly, set the active index in RNA directly. That's because a button that's
+ * scrolled away in the list box isn't created at all.
+ * The custom activate operator (#uiList.custom_activate_opname) is not called in this case
+ * (which may need the row button context).*/
+ RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, index);
+ RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop);
+ ui_apply_but_undo(listbox);
+ }
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+}
+
+static int ui_list_get_increment(const uiList *ui_list, const int type, const int columns)
+{
+ int increment = 0;
+
+ /* Handle column offsets for grid layouts. */
+ if (ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY) &&
+ ELEM(ui_list->layout_type, UILST_LAYOUT_GRID, UILST_LAYOUT_BIG_PREVIEW_GRID)) {
+ increment = (type == EVT_UPARROWKEY) ? -columns : columns;
+ }
+ else {
+ /* Left or right in grid layouts or any direction in single column layouts increments by 1. */
+ increment = ELEM(type, EVT_UPARROWKEY, EVT_LEFTARROWKEY, WHEELUPMOUSE) ? -1 : 1;
+ }
+
+ if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) {
+ increment *= -1;
+ }
+
+ return increment;
+}
+
static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *region, uiBut *listbox)
{
int retval = WM_UI_HANDLER_CONTINUE;
@@ -9219,22 +9549,19 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi
}
}
- if (val == KM_PRESS) {
- if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY) &&
+ if (ELEM(event->type, LEFTMOUSE, EVT_TWEAK_L)) {
+ retval = ui_list_handle_click_drag(C, ui_list, region, event);
+ }
+ else if (val == KM_PRESS) {
+ if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY, EVT_LEFTARROWKEY, EVT_RIGHTARROWKEY) &&
!IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) ||
((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl &&
!IS_EVENT_MOD(event, shift, alt, oskey)))) {
const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop);
- int value, min, max, inc;
+ int value, min, max;
- /* activate up/down the list */
value = value_orig;
- if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) {
- inc = ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE) ? 1 : -1;
- }
- else {
- inc = ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
- }
+ const int inc = ui_list_get_increment(ui_list, type, dyn_data->columns);
if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) {
/* If we have a display order different from
@@ -9281,12 +9608,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi
CLAMP(value, min, max);
if (value != value_orig) {
- RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, value);
- RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop);
-
- ui_apply_but_undo(listbox);
-
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ui_list_activate_row_from_index(C, region, listbox, ui_list, value);
redraw = true;
}
retval = WM_UI_HANDLER_BREAK;
@@ -10255,7 +10577,7 @@ static int ui_handle_menu_event(bContext *C,
/* For buttons that use a hold function,
* exit when mouse-up outside the menu. */
if (block->flag & UI_BLOCK_POPUP_HOLD) {
- /* Note, we could check the cursor is over the parent button. */
+ /* NOTE: we could check the cursor is over the parent button. */
menu->menuretval = UI_RETURN_CANCEL;
retval = WM_UI_HANDLER_CONTINUE;
}
@@ -11314,3 +11636,100 @@ bool UI_but_active_drop_color(bContext *C)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UI Block Interaction API
+ * \{ */
+
+void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks)
+{
+ block->custom_interaction_callbacks = *callbacks;
+}
+
+static uiBlockInteraction_Handle *ui_block_interaction_begin(bContext *C,
+ uiBlock *block,
+ const bool is_click)
+{
+ BLI_assert(block->custom_interaction_callbacks.begin_fn != NULL);
+ uiBlockInteraction_Handle *interaction = MEM_callocN(sizeof(*interaction), __func__);
+
+ int unique_retval_ids_len = 0;
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) {
+ unique_retval_ids_len++;
+ }
+ }
+
+ int *unique_retval_ids = MEM_mallocN(sizeof(*unique_retval_ids) * unique_retval_ids_len,
+ __func__);
+ unique_retval_ids_len = 0;
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (but->active || (but->flag & UI_BUT_DRAG_MULTI)) {
+ unique_retval_ids[unique_retval_ids_len++] = but->retval;
+ }
+ }
+
+ if (unique_retval_ids_len > 1) {
+ qsort(unique_retval_ids, unique_retval_ids_len, sizeof(int), BLI_sortutil_cmp_int);
+ unique_retval_ids_len = BLI_array_deduplicate_ordered(unique_retval_ids,
+ unique_retval_ids_len);
+ unique_retval_ids = MEM_reallocN(unique_retval_ids,
+ sizeof(*unique_retval_ids) * unique_retval_ids_len);
+ }
+
+ interaction->params.is_click = is_click;
+ interaction->params.unique_retval_ids = unique_retval_ids;
+ interaction->params.unique_retval_ids_len = unique_retval_ids_len;
+
+ interaction->user_data = block->custom_interaction_callbacks.begin_fn(
+ C, &interaction->params, block->custom_interaction_callbacks.arg1);
+ return interaction;
+}
+
+static void ui_block_interaction_end(bContext *C,
+ uiBlockInteraction_CallbackData *callbacks,
+ uiBlockInteraction_Handle *interaction)
+{
+ BLI_assert(callbacks->end_fn != NULL);
+ callbacks->end_fn(C, &interaction->params, callbacks->arg1, interaction->user_data);
+ MEM_freeN(interaction->params.unique_retval_ids);
+ MEM_freeN(interaction);
+}
+
+static void ui_block_interaction_update(bContext *C,
+ uiBlockInteraction_CallbackData *callbacks,
+ uiBlockInteraction_Handle *interaction)
+{
+ BLI_assert(callbacks->update_fn != NULL);
+ callbacks->update_fn(C, &interaction->params, callbacks->arg1, interaction->user_data);
+}
+
+/**
+ * \note #ui_block_interaction_begin cannot be called when setting the button state
+ * (e.g. #BUTTON_STATE_NUM_EDITING) for the following reasons.
+ *
+ * - Other buttons may still be activated using #UI_BUT_DRAG_MULTI
+ * which is necessary before gathering all the #uiBut.retval values to initialize
+ * #uiBlockInteraction_Params.unique_retval_ids.
+ * - When clicking on a number button it's not known if the event is a click or a drag.
+ *
+ * Instead, it must be called immediately before the drag action begins.
+ */
+static void ui_block_interaction_begin_ensure(bContext *C,
+ uiBlock *block,
+ uiHandleButtonData *data,
+ const bool is_click)
+{
+ if (data->custom_interaction_handle) {
+ return;
+ }
+ if (block->custom_interaction_callbacks.begin_fn == NULL) {
+ return;
+ }
+
+ uiBlockInteraction_Handle *interaction = ui_block_interaction_begin(C, block, is_click);
+ interaction->user_count = 1;
+ data->custom_interaction_handle = interaction;
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 4defbed940e..43ac646f053 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1180,7 +1180,7 @@ static DrawInfo *icon_ensure_drawinfo(Icon *icon)
return di;
}
-/* note!, returns unscaled by DPI */
+/* NOTE:, returns unscaled by DPI. */
int UI_icon_get_width(int icon_id)
{
Icon *icon = BKE_icon_get(icon_id);
@@ -1500,7 +1500,7 @@ static void icon_draw_rect(float x,
/* sanity check */
if (w <= 0 || h <= 0 || w > 2000 || h > 2000) {
printf("%s: icons are %i x %i pixels?\n", __func__, w, h);
- BLI_assert(!"invalid icon size");
+ BLI_assert_msg(0, "invalid icon size");
return;
}
/* modulate color */
@@ -1519,7 +1519,7 @@ static void icon_draw_rect(float x,
draw_h = h;
draw_x += (w - draw_w) / 2;
}
- /* if the image is squared, the draw_ initialization values are good */
+ /* If the image is squared, the `draw_*` initialization values are good. */
/* first allocate imbuf for scaling and copy preview into it */
ima = IMB_allocImBuf(rw, rh, 32, IB_rect);
@@ -2201,7 +2201,7 @@ int UI_icon_from_library(const ID *id)
return ICON_NONE;
}
-int UI_icon_from_rnaptr(bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
+int UI_icon_from_rnaptr(const bContext *C, PointerRNA *ptr, int rnaicon, const bool big)
{
ID *id = NULL;
@@ -2294,7 +2294,7 @@ int UI_icon_from_idcode(const int idcode)
case ID_ME:
return ICON_MESH_DATA;
case ID_MSK:
- return ICON_MOD_MASK; /* TODO! this would need its own icon! */
+ return ICON_MOD_MASK; /* TODO: this would need its own icon! */
case ID_NT:
return ICON_NODETREE;
case ID_OB:
@@ -2302,9 +2302,9 @@ int UI_icon_from_idcode(const int idcode)
case ID_PA:
return ICON_PARTICLE_DATA;
case ID_PAL:
- return ICON_COLOR; /* TODO! this would need its own icon! */
+ return ICON_COLOR; /* TODO: this would need its own icon! */
case ID_PC:
- return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
+ return ICON_CURVE_BEZCURVE; /* TODO: this would need its own icon! */
case ID_LP:
return ICON_OUTLINER_DATA_LIGHTPROBE;
case ID_SCE:
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index b9a44b5bce9..a07f924e65b 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -262,7 +262,7 @@ struct uiBut {
ListBase extra_op_icons; /** #uiButExtraOpIcon */
- /* Draggable data, type is WM_DRAG_... */
+ /* Drag-able data, type is WM_DRAG_... */
char dragtype;
short dragflag;
void *dragpoin;
@@ -511,6 +511,9 @@ struct uiBlock {
uiBlockHandleFunc handle_func;
void *handle_func_arg;
+ /** Custom interaction data. */
+ uiBlockInteraction_CallbackData custom_interaction_callbacks;
+
/** Custom extra event handling. */
int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *);
@@ -594,11 +597,19 @@ typedef struct uiSafetyRct {
void ui_fontscale(short *points, float aspect);
+extern void ui_block_to_region_fl(const struct ARegion *region,
+ uiBlock *block,
+ float *r_x,
+ float *r_y);
extern void ui_block_to_window_fl(const struct ARegion *region,
uiBlock *block,
float *x,
float *y);
extern void ui_block_to_window(const struct ARegion *region, uiBlock *block, int *x, int *y);
+extern void ui_block_to_region_rctf(const struct ARegion *region,
+ uiBlock *block,
+ rctf *rct_dst,
+ const rctf *rct_src);
extern void ui_block_to_window_rctf(const struct ARegion *region,
uiBlock *block,
rctf *rct_dst,
@@ -617,6 +628,9 @@ extern void ui_window_to_region(const struct ARegion *region, int *x, int *y);
extern void ui_window_to_region_rcti(const struct ARegion *region,
rcti *rect_dst,
const rcti *rct_src);
+extern void ui_window_to_region_rctf(const struct ARegion *region,
+ rctf *rect_dst,
+ const rctf *rct_src);
extern void ui_region_to_window(const struct ARegion *region, int *x, int *y);
extern void ui_region_winrct_get_no_margin(const struct ARegion *region, struct rcti *r_rect);
@@ -928,9 +942,7 @@ const char *ui_textedit_undo(struct uiUndoStack_Text *undo_stack,
int *r_cursor_index);
/* interface_handlers.c */
-PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot,
- int opcontext,
- bool create_props);
+extern void ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext);
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_but_activate_event(struct bContext *C, struct ARegion *region, uiBut *but);
extern void ui_but_activate_over(struct bContext *C, struct ARegion *region, uiBut *but);
@@ -943,6 +955,7 @@ extern void ui_but_execute_end(struct bContext *C,
uiBut *but,
void *active_back);
extern void ui_but_active_free(const struct bContext *C, uiBut *but);
+extern void ui_but_update_view_for_active(const struct bContext *C, const uiBlock *block);
extern int ui_but_menu_direction(uiBut *but);
extern void ui_but_text_password_hide(char password_str[128], uiBut *but, const bool restore);
extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
@@ -1042,8 +1055,18 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle,
int state,
uiMenuItemSeparatorType separator_type,
int *r_xmax);
-void ui_draw_preview_item(
- const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
+void ui_draw_preview_item(const struct uiFontStyle *fstyle,
+ rcti *rect,
+ const char *name,
+ int iconid,
+ int state,
+ eFontStyle_Align text_align);
+void ui_draw_preview_item_stateless(const struct uiFontStyle *fstyle,
+ rcti *rect,
+ const char *name,
+ int iconid,
+ const uchar text_col[4],
+ eFontStyle_Align text_align);
#define UI_TEXT_MARGIN_X 0.4f
#define UI_POPUP_MARGIN (UI_DPI_FAC * 12)
@@ -1125,19 +1148,32 @@ bool ui_but_contains_point_px_icon(const uiBut *but,
bool ui_but_contains_point_px(const uiBut *but, const struct ARegion *region, int x, int y)
ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_list_find_mouse_over(struct ARegion *region,
+uiBut *ui_list_find_mouse_over(const struct ARegion *region,
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
-
+uiBut *ui_list_find_from_row(const struct ARegion *region,
+ const uiBut *row_but) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_list_row_find_mouse_over(const struct ARegion *region,
+ int x,
+ int y) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_list_row_find_from_index(const struct ARegion *region,
+ const int index,
+ uiBut *listbox) ATTR_WARN_UNUSED_RESULT;
+
+typedef bool (*uiButFindPollFn)(const uiBut *but, const void *customdata);
uiBut *ui_but_find_mouse_over_ex(const struct ARegion *region,
const int x,
const int y,
- const bool labeledit) ATTR_WARN_UNUSED_RESULT;
+ const bool labeledit,
+ const uiButFindPollFn find_poll,
+ const void *find_custom_data) ATTR_WARN_UNUSED_RESULT;
uiBut *ui_but_find_mouse_over(const struct ARegion *region,
const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
uiBut *ui_but_find_rect_over(const struct ARegion *region,
const rcti *rect_px) ATTR_WARN_UNUSED_RESULT;
-uiBut *ui_list_find_mouse_over_ex(struct ARegion *region, int x, int y) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_list_find_mouse_over_ex(const struct ARegion *region,
+ int x,
+ int y) ATTR_WARN_UNUSED_RESULT;
bool ui_but_contains_password(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
@@ -1149,6 +1185,7 @@ uiBut *ui_but_next(uiBut *but) ATTR_WARN_UNUSED_RESULT;
uiBut *ui_but_first(uiBlock *block) ATTR_WARN_UNUSED_RESULT;
uiBut *ui_but_last(uiBlock *block) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_block_active_but_get(const uiBlock *block);
bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
bool ui_block_is_popover(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
@@ -1176,7 +1213,7 @@ struct ARegion *ui_screen_region_find_mouse_over(struct bScreen *screen,
const struct wmEvent *event);
/* interface_context_menu.c */
-bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but);
+bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but, const struct wmEvent *event);
void ui_popup_context_menu_for_panel(struct bContext *C,
struct ARegion *region,
struct Panel *panel);
@@ -1204,6 +1241,9 @@ void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
/* interface_eyedropper_gpencil_color.c */
void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot);
+/* interface_template_asset_view.cc */
+struct uiListType *UI_UL_asset_view(void);
+
/**
* For use with #ui_rna_collection_search_update_fn.
*/
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index a17a527c868..8b9539f1d33 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -169,7 +169,7 @@ struct uiLayout {
bool enabled;
bool redalert;
bool keepaspect;
- /** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */
+ /** For layouts inside grid-flow, they and their items shall never have a fixed maximal size. */
bool variable_size;
char alignment;
eUIEmbossType emboss;
@@ -643,7 +643,7 @@ static void ui_item_array(uiLayout *layout,
NULL);
}
else {
- /* note, this block of code is a bit arbitrary and has just been made
+ /* NOTE: this block of code is a bit arbitrary and has just been made
* to work with common cases, but may need to be re-worked */
/* special case, boolean array in a menu, this could be used in a more generic way too */
@@ -662,7 +662,7 @@ static void ui_item_array(uiLayout *layout,
}
}
- /* show checkboxes for rna on a non-emboss block (menu for eg) */
+ /* Show check-boxes for rna on a non-emboss block (menu for eg). */
bool *boolarr = NULL;
if (type == PROP_BOOLEAN &&
ELEM(layout->root->block->emboss, UI_EMBOSS_NONE, UI_EMBOSS_PULLDOWN)) {
@@ -1411,7 +1411,7 @@ BLI_INLINE bool ui_layout_is_radial(const uiLayout *layout)
}
/**
- * Create ui items for enum items in \a item_array.
+ * Create UI items for enum items in \a item_array.
*
* A version of #uiItemsFullEnumO that takes pre-calculated item array.
*/
@@ -1818,7 +1818,7 @@ static void ui_item_rna_size(uiLayout *layout,
}
else if (type == PROP_BOOLEAN) {
if (icon == ICON_NONE) {
- /* Exception for checkboxes, they need a little less space to align nicely. */
+ /* Exception for check-boxes, they need a little less space to align nicely. */
is_checkbox_only = true;
}
icon = ICON_DOT;
@@ -1984,7 +1984,7 @@ void uiItemFullR(uiLayout *layout,
* a label to display in the first column, the heading is inserted there. Otherwise it's inserted
* as a new row before the first item. */
uiLayout *heading_layout = ui_layout_heading_find(layout);
- /* Although checkboxes use the split layout, they are an exception and should only place their
+ /* Although check-boxes use the split layout, they are an exception and should only place their
* label in the second column, to not make that almost empty.
*
* Keep using 'use_prop_sep' instead of disabling it entirely because
@@ -2062,7 +2062,7 @@ void uiItemFullR(uiLayout *layout,
/* Menus and pie-menus don't show checkbox without this. */
if ((layout->root->type == UI_LAYOUT_MENU) ||
- /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */
+ /* Use check-boxes only as a fallback in pie-menu's, when no icon is defined. */
((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
const int prop_flag = RNA_property_flag(prop);
if (type == PROP_BOOLEAN) {
@@ -2353,7 +2353,7 @@ void uiItemFullR(uiLayout *layout,
}
}
- /* Mark non-embossed textfields inside a listbox. */
+ /* Mark non-embossed text-fields inside a list-box. */
if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) &&
ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) {
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
@@ -2831,7 +2831,7 @@ void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
PanelType *pt = (PanelType *)arg_pt;
UI_paneltype_draw(C, pt, layout);
- /* panels are created flipped (from event handling pov) */
+ /* Panels are created flipped (from event handling POV). */
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
@@ -3147,7 +3147,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
but->drawflag |= UI_BUT_TEXT_RIGHT;
}
- /* Mark as a label inside a listbox. */
+ /* Mark as a label inside a list-box. */
if (block->flag & UI_BLOCK_LIST_ITEM) {
but->flag |= UI_BUT_LIST_ITEM;
}
@@ -4639,7 +4639,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
{
litem->root = layout->root;
litem->align = align;
- /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */
+ /* Children of grid-flow layout shall never have "ideal big size" returned as estimated size. */
litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW;
litem->active = true;
litem->enabled = true;
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index ce5c17a0718..376a41ff9bb 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -75,6 +75,32 @@
#include "ED_text.h"
/* -------------------------------------------------------------------- */
+/** \name Immediate redraw helper
+ *
+ * Generally handlers shouldn't do any redrawing, that includes the layout/button definitions. That
+ * violates the Model-View-Controller pattern.
+ *
+ * But there are some operators which really need to re-run the layout definitions for various
+ * reasons. For example, "Edit Source" does it to find out which exact Python code added a button.
+ * Other operators may need to access buttons that aren't currently visible. In Blender's UI code
+ * design that typically means just not adding the button in the first place, for a particular
+ * redraw. So the operator needs to change context and re-create the layout, so the button becomes
+ * available to act on.
+ *
+ * \{ */
+
+static void ui_region_redraw_immediately(bContext *C, ARegion *region)
+{
+ ED_region_do_layout(C, region);
+ WM_draw_region_viewport_bind(region);
+ ED_region_do_draw(C, region);
+ WM_draw_region_viewport_unbind(region);
+ region->do_draw = false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Copy Data Path Operator
* \{ */
@@ -1215,7 +1241,7 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot)
/* ------------------------------------------------------------------------- */
/* EditSource Utility funcs and operator,
- * note, this includes utility functions and button matching checks */
+ * NOTE: this includes utility functions and button matching checks. */
typedef struct uiEditSourceStore {
uiBut but_orig;
@@ -1340,7 +1366,7 @@ static int editsource_text_edit(bContext *C,
txt_move_toline(text, line - 1, false);
/* naughty!, find text area to set, not good behavior
- * but since this is a dev tool lets allow it - campbell */
+ * but since this is a developer tool lets allow it - campbell */
ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0);
if (area) {
SpaceText *st = area->spacedata.first;
@@ -1379,11 +1405,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
- ED_region_do_layout(C, region);
- WM_draw_region_viewport_bind(region);
- ED_region_do_draw(C, region);
- WM_draw_region_viewport_unbind(region);
- region->do_draw = false;
+ ui_region_redraw_immediately(C, region);
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
BLI_ghashIterator_done(&ghi) == false;
@@ -1836,6 +1858,64 @@ static void UI_OT_drop_color(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name UI List Search Operator
+ * \{ */
+
+static bool ui_list_focused_poll(bContext *C)
+{
+ const ARegion *region = CTX_wm_region(C);
+ const wmWindow *win = CTX_wm_window(C);
+ const uiList *list = UI_list_find_mouse_over(region, win->eventstate);
+
+ return list != NULL;
+}
+
+/**
+ * Ensure the filter options are set to be visible in the UI list.
+ * \return if the visibility changed, requiring a redraw.
+ */
+static bool ui_list_unhide_filter_options(uiList *list)
+{
+ if (list->filter_flag & UILST_FLT_SHOW) {
+ /* Nothing to be done. */
+ return false;
+ }
+
+ list->filter_flag |= UILST_FLT_SHOW;
+ return true;
+}
+
+static int ui_list_start_filter_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *region = CTX_wm_region(C);
+ uiList *list = UI_list_find_mouse_over(region, event);
+ /* Poll should check. */
+ BLI_assert(list != NULL);
+
+ if (ui_list_unhide_filter_options(list)) {
+ ui_region_redraw_immediately(C, region);
+ }
+
+ if (!UI_textbutton_activate_rna(C, region, list, "filter_name")) {
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_list_start_filter(wmOperatorType *ot)
+{
+ ot->name = "List Filter";
+ ot->idname = "UI_OT_list_start_filter";
+ ot->description = "Start entering filter text for the list in focus";
+
+ ot->invoke = ui_list_start_filter_invoke;
+ ot->poll = ui_list_focused_poll;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Operator & Keymap Registration
* \{ */
@@ -1860,6 +1940,8 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_button_execute);
WM_operatortype_append(UI_OT_button_string_clear);
+ WM_operatortype_append(UI_OT_list_start_filter);
+
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
WM_operatortype_append(UI_OT_eyedropper_colorramp);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index dc0650af7a7..97d01ac3763 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -258,7 +258,7 @@ static Panel *panel_add_instanced(ARegion *region,
/* Make sure the panel is added to the end of the display-order as well. This is needed for
* loading existing files.
*
- * Note: We could use special behavior to place it after the panel that starts the list of
+ * NOTE: We could use special behavior to place it after the panel that starts the list of
* instanced panels, but that would add complexity that isn't needed for now. */
int max_sortorder = 0;
LISTBASE_FOREACH (Panel *, existing_panel, panels) {
@@ -1892,7 +1892,7 @@ static void ui_do_animate(bContext *C, Panel *panel)
}
else {
if (UI_panel_is_dragging(panel)) {
- /* Note: doing this in #panel_activate_state would require
+ /* NOTE: doing this in #panel_activate_state would require
* removing `const` for context in many other places. */
reorder_instanced_panel_list(C, region, panel);
}
@@ -2563,7 +2563,7 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm
/** \name Window Level Modal Panel Interaction
* \{ */
-/* Note, this is modal handler and should not swallow events for animation. */
+/* NOTE: this is modal handler and should not swallow events for animation. */
static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
{
Panel *panel = userdata;
@@ -2653,7 +2653,7 @@ static void panel_activate_state(const bContext *C, Panel *panel, const uiHandle
/* Initiate edge panning during drags for scrolling beyond the initial region view. */
wmOperatorType *ot = WM_operatortype_find("VIEW2D_OT_edge_pan", true);
- ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT, true);
+ ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT);
}
else if (state == PANEL_STATE_ANIMATION) {
panel_set_flag_recursive(panel, PNL_SELECT, false);
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index 7d561aa1c71..8534c95b6fd 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -78,7 +78,7 @@ bool ui_but_is_toggle(const uiBut *but)
*/
bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
{
- /* note, UI_BTYPE_LABEL is included for highlights, this allows drags */
+ /* NOTE: #UI_BTYPE_LABEL is included for highlights, this allows drags. */
if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) {
return false;
}
@@ -266,11 +266,29 @@ bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEv
return BLI_rcti_isect_pt(&rect, x, y);
}
+static uiBut *ui_but_find(const ARegion *region,
+ const uiButFindPollFn find_poll,
+ const void *find_custom_data)
+{
+ LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+ LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) {
+ if (find_poll && find_poll(but, find_custom_data) == false) {
+ continue;
+ }
+ return but;
+ }
+ }
+
+ return NULL;
+}
+
/* x and y are only used in case event is NULL... */
uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
const int x,
const int y,
- const bool labeledit)
+ const bool labeledit,
+ const uiButFindPollFn find_poll,
+ const void *find_custom_data)
{
uiBut *butover = NULL;
@@ -282,6 +300,9 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
ui_window_to_block_fl(region, block, &mx, &my);
LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) {
+ if (find_poll && find_poll(but, find_custom_data) == false) {
+ continue;
+ }
if (ui_but_is_interactive(but, labeledit)) {
if (but->pie_dir != UI_RADIAL_NONE) {
if (ui_but_isect_pie_seg(block, but)) {
@@ -310,7 +331,7 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event)
{
- return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0);
+ return ui_but_find_mouse_over_ex(region, event->x, event->y, event->ctrl != 0, NULL, NULL);
}
uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
@@ -351,7 +372,7 @@ uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
return butover;
}
-uiBut *ui_list_find_mouse_over_ex(ARegion *region, int x, int y)
+uiBut *ui_list_find_mouse_over_ex(const ARegion *region, int x, int y)
{
if (!ui_region_contains_point_px(region, x, y)) {
return NULL;
@@ -369,11 +390,77 @@ uiBut *ui_list_find_mouse_over_ex(ARegion *region, int x, int y)
return NULL;
}
-uiBut *ui_list_find_mouse_over(ARegion *region, const wmEvent *event)
+uiBut *ui_list_find_mouse_over(const ARegion *region, const wmEvent *event)
{
+ if (event == NULL) {
+ /* If there is no info about the mouse, just act as if there is nothing underneath it. */
+ return NULL;
+ }
return ui_list_find_mouse_over_ex(region, event->x, event->y);
}
+uiList *UI_list_find_mouse_over(const ARegion *region, const wmEvent *event)
+{
+ uiBut *list_but = ui_list_find_mouse_over(region, event);
+ if (!list_but) {
+ return NULL;
+ }
+
+ return list_but->custom_data;
+}
+
+static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but)
+{
+ BLI_assert(listbox_but->type == UI_BTYPE_LISTBOX);
+ BLI_assert(listrow_but->type == UI_BTYPE_LISTROW);
+ /* The list box and its rows have the same RNA data (active data pointer/prop). */
+ return ui_but_rna_equals(listbox_but, listrow_but);
+}
+
+static bool ui_but_is_listbox_with_row(const uiBut *but, const void *customdata)
+{
+ const uiBut *row_but = customdata;
+ return (but->type == UI_BTYPE_LISTBOX) && ui_list_contains_row(but, row_but);
+}
+
+uiBut *ui_list_find_from_row(const ARegion *region, const uiBut *row_but)
+{
+ return ui_but_find(region, ui_but_is_listbox_with_row, row_but);
+}
+
+static bool ui_but_is_listrow(const uiBut *but, const void *UNUSED(customdata))
+{
+ return but->type == UI_BTYPE_LISTROW;
+}
+
+uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int x, const int y)
+{
+ return ui_but_find_mouse_over_ex(region, x, y, false, ui_but_is_listrow, NULL);
+}
+
+struct ListRowFindIndexData {
+ int index;
+ uiBut *listbox;
+};
+
+static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata)
+{
+ const struct ListRowFindIndexData *find_data = customdata;
+
+ return ui_but_is_listrow(but, NULL) && ui_list_contains_row(find_data->listbox, but) &&
+ (but->hardmax == find_data->index);
+}
+
+uiBut *ui_list_row_find_from_index(const ARegion *region, const int index, uiBut *listbox)
+{
+ BLI_assert(listbox->type == UI_BTYPE_LISTBOX);
+ struct ListRowFindIndexData data = {
+ .index = index,
+ .listbox = listbox,
+ };
+ return ui_but_find(region, ui_but_is_listrow_at_index, &data);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -485,6 +572,17 @@ size_t ui_but_tip_len_only_first_line(const uiBut *but)
/** \name Block (#uiBlock) State
* \{ */
+uiBut *ui_block_active_but_get(const uiBlock *block)
+{
+ LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
+ if (but->active) {
+ return but;
+ }
+ }
+
+ return NULL;
+}
+
bool ui_block_is_menu(const uiBlock *block)
{
return (((block->flag & UI_BLOCK_LOOP) != 0) &&
@@ -588,10 +686,9 @@ uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, b
uiBut *ui_region_find_active_but(ARegion *region)
{
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
- LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
- if (but->active) {
- return but;
- }
+ uiBut *but = ui_block_active_but_get(block);
+ if (but) {
+ return but;
}
}
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index e68705e4321..48952c4f121 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -624,7 +624,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt->custom_data = cpicker;
}
- /* Note: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
+ /* NOTE: don't disable UI_BUT_UNDO for RGBA values, since these don't add undo steps. */
/* RGB values */
UI_block_align_begin(block);
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index 6e60ca79aaf..d3c1a97e957 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -403,7 +403,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
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
+ /* 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);
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index a9f72233cb1..b8c4d8ddb09 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -420,7 +420,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
* For now close this style of popovers when accessed. */
UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
- /* panels are created flipped (from event handling pov) */
+ /* Panels are created flipped (from event handling POV). */
pup->block->flag ^= UI_BLOCK_IS_FLIP;
}
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 60e51244384..55a162c883a 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -341,7 +341,7 @@ static void ui_popup_block_position(wmWindow *window,
block->safety.ymax = block->rect.ymax + s1;
}
- /* exception for switched pulldowns... */
+ /* Exception for switched pull-downs. */
if (dir1 && (dir1 & block->direction) == 0) {
if (dir2 == UI_DIR_RIGHT) {
block->safety.xmax = block->rect.xmax + s2;
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index c35dbc5d7a6..c863b1f8bdf 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -599,8 +599,12 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
- ui_draw_preview_item(
- &data->fstyle, &rect, data->items.names[a], data->items.icons[a], state);
+ ui_draw_preview_item(&data->fstyle,
+ &rect,
+ data->items.names[a],
+ data->items.icons[a],
+ state,
+ UI_STYLE_TEXT_LEFT);
}
/* indicate more */
@@ -684,13 +688,13 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region)
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
GPU_blend(GPU_BLEND_ALPHA);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
+ UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
GPU_blend(GPU_BLEND_NONE);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
GPU_blend(GPU_BLEND_ALPHA);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
+ UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymax - 7, ICON_TRIA_UP);
GPU_blend(GPU_BLEND_NONE);
}
}
@@ -986,13 +990,13 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
GPU_blend(GPU_BLEND_ALPHA);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
+ UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
GPU_blend(GPU_BLEND_NONE);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
GPU_blend(GPU_BLEND_ALPHA);
- UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
+ UI_icon_draw(BLI_rcti_size_x(&rect) / 2, rect.ymax - 7, ICON_TRIA_UP);
GPU_blend(GPU_BLEND_NONE);
}
}
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index bf3425dd3eb..10bc3760b42 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -435,7 +435,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
}
}
else {
- /* Note, this is an exceptional case, we could even remove it
+ /* NOTE: this is an exceptional case, we could even remove it
* however there have been reports of tooltips failing, so keep it for now. */
expr_result = BLI_strdup(IFACE_("Internal error!"));
is_error = true;
@@ -492,7 +492,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
}
}
else {
- /* Note, this is an exceptional case, we could even remove it
+ /* NOTE: this is an exceptional case, we could even remove it
* however there have been reports of tooltips failing, so keep it for now. */
expr_result = BLI_strdup(TIP_("Internal error!"));
is_error = true;
@@ -574,7 +574,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
shortcut_toolbar,
ARRAY_SIZE(shortcut_toolbar))) {
/* Generate keymap in order to inspect it.
- * Note, we could make a utility to avoid the keymap generation part of this. */
+ * NOTE: we could make a utility to avoid the keymap generation part of this. */
const char *expr_imports[] = {
"bpy", "bl_keymap_utils", "bl_keymap_utils.keymap_from_toolbar", NULL};
const char *expr =
diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc
new file mode 100644
index 00000000000..5a05813f947
--- /dev/null
+++ b/source/blender/editors/interface/interface_template_asset_view.cc
@@ -0,0 +1,272 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ */
+
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_screen.h"
+
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_ref.hh"
+
+#include "BLO_readfile.h"
+
+#include "ED_asset.h"
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "interface_intern.h"
+
+struct AssetViewListData {
+ AssetLibraryReference asset_library;
+ bScreen *screen;
+};
+
+static void asset_view_item_but_drag_set(uiBut *but,
+ AssetViewListData *list_data,
+ AssetHandle *asset_handle)
+{
+ ID *id = asset_handle->file_data->id;
+ if (id != nullptr) {
+ UI_but_drag_set_id(but, id);
+ return;
+ }
+
+ const blender::StringRef asset_list_path = ED_assetlist_library_path(&list_data->asset_library);
+ char blend_path[FILE_MAX_LIBEXTRA];
+
+ char path[FILE_MAX_LIBEXTRA];
+ BLI_join_dirfile(path, sizeof(path), asset_list_path.data(), asset_handle->file_data->relpath);
+ if (BLO_library_path_explode(path, blend_path, nullptr, nullptr)) {
+ ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
+ UI_but_drag_set_asset(but,
+ asset_handle->file_data->name,
+ BLI_strdup(blend_path),
+ asset_handle->file_data->blentype,
+ FILE_ASSET_IMPORT_APPEND,
+ asset_handle->file_data->preview_icon_id,
+ imbuf,
+ 1.0f);
+ }
+}
+
+static void asset_view_draw_item(uiList *ui_list,
+ bContext *UNUSED(C),
+ uiLayout *layout,
+ PointerRNA *UNUSED(dataptr),
+ PointerRNA *itemptr,
+ int UNUSED(icon),
+ PointerRNA *UNUSED(active_dataptr),
+ const char *UNUSED(active_propname),
+ int UNUSED(index),
+ int UNUSED(flt_flag))
+{
+ AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
+
+ BLI_assert(RNA_struct_is_a(itemptr->type, &RNA_AssetHandle));
+ AssetHandle *asset_handle = (AssetHandle *)itemptr->data;
+
+ uiLayoutSetContextPointer(layout, "asset_handle", itemptr);
+
+ uiBlock *block = uiLayoutGetBlock(layout);
+ /* TODO ED_fileselect_init_layout(). Share somehow? */
+ const float size_x = (96.0f / 20.0f) * UI_UNIT_X;
+ const float size_y = (96.0f / 20.0f) * UI_UNIT_Y;
+ uiBut *but = uiDefIconTextBut(block,
+ UI_BTYPE_PREVIEW_TILE,
+ 0,
+ asset_handle->file_data->preview_icon_id,
+ asset_handle->file_data->name,
+ 0,
+ 0,
+ size_x,
+ size_y,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ ui_def_but_icon(but,
+ asset_handle->file_data->preview_icon_id,
+ /* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
+ UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ if (!ui_list->dyn_data->custom_drag_optype) {
+ asset_view_item_but_drag_set(but, list_data, asset_handle);
+ }
+}
+
+static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
+{
+ AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
+ const wmNotifier *notifier = params->notifier;
+
+ switch (notifier->category) {
+ case NC_ID: {
+ if (ELEM(notifier->action, NA_RENAME)) {
+ ED_assetlist_storage_tag_main_data_dirty();
+ }
+ break;
+ }
+ }
+
+ if (ED_assetlist_listen(&list_data->asset_library, params->notifier)) {
+ ED_region_tag_redraw(params->region);
+ }
+}
+
+uiListType *UI_UL_asset_view()
+{
+ uiListType *list_type = (uiListType *)MEM_callocN(sizeof(*list_type), __func__);
+
+ BLI_strncpy(list_type->idname, "UI_UL_asset_view", sizeof(list_type->idname));
+ list_type->draw_item = asset_view_draw_item;
+ list_type->listener = asset_view_listener;
+
+ return list_type;
+}
+
+static void asset_view_template_refresh_asset_collection(
+ const AssetLibraryReference &asset_library,
+ PointerRNA &assets_dataptr,
+ const char *assets_propname)
+{
+ PropertyRNA *assets_prop = RNA_struct_find_property(&assets_dataptr, assets_propname);
+ if (!assets_prop) {
+ RNA_warning("Asset collection not found");
+ return;
+ }
+ if (!RNA_struct_is_a(RNA_property_pointer_type(&assets_dataptr, assets_prop),
+ &RNA_AssetHandle)) {
+ RNA_warning("Expected a collection property for AssetHandle items");
+ return;
+ }
+
+ RNA_property_collection_clear(&assets_dataptr, assets_prop);
+
+ ED_assetlist_iterate(&asset_library, [&](FileDirEntry &file) {
+ PointerRNA itemptr, fileptr;
+ RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr);
+
+ RNA_pointer_create(nullptr, &RNA_FileSelectEntry, &file, &fileptr);
+ RNA_pointer_set(&itemptr, "file_data", fileptr);
+
+ /* Copy name from file to asset-handle name ID-property. */
+ char name[MAX_NAME];
+ PropertyRNA *file_name_prop = RNA_struct_name_property(fileptr.type);
+ RNA_property_string_get(&fileptr, file_name_prop, name);
+ PropertyRNA *asset_name_prop = RNA_struct_name_property(&RNA_AssetHandle);
+ RNA_property_string_set(&itemptr, asset_name_prop, name);
+
+ return true;
+ });
+}
+
+void uiTemplateAssetView(uiLayout *layout,
+ bContext *C,
+ const char *list_id,
+ PointerRNA *asset_library_dataptr,
+ const char *asset_library_propname,
+ PointerRNA *assets_dataptr,
+ const char *assets_propname,
+ PointerRNA *active_dataptr,
+ const char *active_propname,
+ const AssetFilterSettings *filter_settings,
+ const char *activate_opname,
+ PointerRNA *r_activate_op_properties,
+ const char *drag_opname,
+ PointerRNA *r_drag_op_properties)
+{
+ if (!list_id || !list_id[0]) {
+ RNA_warning("Asset view needs a valid identifier");
+ return;
+ }
+
+ uiLayout *col = uiLayoutColumn(layout, false);
+
+ PropertyRNA *asset_library_prop = RNA_struct_find_property(asset_library_dataptr,
+ asset_library_propname);
+ AssetLibraryReference asset_library = ED_asset_library_reference_from_enum_value(
+ RNA_property_enum_get(asset_library_dataptr, asset_library_prop));
+
+ uiLayout *row = uiLayoutRow(col, true);
+ uiItemFullR(row, asset_library_dataptr, asset_library_prop, RNA_NO_INDEX, 0, 0, "", 0);
+ if (asset_library.type != ASSET_LIBRARY_LOCAL) {
+ uiItemO(row, "", ICON_FILE_REFRESH, "ASSET_OT_list_refresh");
+ }
+
+ ED_assetlist_storage_fetch(&asset_library, filter_settings, C);
+ ED_assetlist_ensure_previews_job(&asset_library, C);
+ const int tot_items = ED_assetlist_size(&asset_library);
+
+ asset_view_template_refresh_asset_collection(asset_library, *assets_dataptr, assets_propname);
+
+ AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data),
+ "AssetViewListData");
+ list_data->asset_library = asset_library;
+ list_data->screen = CTX_wm_screen(C);
+
+ /* TODO can we have some kind of model-view API to handle referencing, filtering and lazy loading
+ * (of previews) of the items? */
+ uiList *list = uiTemplateList_ex(col,
+ C,
+ "UI_UL_asset_view",
+ list_id,
+ assets_dataptr,
+ assets_propname,
+ active_dataptr,
+ active_propname,
+ nullptr,
+ tot_items,
+ 0,
+ UILST_LAYOUT_BIG_PREVIEW_GRID,
+ 0,
+ UI_TEMPLATE_LIST_NO_GRIP,
+ list_data);
+ if (!list) {
+ /* List creation failed. */
+ MEM_freeN(list_data);
+ return;
+ }
+
+ if (activate_opname) {
+ PointerRNA *ptr = UI_list_custom_activate_operator_set(
+ list, activate_opname, r_activate_op_properties != nullptr);
+ if (r_activate_op_properties && ptr) {
+ *r_activate_op_properties = *ptr;
+ }
+ }
+ if (drag_opname) {
+ PointerRNA *ptr = UI_list_custom_drag_operator_set(
+ list, drag_opname, r_drag_op_properties != nullptr);
+ if (r_drag_op_properties && ptr) {
+ *r_drag_op_properties = *ptr;
+ }
+ }
+}
diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc
new file mode 100644
index 00000000000..eaab33e32c9
--- /dev/null
+++ b/source/blender/editors/interface/interface_template_list.cc
@@ -0,0 +1,1310 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ */
+
+#include <cstdlib>
+#include <cstring>
+
+#include "BLI_fnmatch.h"
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_screen.h"
+
+#include "BLT_translation.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+
+#include "interface_intern.h"
+
+/**
+ * The validated data that was passed to #uiTemplateList (typically through Python).
+ * Populated through #ui_template_list_data_retrieve().
+ */
+struct TemplateListInputData {
+ PointerRNA dataptr;
+ PropertyRNA *prop;
+ PointerRNA active_dataptr;
+ PropertyRNA *activeprop;
+ const char *item_dyntip_propname;
+
+ /* Index as stored in the input property. I.e. the index before sorting. */
+ int active_item_idx;
+};
+
+/**
+ * Internal wrapper for a single item in the list (well, actually stored as a vector).
+ */
+struct _uilist_item {
+ PointerRNA item;
+ int org_idx;
+ int flt_flag;
+};
+
+/**
+ * Container for the item vector and additional info.
+ */
+struct TemplateListItems {
+ _uilist_item *item_vec;
+ /* Index of the active item following visual order. I.e. unlike
+ * TemplateListInputData.active_item_idx, this is the index after sorting. */
+ int active_item_idx;
+ int tot_items;
+};
+
+struct TemplateListLayoutDrawData {
+ uiListDrawItemFunc draw_item;
+ uiListDrawFilterFunc draw_filter;
+
+ int rows;
+ int maxrows;
+ int columns;
+};
+
+struct TemplateListVisualInfo {
+ int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
+ int start_idx; /* Index of first item to display. */
+ int end_idx; /* Index of last item to display + 1. */
+};
+
+static void uilist_draw_item_default(struct uiList *ui_list,
+ struct bContext *UNUSED(C),
+ struct uiLayout *layout,
+ struct PointerRNA *UNUSED(dataptr),
+ struct PointerRNA *itemptr,
+ int icon,
+ struct PointerRNA *UNUSED(active_dataptr),
+ const char *UNUSED(active_propname),
+ int UNUSED(index),
+ int UNUSED(flt_flag))
+{
+ PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
+
+ /* Simplest one! */
+ switch (ui_list->layout_type) {
+ case UILST_LAYOUT_GRID:
+ uiItemL(layout, "", icon);
+ break;
+ case UILST_LAYOUT_DEFAULT:
+ case UILST_LAYOUT_COMPACT:
+ default:
+ if (nameprop) {
+ uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
+ }
+ else {
+ uiItemL(layout, "", icon);
+ }
+ break;
+ }
+}
+
+static void uilist_draw_filter_default(struct uiList *ui_list,
+ struct bContext *UNUSED(C),
+ struct uiLayout *layout)
+{
+ PointerRNA listptr;
+ RNA_pointer_create(nullptr, &RNA_UIList, ui_list, &listptr);
+
+ uiLayout *row = uiLayoutRow(layout, false);
+
+ uiLayout *subrow = uiLayoutRow(row, true);
+ uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
+ uiItemR(subrow,
+ &listptr,
+ "use_filter_invert",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_ARROW_LEFTRIGHT);
+
+ if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) {
+ subrow = uiLayoutRow(row, true);
+ uiItemR(subrow,
+ &listptr,
+ "use_filter_sort_alpha",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ ICON_NONE);
+ uiItemR(subrow,
+ &listptr,
+ "use_filter_sort_reverse",
+ UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
+ "",
+ (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC);
+ }
+}
+
+struct StringCmp {
+ char name[MAX_IDPROP_NAME];
+ int org_idx;
+};
+
+static int cmpstringp(const void *p1, const void *p2)
+{
+ /* Case-insensitive comparison. */
+ return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
+}
+
+static void uilist_filter_items_default(struct uiList *ui_list,
+ struct bContext *UNUSED(C),
+ struct PointerRNA *dataptr,
+ const char *propname)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
+
+ const char *filter_raw = ui_list->filter_byname;
+ char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = nullptr;
+ const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
+ const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
+ UILST_FLT_SORT_ALPHA;
+ const int len = RNA_property_collection_length(dataptr, prop);
+
+ dyn_data->items_shown = dyn_data->items_len = len;
+
+ if (len && (order_by_name || filter_raw[0])) {
+ StringCmp *names = nullptr;
+ int order_idx = 0, i = 0;
+
+ if (order_by_name) {
+ names = static_cast<StringCmp *>(MEM_callocN(sizeof(StringCmp) * len, "StringCmp"));
+ }
+ if (filter_raw[0]) {
+ const size_t slen = strlen(filter_raw);
+
+ dyn_data->items_filter_flags = static_cast<int *>(
+ MEM_callocN(sizeof(int) * len, "items_filter_flags"));
+ dyn_data->items_shown = 0;
+
+ /* Implicitly add heading/trailing wildcards if needed. */
+ if (slen + 3 <= sizeof(filter_buff)) {
+ filter = filter_buff;
+ }
+ else {
+ filter = filter_dyn = static_cast<char *>(
+ MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn"));
+ }
+ BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
+ }
+
+ RNA_PROP_BEGIN (dataptr, itemptr, prop) {
+ bool do_order = false;
+
+ char *namebuf = RNA_struct_name_get_alloc(&itemptr, nullptr, 0, nullptr);
+ const char *name = namebuf ? namebuf : "";
+
+ if (filter[0]) {
+ /* Case-insensitive! */
+ if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
+ dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
+ if (!filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ // printf("%s: '%s' matches '%s'\n", __func__, name, filter);
+ }
+ else if (filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ }
+ else {
+ do_order = order_by_name;
+ }
+
+ if (do_order) {
+ names[order_idx].org_idx = order_idx;
+ BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
+ }
+
+ /* free name */
+ if (namebuf) {
+ MEM_freeN(namebuf);
+ }
+ i++;
+ }
+ RNA_PROP_END;
+
+ if (order_by_name) {
+ int new_idx;
+ /* NOTE: order_idx equals either to ui_list->items_len if no filtering done,
+ * or to ui_list->items_shown if filter is enabled,
+ * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
+ * This way, we only sort items we actually intend to draw!
+ */
+ qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
+
+ dyn_data->items_filter_neworder = static_cast<int *>(
+ MEM_mallocN(sizeof(int) * order_idx, "items_filter_neworder"));
+ for (new_idx = 0; new_idx < order_idx; new_idx++) {
+ dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
+ }
+ }
+
+ if (filter_dyn) {
+ MEM_freeN(filter_dyn);
+ }
+ if (names) {
+ MEM_freeN(names);
+ }
+ }
+}
+
+static void uilist_free_dyn_data(uiList *ui_list)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ if (!dyn_data) {
+ return;
+ }
+
+ if (dyn_data->custom_activate_opptr) {
+ WM_operator_properties_free(dyn_data->custom_activate_opptr);
+ MEM_freeN(dyn_data->custom_activate_opptr);
+ }
+ if (dyn_data->custom_drag_opptr) {
+ WM_operator_properties_free(dyn_data->custom_drag_opptr);
+ MEM_freeN(dyn_data->custom_drag_opptr);
+ }
+
+ MEM_SAFE_FREE(dyn_data->items_filter_flags);
+ MEM_SAFE_FREE(dyn_data->items_filter_neworder);
+ MEM_SAFE_FREE(dyn_data->customdata);
+}
+
+/**
+ * Validate input parameters and initialize \a r_data from that. Plus find the list-type and return
+ * it in \a r_list_type.
+ *
+ * \return false if the input data isn't valid. Will also raise an RNA warning in that case.
+ */
+static bool ui_template_list_data_retrieve(const char *listtype_name,
+ const char *list_id,
+ PointerRNA *dataptr,
+ const char *propname,
+ PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ TemplateListInputData *r_input_data,
+ uiListType **r_list_type)
+{
+ memset(r_input_data, 0, sizeof(*r_input_data));
+
+ /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
+ if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
+ RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
+ UI_UL_DEFAULT_CLASS_NAME);
+ return false;
+ }
+
+ if (!active_dataptr->data) {
+ RNA_warning("No active data");
+ return false;
+ }
+
+ r_input_data->dataptr = *dataptr;
+ if (dataptr->data) {
+ r_input_data->prop = RNA_struct_find_property(dataptr, propname);
+ if (!r_input_data->prop) {
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
+ return false;
+ }
+ }
+
+ r_input_data->active_dataptr = *active_dataptr;
+ r_input_data->activeprop = RNA_struct_find_property(active_dataptr, active_propname);
+ if (!r_input_data->activeprop) {
+ RNA_warning(
+ "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
+ return false;
+ }
+
+ if (r_input_data->prop) {
+ const PropertyType type = RNA_property_type(r_input_data->prop);
+ if (type != PROP_COLLECTION) {
+ RNA_warning("Expected a collection data property");
+ return false;
+ }
+ }
+
+ const PropertyType activetype = RNA_property_type(r_input_data->activeprop);
+ if (activetype != PROP_INT) {
+ RNA_warning("Expected an integer active data property");
+ return false;
+ }
+
+ /* Find the uiList type. */
+ if (!(*r_list_type = WM_uilisttype_find(listtype_name, false))) {
+ RNA_warning("List type %s not found", listtype_name);
+ return false;
+ }
+
+ r_input_data->active_item_idx = RNA_property_int_get(&r_input_data->active_dataptr,
+ r_input_data->activeprop);
+ r_input_data->item_dyntip_propname = item_dyntip_propname;
+
+ return true;
+}
+
+static void ui_template_list_collect_items(PointerRNA *list_ptr,
+ PropertyRNA *list_prop,
+ uiListDyn *dyn_data,
+ int filter_exclude,
+ bool order_reverse,
+ int activei,
+ TemplateListItems *r_items)
+{
+ int i = 0;
+ int reorder_i = 0;
+ bool activei_mapping_pending = true;
+
+ RNA_PROP_BEGIN (list_ptr, itemptr, list_prop) {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) {
+ int new_order_idx;
+ if (dyn_data->items_filter_neworder) {
+ new_order_idx = dyn_data->items_filter_neworder[reorder_i++];
+ new_order_idx = order_reverse ? dyn_data->items_shown - new_order_idx - 1 : new_order_idx;
+ }
+ else {
+ new_order_idx = order_reverse ? dyn_data->items_shown - ++reorder_i : reorder_i++;
+ }
+ // printf("%s: ii: %d\n", __func__, ii);
+ r_items->item_vec[new_order_idx].item = itemptr;
+ r_items->item_vec[new_order_idx].org_idx = i;
+ r_items->item_vec[new_order_idx].flt_flag = dyn_data->items_filter_flags ?
+ dyn_data->items_filter_flags[i] :
+ 0;
+
+ if (activei_mapping_pending && activei == i) {
+ activei = new_order_idx;
+ /* So that we do not map again activei! */
+ activei_mapping_pending = false;
+ }
+#if 0 /* For now, do not alter active element, even if it will be hidden... */
+ else if (activei < i) {
+ /* We do not want an active but invisible item!
+ * Only exception is when all items are filtered out...
+ */
+ if (prev_order_idx >= 0) {
+ activei = prev_order_idx;
+ RNA_property_int_set(active_dataptr, activeprop, prev_i);
+ }
+ else {
+ activei = new_order_idx;
+ RNA_property_int_set(active_dataptr, activeprop, i);
+ }
+ }
+ prev_i = i;
+ prev_ii = new_order_idx;
+#endif
+ }
+ i++;
+ }
+ RNA_PROP_END;
+
+ /* If mapping is still pending, no active item was found. Mark as invalid (-1) */
+ r_items->active_item_idx = activei_mapping_pending ? -1 : activei;
+}
+
+/**
+ * Create the UI-list representation of the list items, sorted and filtered if needed.
+ */
+static void ui_template_list_collect_display_items(bContext *C,
+ uiList *ui_list,
+ TemplateListInputData *input_data,
+ const uiListFilterItemsFunc filter_items_fn,
+ TemplateListItems *r_items)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ memset(r_items, 0, sizeof(*r_items));
+
+ /* Filter list items! (not for compact layout, though) */
+ if (input_data->dataptr.data && input_data->prop) {
+ const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
+ int items_shown;
+#if 0
+ int prev_ii = -1, prev_i;
+#endif
+
+ if (ui_list->layout_type == UILST_LAYOUT_COMPACT) {
+ dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(
+ &input_data->dataptr, input_data->prop);
+ }
+ else {
+ // printf("%s: filtering...\n", __func__);
+ filter_items_fn(ui_list, C, &input_data->dataptr, RNA_property_identifier(input_data->prop));
+ // printf("%s: filtering done.\n", __func__);
+ }
+
+ items_shown = dyn_data->items_shown;
+ if (items_shown >= 0) {
+ r_items->item_vec = static_cast<_uilist_item *>(
+ MEM_mallocN(sizeof(*r_items->item_vec) * items_shown, __func__));
+ // printf("%s: items shown: %d.\n", __func__, items_shown);
+
+ ui_template_list_collect_items(&input_data->dataptr,
+ input_data->prop,
+ dyn_data,
+ filter_exclude,
+ order_reverse,
+ input_data->active_item_idx,
+ r_items);
+ }
+ if (dyn_data->items_shown >= 0) {
+ r_items->tot_items = dyn_data->items_shown;
+ }
+ else {
+ r_items->tot_items = dyn_data->items_len;
+ }
+ }
+}
+
+static void ui_template_list_free_items(TemplateListItems *items)
+{
+ if (items->item_vec) {
+ MEM_freeN(items->item_vec);
+ }
+}
+
+static void uilist_prepare(uiList *ui_list,
+ const TemplateListItems *items,
+ const TemplateListLayoutDrawData *layout_data,
+ TemplateListVisualInfo *r_visual_info)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ const bool use_auto_size = (ui_list->list_grip <
+ (layout_data->rows - UI_LIST_AUTO_SIZE_THRESHOLD));
+
+ int actual_rows = layout_data->rows;
+ int actual_maxrows = layout_data->maxrows;
+ int columns = layout_data->columns;
+
+ /* default rows */
+ if (actual_rows <= 0) {
+ actual_rows = 5;
+ }
+ dyn_data->visual_height_min = actual_rows;
+ if (actual_maxrows < actual_rows) {
+ actual_maxrows = max_ii(actual_rows, 5);
+ }
+ if (columns <= 0) {
+ columns = 9;
+ }
+
+ int activei_row;
+ if (columns > 1) {
+ dyn_data->height = (int)ceil((double)items->tot_items / (double)columns);
+ activei_row = (int)floor((double)items->active_item_idx / (double)columns);
+ }
+ else {
+ dyn_data->height = items->tot_items;
+ activei_row = items->active_item_idx;
+ }
+
+ dyn_data->columns = columns;
+
+ if (!use_auto_size) {
+ /* No auto-size, yet we clamp at min size! */
+ actual_rows = max_ii(ui_list->list_grip, actual_rows);
+ }
+ else if ((actual_rows != actual_maxrows) && (dyn_data->height > actual_rows)) {
+ /* Expand size if needed and possible. */
+ actual_rows = min_ii(dyn_data->height, actual_maxrows);
+ }
+
+ /* If list length changes or list is tagged to check this,
+ * and active is out of view, scroll to it. */
+ if ((ui_list->list_last_len != items->tot_items) ||
+ (ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM)) {
+ if (activei_row < ui_list->list_scroll) {
+ ui_list->list_scroll = activei_row;
+ }
+ else if (activei_row >= ui_list->list_scroll + actual_rows) {
+ ui_list->list_scroll = activei_row - actual_rows + 1;
+ }
+ ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
+
+ const int max_scroll = max_ii(0, dyn_data->height - actual_rows);
+ CLAMP(ui_list->list_scroll, 0, max_scroll);
+ ui_list->list_last_len = items->tot_items;
+ dyn_data->visual_height = actual_rows;
+ r_visual_info->visual_items = actual_rows * columns;
+ r_visual_info->start_idx = ui_list->list_scroll * columns;
+ r_visual_info->end_idx = min_ii(r_visual_info->start_idx + actual_rows * columns,
+ items->tot_items);
+}
+
+static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2))
+{
+ uiList *ui_list = static_cast<uiList *>(arg1);
+ uiListDyn *dyn_data = ui_list->dyn_data;
+
+ /* This way we get diff in number of additional items to show (positive) or hide (negative). */
+ const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) /
+ (float)UI_UNIT_Y);
+
+ if (diff != 0) {
+ ui_list->list_grip += diff;
+ dyn_data->resize_prev += diff * UI_UNIT_Y;
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
+
+ /* In case uilist is in popup, we need special refreshing */
+ ED_region_tag_refresh_ui(CTX_wm_menu(C));
+}
+
+static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
+{
+ if (propname && propname[0] && itemptr && itemptr->data) {
+ PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
+
+ if (prop && (RNA_property_type(prop) == PROP_STRING)) {
+ return RNA_property_string_get_alloc(itemptr, prop, nullptr, 0, nullptr);
+ }
+ }
+ return nullptr;
+}
+
+static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip)
+{
+ char *dyn_tooltip = static_cast<char *>(argN);
+ return BLI_sprintfN("%s - %s", tip, dyn_tooltip);
+}
+
+/**
+ * \note Note that \a layout_type may be null.
+ */
+static uiList *ui_list_ensure(bContext *C,
+ uiListType *ui_list_type,
+ const char *list_id,
+ int layout_type,
+ bool sort_reverse,
+ bool sort_lock)
+{
+ /* Allows to work in popups. */
+ ARegion *region = CTX_wm_menu(C);
+ if (region == nullptr) {
+ region = CTX_wm_region(C);
+ }
+
+ /* Find or add the uiList to the current Region. */
+
+ char full_list_id[UI_MAX_NAME_STR];
+ WM_uilisttype_to_full_list_id(ui_list_type, list_id, full_list_id);
+
+ uiList *ui_list = static_cast<uiList *>(
+ BLI_findstring(&region->ui_lists, full_list_id, offsetof(uiList, list_id)));
+
+ if (!ui_list) {
+ ui_list = static_cast<uiList *>(MEM_callocN(sizeof(uiList), "uiList"));
+ BLI_strncpy(ui_list->list_id, full_list_id, sizeof(ui_list->list_id));
+ BLI_addtail(&region->ui_lists, ui_list);
+ ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */
+ if (sort_reverse) {
+ ui_list->filter_sort_flag |= UILST_FLT_SORT_REVERSE;
+ }
+ if (sort_lock) {
+ ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK;
+ }
+ }
+
+ if (!ui_list->dyn_data) {
+ ui_list->dyn_data = static_cast<uiListDyn *>(
+ MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data"));
+ }
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ /* Note that this isn't a `uiListType` callback, it's stored in the runtime list data. Otherwise
+ * the runtime data could leak when the type is unregistered (e.g. on "Reload Scripts"). */
+ dyn_data->free_runtime_data_fn = uilist_free_dyn_data;
+
+ /* Because we can't actually pass type across save&load... */
+ ui_list->type = ui_list_type;
+ ui_list->layout_type = layout_type;
+
+ /* Reset filtering data. */
+ MEM_SAFE_FREE(dyn_data->items_filter_flags);
+ MEM_SAFE_FREE(dyn_data->items_filter_neworder);
+ dyn_data->items_len = dyn_data->items_shown = -1;
+
+ return ui_list;
+}
+
+static void ui_template_list_layout_draw(bContext *C,
+ uiList *ui_list,
+ uiLayout *layout,
+ TemplateListInputData *input_data,
+ TemplateListItems *items,
+ const TemplateListLayoutDrawData *layout_data,
+ const enum uiTemplateListFlags flags)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ const char *active_propname = RNA_property_identifier(input_data->activeprop);
+
+ uiLayout *glob = nullptr, *box, *row, *col, *subrow, *sub, *overlap;
+ char numstr[32];
+ int rnaicon = ICON_NONE, icon = ICON_NONE;
+ uiBut *but;
+
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ /* get icon */
+ if (input_data->dataptr.data && input_data->prop) {
+ StructRNA *ptype = RNA_property_pointer_type(&input_data->dataptr, input_data->prop);
+ rnaicon = RNA_struct_ui_icon(ptype);
+ }
+
+ TemplateListVisualInfo visual_info;
+ switch (ui_list->layout_type) {
+ case UILST_LAYOUT_DEFAULT: {
+ /* layout */
+ box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
+ glob = uiLayoutColumn(box, true);
+ row = uiLayoutRow(glob, false);
+ col = uiLayoutColumn(row, true);
+
+ TemplateListLayoutDrawData adjusted_layout_data = *layout_data;
+ adjusted_layout_data.columns = 1;
+ /* init numbers */
+ uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info);
+
+ int i = 0;
+ if (input_data->dataptr.data && input_data->prop) {
+ /* create list items */
+ for (i = visual_info.start_idx; i < visual_info.end_idx; i++) {
+ PointerRNA *itemptr = &items->item_vec[i].item;
+ void *dyntip_data;
+ const int org_i = items->item_vec[i].org_idx;
+ const int flt_flag = items->item_vec[i].flt_flag;
+ uiBlock *subblock = uiLayoutGetBlock(col);
+
+ overlap = uiLayoutOverlap(col);
+
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
+
+ /* list item behind label & other buttons */
+ uiLayoutRow(overlap, false);
+
+ but = uiDefButR_prop(subblock,
+ UI_BTYPE_LISTROW,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ &input_data->active_dataptr,
+ input_data->activeprop,
+ 0,
+ 0,
+ org_i,
+ 0,
+ 0,
+ TIP_("Double click to rename"));
+ if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr,
+ input_data->item_dyntip_propname))) {
+ UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data, MEM_freeN);
+ }
+
+ sub = uiLayoutRow(overlap, false);
+
+ icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT) {
+ icon = ICON_NONE;
+ }
+ layout_data->draw_item(ui_list,
+ C,
+ sub,
+ &input_data->dataptr,
+ itemptr,
+ icon,
+ &input_data->active_dataptr,
+ active_propname,
+ org_i,
+ flt_flag);
+
+ /* Items should be able to set context pointers for the layout. But the list-row button
+ * swallows events, so it needs the context storage too for handlers to see it. */
+ but->context = uiLayoutGetContextStore(sub);
+
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == items->active_item_idx) {
+ ui_layout_list_set_labels_active(sub);
+ }
+
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
+
+ /* add dummy buttons to fill space */
+ for (; i < visual_info.start_idx + visual_info.visual_items; i++) {
+ uiItemL(col, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (items->tot_items > visual_info.visual_items) {
+ uiLayoutColumn(row, false);
+ uiDefButI(block,
+ UI_BTYPE_SCROLL,
+ 0,
+ "",
+ 0,
+ 0,
+ V2D_SCROLL_WIDTH,
+ UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll,
+ 0,
+ dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height,
+ 0,
+ "");
+ }
+ } break;
+ case UILST_LAYOUT_COMPACT:
+ row = uiLayoutRow(layout, true);
+
+ if ((input_data->dataptr.data && input_data->prop) && (dyn_data->items_shown > 0) &&
+ (items->active_item_idx >= 0) && (items->active_item_idx < dyn_data->items_shown)) {
+ PointerRNA *itemptr = &items->item_vec[items->active_item_idx].item;
+ const int org_i = items->item_vec[items->active_item_idx].org_idx;
+
+ icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT) {
+ icon = ICON_NONE;
+ }
+ layout_data->draw_item(ui_list,
+ C,
+ row,
+ &input_data->dataptr,
+ itemptr,
+ icon,
+ &input_data->active_dataptr,
+ active_propname,
+ org_i,
+ 0);
+ }
+ /* if list is empty, add in dummy button */
+ else {
+ uiItemL(row, "", ICON_NONE);
+ }
+
+ /* next/prev button */
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
+ but = uiDefIconTextButR_prop(block,
+ UI_BTYPE_NUM,
+ 0,
+ 0,
+ numstr,
+ 0,
+ 0,
+ UI_UNIT_X * 5,
+ UI_UNIT_Y,
+ &input_data->active_dataptr,
+ input_data->activeprop,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ if (dyn_data->items_shown == 0) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ break;
+ case UILST_LAYOUT_GRID: {
+ box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
+ glob = uiLayoutColumn(box, true);
+ row = uiLayoutRow(glob, false);
+ col = uiLayoutColumn(row, true);
+ subrow = nullptr; /* Quite gcc warning! */
+
+ uilist_prepare(ui_list, items, layout_data, &visual_info);
+
+ int i = 0;
+ if (input_data->dataptr.data && input_data->prop) {
+ /* create list items */
+ for (i = visual_info.start_idx; i < visual_info.end_idx; i++) {
+ PointerRNA *itemptr = &items->item_vec[i].item;
+ const int org_i = items->item_vec[i].org_idx;
+ const int flt_flag = items->item_vec[i].flt_flag;
+
+ /* create button */
+ if (!(i % layout_data->columns)) {
+ subrow = uiLayoutRow(col, false);
+ }
+
+ uiBlock *subblock = uiLayoutGetBlock(subrow);
+ overlap = uiLayoutOverlap(subrow);
+
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
+
+ /* list item behind label & other buttons */
+ uiLayoutRow(overlap, false);
+
+ but = uiDefButR_prop(subblock,
+ UI_BTYPE_LISTROW,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ &input_data->active_dataptr,
+ input_data->activeprop,
+ 0,
+ 0,
+ org_i,
+ 0,
+ 0,
+ nullptr);
+ UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, false);
+
+ icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
+ layout_data->draw_item(ui_list,
+ C,
+ sub,
+ &input_data->dataptr,
+ itemptr,
+ icon,
+ &input_data->active_dataptr,
+ active_propname,
+ org_i,
+ flt_flag);
+
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == items->active_item_idx) {
+ ui_layout_list_set_labels_active(sub);
+ }
+
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
+
+ /* add dummy buttons to fill space */
+ for (; i < visual_info.start_idx + visual_info.visual_items; i++) {
+ if (!(i % layout_data->columns)) {
+ subrow = uiLayoutRow(col, false);
+ }
+ uiItemL(subrow, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (items->tot_items > visual_info.visual_items) {
+ /* col = */ uiLayoutColumn(row, false);
+ uiDefButI(block,
+ UI_BTYPE_SCROLL,
+ 0,
+ "",
+ 0,
+ 0,
+ V2D_SCROLL_WIDTH,
+ UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll,
+ 0,
+ dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height,
+ 0,
+ "");
+ }
+ break;
+ }
+ case UILST_LAYOUT_BIG_PREVIEW_GRID:
+ box = uiLayoutListBox(layout, ui_list, &input_data->active_dataptr, input_data->activeprop);
+ /* For grip button. */
+ glob = uiLayoutColumn(box, true);
+ /* For scrollbar. */
+ row = uiLayoutRow(glob, false);
+
+ /* TODO ED_fileselect_init_layout(). Share somehow? */
+ float size_x = (96.0f / 20.0f) * UI_UNIT_X;
+ float size_y = (96.0f / 20.0f) * UI_UNIT_Y;
+
+ const int cols_per_row = MAX2((uiLayoutGetWidth(box) - V2D_SCROLL_WIDTH) / size_x, 1);
+ uiLayout *grid = uiLayoutGridFlow(row, true, cols_per_row, true, true, true);
+
+ TemplateListLayoutDrawData adjusted_layout_data = *layout_data;
+ adjusted_layout_data.columns = cols_per_row;
+ uilist_prepare(ui_list, items, &adjusted_layout_data, &visual_info);
+
+ if (input_data->dataptr.data && input_data->prop) {
+ /* create list items */
+ for (int i = visual_info.start_idx; i < visual_info.end_idx; i++) {
+ PointerRNA *itemptr = &items->item_vec[i].item;
+ const int org_i = items->item_vec[i].org_idx;
+ const int flt_flag = items->item_vec[i].flt_flag;
+
+ overlap = uiLayoutOverlap(grid);
+ col = uiLayoutColumn(overlap, false);
+
+ uiBlock *subblock = uiLayoutGetBlock(col);
+ UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
+
+ but = uiDefButR_prop(subblock,
+ UI_BTYPE_LISTROW,
+ 0,
+ "",
+ 0,
+ 0,
+ size_x,
+ size_y,
+ &input_data->active_dataptr,
+ input_data->activeprop,
+ 0,
+ 0,
+ org_i,
+ 0,
+ 0,
+ nullptr);
+ UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
+
+ col = uiLayoutColumn(overlap, false);
+
+ icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
+ layout_data->draw_item(ui_list,
+ C,
+ col,
+ &input_data->dataptr,
+ itemptr,
+ icon,
+ &input_data->active_dataptr,
+ active_propname,
+ org_i,
+ flt_flag);
+
+ /* Items should be able to set context pointers for the layout. But the list-row button
+ * swallows events, so it needs the context storage too for handlers to see it. */
+ but->context = uiLayoutGetContextStore(col);
+
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == items->active_item_idx) {
+ ui_layout_list_set_labels_active(col);
+ }
+
+ UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
+
+ if (items->tot_items > visual_info.visual_items) {
+ /* col = */ uiLayoutColumn(row, false);
+ uiDefButI(block,
+ UI_BTYPE_SCROLL,
+ 0,
+ "",
+ 0,
+ 0,
+ V2D_SCROLL_WIDTH,
+ size_y * dyn_data->visual_height,
+ &ui_list->list_scroll,
+ 0,
+ dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height,
+ 0,
+ "");
+ }
+ break;
+ }
+
+ if (glob) {
+ const bool add_grip_but = (flags & UI_TEMPLATE_LIST_NO_GRIP) == 0;
+
+ /* About #UI_BTYPE_GRIP drag-resize:
+ * We can't directly use results from a grip button, since we have a
+ * rather complex behavior here (sizing by discrete steps and, overall, auto-size feature).
+ * Since we *never* know whether we are grip-resizing or not
+ * (because there is no callback for when a button enters/leaves its "edit mode"),
+ * we use the fact that grip-controlled value (dyn_data->resize) is completely handled
+ * by the grip during the grab resize, so settings its value here has no effect at all.
+ *
+ * It is only meaningful when we are not resizing,
+ * in which case this gives us the correct "init drag" value.
+ * Note we cannot affect `dyn_data->resize_prev here`,
+ * since this value is not controlled by the grip!
+ */
+ dyn_data->resize = dyn_data->resize_prev +
+ (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y;
+
+ row = uiLayoutRow(glob, true);
+ uiBlock *subblock = uiLayoutGetBlock(row);
+ UI_block_emboss_set(subblock, UI_EMBOSS_NONE);
+
+ if (ui_list->filter_flag & UILST_FLT_SHOW) {
+ but = uiDefIconButBitI(subblock,
+ UI_BTYPE_TOGGLE,
+ UILST_FLT_SHOW,
+ 0,
+ ICON_DISCLOSURE_TRI_DOWN,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y * 0.5f,
+ &(ui_list->filter_flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Hide filtering options"));
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ if (add_grip_but) {
+ but = uiDefIconButI(subblock,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10.0f,
+ UI_UNIT_Y * 0.5f,
+ &dyn_data->resize,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, uilist_resize_update_cb, ui_list, nullptr);
+ }
+
+ UI_block_emboss_set(subblock, UI_EMBOSS);
+
+ col = uiLayoutColumn(glob, false);
+ subblock = uiLayoutGetBlock(col);
+ uiDefBut(subblock,
+ UI_BTYPE_SEPR,
+ 0,
+ "",
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y * 0.05f,
+ nullptr,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+
+ layout_data->draw_filter(ui_list, C, col);
+ }
+ else {
+ but = uiDefIconButBitI(subblock,
+ UI_BTYPE_TOGGLE,
+ UILST_FLT_SHOW,
+ 0,
+ ICON_DISCLOSURE_TRI_RIGHT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y * 0.5f,
+ &(ui_list->filter_flag),
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Show filtering options"));
+ UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ if (add_grip_but) {
+ but = uiDefIconButI(subblock,
+ UI_BTYPE_GRIP,
+ 0,
+ ICON_GRIP,
+ 0,
+ 0,
+ UI_UNIT_X * 10.0f,
+ UI_UNIT_Y * 0.5f,
+ &dyn_data->resize,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, uilist_resize_update_cb, ui_list, nullptr);
+ }
+
+ UI_block_emboss_set(subblock, UI_EMBOSS);
+ }
+ }
+}
+
+uiList *uiTemplateList_ex(uiLayout *layout,
+ bContext *C,
+ const char *listtype_name,
+ const char *list_id,
+ PointerRNA *dataptr,
+ const char *propname,
+ PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ int rows,
+ int maxrows,
+ int layout_type,
+ int columns,
+ enum uiTemplateListFlags flags,
+ void *customdata)
+{
+ TemplateListInputData input_data = {nullptr};
+ uiListType *ui_list_type;
+ if (!ui_template_list_data_retrieve(listtype_name,
+ list_id,
+ dataptr,
+ propname,
+ active_dataptr,
+ active_propname,
+ item_dyntip_propname,
+ &input_data,
+ &ui_list_type)) {
+ return nullptr;
+ }
+
+ uiListDrawItemFunc draw_item = ui_list_type->draw_item ? ui_list_type->draw_item :
+ uilist_draw_item_default;
+ uiListDrawFilterFunc draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter :
+ uilist_draw_filter_default;
+ uiListFilterItemsFunc filter_items = ui_list_type->filter_items ? ui_list_type->filter_items :
+ uilist_filter_items_default;
+
+ uiList *ui_list = ui_list_ensure(C,
+ ui_list_type,
+ list_id,
+ layout_type,
+ flags & UI_TEMPLATE_LIST_SORT_REVERSE,
+ flags & UI_TEMPLATE_LIST_SORT_LOCK);
+ uiListDyn *dyn_data = ui_list->dyn_data;
+
+ MEM_SAFE_FREE(dyn_data->customdata);
+ dyn_data->customdata = customdata;
+
+ /* When active item changed since last draw, scroll to it. */
+ if (input_data.active_item_idx != ui_list->list_last_activei) {
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ui_list->list_last_activei = input_data.active_item_idx;
+ }
+
+ TemplateListItems items;
+ ui_template_list_collect_display_items(C, ui_list, &input_data, filter_items, &items);
+
+ TemplateListLayoutDrawData layout_data;
+ layout_data.draw_item = draw_item;
+ layout_data.draw_filter = draw_filter;
+ layout_data.rows = rows;
+ layout_data.maxrows = maxrows;
+ layout_data.columns = columns;
+
+ ui_template_list_layout_draw(C, ui_list, layout, &input_data, &items, &layout_data, flags);
+
+ ui_template_list_free_items(&items);
+
+ return ui_list;
+}
+
+void uiTemplateList(uiLayout *layout,
+ bContext *C,
+ const char *listtype_name,
+ const char *list_id,
+ PointerRNA *dataptr,
+ const char *propname,
+ PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ int rows,
+ int maxrows,
+ int layout_type,
+ int columns,
+ enum uiTemplateListFlags flags)
+{
+ uiTemplateList_ex(layout,
+ C,
+ listtype_name,
+ list_id,
+ dataptr,
+ propname,
+ active_dataptr,
+ active_propname,
+ item_dyntip_propname,
+ rows,
+ maxrows,
+ layout_type,
+ columns,
+ flags,
+ nullptr);
+}
+
+/**
+ * \return: A RNA pointer for the operator properties.
+ */
+PointerRNA *UI_list_custom_activate_operator_set(uiList *ui_list,
+ const char *opname,
+ bool create_properties)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ dyn_data->custom_activate_optype = WM_operatortype_find(opname, false);
+ if (!dyn_data->custom_activate_optype) {
+ return nullptr;
+ }
+
+ if (create_properties) {
+ WM_operator_properties_alloc(&dyn_data->custom_activate_opptr, nullptr, opname);
+ }
+
+ return dyn_data->custom_activate_opptr;
+}
+
+/**
+ * \return: A RNA pointer for the operator properties.
+ */
+PointerRNA *UI_list_custom_drag_operator_set(uiList *ui_list,
+ const char *opname,
+ bool create_properties)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ dyn_data->custom_drag_optype = WM_operatortype_find(opname, false);
+ if (!dyn_data->custom_drag_optype) {
+ return nullptr;
+ }
+
+ if (create_properties) {
+ WM_operator_properties_alloc(&dyn_data->custom_drag_opptr, nullptr, opname);
+ }
+
+ return dyn_data->custom_drag_opptr;
+}
+
+/* -------------------------------------------------------------------- */
+
+/** \name List-types Registration
+ * \{ */
+
+void ED_uilisttypes_ui(void)
+{
+ WM_uilisttype_add(UI_UL_asset_view());
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index 91ad6619889..3105891142f 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -873,7 +873,7 @@ static struct MenuSearch_Data *menu_items_from_ui_create(
/* Finally sort menu items.
*
- * Note: we might want to keep the in-menu order, for now sort all. */
+ * NOTE: we might want to keep the in-menu order, for now sort all. */
BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full);
BLI_ghash_free(menu_parent_map, NULL, NULL);
@@ -1037,7 +1037,7 @@ static void menu_search_update_fn(const bContext *UNUSED(C),
static bool ui_search_menu_create_context_menu(struct bContext *C,
void *arg,
void *active,
- const struct wmEvent *UNUSED(event))
+ const struct wmEvent *event)
{
struct MenuSearch_Data *data = arg;
struct MenuSearch_Item *item = active;
@@ -1058,7 +1058,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C,
CTX_wm_region_set(C, item->wm_context->region);
}
- if (ui_popup_context_menu_for_button(C, but)) {
+ if (ui_popup_context_menu_for_button(C, but, event)) {
has_menu = true;
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 5232d4310a3..766840909cc 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -877,7 +877,7 @@ static uiBut *template_id_def_new_but(uiBlock *block,
BLT_I18NCONTEXT_ID_POINTCLOUD,
BLT_I18NCONTEXT_ID_VOLUME,
BLT_I18NCONTEXT_ID_SIMULATION, );
- /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
+ /* NOTE: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
* check the definition to see if a new call must be added when the limit
* is exceeded. */
@@ -2399,8 +2399,8 @@ static eAutoPropButsReturn template_operator_property_buts_draw_single(
op->type->ui((bContext *)C, op);
op->layout = NULL;
- /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could
- * allow ot.ui callback to return this, but not needed right now. */
+ /* #UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too.
+ * We could allow #wmOperatorType.ui callback to return this, but not needed right now. */
}
else {
wmWindowManager *wm = CTX_wm_manager(C);
@@ -2556,7 +2556,7 @@ void uiTemplateOperatorPropertyButs(
wmWindowManager *wm = CTX_wm_manager(C);
/* If there are only checkbox items, don't use split layout by default. It looks weird if the
- * checkboxes only use half the width. */
+ * check-boxes only use half the width. */
if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) {
flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT;
}
@@ -4015,23 +4015,23 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
case UICURVE_FUNC_RESET_VIEW:
BKE_curvemapping_reset_view(cumap);
break;
- case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */
+ case UICURVE_FUNC_HANDLE_VECTOR: /* Set vector. */
BKE_curvemap_handle_set(cuma, HD_VECT);
BKE_curvemapping_changed(cumap, false);
break;
- case UICURVE_FUNC_HANDLE_AUTO: /* set auto */
+ case UICURVE_FUNC_HANDLE_AUTO: /* Set auto. */
BKE_curvemap_handle_set(cuma, HD_AUTO);
BKE_curvemapping_changed(cumap, false);
break;
- case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */
+ case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* Set auto-clamped. */
BKE_curvemap_handle_set(cuma, HD_AUTO_ANIM);
BKE_curvemapping_changed(cumap, false);
break;
- case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */
+ case UICURVE_FUNC_EXTEND_HOZ: /* Extend horizontal. */
cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
BKE_curvemapping_changed(cumap, false);
break;
- case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */
+ case UICURVE_FUNC_EXTEND_EXP: /* Extend extrapolate. */
cumap->flag |= CUMA_EXTEND_EXTRAPOLATE;
BKE_curvemapping_changed(cumap, false);
break;
@@ -5645,887 +5645,6 @@ void uiTemplateLayers(uiLayout *layout,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name List Template
- * \{ */
-
-static void uilist_draw_item_default(struct uiList *ui_list,
- struct bContext *UNUSED(C),
- struct uiLayout *layout,
- struct PointerRNA *UNUSED(dataptr),
- struct PointerRNA *itemptr,
- int icon,
- struct PointerRNA *UNUSED(active_dataptr),
- const char *UNUSED(active_propname),
- int UNUSED(index),
- int UNUSED(flt_flag))
-{
- PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
-
- /* Simplest one! */
- switch (ui_list->layout_type) {
- case UILST_LAYOUT_GRID:
- uiItemL(layout, "", icon);
- break;
- case UILST_LAYOUT_DEFAULT:
- case UILST_LAYOUT_COMPACT:
- default:
- if (nameprop) {
- uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
- }
- else {
- uiItemL(layout, "", icon);
- }
- break;
- }
-}
-
-static void uilist_draw_filter_default(struct uiList *ui_list,
- struct bContext *UNUSED(C),
- struct uiLayout *layout)
-{
- PointerRNA listptr;
- RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
-
- uiLayout *row = uiLayoutRow(layout, false);
-
- uiLayout *subrow = uiLayoutRow(row, true);
- uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
- uiItemR(subrow,
- &listptr,
- "use_filter_invert",
- UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
- "",
- ICON_ARROW_LEFTRIGHT);
-
- if ((ui_list->filter_sort_flag & UILST_FLT_SORT_LOCK) == 0) {
- subrow = uiLayoutRow(row, true);
- uiItemR(subrow,
- &listptr,
- "use_filter_sort_alpha",
- UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
- "",
- ICON_NONE);
- uiItemR(subrow,
- &listptr,
- "use_filter_sort_reverse",
- UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY,
- "",
- (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_SORT_DESC : ICON_SORT_ASC);
- }
-}
-
-typedef struct {
- char name[MAX_IDPROP_NAME];
- int org_idx;
-} StringCmp;
-
-static int cmpstringp(const void *p1, const void *p2)
-{
- /* Case-insensitive comparison. */
- return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name);
-}
-
-static void uilist_filter_items_default(struct uiList *ui_list,
- struct bContext *UNUSED(C),
- struct PointerRNA *dataptr,
- const char *propname)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
-
- const char *filter_raw = ui_list->filter_byname;
- char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
- const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
- const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) ==
- UILST_FLT_SORT_ALPHA;
- const int len = RNA_property_collection_length(dataptr, prop);
-
- dyn_data->items_shown = dyn_data->items_len = len;
-
- if (len && (order_by_name || filter_raw[0])) {
- StringCmp *names = NULL;
- int order_idx = 0, i = 0;
-
- if (order_by_name) {
- names = MEM_callocN(sizeof(StringCmp) * len, "StringCmp");
- }
- if (filter_raw[0]) {
- const size_t slen = strlen(filter_raw);
-
- dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, "items_filter_flags");
- dyn_data->items_shown = 0;
-
- /* Implicitly add heading/trailing wildcards if needed. */
- if (slen + 3 <= sizeof(filter_buff)) {
- filter = filter_buff;
- }
- else {
- filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn");
- }
- BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3);
- }
-
- RNA_PROP_BEGIN (dataptr, itemptr, prop) {
- bool do_order = false;
-
- char *namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
- const char *name = namebuf ? namebuf : "";
-
- if (filter[0]) {
- /* Case-insensitive! */
- if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
- dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
- if (!filter_exclude) {
- dyn_data->items_shown++;
- do_order = order_by_name;
- }
- // printf("%s: '%s' matches '%s'\n", __func__, name, filter);
- }
- else if (filter_exclude) {
- dyn_data->items_shown++;
- do_order = order_by_name;
- }
- }
- else {
- do_order = order_by_name;
- }
-
- if (do_order) {
- names[order_idx].org_idx = order_idx;
- BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
- }
-
- /* free name */
- if (namebuf) {
- MEM_freeN(namebuf);
- }
- i++;
- }
- RNA_PROP_END;
-
- if (order_by_name) {
- int new_idx;
- /* note: order_idx equals either to ui_list->items_len if no filtering done,
- * or to ui_list->items_shown if filter is enabled,
- * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
- * This way, we only sort items we actually intend to draw!
- */
- qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
-
- dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx,
- "items_filter_neworder");
- for (new_idx = 0; new_idx < order_idx; new_idx++) {
- dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
- }
- }
-
- if (filter_dyn) {
- MEM_freeN(filter_dyn);
- }
- if (names) {
- MEM_freeN(names);
- }
- }
-}
-
-typedef struct {
- PointerRNA item;
- int org_idx;
- int flt_flag;
-} _uilist_item;
-
-typedef struct {
- int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
- int start_idx; /* Index of first item to display. */
- int end_idx; /* Index of last item to display + 1. */
-} uiListLayoutdata;
-
-static void uilist_prepare(uiList *ui_list,
- int len,
- int activei,
- int rows,
- int maxrows,
- int columns,
- uiListLayoutdata *layoutdata)
-{
- uiListDyn *dyn_data = ui_list->dyn_data;
- const bool use_auto_size = (ui_list->list_grip < (rows - UI_LIST_AUTO_SIZE_THRESHOLD));
-
- /* default rows */
- if (rows <= 0) {
- rows = 5;
- }
- dyn_data->visual_height_min = rows;
- if (maxrows < rows) {
- maxrows = max_ii(rows, 5);
- }
- if (columns <= 0) {
- columns = 9;
- }
-
- int activei_row;
- if (columns > 1) {
- dyn_data->height = (int)ceil((double)len / (double)columns);
- activei_row = (int)floor((double)activei / (double)columns);
- }
- else {
- dyn_data->height = len;
- activei_row = activei;
- }
-
- if (!use_auto_size) {
- /* No auto-size, yet we clamp at min size! */
- maxrows = rows = max_ii(ui_list->list_grip, rows);
- }
- else if ((rows != maxrows) && (dyn_data->height > rows)) {
- /* Expand size if needed and possible. */
- rows = min_ii(dyn_data->height, maxrows);
- }
-
- /* If list length changes or list is tagged to check this,
- * and active is out of view, scroll to it. */
- if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) {
- if (activei_row < ui_list->list_scroll) {
- ui_list->list_scroll = activei_row;
- }
- else if (activei_row >= ui_list->list_scroll + rows) {
- ui_list->list_scroll = activei_row - rows + 1;
- }
- ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
- }
-
- const int max_scroll = max_ii(0, dyn_data->height - rows);
- CLAMP(ui_list->list_scroll, 0, max_scroll);
- ui_list->list_last_len = len;
- dyn_data->visual_height = rows;
- layoutdata->visual_items = rows * columns;
- layoutdata->start_idx = ui_list->list_scroll * columns;
- layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
-}
-
-static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2))
-{
- uiList *ui_list = arg1;
- uiListDyn *dyn_data = ui_list->dyn_data;
-
- /* This way we get diff in number of additional items to show (positive) or hide (negative). */
- const int diff = round_fl_to_int((float)(dyn_data->resize - dyn_data->resize_prev) /
- (float)UI_UNIT_Y);
-
- if (diff != 0) {
- ui_list->list_grip += diff;
- dyn_data->resize_prev += diff * UI_UNIT_Y;
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- }
-
- /* In case uilist is in popup, we need special refreshing */
- ED_region_tag_refresh_ui(CTX_wm_menu(C));
-}
-
-static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
-{
- if (propname && propname[0] && itemptr && itemptr->data) {
- PropertyRNA *prop = RNA_struct_find_property(itemptr, propname);
-
- if (prop && (RNA_property_type(prop) == PROP_STRING)) {
- return RNA_property_string_get_alloc(itemptr, prop, NULL, 0, NULL);
- }
- }
- return NULL;
-}
-
-static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const char *tip)
-{
- char *dyn_tooltip = argN;
- return BLI_sprintfN("%s - %s", tip, dyn_tooltip);
-}
-
-void uiTemplateList(uiLayout *layout,
- bContext *C,
- const char *listtype_name,
- const char *list_id,
- PointerRNA *dataptr,
- const char *propname,
- PointerRNA *active_dataptr,
- const char *active_propname,
- const char *item_dyntip_propname,
- int rows,
- int maxrows,
- int layout_type,
- int columns,
- bool sort_reverse,
- bool sort_lock)
-{
- PropertyRNA *prop = NULL, *activeprop;
- _uilist_item *items_ptr = NULL;
- uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
- uiBut *but;
-
- uiListLayoutdata layoutdata;
- char ui_list_id[UI_MAX_NAME_STR];
- char numstr[32];
- int rnaicon = ICON_NONE, icon = ICON_NONE;
- int i = 0, activei = 0;
- int len = 0;
-
- /* validate arguments */
- /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
- if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
- RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
- UI_UL_DEFAULT_CLASS_NAME);
- return;
- }
-
- uiBlock *block = uiLayoutGetBlock(layout);
-
- if (!active_dataptr->data) {
- RNA_warning("No active data");
- return;
- }
-
- if (dataptr->data) {
- prop = RNA_struct_find_property(dataptr, propname);
- if (!prop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
- return;
- }
- }
-
- activeprop = RNA_struct_find_property(active_dataptr, active_propname);
- if (!activeprop) {
- RNA_warning(
- "Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
- return;
- }
-
- if (prop) {
- const PropertyType type = RNA_property_type(prop);
- if (type != PROP_COLLECTION) {
- RNA_warning("Expected a collection data property");
- return;
- }
- }
-
- const PropertyType activetype = RNA_property_type(activeprop);
- if (activetype != PROP_INT) {
- RNA_warning("Expected an integer active data property");
- return;
- }
-
- /* get icon */
- if (dataptr->data && prop) {
- StructRNA *ptype = RNA_property_pointer_type(dataptr, prop);
- rnaicon = RNA_struct_ui_icon(ptype);
- }
-
- /* get active data */
- activei = RNA_property_int_get(active_dataptr, activeprop);
-
- /* Find the uiList type. */
- uiListType *ui_list_type = WM_uilisttype_find(listtype_name, false);
-
- if (ui_list_type == NULL) {
- RNA_warning("List type %s not found", listtype_name);
- return;
- }
-
- uiListDrawItemFunc draw_item = ui_list_type->draw_item ? ui_list_type->draw_item :
- uilist_draw_item_default;
- uiListDrawFilterFunc draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter :
- uilist_draw_filter_default;
- uiListFilterItemsFunc filter_items = ui_list_type->filter_items ? ui_list_type->filter_items :
- uilist_filter_items_default;
-
- /* Find or add the uiList to the current Region. */
- /* We tag the list id with the list type... */
- BLI_snprintf(
- ui_list_id, sizeof(ui_list_id), "%s_%s", ui_list_type->idname, list_id ? list_id : "");
-
- /* Allows to work in popups. */
- ARegion *region = CTX_wm_menu(C);
- if (region == NULL) {
- region = CTX_wm_region(C);
- }
- uiList *ui_list = BLI_findstring(&region->ui_lists, ui_list_id, offsetof(uiList, list_id));
-
- if (!ui_list) {
- ui_list = MEM_callocN(sizeof(uiList), "uiList");
- BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
- BLI_addtail(&region->ui_lists, ui_list);
- ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */
- if (sort_reverse) {
- ui_list->filter_sort_flag |= UILST_FLT_SORT_REVERSE;
- }
- if (sort_lock) {
- ui_list->filter_sort_flag |= UILST_FLT_SORT_LOCK;
- }
- }
-
- if (!ui_list->dyn_data) {
- ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data");
- }
- uiListDyn *dyn_data = ui_list->dyn_data;
-
- /* Because we can't actually pass type across save&load... */
- ui_list->type = ui_list_type;
- ui_list->layout_type = layout_type;
-
- /* Reset filtering data. */
- MEM_SAFE_FREE(dyn_data->items_filter_flags);
- MEM_SAFE_FREE(dyn_data->items_filter_neworder);
- dyn_data->items_len = dyn_data->items_shown = -1;
-
- /* When active item changed since last draw, scroll to it. */
- if (activei != ui_list->list_last_activei) {
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ui_list->list_last_activei = activei;
- }
-
- /* Filter list items! (not for compact layout, though) */
- if (dataptr->data && prop) {
- const int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
- const bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
- int items_shown, idx = 0;
-#if 0
- int prev_ii = -1, prev_i;
-#endif
-
- if (layout_type == UILST_LAYOUT_COMPACT) {
- dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop);
- }
- else {
- // printf("%s: filtering...\n", __func__);
- filter_items(ui_list, C, dataptr, propname);
- // printf("%s: filtering done.\n", __func__);
- }
-
- items_shown = dyn_data->items_shown;
- if (items_shown >= 0) {
- bool activei_mapping_pending = true;
- items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, __func__);
- // printf("%s: items shown: %d.\n", __func__, items_shown);
- RNA_PROP_BEGIN (dataptr, itemptr, prop) {
- if (!dyn_data->items_filter_flags ||
- ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) {
- int ii;
- if (dyn_data->items_filter_neworder) {
- ii = dyn_data->items_filter_neworder[idx++];
- ii = order_reverse ? items_shown - ii - 1 : ii;
- }
- else {
- ii = order_reverse ? items_shown - ++idx : idx++;
- }
- // printf("%s: ii: %d\n", __func__, ii);
- items_ptr[ii].item = itemptr;
- items_ptr[ii].org_idx = i;
- items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] :
- 0;
-
- if (activei_mapping_pending && activei == i) {
- activei = ii;
- /* So that we do not map again activei! */
- activei_mapping_pending = false;
- }
-#if 0 /* For now, do not alter active element, even if it will be hidden... */
- else if (activei < i) {
- /* We do not want an active but invisible item!
- * Only exception is when all items are filtered out...
- */
- if (prev_ii >= 0) {
- activei = prev_ii;
- RNA_property_int_set(active_dataptr, activeprop, prev_i);
- }
- else {
- activei = ii;
- RNA_property_int_set(active_dataptr, activeprop, i);
- }
- }
- prev_i = i;
- prev_ii = ii;
-#endif
- }
- i++;
- }
- RNA_PROP_END;
-
- if (activei_mapping_pending) {
- /* No active item found, set to 'invalid' -1 value... */
- activei = -1;
- }
- }
- if (dyn_data->items_shown >= 0) {
- len = dyn_data->items_shown;
- }
- else {
- len = dyn_data->items_len;
- }
- }
-
- switch (layout_type) {
- case UILST_LAYOUT_DEFAULT:
- /* layout */
- box = uiLayoutListBox(layout, ui_list, active_dataptr, activeprop);
- glob = uiLayoutColumn(box, true);
- row = uiLayoutRow(glob, false);
- col = uiLayoutColumn(row, true);
-
- /* init numbers */
- uilist_prepare(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
-
- if (dataptr->data && prop) {
- /* create list items */
- for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
- PointerRNA *itemptr = &items_ptr[i].item;
- void *dyntip_data;
- const int org_i = items_ptr[i].org_idx;
- const int flt_flag = items_ptr[i].flt_flag;
- uiBlock *subblock = uiLayoutGetBlock(col);
-
- overlap = uiLayoutOverlap(col);
-
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, false);
-
- but = uiDefButR_prop(subblock,
- UI_BTYPE_LISTROW,
- 0,
- "",
- 0,
- 0,
- UI_UNIT_X * 10,
- UI_UNIT_Y,
- active_dataptr,
- activeprop,
- 0,
- 0,
- org_i,
- 0,
- 0,
- TIP_("Double click to rename"));
- if ((dyntip_data = uilist_item_use_dynamic_tooltip(itemptr, item_dyntip_propname))) {
- UI_but_func_tooltip_set(but, uilist_item_tooltip_func, dyntip_data, MEM_freeN);
- }
-
- sub = uiLayoutRow(overlap, false);
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- if (icon == ICON_DOT) {
- icon = ICON_NONE;
- }
- draw_item(ui_list,
- C,
- sub,
- dataptr,
- itemptr,
- icon,
- active_dataptr,
- active_propname,
- org_i,
- flt_flag);
-
- /* Items should be able to set context pointers for the layout. But the list-row button
- * swallows events, so it needs the context storage too for handlers to see it. */
- but->context = uiLayoutGetContextStore(sub);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- /* add dummy buttons to fill space */
- for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
- uiItemL(col, "", ICON_NONE);
- }
-
- /* add scrollbar */
- if (len > layoutdata.visual_items) {
- col = uiLayoutColumn(row, false);
- uiDefButI(block,
- UI_BTYPE_SCROLL,
- 0,
- "",
- 0,
- 0,
- V2D_SCROLL_WIDTH,
- UI_UNIT_Y * dyn_data->visual_height,
- &ui_list->list_scroll,
- 0,
- dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height,
- 0,
- "");
- }
- break;
- case UILST_LAYOUT_COMPACT:
- row = uiLayoutRow(layout, true);
-
- if ((dataptr->data && prop) && (dyn_data->items_shown > 0) && (activei >= 0) &&
- (activei < dyn_data->items_shown)) {
- PointerRNA *itemptr = &items_ptr[activei].item;
- const int org_i = items_ptr[activei].org_idx;
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- if (icon == ICON_DOT) {
- icon = ICON_NONE;
- }
- draw_item(
- ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0);
- }
- /* if list is empty, add in dummy button */
- else {
- uiItemL(row, "", ICON_NONE);
- }
-
- /* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
- but = uiDefIconTextButR_prop(block,
- UI_BTYPE_NUM,
- 0,
- 0,
- numstr,
- 0,
- 0,
- UI_UNIT_X * 5,
- UI_UNIT_Y,
- active_dataptr,
- activeprop,
- 0,
- 0,
- 0,
- 0,
- 0,
- "");
- if (dyn_data->items_shown == 0) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- break;
- case UILST_LAYOUT_GRID:
- box = uiLayoutListBox(layout, ui_list, active_dataptr, activeprop);
- glob = uiLayoutColumn(box, true);
- row = uiLayoutRow(glob, false);
- col = uiLayoutColumn(row, true);
- subrow = NULL; /* Quite gcc warning! */
-
- uilist_prepare(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
-
- if (dataptr->data && prop) {
- /* create list items */
- for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
- PointerRNA *itemptr = &items_ptr[i].item;
- const int org_i = items_ptr[i].org_idx;
- const int flt_flag = items_ptr[i].flt_flag;
-
- /* create button */
- if (!(i % columns)) {
- subrow = uiLayoutRow(col, false);
- }
-
- uiBlock *subblock = uiLayoutGetBlock(subrow);
- overlap = uiLayoutOverlap(subrow);
-
- UI_block_flag_enable(subblock, UI_BLOCK_LIST_ITEM);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, false);
-
- but = uiDefButR_prop(subblock,
- UI_BTYPE_LISTROW,
- 0,
- "",
- 0,
- 0,
- UI_UNIT_X * 10,
- UI_UNIT_Y,
- active_dataptr,
- activeprop,
- 0,
- 0,
- org_i,
- 0,
- 0,
- NULL);
- UI_but_drawflag_enable(but, UI_BUT_NO_TOOLTIP);
-
- sub = uiLayoutRow(overlap, false);
-
- icon = UI_icon_from_rnaptr(C, itemptr, rnaicon, false);
- draw_item(ui_list,
- C,
- sub,
- dataptr,
- itemptr,
- icon,
- active_dataptr,
- active_propname,
- org_i,
- flt_flag);
-
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
-
- UI_block_flag_disable(subblock, UI_BLOCK_LIST_ITEM);
- }
- }
-
- /* add dummy buttons to fill space */
- for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
- if (!(i % columns)) {
- subrow = uiLayoutRow(col, false);
- }
- uiItemL(subrow, "", ICON_NONE);
- }
-
- /* add scrollbar */
- if (len > layoutdata.visual_items) {
- /* col = */ uiLayoutColumn(row, false);
- uiDefButI(block,
- UI_BTYPE_SCROLL,
- 0,
- "",
- 0,
- 0,
- V2D_SCROLL_WIDTH,
- UI_UNIT_Y * dyn_data->visual_height,
- &ui_list->list_scroll,
- 0,
- dyn_data->height - dyn_data->visual_height,
- dyn_data->visual_height,
- 0,
- "");
- }
- break;
- }
-
- if (glob) {
- /* About #UI_BTYPE_GRIP drag-resize:
- * We can't directly use results from a grip button, since we have a
- * rather complex behavior here (sizing by discrete steps and, overall, auto-size feature).
- * Since we *never* know whether we are grip-resizing or not
- * (because there is no callback for when a button enters/leaves its "edit mode"),
- * we use the fact that grip-controlled value (dyn_data->resize) is completely handled
- * by the grip during the grab resize, so settings its value here has no effect at all.
- *
- * It is only meaningful when we are not resizing,
- * in which case this gives us the correct "init drag" value.
- * Note we cannot affect `dyn_data->resize_prev here`,
- * since this value is not controlled by the grip!
- */
- dyn_data->resize = dyn_data->resize_prev +
- (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y;
-
- row = uiLayoutRow(glob, true);
- uiBlock *subblock = uiLayoutGetBlock(row);
- UI_block_emboss_set(subblock, UI_EMBOSS_NONE);
-
- if (ui_list->filter_flag & UILST_FLT_SHOW) {
- but = uiDefIconButBitI(subblock,
- UI_BTYPE_TOGGLE,
- UILST_FLT_SHOW,
- 0,
- ICON_DISCLOSURE_TRI_DOWN,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y * 0.5f,
- &(ui_list->filter_flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Hide filtering options"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-
- but = uiDefIconButI(subblock,
- UI_BTYPE_GRIP,
- 0,
- ICON_GRIP,
- 0,
- 0,
- UI_UNIT_X * 10.0f,
- UI_UNIT_Y * 0.5f,
- &dyn_data->resize,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
-
- UI_block_emboss_set(subblock, UI_EMBOSS);
-
- col = uiLayoutColumn(glob, false);
- subblock = uiLayoutGetBlock(col);
- uiDefBut(subblock,
- UI_BTYPE_SEPR,
- 0,
- "",
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y * 0.05f,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
-
- draw_filter(ui_list, C, col);
- }
- else {
- but = uiDefIconButBitI(subblock,
- UI_BTYPE_TOGGLE,
- UILST_FLT_SHOW,
- 0,
- ICON_DISCLOSURE_TRI_RIGHT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y * 0.5f,
- &(ui_list->filter_flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Show filtering options"));
- UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
-
- but = uiDefIconButI(subblock,
- UI_BTYPE_GRIP,
- 0,
- ICON_GRIP,
- 0,
- 0,
- UI_UNIT_X * 10.0f,
- UI_UNIT_Y * 0.5f,
- &dyn_data->resize,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- UI_but_func_set(but, uilist_resize_update_cb, ui_list, NULL);
-
- UI_block_emboss_set(subblock, UI_EMBOSS);
- }
- }
-
- if (items_ptr) {
- MEM_freeN(items_ptr);
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Running Jobs Template
* \{ */
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 6ad1de68a1f..93a790b53d0 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -29,6 +29,8 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
+#include "ED_screen.h"
+
#include "BLI_alloca.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -38,6 +40,7 @@
#include "BLT_translation.h"
+#include "BKE_context.h"
#include "BKE_lib_id.h"
#include "BKE_report.h"
@@ -48,6 +51,7 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -701,7 +705,7 @@ int UI_calc_float_precision(int prec, double value)
/* Check on the number of decimal places need to display the number,
* this is so 0.00001 is not displayed as 0.00,
- * _but_, this is only for small values si 10.0001 will not get the same treatment.
+ * _but_, this is only for small values as 10.0001 will not get the same treatment.
*/
value = fabs(value);
if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) {
@@ -774,6 +778,98 @@ bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str,
}
/* -------------------------------------------------------------------- */
+
+static rctf ui_but_rect_to_view(const uiBut *but, const ARegion *region, const View2D *v2d)
+{
+ rctf region_rect;
+ ui_block_to_region_rctf(region, but->block, &region_rect, &but->rect);
+
+ rctf view_rect;
+ UI_view2d_region_to_view_rctf(v2d, &region_rect, &view_rect);
+
+ return view_rect;
+}
+
+/**
+ * To get a margin (typically wanted), add the margin to \a rect directly.
+ *
+ * Based on #file_ensure_inside_viewbounds(), could probably share code.
+ *
+ * \return true if anything changed.
+ */
+static bool ui_view2d_cur_ensure_rect_in_view(View2D *v2d, const rctf *rect)
+{
+ const float rect_width = BLI_rctf_size_x(rect);
+ const float rect_height = BLI_rctf_size_y(rect);
+
+ rctf *cur = &v2d->cur;
+ const float cur_width = BLI_rctf_size_x(cur);
+ const float cur_height = BLI_rctf_size_y(cur);
+
+ bool changed = false;
+
+ /* Snap to bottom edge. Also use if rect is higher than view bounds (could be a parameter). */
+ if ((cur->ymin > rect->ymin) || (rect_height > cur_height)) {
+ cur->ymin = rect->ymin;
+ cur->ymax = cur->ymin + cur_height;
+ changed = true;
+ }
+ /* Snap to upper edge. */
+ else if (cur->ymax < rect->ymax) {
+ cur->ymax = rect->ymax;
+ cur->ymin = cur->ymax - cur_height;
+ changed = true;
+ }
+ /* Snap to left edge. Also use if rect is wider than view bounds. */
+ else if ((cur->xmin > rect->xmin) || (rect_width > cur_width)) {
+ cur->xmin = rect->xmin;
+ cur->xmax = cur->xmin + cur_width;
+ changed = true;
+ }
+ /* Snap to right edge. */
+ else if (cur->xmax < rect->xmax) {
+ cur->xmax = rect->xmax;
+ cur->xmin = cur->xmax - cur_width;
+ changed = true;
+ }
+ else {
+ BLI_assert(BLI_rctf_inside_rctf(cur, rect));
+ }
+
+ return changed;
+}
+
+/**
+ * Adjust the view so the rectangle of \a but is in view, with some extra margin.
+ *
+ * It's important that this is only executed after buttons received their final #uiBut.rect. E.g.
+ * #UI_panels_end() modifies them, so if that is executed, this function must not be called before
+ * it.
+ *
+ * \param region: The region the button is placed in. Make sure this is actually the one the button
+ * is placed in, not just the context region.
+ */
+void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but)
+{
+ View2D *v2d = &region->v2d;
+ /* Uninitialized view or region that doesn't use View2D. */
+ if ((v2d->flag & V2D_IS_INIT) == 0) {
+ return;
+ }
+
+ rctf rect = ui_but_rect_to_view(but, region, v2d);
+
+ const int margin = UI_UNIT_X * 0.5f;
+ BLI_rctf_pad(&rect, margin, margin);
+
+ const bool changed = ui_view2d_cur_ensure_rect_in_view(v2d, &rect);
+ if (changed) {
+ UI_view2d_curRect_changed(C, v2d);
+ ED_region_tag_redraw_no_rebuild(region);
+ }
+}
+
+/* -------------------------------------------------------------------- */
/** \name Button Store
*
* Modal Button Store API.
@@ -932,7 +1028,7 @@ void UI_butstore_update(uiBlock *block)
uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p);
/* can be NULL if the buttons removed,
- * note: we could allow passing in a callback when buttons are removed
+ * NOTE: we could allow passing in a callback when buttons are removed
* so the caller can cleanup */
*bs_elem->but_p = but_new;
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 1ab12a2c8ea..0decaa5e45d 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -106,6 +106,7 @@ typedef enum {
/* specials */
UI_WTYPE_ICON,
UI_WTYPE_ICON_LABEL,
+ UI_WTYPE_PREVIEW_TILE,
UI_WTYPE_SWATCH,
UI_WTYPE_RGB_PICKER,
UI_WTYPE_UNITVEC,
@@ -238,7 +239,7 @@ typedef struct uiWidgetTrias {
#define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
typedef struct uiWidgetBase {
- /* TODO remove these completely */
+ /* TODO: remove these completely. */
int totvert, halfwayvert;
float outer_v[WIDGET_SIZE_MAX][2];
float inner_v[WIDGET_SIZE_MAX][2];
@@ -400,7 +401,7 @@ static struct {
GPUBatch *roundbox_widget;
GPUBatch *roundbox_shadow;
- /* TODO remove */
+ /* TODO: remove. */
GPUVertFormat format;
uint vflag_id;
} g_ui_batch_cache = {0};
@@ -524,7 +525,7 @@ void UI_draw_anti_tria(
float draw_color[4];
copy_v4_v4(draw_color, color);
- /* Note: This won't give back the original color. */
+ /* NOTE: This won't give back the original color. */
draw_color[3] *= 1.0f / WIDGET_AA_JITTER;
GPU_blend(GPU_BLEND_ALPHA);
@@ -769,7 +770,7 @@ static void round_box__edges(
BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect);
BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi);
- /* mult */
+ /* Multiply by radius. */
for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
veci[a][0] = radi * cornervec[a][0];
veci[a][1] = radi * cornervec[a][1];
@@ -1378,8 +1379,6 @@ static int ui_but_draw_menu_icon(const uiBut *but)
static void widget_draw_icon(
const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const uchar mono_color[4])
{
- float xs = 0.0f, ys = 0.0f;
-
if (but->flag & UI_BUT_ICON_PREVIEW) {
GPU_blend(GPU_BLEND_ALPHA);
widget_draw_preview(icon, alpha, rect);
@@ -1421,6 +1420,7 @@ static void widget_draw_icon(
if (icon && icon != ICON_BLANK1) {
const float ofs = 1.0f / aspect;
+ float xs, ys;
if (but->drawflag & UI_BUT_ICON_LEFT) {
/* special case - icon_only pie buttons */
@@ -1642,7 +1642,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
/* Corner case, the str already takes all available mem,
* and the ellipsis chars would actually add more chars.
* Better to just trim one or two letters to the right in this case...
- * Note: with a single-char ellipsis, this should never happen! But better be safe
+ * NOTE: with a single-char ellipsis, this should never happen! But better be safe
* here...
*/
ui_text_clip_right_ex(
@@ -2007,14 +2007,15 @@ static void widget_draw_text(const uiFontStyle *fstyle,
drawstr_left_len = INT_MAX;
#ifdef WITH_INPUT_IME
- /* FIXME, IME is modifying 'const char *drawstr! */
+ /* FIXME: IME is modifying `const char *drawstr`! */
ime_data = ui_but_ime_data_get(but);
if (ime_data && ime_data->composite_len) {
/* insert composite string into cursor pos */
BLI_snprintf((char *)drawstr,
UI_MAX_DRAW_STR,
- "%s%s%s",
+ "%.*s%s%s",
+ but->pos,
but->editstr,
ime_data->str_composite,
but->editstr + but->pos);
@@ -2030,8 +2031,11 @@ static void widget_draw_text(const uiFontStyle *fstyle,
/* text button selection, cursor, composite underline */
if (but->editstr && but->pos != -1) {
int but_pos_ofs;
- /* Shape of the cursor for drawing. */
- rcti but_cursor_shape;
+
+#ifdef WITH_INPUT_IME
+ bool ime_reposition_window = false;
+ int ime_win_x, ime_win_y;
+#endif
/* text button selection */
if ((but->selend - but->selsta) > 0) {
@@ -2056,14 +2060,28 @@ static void widget_draw_text(const uiFontStyle *fstyle,
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ rcti selection_shape;
+ selection_shape.xmin = rect->xmin + selsta_draw;
+ selection_shape.xmax = min_ii(rect->xmin + selwidth_draw, rect->xmax - 2);
+ selection_shape.ymin = rect->ymin + U.pixelsize;
+ selection_shape.ymax = rect->ymax - U.pixelsize;
immUniformColor4ubv(wcol->item);
immRecti(pos,
- rect->xmin + selsta_draw,
- rect->ymin + U.pixelsize,
- min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
- rect->ymax - U.pixelsize);
+ selection_shape.xmin,
+ selection_shape.ymin,
+ selection_shape.xmax,
+ selection_shape.ymax);
immUnbindProgram();
+
+#ifdef WITH_INPUT_IME
+ /* IME candidate window uses selection position. */
+ if (!ime_reposition_window) {
+ ime_reposition_window = true;
+ ime_win_x = selection_shape.xmin;
+ ime_win_y = selection_shape.ymin;
+ }
+#endif
}
}
@@ -2071,7 +2089,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
but_pos_ofs = but->pos;
#ifdef WITH_INPUT_IME
- /* if is ime compositing, move the cursor */
+ /* If is IME compositing, move the cursor. */
if (ime_data && ime_data->composite_len && ime_data->cursor_pos != -1) {
but_pos_ofs += ime_data->cursor_pos;
}
@@ -2096,6 +2114,8 @@ static void widget_draw_text(const uiFontStyle *fstyle,
immUniformThemeColor(TH_WIDGET_TEXT_CURSOR);
+ /* Shape of the cursor for drawing. */
+ rcti but_cursor_shape;
but_cursor_shape.xmin = (rect->xmin + t) - U.pixelsize;
but_cursor_shape.ymin = rect->ymin + U.pixelsize;
but_cursor_shape.xmax = (rect->xmin + t) + U.pixelsize;
@@ -2109,16 +2129,24 @@ static void widget_draw_text(const uiFontStyle *fstyle,
but_cursor_shape.ymax);
immUnbindProgram();
- }
#ifdef WITH_INPUT_IME
- if (ime_data && ime_data->composite_len) {
- /* ime cursor following */
- if (but->pos >= but->ofs) {
- ui_but_ime_reposition(but, but_cursor_shape.xmax + 5, but_cursor_shape.ymin + 3, false);
+ /* IME candidate window uses cursor position. */
+ if (!ime_reposition_window) {
+ ime_reposition_window = true;
+ ime_win_x = but_cursor_shape.xmax + 5;
+ ime_win_y = but_cursor_shape.ymin + 3;
}
+#endif
+ }
- /* composite underline */
+#ifdef WITH_INPUT_IME
+ /* IME cursor following. */
+ if (ime_reposition_window) {
+ ui_but_ime_reposition(but, ime_win_x, ime_win_y, false);
+ }
+ if (ime_data && ime_data->composite_len) {
+ /* Composite underline. */
widget_draw_text_ime_underline(fstyle, wcol, but, rect, ime_data, drawstr);
}
#endif
@@ -2494,7 +2522,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
ui_text_clip_middle(fstyle, but, rect);
}
- /* always draw text for textbutton cursor */
+ /* Always draw text for text-button cursor. */
widget_draw_text(fstyle, wcol, but, rect);
ui_but_text_password_hide(password_str, but, true);
@@ -3089,7 +3117,7 @@ void ui_draw_gradient(const rcti *rect,
copy_v3_v3(col1[3], col1[2]);
break;
default:
- BLI_assert(!"invalid 'type' argument");
+ BLI_assert_msg(0, "invalid 'type' argument");
hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]);
copy_v3_v3(col1[0], col1[2]);
copy_v3_v3(col1[1], col1[2]);
@@ -3693,10 +3721,6 @@ static void widget_progressbar(
/* "slider" bar color */
copy_v3_v3_uchar(wcol->inner, wcol->item);
widgetbase_draw(&wtb_bar, wcol);
-
- /* raise text a bit */
- rect->xmin += (BLI_rcti_size_x(&rect_prog) / 2);
- rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
}
static void widget_datasetrow(
@@ -3996,6 +4020,14 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
widgetbase_draw(&wtb, wcol);
}
+static void widget_preview_tile(
+ uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+{
+ const uiStyle *style = UI_style_get();
+ ui_draw_preview_item_stateless(
+ &style->widget, rect, but->drawstr, but->icon, wcol->text, UI_STYLE_TEXT_CENTER);
+}
+
static void widget_menuiconbut(uiWidgetColors *wcol,
rcti *rect,
int UNUSED(state),
@@ -4307,7 +4339,7 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
widget_init(&wtb);
if (but->block->drawextra) {
- /* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
+ /* NOTE: drawextra can change rect +1 or -1, to match round errors of existing previews. */
but->block->drawextra(
C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
@@ -4461,6 +4493,13 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.custom = widget_icon_has_anim;
break;
+ case UI_WTYPE_PREVIEW_TILE:
+ wt.draw = NULL;
+ /* Drawn via the `custom` callback. */
+ wt.text = NULL;
+ wt.custom = widget_preview_tile;
+ break;
+
case UI_WTYPE_SWATCH:
wt.custom = widget_swatch;
break;
@@ -4756,6 +4795,10 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
wt = widget_type(UI_WTYPE_BOX);
break;
+ case UI_BTYPE_PREVIEW_TILE:
+ wt = widget_type(UI_WTYPE_PREVIEW_TILE);
+ break;
+
case UI_BTYPE_EXTRA:
widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
break;
@@ -4909,13 +4952,15 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
wt->draw(&wt->wcol, rect, state, roundboxalign);
}
- if (use_alpha_blend) {
- GPU_blend(GPU_BLEND_ALPHA);
- }
+ if (wt->text) {
+ if (use_alpha_blend) {
+ GPU_blend(GPU_BLEND_ALPHA);
+ }
- wt->text(fstyle, &wt->wcol, but, rect);
- if (use_alpha_blend) {
- GPU_blend(GPU_BLEND_NONE);
+ wt->text(fstyle, &wt->wcol, but, rect);
+ if (use_alpha_blend) {
+ GPU_blend(GPU_BLEND_NONE);
+ }
}
}
@@ -5352,7 +5397,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
}
}
else {
- BLI_assert(!"Unknwon menu item separator type");
+ BLI_assert_msg(0, "Unknwon menu item separator type");
}
if (fstyle->kerning == 1) {
@@ -5437,17 +5482,20 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
}
}
-void ui_draw_preview_item(
- const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
+/**
+ * Version of #ui_draw_preview_item() that does not draw the menu background and item text based on
+ * state. It just draws the preview and text directly.
+ */
+void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
+ rcti *rect,
+ const char *name,
+ int iconid,
+ const uchar text_col[4],
+ eFontStyle_Align text_align)
{
rcti trect = *rect;
const float text_size = UI_UNIT_Y;
float font_dims[2] = {0.0f, 0.0f};
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
-
- /* drawing button background */
- wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
- wt->draw(&wt->wcol, rect, 0, 0);
/* draw icon in rect above the space reserved for the label */
rect->ymin += text_size;
@@ -5459,8 +5507,6 @@ void ui_draw_preview_item(
fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
/* text rect */
- trect.xmin += 0;
- trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
trect.ymin += U.widget_unit / 2;
trect.ymax = trect.ymin + font_dims[1];
if (trect.xmax > rect->xmax - PREVIEW_PAD) {
@@ -5479,11 +5525,27 @@ void ui_draw_preview_item(
UI_fontstyle_draw(fstyle,
&trect,
drawstr,
- wt->wcol.text,
+ text_col,
&(struct uiFontStyleDraw_Params){
- .align = UI_STYLE_TEXT_CENTER,
+ .align = text_align,
});
}
}
+void ui_draw_preview_item(const uiFontStyle *fstyle,
+ rcti *rect,
+ const char *name,
+ int iconid,
+ int state,
+ eFontStyle_Align text_align)
+{
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
+
+ /* drawing button background */
+ wt->state(wt, state, 0, UI_EMBOSS_UNDEFINED);
+ wt->draw(&wt->wcol, rect, 0, 0);
+
+ ui_draw_preview_item_stateless(fstyle, rect, name, iconid, wt->wcol.text, text_align);
+}
+
/** \} */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 5eb20ae601b..e9804840801 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -347,7 +347,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
v2d->keeptot = V2D_KEEPTOT_BOUNDS;
- /* note, scroll is being flipped in ED_region_panels() drawing */
+ /* NOTE: scroll is being flipped in #ED_region_panels() drawing. */
v2d->scroll |= (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
if (do_init) {
@@ -717,7 +717,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
*
* So, resolution is to just shift view by the gap between the extremities.
* We favor moving the 'minimum' across, as that's origin for most things.
- * (XXX - in the past, max was favored... if there are bugs, swap!)
+ * (XXX: in the past, max was favored... if there are bugs, swap!)
*/
if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) {
/* outside boundaries on both sides,
@@ -1059,7 +1059,7 @@ void UI_view2d_zoom_cache_reset(void)
/* While scaling we can accumulate fonts at many sizes (~20 or so).
* Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */
- /* Note: only some views draw text, we could check for this case to avoid cleaning cache. */
+ /* NOTE: only some views draw text, we could check for this case to avoid cleaning cache. */
BLF_cache_clear();
}
@@ -1158,7 +1158,7 @@ void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, const bool xaxis)
* correspondence with pixels for smooth UI drawing,
* but only applied where requested.
*/
- /* XXX temp (ton) */
+ /* XXX(ton): temp. */
xofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_X) ? GLA_PIXEL_OFS : 0.0f;
yofs = 0.0f; // (v2d->flag & V2D_PIXELOFS_Y) ? GLA_PIXEL_OFS : 0.0f;
@@ -1844,7 +1844,7 @@ View2D *UI_view2d_fromcontext(const bContext *C)
return &(region->v2d);
}
-/* same as above, but it returns regionwindow. Utility for pulldowns or buttons */
+/* Same as above, but it returns region-window. Utility for pull-downs or buttons. */
View2D *UI_view2d_fromcontext_rwin(const bContext *C)
{
ScrArea *area = CTX_wm_area(C);
diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c
index 5801b7cdbdb..f7ef8c06389 100644
--- a/source/blender/editors/interface/view2d_draw.c
+++ b/source/blender/editors/interface/view2d_draw.c
@@ -216,7 +216,7 @@ static void draw_parallel_lines(const ParallelLinesSet *lines,
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniform2fv("viewportSize", &viewport[2]);
/* -1.0f offset here is because the line is too fat due to the builtin anti-aliasing.
- * TODO make a variant or a uniform to toggle it off. */
+ * TODO: make a variant or a uniform to toggle it off. */
immUniform1f("lineWidth", U.pixelsize - 1.0f);
}
else {
diff --git a/source/blender/editors/interface/view2d_edge_pan.c b/source/blender/editors/interface/view2d_edge_pan.c
index ca32a754f1d..1d300c7b275 100644
--- a/source/blender/editors/interface/view2d_edge_pan.c
+++ b/source/blender/editors/interface/view2d_edge_pan.c
@@ -160,7 +160,7 @@ static float edge_pan_speed(View2DEdgePanData *vpd,
distance = min - event_loc;
}
else {
- BLI_assert(!"Calculating speed outside of pan zones");
+ BLI_assert_msg(0, "Calculating speed outside of pan zones");
return 0.0f;
}
float distance_factor = distance / (vpd->speed_ramp * U.widget_unit);
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 69acfc657dc..1fd1b6c984d 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -271,7 +271,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
view_pan_apply(C, op);
break;
}
- /* XXX - Mode switching isn't implemented. See comments in 36818.
+ /* XXX: Mode switching isn't implemented. See comments in 36818.
* switch to zoom */
#if 0
case LEFTMOUSE:
@@ -1527,7 +1527,7 @@ struct SmoothView2DStore {
/**
* function to get a factor out of a rectangle
*
- * note: this doesn't always work as well as it might because the target size
+ * NOTE: this doesn't always work as well as it might because the target size
* may not be reached because of clamping the desired rect, we _could_
* attempt to clamp the rect before working out the zoom factor but its
* not really worthwhile for the few cases this happens.
@@ -1745,7 +1745,7 @@ typedef struct v2dScrollerMove {
* This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c,
* as we only need focus bubble info.
*
- * \warning: The start of this struct must not change,
+ * \warning The start of this struct must not change,
* so that it stays in sync with the 'real' version.
* For now, we don't need to have a separate (internal) header for structs like this...
*/
@@ -2132,7 +2132,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
scroller_activate_exit(C, op);
/* can't catch this event for ourselves, so let it go to someone else? */
- /* XXX note: if handlers use mask rect to clip input, input will fail for this case */
+ /* XXX NOTE: if handlers use mask rect to clip input, input will fail for this case. */
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 28838d677f0..12890552b1d 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -63,10 +63,26 @@
# include "WM_api.h"
# include "WM_types.h"
+# include "DEG_depsgraph.h"
+
# include "io_alembic.h"
# include "ABC_alembic.h"
+const EnumPropertyItem rna_enum_abc_export_evaluation_mode_items[] = {
+ {DAG_EVAL_RENDER,
+ "RENDER",
+ 0,
+ "Render",
+ "Use Render settings for object visibility, modifier settings, etc"},
+ {DAG_EVAL_VIEWPORT,
+ "VIEWPORT",
+ 0,
+ "Viewport",
+ "Use Viewport settings for object visibility, modifier settings, etc"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) {
@@ -126,7 +142,6 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"),
.flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"),
.visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only"),
- .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
.face_sets = RNA_boolean_get(op->ptr, "face_sets"),
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
.export_hair = RNA_boolean_get(op->ptr, "export_hair"),
@@ -137,6 +152,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.triangulate = RNA_boolean_get(op->ptr, "triangulate"),
.quad_method = RNA_enum_get(op->ptr, "quad_method"),
.ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
+ .evaluation_mode = RNA_enum_get(op->ptr, "evaluation_mode"),
.global_scale = RNA_float_get(op->ptr, "global_scale"),
};
@@ -194,9 +210,11 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
sub = uiLayoutColumnWithHeading(col, true, IFACE_("Only"));
uiItemR(sub, imfptr, "selected", 0, IFACE_("Selected Objects"), ICON_NONE);
- uiItemR(sub, imfptr, "renderable_only", 0, IFACE_("Renderable Objects"), ICON_NONE);
uiItemR(sub, imfptr, "visible_objects_only", 0, IFACE_("Visible Objects"), ICON_NONE);
+ col = uiLayoutColumn(box, true);
+ uiItemR(col, imfptr, "evaluation_mode", 0, NULL, ICON_NONE);
+
/* Object Data */
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
@@ -355,12 +373,6 @@ void WM_OT_alembic_export(wmOperatorType *ot)
ot->srna, "selected", 0, "Selected Objects Only", "Export only selected objects");
RNA_def_boolean(ot->srna,
- "renderable_only",
- 1,
- "Renderable Objects Only",
- "Export only objects marked renderable in the outliner");
-
- RNA_def_boolean(ot->srna,
"visible_objects_only",
0,
"Visible Objects Only",
@@ -468,6 +480,14 @@ void WM_OT_alembic_export(wmOperatorType *ot)
"This option is deprecated; EXECUTE this operator to run in the foreground, and INVOKE it "
"to run as a background job");
+ RNA_def_enum(ot->srna,
+ "evaluation_mode",
+ rna_enum_abc_export_evaluation_mode_items,
+ DAG_EVAL_RENDER,
+ "Use Settings for",
+ "Determines visibility of objects, modifier settings, and other areas where there "
+ "are different settings for viewport and rendering");
+
/* This dummy prop is used to check whether we need to init the start and
* end frame values to that of the scene's, otherwise they are reset at
* every change, draw update. */
diff --git a/source/blender/editors/io/io_gpencil.h b/source/blender/editors/io/io_gpencil.h
index b347be00412..428b09f0e9c 100644
--- a/source/blender/editors/io/io_gpencil.h
+++ b/source/blender/editors/io/io_gpencil.h
@@ -25,8 +25,8 @@
*/
struct ARegion;
-struct bContext;
struct View3D;
+struct bContext;
struct wmOperatorType;
void WM_OT_gpencil_import_svg(struct wmOperatorType *ot);
diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c
index 8d8e1e9f06a..e6f190f335b 100644
--- a/source/blender/editors/lattice/editlattice_select.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -236,7 +236,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
}
}
- /* TODO, only notify changes */
+ /* TODO: only notify changes. */
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -514,7 +514,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
BPoint *bp;
int a, tot;
- if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
+ if (BLI_listbase_is_empty(&lt->vertex_group_names) || lt->dvert == NULL) {
continue;
}
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
index d92a81179cc..23eaf991fd3 100644
--- a/source/blender/editors/lattice/editlattice_undo.c
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -240,7 +240,7 @@ static void lattice_undosys_step_decode(struct bContext *C,
}
undolatt_to_editlatt(&elem->data, lt->editlatt);
lt->editlatt->needs_flush_to_id = 1;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&lt->id, ID_RECALC_GEOMETRY);
}
/* The first element is always active */
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 36edbbe31d6..880d27e1615 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -145,7 +145,7 @@ static void setup_vertex_point(Mask *mask,
/* parent */
reference_parent_point = close_point;
- /* note, we may want to copy other attributes later, radius? pressure? color? */
+ /* NOTE: we may want to copy other attributes later, radius? pressure? color? */
}
}
@@ -189,7 +189,7 @@ static void finSelectedSplinePoint(MaskLayer *mask_layer,
*point = NULL;
if (check_active) {
- /* TODO, having an active point but no active spline is possible, why? */
+ /* TODO: having an active point but no active spline is possible, why? */
if (mask_layer->act_spline && mask_layer->act_point &&
MASKPOINT_ISSEL_ANY(mask_layer->act_point)) {
*spline = mask_layer->act_spline;
@@ -277,7 +277,7 @@ static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2
setup_vertex_point(mask, spline, new_point, co, u, ctime, NULL, true);
- /* TODO - we could pass the spline! */
+ /* TODO: we could pass the spline! */
BKE_mask_layer_shape_changed_add(mask_layer,
BKE_mask_layer_shape_spline_to_index(mask_layer, spline) +
point_index + 1,
@@ -479,7 +479,7 @@ static int add_vertex_handle_cyclic_at_point(bContext *C,
spline->flag |= MASK_SPLINE_CYCLIC;
- /* TODO, update keyframes in time. */
+ /* TODO: update keyframes in time. */
BKE_mask_calc_handle_point_auto(spline, active_point, false);
BKE_mask_calc_handle_point_auto(spline, other_point, false);
@@ -526,7 +526,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
float co[2];
RNA_float_get_array(op->ptr, "location", co);
- /* TODO, having an active point but no active spline is possible, why? */
+ /* TODO: having an active point but no active spline is possible, why? */
if (mask_layer && mask_layer->act_spline && mask_layer->act_point &&
MASKPOINT_ISSEL_ANY(mask_layer->act_point)) {
MaskSpline *spline = mask_layer->act_spline;
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index d3fa0e93597..de8ea8e21eb 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -211,7 +211,7 @@ static void draw_spline_points(const bContext *C,
undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
}
- /* TODO, add this to sequence editor */
+ /* TODO: add this to sequence editor. */
float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
mask_spline_color_get(mask_layer, spline, is_spline_sel, rgb_spline);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 3476f1ca735..6fa7457ce14 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -390,7 +390,7 @@ static void select_sliding_point(Mask *mask,
point->bezt.f3 |= SELECT;
break;
default:
- BLI_assert(!"Unexpected situation in select_sliding_point()");
+ BLI_assert_msg(0, "Unexpected situation in select_sliding_point()");
}
mask_layer->act_spline = spline;
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 4ce4a416796..a5a3489c143 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -173,7 +173,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)
MaskSplinePoint *point = &spline->points[i];
if (MASKPOINT_ISSEL_ANY(point)) {
- /* TODO - nicer access here */
+ /* TODO: nicer access here. */
shape_ele_dst->value[6] = shape_ele_src->value[6];
}
@@ -291,7 +291,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
BLI_addtail(&shapes_tmp, mask_layer_shape_tmp);
}
- /* re-key, note: can't modify the keys here since it messes uop */
+ /* re-key, NOTE: can't modify the keys here since it messes up. */
for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp;
mask_layer_shape_tmp = mask_layer_shape_tmp->next) {
BKE_mask_layer_evaluate(mask_layer, mask_layer_shape_tmp->frame, true);
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index b7ee50a9461..648008a4779 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -65,7 +65,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
return;
}
- /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */
+ /* NOTE: call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags. */
/* we could call this directly in all areas that change selection,
* since this could become slow for realtime updates (circle-select for eg) */
@@ -433,7 +433,7 @@ bool paintface_mouse_select(
/* image window redraw */
paintface_flush_flags(C, ob, SELECT);
- ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
+ ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */
return true;
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 110f1975d8d..01736f2919a 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -279,7 +279,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
for (int i = 0; i < NUM_VALUE_KINDS; i++) {
opdata->shift_value[i] = -1.0f;
opdata->initial_length[i] = -1.0f;
- /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */
+ /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */
opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
initNumInput(&opdata->num_input[i]);
@@ -347,7 +347,7 @@ static bool edbm_bevel_calc(wmOperator *op)
/* revert to original mesh */
if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
+ EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false);
}
const int material = CLAMPIS(material_init, -1, obedit->totcol - 1);
@@ -436,7 +436,7 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false);
+ EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup);
}
ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
if (v3d) {
@@ -456,7 +456,7 @@ static void edbm_bevel_cancel(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
Object *obedit = opdata->ob_store[ob_index].ob;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true);
+ EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true);
EDBM_update(obedit->data,
&(const struct EDBMUpdate_Params){
.calc_looptri = false,
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 42cf36dda81..3c8afe8e7db 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -67,7 +67,7 @@ typedef struct {
/* Aligned with objects array. */
struct {
- BMBackup mesh;
+ BMBackup mesh_backup;
bool is_valid;
bool is_dirty;
} * backup;
@@ -160,7 +160,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (em->bm->totedgesel != 0) {
opdata->backup[ob_index].is_valid = true;
- opdata->backup[ob_index].mesh = EDBM_redo_state_store(em);
+ opdata->backup[ob_index].mesh_backup = EDBM_redo_state_store(em);
}
}
@@ -184,7 +184,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata)
for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) {
if (opdata->backup[ob_index].is_valid) {
- EDBM_redo_state_free(&opdata->backup[ob_index].mesh, NULL, false);
+ EDBM_redo_state_free(&opdata->backup[ob_index].mesh_backup);
}
}
MEM_freeN(opdata->backup);
@@ -280,7 +280,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
/* -------------------------------------------------------------------- */
/* Modal support */
- /* Note: keep this isolated, exec can work without this */
+ /* NOTE: keep this isolated, exec can work without this. */
if (opdata != NULL) {
mesh_bisect_interactive_calc(C, op, plane_co, plane_no);
/* Write back to the props. */
@@ -301,7 +301,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
if (opdata != NULL) {
if (opdata->backup[ob_index].is_dirty) {
- EDBM_redo_state_restore(opdata->backup[ob_index].mesh, em, false);
+ EDBM_redo_state_restore(&opdata->backup[ob_index].mesh_backup, em, false);
opdata->backup[ob_index].is_dirty = false;
}
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 1c27ab00715..18f51ae9df2 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -209,7 +209,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
- EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false);
+ EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup);
}
ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
if (v3d) {
@@ -235,7 +235,7 @@ static void edbm_inset_cancel(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
Object *obedit = opdata->ob_store[ob_index].ob;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true);
+ EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true);
EDBM_update(obedit->data,
&(const struct EDBMUpdate_Params){
.calc_looptri = false,
@@ -276,7 +276,7 @@ static bool edbm_inset_calc(wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
+ EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false);
}
if (use_individual) {
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 0e2dd492e06..73f6a3f3238 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -157,7 +157,7 @@ typedef struct KnifePosData {
typedef struct KnifeTool_OpData {
ARegion *region; /* region that knifetool was activated in */
void *draw_handle; /* for drawing preview loop */
- ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */
+ ViewContext vc; /* NOTE: _don't_ use 'mval', instead use the one we define below. */
float mval[2]; /* mouse value with snapping applied */
// bContext *C;
@@ -1475,7 +1475,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
}
}
- /* Note: as following loop progresses, the 'v' fields of
+ /* NOTE: as following loop progresses, the 'v' fields of
* the linehits will be filled in (as edges are split or
* in-face verts are made), so it may be true that both
* the v and the kfe or f fields will be non-NULL. */
@@ -1760,7 +1760,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd,
if (RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d)) {
float view_clip[2][3];
- /* note: view_clip[0] should never get clipped */
+ /* NOTE: view_clip[0] should never get clipped. */
copy_v3_v3(view_clip[0], p_ofs);
madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist);
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index aa144dd3f3c..09b17acf56d 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -30,6 +30,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
@@ -59,7 +60,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ARegion *region = CTX_wm_region(C);
- struct Mesh *me_eval;
+ const struct Mesh *me_eval;
bool me_eval_needs_free;
if (ob->type == OB_MESH || ob->runtime.data_eval) {
@@ -113,7 +114,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
BKE_nurbList_free(&nurbslist);
if (me_eval_needs_free) {
- BKE_mesh_free(me_eval);
+ BKE_mesh_free((struct Mesh *)me_eval);
}
}
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 71319338a53..0a4fecde6ea 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -241,7 +241,7 @@ static void ringsel_finish(bContext *C, wmOperator *op)
* in editmesh_select.c (around line 1000)... */
/* sets as active, useful for other tools */
if (em->selectmode & SCE_SELECT_VERTEX) {
- /* low priority TODO, get vertrex close to mouse */
+ /* low priority TODO: get vertrex close to mouse. */
BM_select_history_store(em->bm, lcd->eed->v1);
}
if (em->selectmode & SCE_SELECT_EDGE) {
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 993905462db..cccfc7e934c 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -126,7 +126,7 @@ static int geometry_extract_apply(bContext *C,
.calc_face_normal = true,
}));
- BMEditMesh *em = BKE_editmesh_create(bm, false);
+ BMEditMesh *em = BKE_editmesh_create(bm);
/* Generate the tags for deleting geometry in the extracted object. */
tag_fn(bm, params);
@@ -206,7 +206,7 @@ static int geometry_extract_apply(bContext *C,
}),
mesh);
- BKE_editmesh_free(em);
+ BKE_editmesh_free_data(em);
MEM_freeN(em);
if (new_mesh->totvert == 0) {
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index 593545ddcef..30a453a32ee 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -29,6 +29,7 @@
#include "DNA_windowmanager_types.h"
#ifdef WITH_FREESTYLE
+# include "BKE_customdata.h"
# include "DNA_meshdata_types.h"
#endif
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 8626520ec37..5a2a090b725 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -927,7 +927,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed
/* single edge, extend */
if (i == 1 && e_best->l) {
- /* note: if the case of 3 edges has one change in loop stepping,
+ /* NOTE: if the case of 3 edges has one change in loop stepping,
* if this becomes more involved we may be better off splitting
* the 3 edge case into its own else-if branch */
if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) {
@@ -975,7 +975,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed
BM_mesh_edgesplit(em->bm, true, true, true);
- /* note: the output of the bmesh operator is ignored, since we built
+ /* NOTE: the output of the bmesh operator is ignored, since we built
* the contiguous loop pairs to split already, its possible that some
* edge did not split even though it was tagged which would not work
* as expected (but not crash), however there are checks to ensure
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index d8973e100bc..830c9abb41e 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -35,6 +35,8 @@
#include "BLI_utildefines_stack.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_report.h"
@@ -434,7 +436,7 @@ struct NearestEdgeUserData {
struct NearestEdgeUserData_Hit hit_cycle;
};
-/* note; uses v3d, so needs active 3d window */
+/* NOTE: uses v3d, so needs active 3d window. */
static void find_nearest_edge__doClosest(
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
@@ -964,7 +966,7 @@ static bool unified_findnearest(ViewContext *vc,
}
}
- /* return only one of 3 pointers, for frontbuffer redraws */
+ /* Return only one of 3 pointers, for front-buffer redraws. */
if (hit.v.ele) {
hit.f.ele = NULL;
hit.e.ele = NULL;
@@ -3446,7 +3448,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in
select_linked_delimit_begin(bm, delimit);
}
- /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */
+ /* NOTE: logic closely matches #edbm_select_linked_exec, keep in sync. */
if (ele->head.htype == BM_VERT) {
BMVert *eve = (BMVert *)ele;
@@ -4739,10 +4741,11 @@ static bool edbm_select_ungrouped_poll(bContext *C)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ const ListBase *defbase = BKE_object_defgroup_list(obedit);
if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode");
}
- else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) {
+ else if (BLI_listbase_is_empty(defbase) || cd_dvert_offset == -1) {
CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object");
}
else {
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index 2ffeaa06751..c452f7a7487 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -29,6 +29,8 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_material.h"
@@ -559,7 +561,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
* \{ */
/**
- * Note: This is not normal, but the edge direction itself and always in
+ * NOTE: This is not normal, but the edge direction itself and always in
* a positive quadrant (tries z, y then x).
* Therefore we need to use the entire object transformation matrix.
*/
@@ -1041,7 +1043,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
if (cd_dvert_offset == -1) {
continue;
}
- defbase_len = BLI_listbase_count(&ob->defbase);
+ defbase_len = BKE_object_defgroup_count(ob);
if (defbase_len == 0) {
continue;
}
@@ -1090,8 +1092,10 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
/* We store the names of the vertex groups, so we can select
* vertex groups with the same name in different objects. */
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
int i = 0;
- LISTBASE_FOREACH (bDeformGroup *, dg, &ob->defbase) {
+ LISTBASE_FOREACH (bDeformGroup *, dg, defbase) {
if (BLI_BITMAP_TEST(defbase_selected, i)) {
BLI_gset_add(gset, dg->name);
}
@@ -1128,7 +1132,8 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
if (cd_dvert_offset == -1) {
continue;
}
- defbase_len = BLI_listbase_count(&ob->defbase);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ defbase_len = BLI_listbase_count(defbase);
if (defbase_len == 0) {
continue;
}
@@ -1141,7 +1146,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
GSetIterator gs_iter;
GSET_ITER (gs_iter, gset) {
const char *name = BLI_gsetIterator_getKey(&gs_iter);
- int vgroup_id = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
+ int vgroup_id = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name));
if (vgroup_id != -1) {
BLI_BITMAP_ENABLE(defbase_selected, vgroup_id);
found_any = true;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index fe9656d277e..41a9f426798 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -44,6 +44,7 @@
#include "BLI_string.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
@@ -145,7 +146,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* Note, these values must match delete_mesh() event values */
+/* NOTE: these values must match delete_mesh() event values. */
static const EnumPropertyItem prop_mesh_cornervert_types[] = {
{SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
{SUBD_CORNER_PATH, "PATH", 0, "Path", ""},
@@ -245,7 +246,7 @@ static void mesh_operator_edgering_props(wmOperatorType *ot,
const int cuts_min,
const int cuts_default)
{
- /* Note, these values must match delete_mesh() event values */
+ /* NOTE: these values must match delete_mesh() event values. */
static const EnumPropertyItem prop_subd_edgering_types[] = {
{SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
{SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""},
@@ -431,7 +432,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot)
/** \name Delete Operator
* \{ */
-/* Note, these values must match delete_mesh() event values */
+/* NOTE: these values must match delete_mesh() event values. */
enum {
MESH_DELETE_VERT = 0,
MESH_DELETE_EDGE = 1,
@@ -973,7 +974,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
#ifdef USE_FACE_CREATE_SEL_EXTEND
/* normally we would want to leave the new geometry selected,
* but being able to press F many times to add geometry is too useful! */
- if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
+ if (ele_desel && (BMO_slot_buffer_len(bmop.slots_out, "faces.out") == 1) &&
(ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) {
edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
}
@@ -1264,9 +1265,12 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator *
}
}
if (checks_succeded) {
+ BMBackup em_backup = EDBM_redo_state_store(em);
+
BM_custom_loop_normals_to_vector_layer(bm);
BMO_op_exec(bm, &bmop);
+ const bool failure = BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL);
len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
if (len && is_pair) {
@@ -1275,8 +1279,14 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator *
em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
}
- if (!EDBM_op_finish(em, &bmop, op, true)) {
+ bool em_backup_free = true;
+ if (!EDBM_op_finish(em, &bmop, op, false)) {
+ len = 0;
+ }
+ else if (failure) {
len = 0;
+ EDBM_redo_state_restore_and_free(&em_backup, em, true);
+ em_backup_free = false;
}
else {
/* so newly created edges get the selection state from the vertex */
@@ -1291,6 +1301,10 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator *
.is_destructive = true,
});
}
+
+ if (em_backup_free) {
+ EDBM_redo_state_free(&em_backup);
+ }
}
MEM_freeN(verts);
@@ -2331,7 +2345,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
BMO_slot_buffer_hflag_enable(
em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
- const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out");
+ const int tot_rotate = BMO_slot_buffer_len(bmop.slots_out, "edges.out");
const int tot_failed = tot - tot_rotate;
tot_rotate_all += tot_rotate;
@@ -3012,10 +3026,8 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
- /* execute the operator */
BMO_op_exec(em->bm, &bmop);
if (!EDBM_op_finish(em, &bmop, op, true)) {
@@ -3050,13 +3062,10 @@ static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op)
BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT);
- /* execute the operator */
BMO_op_exec(em->bm, &bmop);
- /* finish the operator */
if (!EDBM_op_finish(em, &bmop, op, true)) {
continue;
}
@@ -3091,13 +3100,10 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op)
BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
- /* execute the operator */
BMO_op_exec(em->bm, &bmop);
- /* finish the operator */
if (!EDBM_op_finish(em, &bmop, op, true)) {
continue;
}
@@ -3133,15 +3139,12 @@ static int edbm_reverse_colors_exec(bContext *C, wmOperator *op)
BMOperator bmop;
- /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT);
- /* execute the operator */
BMO_op_exec(em->bm, &bmop);
- /* finish the operator */
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
+ continue;
}
EDBM_update(obedit->data,
@@ -4222,7 +4225,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
/* for ED_view3d_project_float_object */
ED_view3d_init_mats_rv3d(obedit, region->regiondata);
- /* TODO, investigate using index lookup for screen_vert_coords() rather than a hash table */
+ /* TODO: investigate using index lookup for #screen_vert_coords() rather than a hash table. */
/* the floating point coordinates of verts in screen space will be
* stored in a hash table according to the vertices pointer */
@@ -5737,7 +5740,7 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op)
float *vweights = MEM_mallocN(sizeof(*vweights) * bm->totvert, __func__);
{
const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- const int defbase_act = obedit->actdef - 1;
+ const int defbase_act = BKE_object_defgroup_active_index_get(obedit) - 1;
if (use_vertex_group && (cd_dvert_offset == -1)) {
BKE_report(op->reports, RPT_WARNING, "No active vertex group");
@@ -5874,7 +5877,7 @@ void MESH_OT_decimate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* Note, keep in sync with 'rna_def_modifier_decimate' */
+ /* NOTE: keep in sync with 'rna_def_modifier_decimate'. */
RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna,
@@ -6558,7 +6561,7 @@ enum {
typedef struct BMElemSort {
/** Sort factor */
float srt;
- /** Original index of this element _in its mempool_ */
+ /** Original index of this element (in its #BLI_mempool). */
int org_idx;
} BMElemSort;
@@ -6751,7 +6754,7 @@ static void sort_bmelem_flag(bContext *C,
BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
if (BM_elem_flag_test(fa, flag)) {
/* Reverse materials' order, not order of faces inside each mat! */
- /* Note: cannot use totcol, as mat_nr may sometimes be greater... */
+ /* NOTE: cannot use totcol, as mat_nr may sometimes be greater... */
float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr;
pb[i] = false;
sb[affected[2]].org_idx = i;
@@ -7304,7 +7307,7 @@ static int edbm_bridge_edge_loops_for_single_editmesh(wmOperator *op,
BMO_op_exec(em->bm, &bmop);
- if (!BMO_error_occurred(em->bm)) {
+ if (!BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) {
/* when merge is used the edges are joined and remain selected */
if (use_merge == false) {
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -7670,7 +7673,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
/* Hull fails if input is coplanar */
- if (BMO_error_occurred(em->bm)) {
+ if (BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) {
EDBM_op_finish(em, &bmop, op, true);
continue;
}
@@ -8385,7 +8388,7 @@ static void point_normals_update_header(bContext *C, wmOperator *op)
ED_area_status_text(CTX_wm_area(C), header);
}
-/* TODO move that to generic function in BMesh? */
+/* TODO: move that to generic function in BMesh? */
static void bmesh_selected_verts_center_calc(BMesh *bm, float *r_center)
{
BMVert *v;
@@ -9691,7 +9694,7 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op)
BKE_lnor_space_custom_data_to_normal(
bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
- /* Note: again, this is not true spherical interpolation that normals would need...
+ /* NOTE: again, this is not true spherical interpolation that normals would need...
* But it's probably good enough for now. */
mul_v3_fl(current_normal, 1.0f - factor);
mul_v3_fl(smooth_normal[i], factor);
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 112de68b52c..fc9e1aa8b1a 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -33,6 +33,7 @@
#include "BLI_listbase.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
#include "BKE_layer.h"
@@ -671,7 +672,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *
em->bm->shapenr = um->shapenr;
- EDBM_mesh_free(em);
+ EDBM_mesh_free_data(em);
bm = BM_mesh_create(&allocsize,
&((struct BMeshCreateParams){
@@ -681,13 +682,21 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *
BM_mesh_bm_from_me(bm,
&um->me,
(&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
+ /* Handled with tessellation. */
+ .calc_face_normal = false,
.active_shapekey = um->shapenr,
}));
- em_tmp = BKE_editmesh_create(bm, true);
+ em_tmp = BKE_editmesh_create(bm);
*em = *em_tmp;
+ /* Calculate face normals and tessellation at once since it's multi-threaded.
+ * The vertex normals are stored in the undo-mesh, so this doesn't need to be updated. */
+ BKE_editmesh_looptri_calc_ex(em,
+ &(const struct BMeshCalcTessellation_Params){
+ .face_normals = true,
+ });
+
em->selectmode = um->selectmode;
bm->selectmode = um->selectmode;
@@ -865,7 +874,7 @@ static void mesh_undosys_step_decode(struct bContext *C,
BMEditMesh *em = me->edit_mesh;
undomesh_to_editmesh(&elem->data, obedit, em, me->key);
em->needs_flush_to_id = 1;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY);
}
/* The first element is always active */
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 141b69f0465..85c646d689c 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -68,6 +68,9 @@
* just as the undo stack would.
* So leaving this as an interface for further work */
+/**
+ * Save a copy of the #BMesh for restoring later.
+ */
BMBackup EDBM_redo_state_store(BMEditMesh *em)
{
BMBackup backup;
@@ -75,42 +78,41 @@ BMBackup EDBM_redo_state_store(BMEditMesh *em)
return backup;
}
-void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
+void EDBM_redo_state_restore(BMBackup *backup, BMEditMesh *em, bool recalc_looptri)
{
BMesh *tmpbm;
- if (!em || !backup.bmcopy) {
- return;
- }
BM_mesh_data_free(em->bm);
- tmpbm = BM_mesh_copy(backup.bmcopy);
+ tmpbm = BM_mesh_copy(backup->bmcopy);
*em->bm = *tmpbm;
MEM_freeN(tmpbm);
tmpbm = NULL;
- if (recalctess) {
+ if (recalc_looptri) {
BKE_editmesh_looptri_calc(em);
}
}
-void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
+/**
+ * Delete the backup, flushing it to an edit-mesh.
+ */
+void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptri)
{
- if (em && backup->bmcopy) {
- BM_mesh_data_free(em->bm);
- *em->bm = *backup->bmcopy;
- }
- else if (backup->bmcopy) {
- BM_mesh_data_free(backup->bmcopy);
+ BM_mesh_data_free(em->bm);
+ *em->bm = *backup->bmcopy;
+ MEM_freeN(backup->bmcopy);
+ backup->bmcopy = NULL;
+ if (recalc_looptri) {
+ BKE_editmesh_looptri_calc(em);
}
+}
+void EDBM_redo_state_free(BMBackup *backup)
+{
if (backup->bmcopy) {
+ BM_mesh_data_free(backup->bmcopy);
MEM_freeN(backup->bmcopy);
}
- backup->bmcopy = NULL;
-
- if (recalctess && em) {
- BKE_editmesh_looptri_calc(em);
- }
}
/** \} */
@@ -132,75 +134,76 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *
return false;
}
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
-
va_end(list);
return true;
}
-/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */
+/**
+ * The return value:
+ * - False on error (the mesh must not be changed).
+ * - True on success, executes and finishes a #BMesh operator.
+ */
bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
{
const char *errmsg;
- BMO_op_finish(em->bm, bmop);
-
- if (BMO_error_get(em->bm, &errmsg, NULL)) {
- BMEditMesh *emcopy = em->emcopy;
+#ifndef NDEBUG
+ struct {
+ int verts_len, edges_len, loops_len, faces_len;
+ } em_state_prev = {
+ .verts_len = em->bm->totvert,
+ .edges_len = em->bm->totedge,
+ .loops_len = em->bm->totloop,
+ .faces_len = em->bm->totface,
+ };
+#endif
- if (do_report) {
- BKE_report(op->reports, RPT_ERROR, errmsg);
- }
+ BMO_op_finish(em->bm, bmop);
- EDBM_mesh_free(em);
- *em = *emcopy;
-
- MEM_freeN(emcopy);
- em->emcopyusers = 0;
- em->emcopy = NULL;
-
- /**
- * Note, we could pass in the mesh, however this is an exceptional case, allow a slow lookup.
- *
- * This is needed because the COW mesh makes a full copy of the #BMEditMesh
- * instead of sharing the pointer, tagging since this has been freed above,
- * the #BMEditMesh.emcopy needs to be flushed to the COW edit-mesh, see T55457.
- */
- {
- Main *bmain = G_MAIN;
- for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
- if (mesh->edit_mesh == em) {
- DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE);
- break;
- }
+ bool changed = false;
+ bool changed_was_set = false;
+
+ eBMOpErrorLevel level;
+ while (BMO_error_pop(em->bm, &errmsg, NULL, &level)) {
+ ReportType type = RPT_INFO;
+ switch (level) {
+ case BMO_ERROR_CANCEL: {
+ changed_was_set = true;
+ break;
+ }
+ case BMO_ERROR_WARN: {
+ type = RPT_WARNING;
+ changed_was_set = true;
+ changed = true;
+ break;
+ }
+ case BMO_ERROR_FATAL: {
+ type = RPT_ERROR;
+ changed_was_set = true;
+ changed = true;
+ break;
}
}
- /* when copying, tessellation isn't to for faster copying,
- * but means we need to re-tessellate here */
- if (em->looptris == NULL) {
- BKE_editmesh_looptri_calc(em);
+ if (do_report) {
+ BKE_report(op->reports, type, errmsg);
}
-
- return false;
}
-
- em->emcopyusers--;
- if (em->emcopyusers < 0) {
- printf("warning: em->emcopyusers was less than zero.\n");
+ if (changed_was_set == false) {
+ changed = true;
}
- if (em->emcopyusers <= 0) {
- BKE_editmesh_free(em->emcopy);
- MEM_freeN(em->emcopy);
- em->emcopy = NULL;
+#ifndef NDEBUG
+ if (changed == false) {
+ BLI_assert((em_state_prev.verts_len == em->bm->totvert) &&
+ (em_state_prev.edges_len == em->bm->totedge) &&
+ (em_state_prev.loops_len == em->bm->totloop) &&
+ (em_state_prev.faces_len == em->bm->totface));
}
+#endif
- return true;
+ return changed;
}
bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
@@ -217,11 +220,6 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
return false;
}
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
-
BMO_op_exec(bm, &bmop);
va_end(list);
@@ -249,11 +247,6 @@ bool EDBM_op_call_and_selectf(BMEditMesh *em,
return false;
}
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
-
BMO_op_exec(bm, &bmop);
slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out);
@@ -284,11 +277,6 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
return false;
}
- if (!em->emcopy) {
- em->emcopy = BKE_editmesh_copy(em);
- }
- em->emcopyusers++;
-
BMO_op_exec(bm, &bmop);
va_end(list);
@@ -317,17 +305,13 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
if (me->edit_mesh) {
/* this happens when switching shape keys */
- EDBM_mesh_free(me->edit_mesh);
+ EDBM_mesh_free_data(me->edit_mesh);
MEM_freeN(me->edit_mesh);
}
- /* currently executing operators re-tessellates, so we can avoid doing here
- * but at some point it may need to be added back. */
-#if 0
- me->edit_mesh = BKE_editmesh_create(bm, true);
-#else
- me->edit_mesh = BKE_editmesh_create(bm, false);
-#endif
+ /* Executing operators re-tessellates,
+ * so we can avoid doing here but at some point it may need to be added back. */
+ me->edit_mesh = BKE_editmesh_create(bm);
me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode;
me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
@@ -338,7 +322,8 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
/**
* \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates).
- * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913
+ * Most callers should run #DEG_id_tag_update on `ob->data`, see: T46738, T46913.
+ * This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh.
*/
void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
{
@@ -358,25 +343,6 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
.calc_object_remap = true,
.update_shapekey_indices = !free_data,
}));
-
- /* Free derived mesh. usually this would happen through depsgraph but there
- * are exceptions like file save that will not cause this, and we want to
- * avoid ending up with an invalid derived mesh then.
- *
- * Do it for all objects which shares the same mesh datablock, since their
- * derived meshes might also be referencing data which was just freed,
- *
- * Annoying enough, but currently seems most efficient way to avoid access
- * of freed data on scene update, especially in cases when there are dependency
- * cycles.
- */
-#if 0
- for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) {
- if (other_object->data == ob->data) {
- BKE_object_free_derived_caches(other_object);
- }
- }
-#endif
}
void EDBM_mesh_clear(BMEditMesh *em)
@@ -384,8 +350,8 @@ void EDBM_mesh_clear(BMEditMesh *em)
/* clear bmesh */
BM_mesh_clear(em->bm);
- /* free derived meshes */
- BKE_editmesh_free_derivedmesh(em);
+ /* Free evaluated meshes & cache. */
+ BKE_editmesh_free_derived_caches(em);
/* free tessellation data */
em->tottri = 0;
@@ -401,9 +367,9 @@ void EDBM_mesh_load(Main *bmain, Object *ob)
}
/**
- * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free
+ * Should only be called on the active edit-mesh, otherwise call #BKE_editmesh_free_data.
*/
-void EDBM_mesh_free(BMEditMesh *em)
+void EDBM_mesh_free_data(BMEditMesh *em)
{
/* These tables aren't used yet, so it's not strictly necessary
* to 'end' them but if someone tries to start using them,
@@ -411,7 +377,7 @@ void EDBM_mesh_free(BMEditMesh *em)
ED_mesh_mirror_spatial_table_end(NULL);
ED_mesh_mirror_topo_table_end(NULL);
- BKE_editmesh_free(em);
+ BKE_editmesh_free_data(em);
}
/** \} */
@@ -1472,7 +1438,7 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params)
}
if (params->is_destructive) {
- /* TODO. we may be able to remove this now! - Campbell */
+ /* TODO(campbell): we may be able to remove this now! */
// BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP);
}
else {
@@ -1483,8 +1449,8 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params)
BM_lnorspace_invalidate(em->bm, false);
em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET;
}
- /* don't keep stale derivedMesh data around, see: T38872. */
- BKE_editmesh_free_derivedmesh(em);
+ /* Don't keep stale evaluated mesh data around, see: T38872. */
+ BKE_editmesh_free_derived_caches(em);
#ifdef DEBUG
{
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 7c6dc6516ed..73b3fb9724e 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -34,6 +34,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
@@ -252,7 +253,7 @@ void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
-/* note: keep in sync with ED_mesh_color_add */
+/* NOTE: keep in sync with #ED_mesh_color_add. */
int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, const bool do_init)
{
BMEditMesh *em;
@@ -377,7 +378,7 @@ bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name)
return false;
}
-/* note: keep in sync with ED_mesh_uv_texture_add */
+/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */
int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init)
{
BMEditMesh *em;
@@ -483,7 +484,7 @@ bool ED_mesh_color_remove_named(Mesh *me, const char *name)
/*********************** Sculpt Vertex colors operators ************************/
-/* note: keep in sync with ED_mesh_uv_texture_add */
+/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */
int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init)
{
BMEditMesh *em;
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 25d3eaf11d4..5eb69aab48b 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -308,8 +308,9 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
last = 0;
- /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
- * but you can't ever access the last 'a' index of MirrTopoPairs */
+ /* Get the pairs out of the sorted hashes.
+ * NOTE: `totvert + 1` means we can use the previous 2,
+ * but you can't ever access the last 'a' index of #MirrTopoPairs. */
if (em) {
BMVert **vtable = em->bm->vtable;
for (a = 1; a <= totvert; a++) {
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index f306612f295..27fb21e1dfb 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -390,7 +390,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* Apply parent transform if the active object's parent was joined to it.
- * Note: This doesn't apply recursive parenting. */
+ * NOTE: This doesn't apply recursive parenting. */
if (join_parent) {
ob->parent = NULL;
BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false);
@@ -475,16 +475,17 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
me = ob_iter->data;
/* Join this object's vertex groups to the base one's */
- for (dg = ob_iter->defbase.first; dg; dg = dg->next) {
+ for (dg = me->vertex_group_names.first; dg; dg = dg->next) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
if (!BKE_object_defgroup_find_name(ob, dg->name)) {
odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup");
memcpy(odg, dg, sizeof(bDeformGroup));
- BLI_addtail(&ob->defbase, odg);
+ BLI_addtail(&mesh_active->vertex_group_names, odg);
}
}
- if (ob->defbase.first && ob->actdef == 0) {
- ob->actdef = 1;
+ if (!BLI_listbase_is_empty(&mesh_active->vertex_group_names) &&
+ me->vertex_group_active_index == 0) {
+ me->vertex_group_active_index = 1;
}
/* Join this object's face maps to the base one's. */
@@ -1060,7 +1061,7 @@ static float *editmesh_get_mirror_uv(
cent_vec[1] = face_cent[1];
}
- /* TODO - Optimize */
+ /* TODO: Optimize. */
{
BMIter iter;
BMFace *efa;
@@ -1473,19 +1474,21 @@ bool ED_mesh_pick_vert(
MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve)
{
- if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) {
+ if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH) {
Mesh *me = ob->data;
- BMesh *bm = me->edit_mesh->bm;
- const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ if (!BLI_listbase_is_empty(&me->vertex_group_names)) {
+ BMesh *bm = me->edit_mesh->bm;
+ const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- if (cd_dvert_offset != -1) {
- BMVert *eve = BM_mesh_active_vert_get(bm);
+ if (cd_dvert_offset != -1) {
+ BMVert *eve = BM_mesh_active_vert_get(bm);
- if (eve) {
- if (r_eve) {
- *r_eve = eve;
+ if (eve) {
+ if (r_eve) {
+ *r_eve = eve;
+ }
+ return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
}
- return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
}
}
}
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index a8b471a7c92..f7b53b5513f 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -215,7 +215,7 @@ static void mball_undosys_step_decode(struct bContext *C,
}
undomball_to_editmball(&elem->data, mb);
mb->needs_flush_to_id = 1;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&mb->id, ID_RECALC_GEOMETRY);
}
/* The first element is always active */
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 11cf3ea5083..8ae74fbfafa 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -407,7 +407,7 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
"Enter edit mode when adding this object");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
- /* note: this property gets hidden for add-camera operator */
+ /* NOTE: this property gets hidden for add-camera operator. */
prop = RNA_def_enum(
ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object");
RNA_def_property_update_runtime(prop, view_align_update);
@@ -1325,7 +1325,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
bool newob = false;
- /* Note: We use 'Y' here (not 'Z'), as */
+ /* NOTE: We use 'Y' here (not 'Z'), as. */
WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, NULL, &local_view_bits, NULL)) {
return OPERATOR_CANCELLED;
@@ -1845,7 +1845,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
* ready to be moved around to re-time the sound and/or make new sound clips. */
{
/* create new data for NLA hierarchy */
- AnimData *adt = BKE_animdata_add_id(&ob->id);
+ AnimData *adt = BKE_animdata_ensure_id(&ob->id);
NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data);
strip->start = CFRA;
@@ -1977,7 +1977,7 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot)
/** \name Delete Object Operator
* \{ */
/* remove base from a specific scene */
-/* note: now unlinks constraints as well */
+/* NOTE: now unlinks constraints as well. */
void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
@@ -2163,7 +2163,7 @@ static void copy_object_set_idnew(bContext *C)
/** \name Make Instanced Objects Real Operator
* \{ */
-/* XXX TODO That whole hierarchy handling based on persistent_id tricks is
+/* XXX TODO: That whole hierarchy handling based on persistent_id tricks is
* very confusing and convoluted, and it will fail in many cases besides basic ones.
* Think this should be replaced by a proper tree-like representation of the instantiations,
* should help a lot in both readability, and precise consistent rebuilding of hierarchy.
@@ -2442,7 +2442,7 @@ static void make_object_duplilist_real(bContext *C,
}
if (ob_dst->parent) {
- /* note, this may be the parent of other objects, but it should
+ /* NOTE: this may be the parent of other objects, but it should
* still work out ok */
BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
@@ -2906,7 +2906,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
}
/* make new mesh data from the original copy */
- /* note: get the mesh from the original, not from the copy in some
+ /* NOTE: get the mesh from the original, not from the copy in some
* cases this doesn't give correct results (when MDEF is used for eg)
*/
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
@@ -3349,8 +3349,8 @@ static Base *object_add_duplicate_internal(Main *bmain,
/* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
/* leaves selection of base/object unaltered.
- * note: don't call this within a loop since clear_* funcs loop over the entire database.
- * note: caller must do DAG_relations_tag_update(bmain);
+ * NOTE: don't call this within a loop since clear_* funcs loop over the entire database.
+ * NOTE: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
Base *ED_object_add_duplicate(
Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag)
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index a5cad4e087c..3a10a423e91 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -566,7 +566,7 @@ static int multiresbake_image_exec(bContext *C, wmOperator *op)
WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
WM_JOB_TYPE_OBJECT_BAKE_TEXTURE);
WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob);
- WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
+ WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO: only draw bake image, can we enforce this. */
WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL);
G.is_break = false;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index e941b27879b..233f2a65dac 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -158,7 +158,7 @@ static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
/**
* for exec() when there is no render job
- * note: this won't check for the escape key being pressed, but doing so isn't thread-safe.
+ * NOTE: this won't check for the escape key being pressed, but doing so isn't thread-safe.
*/
static int bake_break(void *UNUSED(rjv))
{
@@ -1939,7 +1939,7 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
WM_JOB_TYPE_OBJECT_BAKE);
WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
- /* TODO - only draw bake image, can we enforce this */
+ /* TODO: only draw bake image, can we enforce this. */
WM_jobs_timer(
wm_job, 0.5, (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) ? NC_GEOM | ND_DATA : NC_IMAGE, 0);
WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index a7aa6b4d6a4..4970338973d 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1731,7 +1731,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* force depsgraph to get recalculated since relationships removed */
DEG_relations_tag_update(bmain);
- /* note, calling BIK_clear_data() isn't needed here */
+ /* NOTE: calling BIK_clear_data() isn't needed here. */
return OPERATOR_FINISHED;
}
@@ -1745,7 +1745,7 @@ void POSE_OT_constraints_clear(wmOperatorType *ot)
/* callbacks */
ot->exec = pose_constraints_clear_exec;
- /* XXX - do we want to ensure there are selected bones too? */
+ /* XXX: do we want to ensure there are selected bones too? */
ot->poll = ED_operator_object_active_local_editable_posemode_exclusive;
}
@@ -2461,7 +2461,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* Refresh depsgraph. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* Note, notifier might evolve. */
+ /* NOTE: notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
}
}
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 7b7970fbfe5..6251fb799c5 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -33,6 +33,7 @@
#include "BKE_context.h"
#include "BKE_data_transfer.h"
+#include "BKE_deform.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_mesh_runtime.h"
@@ -96,7 +97,7 @@ static const EnumPropertyItem DT_layer_items[] = {
{0, NULL, 0, NULL, NULL},
};
-/* Note: rna_enum_dt_layers_select_src_items enum is from rna_modifier.c */
+/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.c. */
static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *UNUSED(prop),
@@ -122,9 +123,14 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
RNA_enum_items_add_value(
&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);
- if (data_type == DT_TYPE_MDEFORMVERT) {
- Object *ob_src = CTX_data_active_object(C);
+ Object *ob_src = CTX_data_active_object(C);
+ if (ob_src == NULL) {
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+ return item;
+ }
+ if (data_type == DT_TYPE_MDEFORMVERT && BKE_object_supports_vertex_groups(ob_src)) {
if (BKE_object_pose_armature_get(ob_src)) {
RNA_enum_items_add_value(
&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
@@ -132,66 +138,57 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
}
- if (ob_src) {
- bDeformGroup *dg;
- int i;
+ const bDeformGroup *dg;
+ int i;
- RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_item_add_separator(&item, &totitem);
- for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = dg->name;
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
+ const ListBase *defbase = BKE_object_defgroup_list(ob_src);
+ for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
else if (data_type == DT_TYPE_SHAPEKEY) {
/* TODO */
}
else if (data_type == DT_TYPE_UV) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (ob_src) {
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.lmask |= CD_MASK_MLOOPUV;
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
- int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.lmask |= CD_MASK_MLOOPUV;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
+ int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
- RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_item_add_separator(&item, &totitem);
- for (int i = 0; i < num_data; i++) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
- &me_eval->ldata, CD_MLOOPUV, i);
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
+ for (int i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
+ &me_eval->ldata, CD_MLOOPUV, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
else if (data_type == DT_TYPE_VCOL) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (ob_src) {
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.lmask |= CD_MASK_MLOOPCOL;
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
- int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.lmask |= CD_MASK_MLOOPCOL;
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
+ int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
- RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_item_add_separator(&item, &totitem);
- for (int i = 0; i < num_data; i++) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
- &me_eval->ldata, CD_MLOOPCOL, i);
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
+ for (int i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
+ &me_eval->ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
@@ -201,7 +198,7 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
return item;
}
-/* Note: rna_enum_dt_layers_select_dst_items enum is from rna_modifier.c */
+/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.c`. */
static const EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *UNUSED(prop),
@@ -255,7 +252,7 @@ static const EnumPropertyItem *dt_layers_select_itemf(bContext *C,
return dt_layers_select_src_itemf(C, ptr, prop, r_free);
}
-/* Note: rna_enum_dt_mix_mode_items enum is from rna_modifier.c */
+/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.c`. */
static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *UNUSED(prop),
@@ -511,7 +508,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
}
#if 0 /* TODO */
- /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
+ /* NOTE: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
#else
return OPERATOR_FINISHED;
@@ -767,7 +764,7 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
}
/******************************************************************************/
-/* Note: This operator is hybrid, it can work as a usual standalone Object operator,
+/* NOTE: This operator is hybrid, it can work as a usual standalone Object operator,
* or as a DataTransfer modifier tool.
*/
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 1ca967d9112..6108691b2f1 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -134,8 +134,8 @@ Object *ED_object_context(const bContext *C)
return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
}
-/* find the correct active object per context
- * note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */
+/* Find the correct active object per context.
+ * NOTE: context can be NULL when called from a enum with #PROP_ENUM_NO_CONTEXT. */
Object *ED_object_active_context(const bContext *C)
{
Object *ob = NULL;
@@ -557,7 +557,7 @@ static bool ED_object_editmode_load_free_ex(Main *bmain,
}
if (free_data) {
- EDBM_mesh_free(me->edit_mesh);
+ EDBM_mesh_free_data(me->edit_mesh);
MEM_freeN(me->edit_mesh);
me->edit_mesh = NULL;
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index fcee2818b22..5065a2c00f0 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -105,14 +105,13 @@ static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar,
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
{
- const int cd_dvert_offset = obedit->actdef ?
+ const int active_index = BKE_object_defgroup_active_index_get(obedit);
+ const int cd_dvert_offset = active_index ?
CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) :
-1;
- zero_v3(r_cent);
-
if (cd_dvert_offset != -1) {
- const int defgrp_index = obedit->actdef - 1;
+ const int defgrp_index = active_index - 1;
int totvert = 0;
MDeformVert *dvert;
@@ -129,7 +128,8 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name,
}
}
if (totvert) {
- bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
+ const ListBase *defbase = BKE_object_defgroup_list(obedit);
+ bDeformGroup *dg = BLI_findlink(defbase, defgrp_index);
BLI_strncpy(r_name, dg->name, sizeof(dg->name));
mul_v3_fl(r_cent, 1.0f / (float)totvert);
return true;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 5bf04e195fe..5a3a28b5a3f 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -247,7 +247,6 @@ void OBJECT_OT_vertex_group_assign_new(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot);
-void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 620c58196dd..7bbca7ea9e6 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -2598,7 +2598,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
- /* note: we use EditBones here, easier to set them up and use
+ /* NOTE: we use EditBones here, easier to set them up and use
* edit-armature functions to convert back to regular bones */
for (int v = 0; v < me->totvert; v++) {
if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 00ef439c18a..a438c760d3b 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -201,7 +201,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_remove_from);
WM_operatortype_append(OBJECT_OT_vertex_group_select);
WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
WM_operatortype_append(OBJECT_OT_vertex_group_copy);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
@@ -322,7 +321,7 @@ void ED_keymap_object(wmKeyConfig *keyconf)
keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0);
/* Object Mode ---------------------------------------------------------------- */
- /* Note: this keymap gets disabled in non-objectmode. */
+ /* NOTE: this keymap gets disabled in non-objectmode. */
keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0);
keymap->poll = object_mode_poll;
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 15695c4c6f7..c61965b3e23 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -593,7 +593,7 @@ void ED_object_parent_clear(Object *ob, const int type)
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
}
-/* note, poll should check for editable scene */
+/* NOTE: poll should check for editable scene. */
static int parent_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -791,8 +791,8 @@ bool ED_object_parent_set(ReportList *reports,
* NOTE: the old (2.4x) method was to set ob->partype = PARSKEL,
* creating the virtual modifiers.
*/
- ob->partype = PAROBJECT; /* Note: DNA define, not operator property. */
- /* ob->partype = PARSKEL; */ /* Note: DNA define, not operator property. */
+ ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
+ /* ob->partype = PARSKEL; */ /* NOTE: DNA define, not operator property. */
/* BUT, to keep the deforms, we need a modifier,
* and then we need to set the object that it uses
@@ -837,14 +837,14 @@ bool ED_object_parent_set(ReportList *reports,
}
break;
case PAR_BONE:
- ob->partype = PARBONE; /* Note: DNA define, not operator property. */
+ ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
if (pchan->bone) {
pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
}
break;
case PAR_BONE_RELATIVE:
- ob->partype = PARBONE; /* Note: DNA define, not operator property. */
+ ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
if (pchan->bone) {
pchan->bone->flag |= BONE_RELATIVE_PARENTING;
pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
@@ -860,7 +860,7 @@ bool ED_object_parent_set(ReportList *reports,
break;
case PAR_OBJECT:
case PAR_FOLLOW:
- ob->partype = PAROBJECT; /* Note: DNA define, not operator property. */
+ ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
break;
}
@@ -1248,7 +1248,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
/* set parenting type for object - object only... */
ob->parent = par;
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
}
}
}
@@ -1298,7 +1298,7 @@ static const EnumPropertyItem prop_clear_track_types[] = {
{0, NULL, 0, NULL, NULL},
};
-/* note, poll should check for editable scene */
+/* NOTE: poll should check for editable scene. */
static int object_track_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -2022,7 +2022,7 @@ static void single_obdata_users(
break;
default:
printf("ERROR %s: can't copy %s\n", __func__, id->name);
- BLI_assert(!"This should never happen.");
+ BLI_assert_msg(0, "This should never happen.");
/* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
BKE_scene_objects_iterator_end(&iter_macro);
@@ -2061,6 +2061,23 @@ static void single_object_action_users(
FOREACH_OBJECT_FLAG_END;
}
+static void single_objectdata_action_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+{
+ FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
+ if (!ID_IS_LINKED(ob) && ob->data != NULL) {
+ ID *id_obdata = (ID *)ob->data;
+ AnimData *adt = BKE_animdata_from_id(id_obdata);
+ ID *id_act = (ID *)adt->action;
+ if (id_act && id_act->us > 1) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ BKE_animdata_copy_id_action(bmain, id_obdata);
+ }
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
+}
+
static void single_mat_users(
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
@@ -2236,7 +2253,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "type");
int a;
- /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
+ /* NOTE: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
if (mode == MAKE_LOCAL_ALL) {
ViewLayer *view_layer = CTX_data_view_layer(C);
Collection *collection = CTX_data_collection(C);
@@ -2643,6 +2660,10 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
single_object_action_users(bmain, scene, view_layer, v3d, flag);
}
+ if (RNA_boolean_get(op->ptr, "obdata_animation")) {
+ single_objectdata_action_users(bmain, scene, view_layer, v3d, flag);
+ }
+
BKE_main_id_newptr_and_tag_clear(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -2684,8 +2705,16 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block");
- RNA_def_boolean(
- ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
+ RNA_def_boolean(ot->srna,
+ "animation",
+ 0,
+ "Object Animation",
+ "Make object animation data local to each object");
+ RNA_def_boolean(ot->srna,
+ "obdata_animation",
+ 0,
+ "Object Data Animation",
+ "Make object data (mesh, curve etc.) animation data local to each object");
}
/** \} */
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 1a0c5a6a83f..eb37aebcff2 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -295,7 +295,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_
return false;
}
- /* TODO, use 'reveal_hidden', as is done with bones. */
+ /* TODO: use 'reveal_hidden', as is done with bones. */
if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) {
/* Select if not selected. */
@@ -1496,7 +1496,7 @@ void OBJECT_OT_select_random(wmOperatorType *ot)
ot->idname = "OBJECT_OT_select_random";
/* api callbacks */
- /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
+ /*ot->invoke = object_select_random_invoke XXX: need a number popup ;*/
ot->exec = object_select_random_exec;
ot->poll = objects_selectable_poll;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index d1e912b2f37..4c4727f51ee 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -1152,51 +1152,53 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
for (int object_index = 0; object_index < num_objects; object_index++) {
Object *ob = objects[object_index];
+ if (ob->flag & OB_DONE) {
+ continue;
+ }
- if ((ob->flag & OB_DONE) == 0) {
- bool do_inverse_offset = false;
- ob->flag |= OB_DONE;
+ bool do_inverse_offset = false;
+ ob->flag |= OB_DONE;
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
- if (ob->data == NULL) {
- /* special support for dupligroups */
- if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
- (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
- if (ID_IS_LINKED(ob->instance_collection)) {
- tot_lib_error++;
+ if (ob->data == NULL) {
+ /* special support for dupligroups */
+ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
+ (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
+ if (ID_IS_LINKED(ob->instance_collection)) {
+ tot_lib_error++;
+ }
+ else {
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
}
else {
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else {
- float min[3], max[3];
- /* only bounds support */
- 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);
- mul_m4_v3(ob->imat, cent);
- }
+ float min[3], max[3];
+ /* only bounds support */
+ 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);
+ mul_m4_v3(ob->imat, cent);
+ }
- add_v3_v3(ob->instance_collection->instance_offset, cent);
+ add_v3_v3(ob->instance_collection->instance_offset, cent);
- tot_change++;
- ob->instance_collection->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
+ tot_change++;
+ ob->instance_collection->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
}
}
- else if (ID_IS_LINKED(ob->data)) {
- tot_lib_error++;
- }
-
- if (obedit == NULL && ob->type == OB_MESH) {
+ }
+ else if (ID_IS_LINKED(ob->data)) {
+ tot_lib_error++;
+ }
+ else if (ob->type == OB_MESH) {
+ if (obedit == NULL) {
Mesh *me = ob->data;
if (centermode == ORIGIN_TO_CURSOR) {
@@ -1222,265 +1224,265 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
me->id.tag |= LIB_TAG_DOIT;
do_inverse_offset = true;
}
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else if (around == V3D_AROUND_CENTER_BOUNDS) {
- BKE_curve_center_bounds(cu, cent);
- }
- else { /* #V3D_AROUND_CENTER_MEDIAN. */
- BKE_curve_center_median(cu, cent);
- }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_BOUNDS) {
+ BKE_curve_center_bounds(cu, cent);
+ }
+ else { /* #V3D_AROUND_CENTER_MEDIAN. */
+ BKE_curve_center_median(cu, cent);
+ }
- /* don't allow Z change if curve is 2D */
- if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) {
- cent[2] = 0.0;
- }
+ /* don't allow Z change if curve is 2D */
+ if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) {
+ cent[2] = 0.0;
+ }
- negate_v3_v3(cent_neg, cent);
- BKE_curve_translate(cu, cent_neg, 1);
+ negate_v3_v3(cent_neg, cent);
+ BKE_curve_translate(cu, cent_neg, 1);
- tot_change++;
- cu->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
+ tot_change++;
+ cu->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
- if (obedit) {
- if (centermode == GEOMETRY_TO_ORIGIN) {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- break;
+ if (obedit) {
+ if (centermode == GEOMETRY_TO_ORIGIN) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
}
+ break;
}
- else if (ob->type == OB_FONT) {
- /* Get from bounding-box. */
+ }
+ else if (ob->type == OB_FONT) {
+ /* Get from bounding-box. */
- Curve *cu = ob->data;
+ Curve *cu = ob->data;
- if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
- /* Do nothing. */
+ if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
+ /* Do nothing. */
+ }
+ else {
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* Done. */
}
else {
- if (centermode == ORIGIN_TO_CURSOR) {
- /* Done. */
- }
- else {
- /* extra 0.5 is the height o above line */
- cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
- cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
- }
+ /* extra 0.5 is the height o above line */
+ cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
+ cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
+ }
- cent[2] = 0.0f;
+ cent[2] = 0.0f;
- cu->xof = cu->xof - cent[0];
- cu->yof = cu->yof - cent[1];
+ cu->xof = cu->xof - cent[0];
+ cu->yof = cu->yof - cent[1];
- tot_change++;
- cu->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
+ tot_change++;
+ cu->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
}
- else if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
- if (ID_REAL_USERS(arm) > 1) {
+ if (ID_REAL_USERS(arm) > 1) {
#if 0
BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
return;
#endif
- tot_multiuser_arm_error++;
- }
- else {
- /* Function to recenter armatures in editarmature.c
- * Bone + object locations are handled there.
- */
- ED_armature_origin_set(bmain, ob, cursor, centermode, around);
+ tot_multiuser_arm_error++;
+ }
+ else {
+ /* Function to recenter armatures in editarmature.c
+ * Bone + object locations are handled there.
+ */
+ ED_armature_origin_set(bmain, ob, cursor, centermode, around);
- tot_change++;
- arm->id.tag |= LIB_TAG_DOIT;
- /* do_inverse_offset = true; */ /* docenter_armature() handles this */
+ tot_change++;
+ arm->id.tag |= LIB_TAG_DOIT;
+ /* do_inverse_offset = true; */ /* docenter_armature() handles this */
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- BKE_object_transform_copy(ob_eval, ob);
- BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
- BKE_object_where_is_calc(depsgraph, scene, ob_eval);
- BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_transform_copy(ob_eval, ob);
+ BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
+ BKE_object_where_is_calc(depsgraph, scene, ob_eval);
+ BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
- ignore_parent_tx(bmain, depsgraph, scene, ob);
+ ignore_parent_tx(bmain, depsgraph, scene, ob);
- if (obedit) {
- break;
- }
+ if (obedit) {
+ break;
}
}
- else if (ob->type == OB_MBALL) {
- MetaBall *mb = ob->data;
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else if (around == V3D_AROUND_CENTER_BOUNDS) {
- BKE_mball_center_bounds(mb, cent);
- }
- else { /* #V3D_AROUND_CENTER_MEDIAN. */
- BKE_mball_center_median(mb, cent);
- }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_BOUNDS) {
+ BKE_mball_center_bounds(mb, cent);
+ }
+ else { /* #V3D_AROUND_CENTER_MEDIAN. */
+ BKE_mball_center_median(mb, cent);
+ }
- negate_v3_v3(cent_neg, cent);
- BKE_mball_translate(mb, cent_neg);
+ negate_v3_v3(cent_neg, cent);
+ BKE_mball_translate(mb, cent_neg);
- tot_change++;
- mb->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
+ tot_change++;
+ mb->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
- if (obedit) {
- if (centermode == GEOMETRY_TO_ORIGIN) {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- break;
+ if (obedit) {
+ if (centermode == GEOMETRY_TO_ORIGIN) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
}
+ break;
}
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else if (around == V3D_AROUND_CENTER_BOUNDS) {
- BKE_lattice_center_bounds(lt, cent);
- }
- else { /* #V3D_AROUND_CENTER_MEDIAN. */
- BKE_lattice_center_median(lt, cent);
- }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_BOUNDS) {
+ BKE_lattice_center_bounds(lt, cent);
+ }
+ else { /* #V3D_AROUND_CENTER_MEDIAN. */
+ BKE_lattice_center_median(lt, cent);
+ }
- negate_v3_v3(cent_neg, cent);
- BKE_lattice_translate(lt, cent_neg, 1);
+ negate_v3_v3(cent_neg, cent);
+ BKE_lattice_translate(lt, cent_neg, 1);
- tot_change++;
- lt->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- float gpcenter[3];
- if (gpd) {
- if (centermode == ORIGIN_TO_GEOMETRY) {
- zero_v3(gpcenter);
- BKE_gpencil_centroid_3d(gpd, gpcenter);
- add_v3_v3(gpcenter, ob->obmat[3]);
- }
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(gpcenter, cursor);
- }
- if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) {
- bGPDspoint *pt;
- float imat[3][3], bmat[3][3];
- float offset_global[3];
- float offset_local[3];
- int i;
-
- sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
- copy_m3_m4(bmat, obact->obmat);
- invert_m3_m3(imat, bmat);
- mul_m3_v3(imat, offset_global);
- mul_v3_m3v3(offset_local, imat, offset_global);
-
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
-
- /* recalculate all strokes
- * (all layers are considered without evaluating lock attributes) */
- LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
- /* calculate difference matrix */
- BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
- /* undo matrix */
- invert_m4_m4(inverse_diff_mat, diff_mat);
- LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float mpt[3];
- mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
- sub_v3_v3(mpt, offset_local);
- mul_v3_m4v3(&pt->x, diff_mat, mpt);
- }
+ tot_change++;
+ lt->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ float gpcenter[3];
+ if (gpd) {
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ zero_v3(gpcenter);
+ BKE_gpencil_centroid_3d(gpd, gpcenter);
+ add_v3_v3(gpcenter, ob->obmat[3]);
+ }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(gpcenter, cursor);
+ }
+ if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) {
+ bGPDspoint *pt;
+ float imat[3][3], bmat[3][3];
+ float offset_global[3];
+ float offset_local[3];
+ int i;
+
+ sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
+ copy_m3_m4(bmat, obact->obmat);
+ invert_m3_m3(imat, bmat);
+ mul_m3_v3(imat, offset_global);
+ mul_v3_m3v3(offset_local, imat, offset_global);
+
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ /* recalculate all strokes
+ * (all layers are considered without evaluating lock attributes) */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* calculate difference matrix */
+ BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
+ /* undo matrix */
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float mpt[3];
+ mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
+ sub_v3_v3(mpt, offset_local);
+ mul_v3_m4v3(&pt->x, diff_mat, mpt);
}
}
}
- tot_change++;
- if (centermode == ORIGIN_TO_GEOMETRY) {
- copy_v3_v3(ob->loc, gpcenter);
- }
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- ob->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
}
- else {
- BKE_report(op->reports,
- RPT_WARNING,
- "Grease Pencil Object does not support this set origin option");
+ tot_change++;
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ copy_v3_v3(ob->loc, gpcenter);
}
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ ob->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Grease Pencil Object does not support this set origin option");
}
}
+ }
- /* offset other selected objects */
- if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
- float obmat[4][4];
+ /* offset other selected objects */
+ if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
+ float obmat[4][4];
- /* was the object data modified
- * note: the functions above must set 'cent' */
+ /* was the object data modified
+ * NOTE: the functions above must set 'cent'. */
- /* convert the offset to parent space */
- BKE_object_to_mat4(ob, obmat);
- mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
+ /* convert the offset to parent space */
+ BKE_object_to_mat4(ob, obmat);
+ mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
- add_v3_v3(ob->loc, centn);
+ add_v3_v3(ob->loc, centn);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- BKE_object_transform_copy(ob_eval, ob);
- BKE_object_where_is_calc(depsgraph, scene, ob_eval);
- if (ob->type == OB_ARMATURE) {
- /* needed for bone parents */
- BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
- BKE_pose_where_is(depsgraph, scene, ob_eval);
- }
-
- ignore_parent_tx(bmain, depsgraph, scene, ob);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_transform_copy(ob_eval, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob_eval);
+ if (ob->type == OB_ARMATURE) {
+ /* needed for bone parents */
+ BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
+ }
- /* other users? */
- // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
- //{
-
- /* use existing context looper */
- for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) {
- Object *ob_other = objects[other_object_index];
-
- if ((ob_other->flag & OB_DONE) == 0 &&
- ((ob->data && (ob->data == ob_other->data)) ||
- (ob->instance_collection == ob_other->instance_collection &&
- (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) {
- 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 */
- add_v3_v3(ob_other->loc, centn);
-
- Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
- BKE_object_transform_copy(ob_other_eval, ob_other);
- BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
- if (ob_other->type == OB_ARMATURE) {
- /* needed for bone parents */
- BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
- BKE_pose_where_is(depsgraph, scene, ob_other_eval);
- }
- ignore_parent_tx(bmain, depsgraph, scene, ob_other);
+ ignore_parent_tx(bmain, depsgraph, scene, ob);
+
+ /* other users? */
+ // CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
+ //{
+
+ /* use existing context looper */
+ for (int other_object_index = 0; other_object_index < num_objects; other_object_index++) {
+ Object *ob_other = objects[other_object_index];
+
+ if ((ob_other->flag & OB_DONE) == 0 &&
+ ((ob->data && (ob->data == ob_other->data)) ||
+ (ob->instance_collection == ob_other->instance_collection &&
+ (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) {
+ 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 */
+ add_v3_v3(ob_other->loc, centn);
+
+ Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
+ BKE_object_transform_copy(ob_other_eval, ob_other);
+ BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
+ if (ob_other->type == OB_ARMATURE) {
+ /* needed for bone parents */
+ BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
+ BKE_pose_where_is(depsgraph, scene, ob_other_eval);
}
+ ignore_parent_tx(bmain, depsgraph, scene, ob_other);
}
- // CTX_DATA_END;
}
+ // CTX_DATA_END;
}
}
MEM_freeN(objects);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index e6cde60e9aa..f64f95c5322 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -130,7 +130,7 @@ bool ED_vgroup_sync_from_pose(Object *ob)
if (arm->act_bone) {
int def_num = BKE_object_defgroup_name_index(ob, arm->act_bone->name);
if (def_num != -1) {
- ob->actdef = def_num + 1;
+ BKE_object_defgroup_active_index_set(ob, def_num + 1);
return true;
}
}
@@ -389,11 +389,16 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
int dvert_tot_from;
int dvert_tot;
int i;
- int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
- int defbase_tot = BLI_listbase_count(&ob->defbase);
+ ListBase *defbase_dst = BKE_object_defgroup_list_mutable(ob);
+ const ListBase *defbase_src = BKE_object_defgroup_list(ob_from);
+
+ int defbase_tot_from = BLI_listbase_count(defbase_src);
+ int defbase_tot = BLI_listbase_count(defbase_dst);
bool new_vgroup = false;
- if (ob == ob_from) {
+ BLI_assert(ob != ob_from);
+
+ if (ob->data == ob_from->data) {
return true;
}
@@ -429,9 +434,9 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
}
/* do the copy */
- BLI_freelistN(&ob->defbase);
- BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
- ob->actdef = ob_from->actdef;
+ BLI_freelistN(defbase_dst);
+ BLI_duplicatelist(defbase_dst, defbase_src);
+ BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_active_index_get(ob_from));
if (defbase_tot_from < defbase_tot) {
/* correct vgroup indices because the number of vgroups is being reduced. */
@@ -509,7 +514,7 @@ void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array,
}
}
-/* TODO, cache flip data to speedup calls within a loop. */
+/* TODO: cache flip data to speedup calls within a loop. */
static void mesh_defvert_mirror_update_internal(Object *ob,
MDeformVert *dvert_dst,
MDeformVert *dvert_src,
@@ -882,7 +887,8 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight,
/* add the vert to the deform group with the
* specified assign mode
*/
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const int def_nr = BLI_findindex(defbase, dg);
MDeformVert *dv = NULL;
int tot;
@@ -913,7 +919,8 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
/* TODO(campbell): This is slow in a loop, better pass def_nr directly,
* but leave for later. */
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const int def_nr = BLI_findindex(defbase, dg);
if (def_nr != -1) {
MDeformVert *dvert = NULL;
@@ -989,7 +996,8 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
{
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const int def_nr = BLI_findindex(defbase, dg);
if (def_nr == -1) {
return -1;
@@ -1000,9 +1008,9 @@ float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
void ED_vgroup_select_by_name(Object *ob, const char *name)
{
- /* note: ob->actdef==0 signals on painting to create a new one,
+ /* NOTE: actdef==0 signals on painting to create a new one,
* if a bone in posemode is selected */
- ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1;
+ BKE_object_defgroup_active_index_set(ob, BKE_object_defgroup_name_index(ob, name) + 1);
}
/** \} */
@@ -1014,9 +1022,10 @@ void ED_vgroup_select_by_name(Object *ob, const char *name)
/* only in editmode */
static void vgroup_select_verts(Object *ob, int select)
{
- const int def_nr = ob->actdef - 1;
+ const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ if (!BLI_findlink(defbase, def_nr)) {
return;
}
@@ -1111,7 +1120,9 @@ static void vgroup_duplicate(Object *ob)
MDeformVert **dvert_array = NULL;
int i, idg, icdg, dvert_tot = 0;
- dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
+ dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1);
if (!dg) {
return;
}
@@ -1127,13 +1138,13 @@ static void vgroup_duplicate(Object *ob)
BLI_strncpy(cdg->name, name, sizeof(cdg->name));
BKE_object_defgroup_unique_name(cdg, ob);
- BLI_addtail(&ob->defbase, cdg);
+ BLI_addtail(defbase, cdg);
- idg = (ob->actdef - 1);
- ob->actdef = BLI_listbase_count(&ob->defbase);
- icdg = (ob->actdef - 1);
+ idg = BKE_object_defgroup_active_index_get(ob) - 1;
+ BKE_object_defgroup_active_index_set(ob, BLI_listbase_count(defbase));
+ icdg = BKE_object_defgroup_active_index_get(ob) - 1;
- /* TODO, we might want to allow only copy selected verts here? - campbell */
+ /* TODO(campbell): we might want to allow only copy selected verts here? */
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
if (dvert_array) {
@@ -1157,11 +1168,12 @@ static bool vgroup_normalize(Object *ob)
MDeformWeight *dw;
MDeformVert *dv, **dvert_array = NULL;
int dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
+ const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ if (!BLI_findlink(defbase, def_nr)) {
return false;
}
@@ -1639,7 +1651,7 @@ static bool vgroup_normalize_all(Object *ob,
{
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
+ const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
const bool use_vert_sel = vertex_group_use_vert_sel(ob);
@@ -1651,7 +1663,8 @@ static bool vgroup_normalize_all(Object *ob,
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const int defbase_tot = BLI_listbase_count(defbase);
bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
bool changed = false;
@@ -1742,7 +1755,7 @@ static const EnumPropertyItem vgroup_lock_mask[] = {
static bool *vgroup_selected_get(Object *ob)
{
- int sel_count = 0, defbase_tot = BLI_listbase_count(&ob->defbase);
+ int sel_count = 0, defbase_tot = BKE_object_defgroup_count(ob);
bool *mask;
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
@@ -1759,8 +1772,9 @@ static bool *vgroup_selected_get(Object *ob)
mask = MEM_callocN(defbase_tot * sizeof(bool), __func__);
}
- if (sel_count == 0 && ob->actdef >= 1 && ob->actdef <= defbase_tot) {
- mask[ob->actdef - 1] = true;
+ const int actdef = BKE_object_defgroup_active_index_get(ob);
+ if (sel_count == 0 && actdef >= 1 && actdef <= defbase_tot) {
+ mask[actdef - 1] = true;
}
return mask;
@@ -1775,11 +1789,12 @@ static void vgroup_lock_all(Object *ob, int action, int mask)
if (mask != VGROUP_MASK_ALL) {
selected = vgroup_selected_get(ob);
}
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
if (action == VGROUP_TOGGLE) {
action = VGROUP_LOCK;
- for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
+ for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) {
switch (mask) {
case VGROUP_MASK_INVERT_UNSELECTED:
case VGROUP_MASK_SELECTED:
@@ -1802,7 +1817,7 @@ static void vgroup_lock_all(Object *ob, int action, int mask)
}
}
- for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
+ for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) {
switch (mask) {
case VGROUP_MASK_SELECTED:
if (!selected[i]) {
@@ -2352,8 +2367,8 @@ static void dvert_mirror_op(MDeformVert *dvert,
}
}
-/* TODO, vgroup locking */
-/* TODO, face masking */
+/* TODO: vgroup locking. */
+/* TODO: face masking. */
void ED_vgroup_mirror(Object *ob,
const bool mirror_weights,
const bool flip_vgroups,
@@ -2379,13 +2394,15 @@ void ED_vgroup_mirror(Object *ob,
MDeformVert *dvert, *dvert_mirr;
char sel, sel_mirr;
int *flip_map = NULL, flip_map_len;
- const int def_nr = ob->actdef - 1;
+ const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
int totmirr = 0, totfail = 0;
*r_totmirr = *r_totfail = 0;
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
if ((mirror_weights == false && flip_vgroups == false) ||
- (BLI_findlink(&ob->defbase, def_nr) == NULL)) {
+ (BLI_findlink(defbase, def_nr) == NULL)) {
return;
}
@@ -2569,7 +2586,8 @@ cleanup:
static void vgroup_delete_active(Object *ob)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1);
if (!dg) {
return;
}
@@ -2580,9 +2598,10 @@ static void vgroup_delete_active(Object *ob)
/* only in editmode */
static void vgroup_assign_verts(Object *ob, const float weight)
{
- const int def_nr = ob->actdef - 1;
+ const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
- if (!BLI_findlink(&ob->defbase, def_nr)) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ if (!BLI_findlink(defbase, def_nr)) {
return;
}
@@ -2700,7 +2719,8 @@ static bool vertex_group_poll_ex(bContext *C, Object *ob)
return false;
}
- if (BLI_listbase_is_empty(&ob->defbase)) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ if (BLI_listbase_is_empty(defbase)) {
CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups");
return false;
}
@@ -2823,8 +2843,10 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C)
return false;
}
- if (ob->actdef != 0) {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ const int def_nr = BKE_object_defgroup_active_index_get(ob);
+ if (def_nr != 0) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const bDeformGroup *dg = BLI_findlink(defbase, def_nr - 1);
if (dg) {
return !(dg->flag & DG_LOCK_WEIGHT);
}
@@ -3025,8 +3047,8 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
}
}
else {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
-
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1);
if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
return OPERATOR_CANCELLED;
}
@@ -3774,7 +3796,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
- /* note, would normally return canceled, except we want the redo
+ /* NOTE: would normally return canceled, except we want the redo
* UI to show up for users to change */
return OPERATOR_FINISHED;
}
@@ -3860,55 +3882,6 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Vertex Group Copy to Linked Operator
- * \{ */
-
-static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob_active = ED_object_context(C);
- int retval = OPERATOR_CANCELLED;
-
- FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
- if (ob_iter->type == ob_active->type) {
- if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
- BLI_freelistN(&ob_iter->defbase);
- BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
- ob_iter->actdef = ob_active->actdef;
-
- DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
-
- retval = OPERATOR_FINISHED;
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- return retval;
-}
-
-void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Copy Vertex Groups to Linked";
- ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
- ot->description =
- "Replace vertex groups of all users of the same geometry data by vertex groups of active "
- "object";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_to_linked_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Vertex Group Copy to Selected Operator
* \{ */
@@ -3919,7 +3892,7 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
int fail = 0;
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
- if (obact != ob) {
+ if (obact != ob && BKE_object_supports_vertex_groups(ob)) {
if (ED_vgroup_array_copy(ob, obact)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
DEG_relations_tag_update(CTX_data_main(C));
@@ -3936,8 +3909,8 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
if ((changed_tot == 0 && fail == 0) || fail) {
BKE_reportf(op->reports,
RPT_ERROR,
- "Copy vertex groups to selected: %d done, %d failed (object data must have "
- "matching indices)",
+ "Copy vertex groups to selected: %d done, %d failed (object data must support "
+ "vertex groups and have matching indices)",
changed_tot,
fail);
}
@@ -3972,7 +3945,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op)
int nr = RNA_enum_get(op->ptr, "group");
BLI_assert(nr + 1 >= 0);
- ob->actdef = nr + 1;
+ BKE_object_defgroup_active_index_set(ob, nr + 1);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
@@ -3999,7 +3972,8 @@ static const EnumPropertyItem *vgroup_itemf(bContext *C,
return DummyRNA_NULL_items;
}
- for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ for (a = 0, def = defbase->first; def; def = def->next, a++) {
tmp.value = a;
tmp.icon = ICON_GROUP_VERTEX;
tmp.identifier = def->name;
@@ -4048,13 +4022,13 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
* with the order of vgroups then call vgroup_do_remap after */
static char *vgroup_init_remap(Object *ob)
{
- bDeformGroup *def;
- int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ int defbase_tot = BLI_listbase_count(defbase);
char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
char *name;
name = name_array;
- for (def = ob->defbase.first; def; def = def->next) {
+ for (const bDeformGroup *def = defbase->first; def; def = def->next) {
BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
name += MAX_VGROUP_NAME;
}
@@ -4065,8 +4039,9 @@ static char *vgroup_init_remap(Object *ob)
static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
{
MDeformVert *dvert = NULL;
- bDeformGroup *def;
- int defbase_tot = BLI_listbase_count(&ob->defbase);
+ const bDeformGroup *def;
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ int defbase_tot = BLI_listbase_count(defbase);
/* Needs a dummy index at the start. */
int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
@@ -4076,8 +4051,8 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
int i;
name = name_array;
- for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
- sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
+ for (def = defbase->first, i = 0; def; def = def->next, i++) {
+ sort_map[i] = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name));
name += MAX_VGROUP_NAME;
BLI_assert(sort_map[i] != -1);
@@ -4130,8 +4105,9 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
sort_map_update[0] = 0;
BKE_object_defgroup_remap_update_users(ob, sort_map_update);
- BLI_assert(sort_map_update[ob->actdef] >= 0);
- ob->actdef = sort_map_update[ob->actdef];
+ BLI_assert(sort_map_update[BKE_object_defgroup_active_index_get(ob)] >= 0);
+ BKE_object_defgroup_active_index_set(ob,
+ sort_map_update[BKE_object_defgroup_active_index_get(ob)]);
MEM_freeN(sort_map_update);
@@ -4159,6 +4135,7 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
bonebase = &armature->bonebase;
}
}
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
if (bonebase != NULL) {
Bone *bone;
@@ -4167,8 +4144,8 @@ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
vgroup_sort_bone_hierarchy(ob, &bone->childbase);
if (dg != NULL) {
- BLI_remlink(&ob->defbase, dg);
- BLI_addhead(&ob->defbase, dg);
+ BLI_remlink(defbase, dg);
+ BLI_addhead(defbase, dg);
}
}
}
@@ -4189,10 +4166,12 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op)
/* Init remapping. */
name_array = vgroup_init_remap(ob);
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
/* Sort vgroup names. */
switch (sort_type) {
case SORT_TYPE_NAME:
- BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
+ BLI_listbase_sort(defbase, vgroup_sort_name);
break;
case SORT_TYPE_BONEHIERARCHY:
vgroup_sort_bone_hierarchy(ob, NULL);
@@ -4250,14 +4229,16 @@ static int vgroup_move_exec(bContext *C, wmOperator *op)
int dir = RNA_enum_get(op->ptr, "direction");
int ret = OPERATOR_FINISHED;
- def = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
+ def = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1);
if (!def) {
return OPERATOR_CANCELLED;
}
name_array = vgroup_init_remap(ob);
- if (BLI_listbase_link_move(&ob->defbase, def, dir)) {
+ if (BLI_listbase_link_move(defbase, def, dir)) {
ret = vgroup_do_remap(ob, name_array, op);
if (ret != OPERATOR_CANCELLED) {
@@ -4376,7 +4357,8 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *dg = BLI_findlink(defbase, def_nr);
if (!dg) {
BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index");
@@ -4498,7 +4480,7 @@ static int vertex_weight_set_active_exec(bContext *C, wmOperator *op)
const int wg_index = RNA_int_get(op->ptr, "weight_group");
if (wg_index != -1) {
- ob->actdef = wg_index + 1;
+ BKE_object_defgroup_active_index_set(ob, wg_index + 1);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 3f15d572cdd..f2bbd6d5084 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -300,7 +300,7 @@ static void pe_update_hair_particle_edit_pointers(PTCacheEdit *edit)
/* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set
*
- * note: this function runs on poll, therefore it can runs many times a second
+ * NOTE: this function runs on poll, therefore it can runs many times a second
* keep it fast! */
static PTCacheEdit *pe_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob, bool create)
{
@@ -537,7 +537,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob);
- Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval);
+ const Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval);
memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
@@ -631,7 +631,7 @@ static bool key_inside_circle(const PEData *data, float rad, const float co[3],
float dx, dy, dist;
int screen_co[2];
- /* TODO, should this check V3D_PROJ_TEST_CLIP_BB too? */
+ /* TODO: should this check V3D_PROJ_TEST_CLIP_BB too? */
if (ED_view3d_project_int_global(data->vc.region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) !=
V3D_PROJ_RET_OK) {
return 0;
@@ -5444,7 +5444,7 @@ void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, O
edit = PE_create_current(depsgraph, scene, ob);
/* Mesh may have changed since last entering editmode.
- * note, this may have run before if the edit data was just created,
+ * NOTE: this may have run before if the edit data was just created,
* so could avoid this and speed up a little. */
if (edit && edit->psys) {
/* Make sure pointer to the evaluated modifier data is up to date,
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 6bcc9df16bf..387d10d538b 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -848,7 +848,8 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
copy_m4_m4(imat, target_ob->obmat);
}
else {
- /* note: using target_dm here, which is in target_ob object space and has full modifiers */
+ /* NOTE: using target_dm here, which is in target_ob object space and has full modifiers.
+ */
psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat);
invert_m4_m4(imat, hairmat);
}
@@ -1160,7 +1161,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
}
MEM_freeN(tmp_psys);
- /* note: do this after creating DM copies for all the particle system modifiers,
+ /* NOTE: do this after creating DM copies for all the particle system modifiers,
* the remapping otherwise makes final_dm invalid!
*/
for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; psys;
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index d39570857ab..d5ad5a5eb84 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -121,7 +121,7 @@ static bool image_buffer_calc_tile_rect(const RenderResult *rr,
{
int tile_y, tile_height, tile_x, tile_width;
- /* if renrect argument, we only refresh scanlines */
+ /* When `renrect` argument is not NULL, we only refresh scan-lines. */
if (renrect) {
/* if (tile_height == recty), rendering of layer is ready,
* we should not draw, other things happen... */
@@ -793,7 +793,7 @@ static int render_breakjob(void *rjv)
/**
* For exec() when there is no render job
- * note: this won't check for the escape key being pressed, but doing so isn't thread-safe.
+ * NOTE: this won't check for the escape key being pressed, but doing so isn't thread-safe.
*/
static int render_break(void *UNUSED(rjv))
{
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index f36ce7408b5..5aa63ac56d8 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -54,7 +54,9 @@
#include "DNA_space_types.h"
#include "DNA_world_types.h"
+#include "BKE_animsys.h"
#include "BKE_appdir.h"
+#include "BKE_armature.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -93,6 +95,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_armature.h"
#include "ED_datafiles.h"
#include "ED_render.h"
#include "ED_screen.h"
@@ -151,6 +154,10 @@ typedef struct IconPreview {
void *owner;
ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */
ListBase sizes;
+
+ /* May be NULL, is used for rendering IDs that require some other object for it to be applied on
+ * before the ID can be represented as an image, for example when rendering an Action. */
+ struct Object *active_object;
} IconPreview;
/** \} */
@@ -253,7 +260,7 @@ static const char *preview_collection_name(const char pr_type)
case MA_ATMOS:
return "Atmosphere";
default:
- BLI_assert(!"Unknown preview type");
+ BLI_assert_msg(0, "Unknown preview type");
return "";
}
}
@@ -335,7 +342,7 @@ static ID *duplicate_ids(ID *id, const bool allow_failure)
return NULL;
default:
if (!allow_failure) {
- BLI_assert(!"ID type preview not supported.");
+ BLI_assert_msg(0, "ID type preview not supported.");
}
return NULL;
}
@@ -794,7 +801,7 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview
NULL,
NULL,
err_out);
- /* TODO color-management? */
+ /* TODO: color-management? */
U.pixelsize = pixelsize_old;
@@ -813,9 +820,50 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview
/** \name Action Preview
* \{ */
-/* Render a pose. It is assumed that the pose has already been applied and that the scene camera is
- * capturing the pose. In other words, this function just renders from the scene camera without
- * evaluating the Action stored in preview->id. */
+static struct PoseBackup *action_preview_render_prepare(IconPreview *preview)
+{
+ Object *object = preview->active_object;
+ if (object == NULL) {
+ WM_report(RPT_WARNING, "No active object, unable to apply the Action before rendering");
+ return NULL;
+ }
+ if (object->pose == NULL) {
+ WM_reportf(RPT_WARNING,
+ "Object %s has no pose, unable to apply the Action before rendering",
+ object->id.name + 2);
+ return NULL;
+ }
+
+ /* Create a backup of the current pose. */
+ struct bAction *action = (struct bAction *)preview->id;
+ struct PoseBackup *pose_backup = ED_pose_backup_create_all_bones(object, action);
+
+ /* Apply the Action as pose, so that it can be rendered. This assumes the Action represents a
+ * single pose, and that thus the evaluation time doesn't matter. */
+ AnimationEvalContext anim_eval_context = {preview->depsgraph, 0.0f};
+ BKE_pose_apply_action_all_bones(object, action, &anim_eval_context);
+
+ /* Force evaluation of the new pose, before the preview is rendered. */
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ DEG_evaluate_on_refresh(preview->depsgraph);
+
+ return pose_backup;
+}
+
+static void action_preview_render_cleanup(IconPreview *preview, struct PoseBackup *pose_backup)
+{
+ if (pose_backup == NULL) {
+ return;
+ }
+ ED_pose_backup_restore(pose_backup);
+ ED_pose_backup_free(pose_backup);
+
+ DEG_id_tag_update(&preview->active_object->id, ID_RECALC_GEOMETRY);
+}
+
+/* Render a pose from the scene camera. It is assumed that the scene camera is
+ * capturing the pose. The pose is applied temporarily to the current object
+ * before rendering. */
static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
{
char err_out[256] = "";
@@ -827,6 +875,9 @@ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview
BLI_assert(depsgraph != NULL);
BLI_assert(preview->scene == DEG_get_input_scene(depsgraph));
+ /* Apply the pose before getting the evaluated scene, so that the new pose is evaluated. */
+ struct PoseBackup *pose_backup = action_preview_render_prepare(preview);
+
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *camera_eval = scene_eval->camera;
if (camera_eval == NULL) {
@@ -850,6 +901,8 @@ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview
NULL,
err_out);
+ action_preview_render_cleanup(preview, pose_backup);
+
if (err_out[0] != '\0') {
printf("Error rendering Action %s preview: %s\n", preview->id->name + 2, err_out);
}
@@ -1255,8 +1308,9 @@ static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
scaledy = (float)h;
}
- ex = (short)scaledx;
- ey = (short)scaledy;
+ /* Scaling down must never assign zero width/height, see: T89868. */
+ ex = MAX2(1, (short)scaledx);
+ ey = MAX2(1, (short)scaledy);
dx = (w - ex) / 2;
dy = (h - ey) / 2;
@@ -1469,7 +1523,7 @@ static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size,
}
}
- BLI_assert(!"The searched icon size does not match any in the preview image");
+ BLI_assert_msg(0, "The searched icon size does not match any in the preview image");
return -1;
}
@@ -1625,6 +1679,7 @@ void ED_preview_icon_render(
/* Control isn't given back to the caller until the preview is done. So we don't need to copy
* the ID to avoid thread races. */
ip.id_copy = duplicate_ids(id, true);
+ ip.active_object = CTX_data_active_object(C);
icon_preview_add_size(&ip, rect, sizex, sizey);
@@ -1666,6 +1721,7 @@ void ED_preview_icon_job(
ip->bmain = CTX_data_main(C);
ip->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ip->scene = DEG_get_input_scene(ip->depsgraph);
+ ip->active_object = CTX_data_active_object(C);
ip->owner = owner;
ip->id = id;
ip->id_copy = duplicate_ids(id, false);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index ae9f80f746a..d2b1ebdad78 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -294,7 +294,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
}
else {
/* Find the first matching material.
- * Note: there may be multiple but that's not a common use case. */
+ * NOTE: there may be multiple but that's not a common use case. */
for (int i = 0; i < ob->totcol; i++) {
const Material *mat = BKE_object_material_get(ob, i + 1);
if (mat_active == mat) {
@@ -401,7 +401,7 @@ static int material_slot_de_select(bContext *C, bool select)
}
else {
/* Find the first matching material.
- * Note: there may be multiple but that's not a common use case. */
+ * NOTE: there may be multiple but that's not a common use case. */
for (int i = 0; i < ob->totcol; i++) {
const Material *mat = BKE_object_material_get(ob, i + 1);
if (mat_active == mat) {
@@ -1183,7 +1183,7 @@ static int light_cache_bake_exec(bContext *C, wmOperator *op)
G.is_break = false;
- /* TODO abort if selected engine is not eevee. */
+ /* TODO: abort if selected engine is not eevee. */
void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra);
light_cache_bake_tag_cache(scene, op);
@@ -2418,7 +2418,7 @@ static void paste_mtex_copybuf(ID *id)
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
default:
- BLI_assert(!"invalid id type");
+ BLI_assert_msg(0, "invalid id type");
return;
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 175efc5387b..c351ade9954 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -161,6 +161,12 @@ void ED_region_do_listen(wmRegionListenerParams *params)
if (region->type && region->type->listener) {
region->type->listener(params);
}
+
+ LISTBASE_FOREACH (uiList *, list, &region->ui_lists) {
+ if (list->type && list->type->listener) {
+ list->type->listener(list, params);
+ }
+ }
}
/* only exported for WM */
@@ -1539,8 +1545,8 @@ static void region_rect_recursive(
region->winx = BLI_rcti_size_x(&region->winrct) + 1;
region->winy = BLI_rcti_size_y(&region->winrct) + 1;
- /* if region opened normally, we store this for hide/reveal usage */
- /* prevent rounding errors for UI_DPI_FAC mult and divide */
+ /* If region opened normally, we store this for hide/reveal usage. */
+ /* Prevent rounding errors for UI_DPI_FAC multiply and divide. */
if (region->winx > 1) {
region->sizex = (region->winx + 0.5f) / UI_DPI_FAC;
}
@@ -1680,7 +1686,7 @@ static void ed_default_handlers(
{
BLI_assert(region ? (&region->handlers == handlers) : (&area->handlers == handlers));
- /* note, add-handler checks if it already exists */
+ /* NOTE: add-handler checks if it already exists. */
/* XXX it would be good to have boundbox checks for some of these... */
if (flag & ED_KEYMAP_UI) {
@@ -2081,7 +2087,7 @@ void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free)
}
BKE_spacedata_copylist(&area_dst->spacedata, &area_src->spacedata);
- /* Note; SPACE_EMPTY is possible on new screens */
+ /* NOTE: SPACE_EMPTY is possible on new screens. */
/* regions */
if (do_free) {
@@ -3018,6 +3024,8 @@ void ED_region_panels_layout_ex(const bContext *C,
y = -y;
}
+ UI_blocklist_update_view_for_buttons(C, &region->uiblocks);
+
if (update_tot_size) {
/* this also changes the 'cur' */
UI_view2d_totRect_set(v2d, x, y);
@@ -3672,7 +3680,7 @@ static void region_visible_rect_calc(ARegion *region, rcti *rect)
/* Skip floating. */
}
else {
- BLI_assert(!"Region overlap with unknown alignment");
+ BLI_assert_msg(0, "Region overlap with unknown alignment");
}
}
}
diff --git a/source/blender/editors/screen/area_query.c b/source/blender/editors/screen/area_query.c
index d569e56e11b..fd4f3964398 100644
--- a/source/blender/editors/screen/area_query.c
+++ b/source/blender/editors/screen/area_query.c
@@ -88,7 +88,7 @@ bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_re
r_region_gutter->xmin = r_region_gutter->xmax - category_tabs_width;
}
else {
- BLI_assert(!"Unsupported alignment");
+ BLI_assert_msg(0, "Unsupported alignment");
}
return true;
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index e366760a55d..f651fd4fb61 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -126,7 +126,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
components = 1;
}
else {
- BLI_assert(!"Incompatible format passed to immDrawPixels");
+ BLI_assert_msg(0, "Incompatible format passed to immDrawPixels");
return;
}
@@ -426,7 +426,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf,
format = GPU_RGBA16F;
}
else {
- BLI_assert(!"Incompatible number of channels for GLSL display");
+ BLI_assert_msg(0, "Incompatible number of channels for GLSL display");
}
if (format != 0) {
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 45cf1775ccb..3ce2f326dca 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -36,6 +36,7 @@
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
@@ -111,6 +112,8 @@ const char *screen_context_dir[] = {
"selected_editable_fcurves",
"active_editable_fcurve",
"selected_editable_keyframes",
+ "ui_list",
+ "asset_library",
NULL,
};
@@ -896,11 +899,11 @@ static eContextResult screen_ctx_active_operator(const bContext *C, bContextData
/* do nothing */
}
else {
- /* note, this checks poll, could be a problem, but this also
+ /* NOTE: this checks poll, could be a problem, but this also
* happens for the toolbar */
op = WM_operator_last_redo(C);
}
- /* TODO, get the operator from popup's */
+ /* TODO: get the operator from popup's. */
if (op && op->ptr) {
CTX_data_pointer_set(result, NULL, &RNA_Operator, op);
@@ -1024,6 +1027,23 @@ static eContextResult screen_ctx_selected_editable_keyframes(const bContext *C,
return CTX_RESULT_NO_DATA;
}
+static eContextResult screen_ctx_asset_library(const bContext *C, bContextDataResult *result)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ CTX_data_pointer_set(
+ result, &workspace->id, &RNA_AssetLibraryReference, &workspace->active_asset_library);
+ return CTX_RESULT_OK;
+}
+
+static eContextResult screen_ctx_ui_list(const bContext *C, bContextDataResult *result)
+{
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *region = CTX_wm_region(C);
+ uiList *list = UI_list_find_mouse_over(region, win->eventstate);
+ CTX_data_pointer_set(result, NULL, &RNA_UIList, list);
+ return CTX_RESULT_OK;
+}
+
/* Registry of context callback functions. */
typedef eContextResult (*context_callback)(const bContext *C, bContextDataResult *result);
@@ -1098,6 +1118,8 @@ static void ensure_ed_screen_context_functions(void)
register_context_function("selected_visible_fcurves", screen_ctx_selected_visible_fcurves);
register_context_function("active_editable_fcurve", screen_ctx_active_editable_fcurve);
register_context_function("selected_editable_keyframes", screen_ctx_selected_editable_keyframes);
+ register_context_function("asset_library", screen_ctx_asset_library);
+ register_context_function("ui_list", screen_ctx_ui_list);
}
/* Entry point for the screen context. */
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index e2d95035ba8..2a81fcfde8f 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -125,9 +125,9 @@ ScrArea *area_split(const wmWindow *win,
return NULL;
}
- /* note regarding (fac > 0.5f) checks below.
+ /* NOTE(campbell): regarding (fac > 0.5f) checks below.
* normally it shouldn't matter which is used since the copy should match the original
- * however with viewport rendering and python console this isn't the case. - campbell */
+ * however with viewport rendering and python console this isn't the case. */
if (dir_axis == SCREEN_AXIS_H) {
/* new vertices */
@@ -1683,7 +1683,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
sad->region = CTX_wm_region(C);
/* If start-frame is larger than current frame, we put current-frame on start-frame.
- * note: first frame then is not drawn! (ton) */
+ * NOTE(ton): first frame then is not drawn! */
if (PRVRANGEON) {
if (scene->r.psfra > scene->r.cfra) {
sad->sfra = scene->r.cfra;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 159b649ec71..ffeaf514642 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -2792,9 +2792,9 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
CLAMP(rmd->region->sizey, 0, rmd->maxsize);
- /* note, 'UI_UNIT_Y/4' means you need to drag the footer and execute region
+ /* NOTE: `UI_UNIT_Y / 4` means you need to drag the footer and execute region
* almost all the way down for it to become hidden, this is done
- * otherwise its too easy to do this by accident */
+ * otherwise its too easy to do this by accident. */
if (size_no_snap < (UI_UNIT_Y / 4) / aspect) {
rmd->region->sizey = rmd->origval;
if (!(rmd->region->flag & RGN_FLAG_HIDDEN)) {
@@ -5219,7 +5219,7 @@ static void SCREEN_OT_delete(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Region Alpha Blending Operator
*
- * Implementation note: a disappearing region needs at least 1 last draw with
+ * Implementation NOTE: a disappearing region needs at least 1 last draw with
* 100% back-buffer texture over it - then triple buffer will clear it entirely.
* This because flag #RGN_FLAG_HIDDEN is set in end - region doesn't draw at all then.
*
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 324fd5d3075..39d776e0054 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -176,7 +176,7 @@ void imapaint_image_update(
ibuf->userflags |= IB_MIPMAP_INVALID;
}
- /* todo: should set_tpage create ->rect? */
+ /* TODO: should set_tpage create ->rect? */
if (texpaint || (sima && sima->lock)) {
int w = imapaintpartial.x2 - imapaintpartial.x1;
int h = imapaintpartial.y2 - imapaintpartial.y1;
@@ -681,7 +681,7 @@ static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mou
{
PaintOperation *pop;
- /* TODO Should avoid putting this here. Instead, last position should be requested
+ /* TODO: Should avoid putting this here. Instead, last position should be requested
* from stroke system. */
if (!(pop = texture_paint_init(C, op, mouse))) {
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 392f39bbb94..23b90171a1d 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -784,11 +784,10 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
bool do_random = false;
bool do_partial_update = false;
- bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) &&
- ((ELEM(brush->gradient_stroke_mode,
- BRUSH_GRADIENT_SPACING_REPEAT,
- BRUSH_GRADIENT_SPACING_CLAMP)) ||
- (cache->last_pressure != pressure)));
+ bool update_color = ((brush->flag & BRUSH_USE_GRADIENT) && (ELEM(brush->gradient_stroke_mode,
+ BRUSH_GRADIENT_SPACING_REPEAT,
+ BRUSH_GRADIENT_SPACING_CLAMP) ||
+ (cache->last_pressure != pressure)));
float tex_rotation = -brush->mtex.rot;
float mask_rotation = -brush->mask_mtex.rot;
@@ -1248,7 +1247,7 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short paint
static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, const int *pos)
{
- /* note: allocImbuf returns zero'd memory, so regions outside image will
+ /* NOTE: allocImbuf returns zero'd memory, so regions outside image will
* have zero alpha, and hence not be blended onto the image */
int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 2437e0d1939..bd05d309421 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -930,7 +930,7 @@ static bool project_bucket_point_occluded(const ProjPaintState *ps,
}
if (isect_ret >= 1) {
- /* TODO - we may want to cache the first hit,
+ /* TODO: we may want to cache the first hit,
* it is not possible to swap the face order in the list anymore */
return true;
}
@@ -1661,7 +1661,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
const float *lt_other_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other)};
- /* BKE_image_acquire_ibuf - TODO - this may be slow */
+ /* #BKE_image_acquire_ibuf - TODO: this may be slow. */
uchar rgba_ub[4];
float rgba_f[4];
@@ -1768,7 +1768,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
angle_cos = dot_v3v3(viewDirPersp, no);
}
- /* If backface culling is disabled, allow painting on back faces. */
+ /* If back-face culling is disabled, allow painting on back faces. */
if (!ps->do_backfacecull) {
angle_cos = fabsf(angle_cos);
}
@@ -1959,7 +1959,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
const float *lt_other_tri_uv[3] = {
PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)};
- /* BKE_image_acquire_ibuf - TODO - this may be slow */
+ /* #BKE_image_acquire_ibuf - TODO: this may be slow. */
if (ibuf->rect_float) {
if (ibuf_other->rect_float) { /* from float to float */
@@ -2052,7 +2052,7 @@ static bool line_clip_rect2f(const rctf *cliprect,
float l2_clip[2])
{
/* first account for horizontal, then vertical lines */
- /* horiz */
+ /* Horizontal. */
if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
/* is the line out of range on its Y axis? */
if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
@@ -3160,7 +3160,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
//#endif
}
-#if 0 /* TODO - investigate why this doesn't work sometimes! it should! */
+#if 0 /* TODO: investigate why this doesn't work sometimes! it should! */
/* no intersection for this entire row,
* after some intersection above means we can quit now */
if (has_x_isect == 0 && has_isect) {
@@ -3401,7 +3401,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
}
}
-# if 0 /* TODO - investigate why this doesn't work sometimes! it should! */
+# if 0 /* TODO: investigate why this doesn't work sometimes! it should! */
/* no intersection for this entire row,
* after some intersection above means we can quit now */
if (has_x_isect == 0 && has_isect) {
@@ -3432,8 +3432,8 @@ static void project_paint_bucket_bounds(const ProjPaintState *ps,
{
/* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
- /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f
- * is always truncated to 1, is this really correct?? - jwilkins */
+ /* XXX(jwilkins ): the offset of 0.5 is always truncated to zero and the offset of 1.5f
+ * is always truncated to 1, is this really correct? */
/* these offsets of 0.5 and 1.5 seem odd but they are correct */
bucketMin[0] =
@@ -3553,18 +3553,18 @@ static void project_bucket_init(const ProjPaintState *ps,
ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
}
-/* We want to know if a bucket and a face overlap in screen-space
+/* We want to know if a bucket and a face overlap in screen-space.
*
- * Note, if this ever returns false positives its not that bad, since a face in the bounding area
+ * NOTE: if this ever returns false positives its not that bad, since a face in the bounding area
* will have its pixels calculated when it might not be needed later, (at the moment at least)
- * obviously it shouldn't have bugs though */
+ * obviously it shouldn't have bugs though. */
static bool project_bucket_face_isect(ProjPaintState *ps,
int bucket_x,
int bucket_y,
const MLoopTri *lt)
{
- /* TODO - replace this with a trickier method that uses side-of-line for all
+ /* TODO: replace this with a trickier method that uses side-of-line for all
* #ProjPaintState.screenCoords edges against the closest bucket corner. */
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
rctf bucket_bounds;
@@ -3611,7 +3611,7 @@ static bool project_bucket_face_isect(ProjPaintState *ps,
}
/* Add faces to the bucket but don't initialize its pixels
- * TODO - when painting occluded, sort the faces on their min-Z
+ * TODO: when painting occluded, sort the faces on their min-Z
* and only add faces that faces that are not occluded */
static void project_paint_delayed_face_init(ProjPaintState *ps,
const MLoopTri *lt,
@@ -3824,7 +3824,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
}
else {
- /* TODO - deal with cases where 1 side of a face goes behind the view ?
+ /* TODO: deal with cases where 1 side of a face goes behind the view ?
*
* After some research this is actually very tricky, only option is to
* clip the derived mesh before painting, which is a Pain */
@@ -4358,7 +4358,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
#endif // PROJ_DEBUG_WINCLIP
- /* backface culls individual triangles but mask normal will use polygon */
+ /* Back-face culls individual triangles but mask normal will use polygon. */
if (ps->do_backfacecull) {
if (ps->do_mask_normal) {
if (prev_poly != lt->poly) {
@@ -4696,7 +4696,7 @@ static bool project_image_refresh_tagged(ProjPaintState *ps)
/* look over each bound cell */
for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
pr = &(projIma->partRedrawRect[i]);
- if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
+ if (pr->x2 != -1) { /* TODO: use 'enabled' ? */
set_imapaintpartial(pr);
imapaint_image_update(NULL, projIma->ima, projIma->ibuf, &projIma->iuser, true);
redraw = 1;
@@ -5393,7 +5393,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
samplecos[2] = 0.0f;
}
- /* note, for clone and smear,
+ /* 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);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index da34723eed4..d968b6cc319 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -293,8 +293,8 @@ typedef struct SculptGestureContext {
/* These store the view origin and normal in world space, which is used in some gestures to
* generate geometry aligned from the view directly in world space. */
/* World space view origin and normal are not affected by object symmetry when doing symmetry
- * passes, so there is no separate variables with the true_ prefix to store their original values
- * without symmetry modifications. */
+ * passes, so there is no separate variables with the `true_` prefix to store their original
+ * values without symmetry modifications. */
float world_space_view_origin[3];
float world_space_view_normal[3];
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index e2b21145c2d..f08771292a8 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1307,7 +1307,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect);
WM_operatortype_append(BRUSH_OT_stencil_reset_transform);
- /* note, particle uses a different system, can be added with existing operators in wm.py */
+ /* NOTE: particle uses a different system, can be added with existing operators in `wm.py`. */
WM_operatortype_append(PAINT_OT_brush_select);
/* image */
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 2484f382ed4..709e04d807d 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -752,7 +752,7 @@ static int vert_select_ungrouped_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
Mesh *me = ob->data;
- if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) {
+ if (BLI_listbase_is_empty(&me->vertex_group_names) || (me->dvert == NULL)) {
BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index fe36d62b832..9387b84f437 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -179,7 +179,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev,
* (without evaluating modifiers) */
static bool vertex_paint_use_fast_update_check(Object *ob)
{
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
if (me_eval != NULL) {
Mesh *me = BKE_mesh_from_object(ob);
@@ -996,7 +996,7 @@ static void do_weight_paint_vertex_multi(
dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
if (curw == 0.0f) {
- /* note: no weight to assign to this vertex, could add all groups? */
+ /* NOTE: no weight to assign to this vertex, could add all groups? */
return;
}
@@ -1607,13 +1607,13 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
/* check if we are attempting to paint onto a locked vertex group,
* and other options disallow it from doing anything useful */
bDeformGroup *dg;
- dg = BLI_findlink(&ob->defbase, vgroup_index.active);
+ dg = BLI_findlink(&me->vertex_group_names, vgroup_index.active);
if (dg->flag & DG_LOCK_WEIGHT) {
BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting");
return false;
}
if (vgroup_index.mirror != -1) {
- dg = BLI_findlink(&ob->defbase, vgroup_index.mirror);
+ dg = BLI_findlink(&me->vertex_group_names, vgroup_index.mirror);
if (dg->flag & DG_LOCK_WEIGHT) {
BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting");
return false;
@@ -1622,7 +1622,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
}
/* check that multipaint groups are unlocked */
- defbase_tot = BLI_listbase_count(&ob->defbase);
+ defbase_tot = BLI_listbase_count(&me->vertex_group_names);
defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel);
if (ts->multipaint && defbase_tot_sel > 1) {
@@ -1636,7 +1636,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
for (i = 0; i < defbase_tot; i++) {
if (defbase_sel[i]) {
- dg = BLI_findlink(&ob->defbase, i);
+ dg = BLI_findlink(&me->vertex_group_names, i);
if (dg->flag & DG_LOCK_WEIGHT) {
BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting");
MEM_freeN(defbase_sel);
@@ -2025,7 +2025,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
const Brush *brush = data->brush;
const StrokeCache *cache = ss->cache;
- /* note: normally `BKE_brush_weight_get(scene, brush)` is used,
+ /* NOTE: normally `BKE_brush_weight_get(scene, brush)` is used,
* however in this case we calculate a new weight each time. */
const float paintweight = data->strength;
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
@@ -2046,7 +2046,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
/* Test to see if the vertex coordinates are within the spherical brush region. */
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* Note: grids are 1:1 with corners (aka loops).
+ /* NOTE: grids are 1:1 with corners (aka loops).
* For multires, take the vert whose loop corresponds to the current grid.
* Otherwise, take the current vert. */
const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
@@ -2498,7 +2498,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
for (i = 0; i < PSYS_TOT_VG; i++) {
- if (psys->vgroup[i] == ob->actdef) {
+ if (psys->vgroup[i] == BKE_object_defgroup_active_index_get(ob)) {
psys->recalc |= ID_RECALC_PSYS_RESET;
break;
}
@@ -2885,7 +2885,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
/* Test to see if the vertex coordinates are within the spherical brush region. */
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- /* Note: Grids are 1:1 with corners (aka loops).
+ /* NOTE: Grids are 1:1 with corners (aka loops).
* For grid based pbvh, take the vert whose loop corresponds to the current grid.
* Otherwise, take the current vert. */
const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
@@ -2912,7 +2912,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
/* If we're painting with a texture, sample the texture color and alpha. */
float tex_alpha = 1.0;
if (data->vpd->is_texbrush) {
- /* Note: we may want to paint alpha as vertex color alpha. */
+ /* NOTE: we may want to paint alpha as vertex color alpha. */
tex_alpha = tex_color_alpha_ubyte(
data, data->vpd->vertexcosnos[v_index].co, &color_final);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
index 96d22fe4a21..9f023dd6e63 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -149,7 +149,7 @@ static bool vertex_paint_from_weight(Object *ob)
/* TODO: respect selection. */
/* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway. */
mp = me->mpoly;
- vgroup_active = ob->actdef - 1;
+ vgroup_active = me->vertex_group_active_index - 1;
for (int i = 0; i < me->totpoly; i++, mp++) {
MLoopCol *lcol = &me->mloopcol[mp->loopstart];
uint j = 0;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 7991987ae1f..cb8dc838422 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -183,7 +183,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
ED_view3d_viewcontext_init(C, &vc, depsgraph);
me = BKE_mesh_from_object(vc.obact);
- if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) {
+ if (me && me->dvert && vc.v3d && vc.rv3d && (me->vertex_group_active_index != 0)) {
const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int v_idx_best = -1;
uint index;
@@ -213,9 +213,9 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
if (v_idx_best != -1) { /* should always be valid */
ToolSettings *ts = vc.scene->toolsettings;
Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
- const int vgroup_active = vc.obact->actdef - 1;
+ const int vgroup_active = me->vertex_group_active_index - 1;
float vgroup_weight = BKE_defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
- const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
+ const int defbase_tot = BLI_listbase_count(&me->vertex_group_names);
bool use_lock_relative = ts->wpaint_lock_relative;
bool *defbase_locked = NULL, *defbase_unlocked = NULL;
@@ -331,8 +331,8 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C,
ED_view3d_viewcontext_init(C, &vc, depsgraph);
me = BKE_mesh_from_object(vc.obact);
- if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
- const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
+ if (me && me->dvert && vc.v3d && vc.rv3d && me->vertex_group_names.first) {
+ const int defbase_tot = BLI_listbase_count(&me->vertex_group_names);
const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
bool found = false;
@@ -372,7 +372,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C,
int totitem = 0;
int i = 0;
bDeformGroup *dg;
- for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
+ for (dg = me->vertex_group_names.first; dg && i < defbase_tot; i++, dg = dg->next) {
if (groups[i]) {
item_tmp.identifier = item_tmp.name = dg->name;
item_tmp.value = i;
@@ -401,14 +401,14 @@ static int weight_sample_group_exec(bContext *C, wmOperator *op)
ED_view3d_viewcontext_init(C, &vc, depsgraph);
BLI_assert(type + 1 >= 0);
- vc.obact->actdef = type + 1;
+ BKE_object_defgroup_active_index_set(vc.obact, type + 1);
DEG_id_tag_update(&vc.obact->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact);
return OPERATOR_FINISHED;
}
-/* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active
+/* TODO: we could make this a menu into OBJECT_OT_vertex_group_set_active
* rather than its own operator */
void PAINT_OT_weight_sample_group(wmOperatorType *ot)
{
@@ -458,7 +458,7 @@ static bool weight_paint_set(Object *ob, float paintweight)
return false;
}
- vgroup_active = ob->actdef - 1;
+ vgroup_active = BKE_object_defgroup_active_index_get(ob) - 1;
/* if mirror painting, find the other group */
if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) {
@@ -540,7 +540,7 @@ static int weight_paint_set_exec(bContext *C, wmOperator *op)
}
if (weight_paint_set(obact, vgroup_weight)) {
- ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
+ ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
@@ -815,7 +815,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.sco_start = sco_start;
data.sco_end = sco_end;
data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
- data.def_nr = ob->actdef - 1;
+ data.def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
data.vert_cache = vert_cache;
data.vert_visit = NULL;
@@ -863,7 +863,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
}
if (scene->toolsettings->auto_normalize) {
- const int vgroup_num = BLI_listbase_count(&ob->defbase);
+ const int vgroup_num = BLI_listbase_count(&me->vertex_group_names);
bool *vgroup_validmap = BKE_object_defgroup_validmap_get(ob, vgroup_num);
if (vgroup_validmap != NULL) {
MDeformVert *dvert = me->dvert;
@@ -891,7 +891,7 @@ static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEve
if (ret & OPERATOR_RUNNING_MODAL) {
struct ARegion *region = CTX_wm_region(C);
if (region->regiontype == RGN_TYPE_WINDOW) {
- /* TODO, hardcoded, extend WM_gesture_straightline_ */
+ /* TODO: hard-coded, extend `WM_gesture_straightline_*`. */
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
wmGesture *gesture = op->customdata;
gesture->is_active = true;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
index d6a118bbd59..19ffa0c952d 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
@@ -79,8 +79,10 @@ bool ED_wpaint_ensure_data(bContext *C,
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
/* this happens on a Bone select, when no vgroup existed yet */
- if (ob->actdef <= 0) {
+ if (me->vertex_group_active_index <= 0) {
Object *modob;
if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) {
Bone *actbone = ((bArmature *)modob->data)->act_bone;
@@ -94,32 +96,33 @@ bool ED_wpaint_ensure_data(bContext *C,
DEG_relations_tag_update(CTX_data_main(C));
}
else {
- int actdef = 1 + BLI_findindex(&ob->defbase, dg);
+
+ int actdef = 1 + BLI_findindex(defbase, dg);
BLI_assert(actdef >= 0);
- ob->actdef = actdef;
+ me->vertex_group_active_index = actdef;
}
}
}
}
}
- if (BLI_listbase_is_empty(&ob->defbase)) {
+ if (BLI_listbase_is_empty(defbase)) {
BKE_object_defgroup_add(ob);
DEG_relations_tag_update(CTX_data_main(C));
}
/* ensure we don't try paint onto an invalid group */
- if (ob->actdef <= 0) {
+ if (me->vertex_group_active_index <= 0) {
BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting");
return false;
}
if (vgroup_index) {
- vgroup_index->active = ob->actdef - 1;
+ vgroup_index->active = me->vertex_group_active_index - 1;
}
if (flag & WPAINT_ENSURE_MIRROR) {
if (ME_USING_MIRROR_X_VERTEX_GROUPS(me)) {
- int mirror = ED_wpaint_mirror_vgroup_ensure(ob, ob->actdef - 1);
+ int mirror = ED_wpaint_mirror_vgroup_ensure(ob, me->vertex_group_active_index - 1);
if (vgroup_index) {
vgroup_index->mirror = mirror;
}
@@ -133,7 +136,8 @@ bool ED_wpaint_ensure_data(bContext *C,
/* mirror_vgroup is set to -1 when invalid */
int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
{
- bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *defgroup = BLI_findlink(defbase, vgroup_active);
if (defgroup) {
int mirrdef;
@@ -143,7 +147,7 @@ int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
mirrdef = BKE_object_defgroup_name_index(ob, name_flip);
if (mirrdef == -1) {
if (BKE_object_defgroup_new(ob, name_flip)) {
- mirrdef = BLI_listbase_count(&ob->defbase) - 1;
+ mirrdef = BLI_listbase_count(defbase) - 1;
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index ab5c46f4bc5..83388c1aef2 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2394,7 +2394,7 @@ static float brush_strength(const Sculpt *sd,
case BRUSH_MASK_SMOOTH:
return alpha * pressure * feather;
}
- BLI_assert(!"Not supposed to happen");
+ BLI_assert_msg(0, "Not supposed to happen");
return 0.0f;
case SCULPT_TOOL_CREASE:
@@ -3316,7 +3316,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
- /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
+ /* XXX: this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
* initialize before threads so they can do curve mapping. */
BKE_curvemapping_init(brush->curve);
@@ -3395,7 +3395,7 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
- /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
+ /* XXX: this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
* initialize before threads so they can do curve mapping. */
BKE_curvemapping_init(brush->curve);
@@ -5791,7 +5791,7 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
BKE_keyblock_update_from_vertcos(ob, kb, vertCos);
}
-/* Note: we do the topology update before any brush actions to avoid
+/* NOTE: we do the topology update before any brush actions to avoid
* issues with the proxies. The size of the proxy can't change, so
* topology must be updated first. */
static void sculpt_topology_update(Sculpt *sd,
@@ -6362,7 +6362,7 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
MEM_SAFE_FREE(nodes);
/* Modifiers could depend on mesh normals, so we should update them.
- * Note, then if sculpting happens on locked key, normals should be re-calculate after applying
+ * NOTE: then if sculpting happens on locked key, normals should be re-calculate after applying
* coords from key-block on base mesh. */
BKE_mesh_calc_normals(me);
}
@@ -7874,7 +7874,7 @@ static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float
static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
{
/* Don't start the stroke until mouse goes over the mesh.
- * note: mouse will only be null when re-executing the saved stroke.
+ * NOTE: mouse will only be null when re-executing the saved stroke.
* We have exception for 'exec' strokes since they may not set 'mouse',
* only 'location', see: T52195. */
if (((op->flag & OP_IS_INVOKE) == 0) || (mouse == NULL) ||
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index 5f5fb51d75f..35f48400fe2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -209,7 +209,7 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au
Brush *brush = BKE_paint_brush(&sd->paint);
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
- BLI_assert(!"Topology masking: pmap missing");
+ BLI_assert_msg(0, "Topology masking: pmap missing");
return NULL;
}
@@ -248,7 +248,7 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
- BLI_assert(!"Face Sets automasking: pmap missing");
+ BLI_assert_msg(0, "Face Sets automasking: pmap missing");
return NULL;
}
@@ -273,7 +273,7 @@ float *SCULPT_boundary_automasking_init(Object *ob,
SculptSession *ss = ob->sculpt;
if (!ss->pmap) {
- BLI_assert(!"Boundary Edges masking: pmap missing");
+ BLI_assert_msg(0, "Boundary Edges masking: pmap missing");
return NULL;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 43704c73faf..696c3332a2b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -704,7 +704,7 @@ typedef struct SculptThreadedTaskData {
/* Data specific to some callbacks. */
- /* Note: even if only one or two of those are used at a time,
+ /* NOTE: even if only one or two of those are used at a time,
* keeping them separated, names help figuring out
* what it is, and memory overhead is ridiculous anyway. */
float flippedbstrength;
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
index 61984610a5a..eabbfe43e03 100644
--- a/source/blender/editors/sculpt_paint/sculpt_smooth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -367,7 +367,7 @@ void SCULPT_smooth(Sculpt *sd,
last = max_iterations * (bstrength - count * fract);
if (type == PBVH_FACES && !ss->pmap) {
- BLI_assert(!"sculpt smooth: pmap missing");
+ BLI_assert_msg(0, "sculpt smooth: pmap missing");
return;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 71166b7c20c..501a1e53276 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -766,7 +766,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
case SCULPT_UNDO_DYNTOPO_BEGIN:
case SCULPT_UNDO_DYNTOPO_END:
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
- BLI_assert(!"Dynamic topology should've already been handled");
+ BLI_assert_msg(0, "Dynamic topology should've already been handled");
break;
}
}
@@ -1065,7 +1065,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_DYNTOPO_BEGIN:
case SCULPT_UNDO_DYNTOPO_END:
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
- BLI_assert(!"Dynamic topology should've already been handled");
+ BLI_assert_msg(0, "Dynamic topology should've already been handled");
case SCULPT_UNDO_GEOMETRY:
case SCULPT_UNDO_FACE_SETS:
break;
@@ -1355,7 +1355,7 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
case SCULPT_UNDO_DYNTOPO_BEGIN:
case SCULPT_UNDO_DYNTOPO_END:
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
- BLI_assert(!"Dynamic topology should've already been handled");
+ BLI_assert_msg(0, "Dynamic topology should've already been handled");
case SCULPT_UNDO_GEOMETRY:
case SCULPT_UNDO_FACE_SETS:
break;
@@ -1432,7 +1432,7 @@ void SCULPT_undo_push_end_ex(const bool use_nested_undo)
typedef struct SculptUndoStep {
UndoStep step;
- /* Note: will split out into list for multi-object-sculpt-mode. */
+ /* NOTE: will split out into list for multi-object-sculpt-mode. */
UndoSculpt data;
} SculptUndoStep;
@@ -1549,7 +1549,7 @@ static void sculpt_undosys_step_decode(
ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
/* Sculpt needs evaluated state.
- * Note: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate
+ * NOTE: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate
* (some) evaluated data. */
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
@@ -1608,7 +1608,7 @@ void ED_sculpt_undosys_type(UndoType *ut)
ut->step_decode = sculpt_undosys_step_decode;
ut->step_free = sculpt_undosys_step_free;
- ut->flags = 0;
+ ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP;
ut->step_size = sizeof(SculptUndoStep);
}
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 9e69b0a72db..d69c7ab8d48 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -813,7 +813,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op)
NlaTrack *act_track;
Scene *scene = CTX_data_scene(C);
- float ctime = BKE_scene_frame_get(scene);
+ float ctime = BKE_scene_ctime_get(scene);
/* Get active track */
act_track = BKE_nlatrack_find_tweaked(adt);
@@ -925,7 +925,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op)
NlaTrack *nlt;
Scene *scene = CTX_data_scene(C);
- float ctime = BKE_scene_frame_get(scene);
+ float ctime = BKE_scene_ctime_get(scene);
/* Sanity Check */
if (adt == NULL) {
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index d305f7504f3..ce07b9c5fad 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -263,7 +263,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_MASK) {
- /* TODO --- this is a copy of gpencil */
+ /* TODO: this is a copy of gpencil. */
/* frames less than one get less saturated background */
uchar *color = sel ? col1 : col2;
immUniformColor4ubv(color);
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index ae9d5445e1d..6f4e295cbb2 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -576,7 +576,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
}
}
else if (ac.datatype == ANIMCONT_MASK) {
- /* FIXME... */
+ /* FIXME: support this case. */
BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode");
return OPERATOR_CANCELLED;
}
@@ -629,7 +629,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
}
}
else if (ac.datatype == ANIMCONT_MASK) {
- /* FIXME... */
+ /* FIXME: support this case. */
BKE_report(op->reports,
RPT_ERROR,
"Keyframe pasting is not available for grease pencil or mask mode");
@@ -1454,7 +1454,7 @@ static void sethandles_action_keys(bAnimContext *ac, short mode)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting flags for handles
- * Note: we do not supply KeyframeEditData to the looper yet.
+ * NOTE: we do not supply KeyframeEditData to the looper yet.
* Currently that's not necessary here.
*/
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -1537,7 +1537,7 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting BezTriple interpolation
- * Note: we do not supply KeyframeEditData to the looper yet.
+ * NOTE: we do not supply KeyframeEditData to the looper yet.
* Currently that's not necessary here.
*/
for (ale = anim_data.first; ale; ale = ale->next) {
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index a51d9086dea..0d5b197ae93 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -933,8 +933,8 @@ static const EnumPropertyItem prop_column_select_types[] = {
/* ------------------- */
/* Selects all visible keyframes between the specified markers */
-/* TODO, this is almost an _exact_ duplicate of a function of the same name in graph_select.c
- * should de-duplicate - campbell */
+/* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in
+ * graph_select.c should de-duplicate. */
static void markers_selectkeys_between(bAnimContext *ac)
{
ListBase anim_data = {NULL, NULL};
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 26b087168f9..28482faf6e3 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -530,7 +530,7 @@ static void action_listener(const wmSpaceTypeListenerParams *params)
}
break;
case NC_ANIMATION:
- /* for NLA tweakmode enter/exit, need complete refresh */
+ /* For NLA tweak-mode enter/exit, need complete refresh. */
if (wmn->data == ND_NLA_ACTCHANGE) {
saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
ED_area_tag_refresh(area);
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index adb824b8934..b3b3eafb6e7 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -129,6 +129,8 @@ void ED_spacetypes_init(void)
ED_screen_user_menu_register();
+ ED_uilisttypes_ui();
+
/* Gizmo types. */
ED_gizmotypes_button_2d();
ED_gizmotypes_dial_3d();
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index a2d9235cfb2..70b715e0119 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -126,7 +126,7 @@ static bool buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win
return false;
}
-/* note: this function can return true without adding a world to the path
+/* NOTE: this function can return true without adding a world to the path
* so the buttons stay visible, but be sure to check the ID type if a ID_WO */
static bool buttons_context_path_world(ButsContextPath *path)
{
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 7564fa4b930..9cb363ff0c9 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -34,8 +34,8 @@ struct Tex;
struct bContext;
struct bContextDataResult;
struct bNode;
-struct bNodeTree;
struct bNodeSocket;
+struct bNodeTree;
struct wmOperatorType;
struct SpaceProperties_Runtime {
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 97e3cb750c1..f1debcef5a9 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -451,7 +451,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
/* set user as active */
if (user->node) {
- ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL);
+ ED_node_set_active(CTX_data_main(C), NULL, user->ntree, user->node, NULL);
ct->texture = NULL;
/* Not totally sure if we should also change selection? */
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 2da13646a8b..67b4fd61d38 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -1025,7 +1025,7 @@ static void prefetch_startjob(void *pjv, short *stop, short *do_update, float *p
progress);
}
else {
- BLI_assert(!"Unknown movie clip source when prefetching frames");
+ BLI_assert_msg(0, "Unknown movie clip source when prefetching frames");
}
}
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index e0a524a79c1..326c221a2e3 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -1214,7 +1214,7 @@ static void clip_header_region_listener(const wmRegionListenerParams *params)
switch (wmn->data) {
/* for proportional editmode only */
case ND_TOOLSETTINGS:
- /* TODO - should do this when in mask mode only but no data available */
+ /* TODO: should do this when in mask mode only but no data available. */
// if (sc->mode == SC_MODE_MASKEDIT)
{
ED_region_tag_redraw(region);
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index 9b4b020b276..bdb7c622cd2 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -415,7 +415,7 @@ static int console_insert_exec(bContext *C, wmOperator *op)
static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- /* Note, the "text" property is always set from key-map,
+ /* NOTE: the "text" property is always set from key-map,
* so we can't use #RNA_struct_property_is_set, check the length instead. */
if (!RNA_string_length(op->ptr, "text")) {
/* if alt/ctrl/super are pressed pass through except for utf8 character event
@@ -790,7 +790,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op)
SpaceConsole *sc = CTX_wm_space_console(C);
ARegion *region = CTX_wm_region(C);
- /* TODO - stupid, just prevents crashes when no command line */
+ /* TODO: stupid, just prevents crashes when no command line. */
ConsoleLine *ci = console_history_verify(C);
const bool reverse = RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */
int prev_len = ci->len;
@@ -1109,7 +1109,7 @@ typedef struct SetConsoleCursor {
int sel_init;
} SetConsoleCursor;
-/* TODO, cursor placement without selection */
+/* TODO: cursor placement without selection. */
static void console_cursor_set_to_pos(
SpaceConsole *sc, ARegion *region, SetConsoleCursor *scu, const int mval[2], int UNUSED(sel))
{
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 56a6204b385..3029eed1017 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -107,7 +107,7 @@ static SpaceLink *console_duplicate(SpaceLink *sl)
/* clear or remove stuff from old */
- /* TODO - duplicate?, then we also need to duplicate the py namespace */
+ /* TODO: duplicate?, then we also need to duplicate the py namespace. */
BLI_listbase_clear(&sconsolen->scrollback);
BLI_listbase_clear(&sconsolen->history);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index d947d361fdf..a314a85491d 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -110,7 +110,7 @@ void ED_file_path_button(bScreen *screen,
UI_but_func_complete_set(but, autocomplete_directory, NULL);
UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);
- /* TODO, directory editing is non-functional while a library is loaded
+ /* TODO: directory editing is non-functional while a library is loaded
* until this is properly supported just disable it. */
if (sfile && sfile->files && filelist_lib(sfile->files)) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
@@ -170,7 +170,7 @@ static void file_draw_icon(const SpaceFile *sfile,
UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path), MEM_freeN);
if (drag) {
- /* TODO duplicated from file_draw_preview(). */
+ /* TODO: duplicated from file_draw_preview(). */
ID *id;
if ((id = filelist_file_get_id(file))) {
@@ -523,6 +523,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
char orgname[FILE_MAX + 12];
char filename[FILE_MAX + 12];
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
ARegion *region = CTX_wm_region(C);
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
@@ -542,17 +543,15 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
else {
/* If rename is successful, scroll to newly renamed entry. */
BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile));
- params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
-
- if (sfile->smoothscroll_timer != NULL) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
- }
- sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0);
- sfile->scroll_offset = 0;
+ file_params_invoke_rename_postscroll(wm, win, sfile);
}
/* to make sure we show what is on disk */
- ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
+ ED_fileselect_clear(wm, sfile);
+ }
+ else {
+ /* Renaming failed, reset the name for further renaming handling. */
+ BLI_strncpy(params->renamefile, oldname, sizeof(params->renamefile));
}
ED_region_tag_redraw(region);
@@ -727,40 +726,45 @@ static void draw_columnheader_columns(const FileSelectParams *params,
/**
* Updates the stat string stored in file->entry if necessary.
*/
-static const char *filelist_get_details_column_string(FileAttributeColumnType column,
- const FileDirEntry *file,
- const bool small_size,
- const bool update_stat_strings)
+static const char *filelist_get_details_column_string(
+ FileAttributeColumnType column,
+ /* Generated string will be cached in the file, so non-const. */
+ FileDirEntry *file,
+ const bool small_size,
+ const bool update_stat_strings)
{
switch (column) {
case COLUMN_DATETIME:
if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
- if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) {
+ if ((file->draw_data.datetime_str[0] == '\0') || update_stat_strings) {
char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN];
bool is_today, is_yesterday;
BLI_filelist_entry_datetime_to_string(
- NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday);
+ NULL, file->time, small_size, time, date, &is_today, &is_yesterday);
if (is_today || is_yesterday) {
BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date));
}
- BLI_snprintf(
- file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time);
+ BLI_snprintf(file->draw_data.datetime_str,
+ sizeof(file->draw_data.datetime_str),
+ "%s %s",
+ date,
+ time);
}
- return file->entry->datetime_str;
+ return file->draw_data.datetime_str;
}
break;
case COLUMN_SIZE:
if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
!(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ if ((file->draw_data.size_str[0] == '\0') || update_stat_strings) {
BLI_filelist_entry_size_to_string(
- NULL, file->entry->size, small_size, file->entry->size_str);
+ NULL, file->size, small_size, file->draw_data.size_str);
}
- return file->entry->size_str;
+ return file->draw_data.size_str;
}
break;
default:
@@ -772,7 +776,7 @@ static const char *filelist_get_details_column_string(FileAttributeColumnType co
static void draw_details_columns(const FileSelectParams *params,
const FileLayout *layout,
- const FileDirEntry *file,
+ FileDirEntry *file,
const int pos_x,
const int pos_y,
const uchar text_col[4])
@@ -813,6 +817,8 @@ static void draw_details_columns(const FileSelectParams *params,
void file_draw_list(const bContext *C, ARegion *region)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
FileLayout *layout = ED_fileselect_get_layout(sfile, region);
@@ -883,12 +889,12 @@ void file_draw_list(const bContext *C, ARegion *region)
// printf("%s: preview task: %d\n", __func__, previews_running);
if (previews_running && !sfile->previews_timer) {
sfile->previews_timer = WM_event_add_timer_notifier(
- CTX_wm_manager(C), CTX_wm_window(C), NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01);
+ wm, win, NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01);
}
if (!previews_running && sfile->previews_timer) {
/* Preview is not running, no need to keep generating update events! */
// printf("%s: Inactive preview task, sleeping!\n", __func__);
- WM_event_remove_timer_notifier(CTX_wm_manager(C), CTX_wm_window(C), sfile->previews_timer);
+ WM_event_remove_timer_notifier(wm, win, sfile->previews_timer);
sfile->previews_timer = NULL;
}
}
@@ -999,8 +1005,19 @@ void file_draw_list(const bContext *C, ARegion *region)
UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */
UI_but_flag_disable(but, UI_BUT_UNDO);
if (false == UI_but_active_only(C, region, block, but)) {
- file_selflag = filelist_entry_select_set(
- sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
+ /* Note that this is the only place where we can also handle a cancelled renaming. */
+
+ file_params_rename_end(wm, win, sfile, file);
+
+ /* After the rename button is removed, we need to make sure the view is redrawn once more,
+ * in case selection changed. Usually UI code would trigger that redraw, but the rename
+ * operator may have been called from a different region.
+ * Tagging regions for redrawing while drawing is rightfully prevented. However, this
+ * active button removing basically introduces handling logic to drawing code. So a
+ * notifier should be an acceptable workaround. */
+ WM_event_add_notifier_ex(wm, win, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
+ file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL);
}
}
@@ -1088,7 +1105,7 @@ bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region)
return false;
}
/* Check if the library exists. */
- if ((asset_params->asset_library.type == FILE_ASSET_LIBRARY_LOCAL) ||
+ if ((asset_params->asset_library.type == ASSET_LIBRARY_LOCAL) ||
filelist_is_dir(sfile->files, asset_params->base_params.dir)) {
return false;
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index a7c57459729..0bbed65671c 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -109,10 +109,22 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
float file_string_width(const char *str);
float file_font_pointsize(void);
+void file_select_deselect_all(SpaceFile *sfile, uint flag);
int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file);
int autocomplete_directory(struct bContext *C, char *str, void *arg_v);
int autocomplete_file(struct bContext *C, char *str, void *arg_v);
+void file_params_smoothscroll_timer_clear(struct wmWindowManager *wm,
+ struct wmWindow *win,
+ SpaceFile *sfile);
+void file_params_renamefile_clear(struct FileSelectParams *params);
+void file_params_invoke_rename_postscroll(struct wmWindowManager *wm,
+ struct wmWindow *win,
+ SpaceFile *sfile);
+void file_params_rename_end(struct wmWindowManager *wm,
+ struct wmWindow *win,
+ SpaceFile *sfile,
+ struct FileDirEntry *rename_file);
void file_params_renamefile_activate(struct SpaceFile *sfile, struct FileSelectParams *params);
typedef void *onReloadFnData;
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 0584e2ff938..995383d9d0e 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -104,15 +104,6 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile,
return sel;
}
-static void file_deselect_all(SpaceFile *sfile, uint flag)
-{
- FileSelection sel;
- sel.first = 0;
- sel.last = filelist_files_ensure(sfile->files) - 1;
-
- filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
-}
-
typedef enum FileSelect {
FILE_SELECT_NOTHING = 0,
FILE_SELECT_DIR = 1,
@@ -239,7 +230,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
}
/**
- * \warning: loops over all files so better use cautiously
+ * \warning Loops over all files so better use cautiously.
*/
static bool file_is_any_selected(struct FileList *files)
{
@@ -444,7 +435,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
int idx;
- file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
+ file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
filelist_entries_select_index_range_set(
sfile->files, &sel, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@@ -472,7 +463,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
params->highlight_file = -1;
params->sel_first = params->sel_last = -1;
fileselect_file_set(sfile, params->active_file);
- file_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
+ file_select_deselect_all(sfile, FILE_SEL_HIGHLIGHTED);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
@@ -491,7 +482,7 @@ static int file_box_select_exec(bContext *C, wmOperator *op)
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const bool select = (sel_op != SEL_OP_SUB);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- file_deselect_all(sfile, FILE_SEL_SELECTED);
+ file_select_deselect_all(sfile, FILE_SEL_SELECTED);
}
ED_fileselect_layout_isect_rect(sfile->layout, &region->v2d, &rect, &rect);
@@ -573,7 +564,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if ((idx >= 0) && (idx < numfiles)) {
/* single select, deselect all selected first */
if (!extend) {
- file_deselect_all(sfile, FILE_SEL_SELECTED);
+ file_select_deselect_all(sfile, FILE_SEL_SELECTED);
}
}
}
@@ -588,7 +579,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (ret == FILE_SELECT_NOTHING) {
if (deselect_all) {
- file_deselect_all(sfile, FILE_SEL_SELECTED);
+ file_select_deselect_all(sfile, FILE_SEL_SELECTED);
}
}
else if (ret == FILE_SELECT_DIR) {
@@ -721,7 +712,7 @@ static bool file_walk_select_selection_set(wmWindow *win,
}
else {
/* deselect all first */
- file_deselect_all(sfile, FILE_SEL_SELECTED);
+ file_select_deselect_all(sfile, FILE_SEL_SELECTED);
/* highlight file under mouse pos */
params->highlight_file = -1;
@@ -1023,7 +1014,7 @@ void FILE_OT_view_selected(wmOperatorType *ot)
/* Note we could get rid of this one, but it's used by some addon so...
* Does not hurt keeping it around for now. */
-/* TODO disallow bookmark editing in assets mode? */
+/* TODO: disallow bookmark editing in assets mode? */
static int bookmark_select_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -1882,7 +1873,7 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
SpaceFile *sfile = CTX_wm_space_file(C);
struct FSMenu *fsmenu = ED_fsmenu_get();
- ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
+ ED_fileselect_clear(wm, sfile);
/* refresh system directory menu */
fsmenu_refresh_system_category(fsmenu);
@@ -2059,13 +2050,15 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
}
}
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
/* if we are not editing, we are done */
if (edit_idx == -1) {
/* Do not invalidate timer if filerename is still pending,
* we might still be building the filelist and yet have to find edited entry. */
if (params->rename_flag == 0) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
- sfile->smoothscroll_timer = NULL;
+ file_params_smoothscroll_timer_clear(wm, win, sfile);
}
return OPERATOR_PASS_THROUGH;
}
@@ -2073,8 +2066,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* we need the correct area for scrolling */
region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (!region || region->regiontype != RGN_TYPE_WINDOW) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
- sfile->smoothscroll_timer = NULL;
+ file_params_smoothscroll_timer_clear(wm, win, sfile);
return OPERATOR_PASS_THROUGH;
}
@@ -2093,7 +2085,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
sfile->layout, (int)region->v2d.cur.xmin, (int)-region->v2d.cur.ymax);
const int last_visible_item = first_visible_item + numfiles_layout + 1;
- /* Note: the special case for vertical layout is because filename is at the bottom of items then,
+ /* NOTE: the special case for vertical layout is because filename is at the bottom of items then,
* so we artificially move current row back one step, to ensure we show bottom of
* active item rather than its top (important in case visible height is low). */
const int middle_offset = max_ii(
@@ -2131,13 +2123,11 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
(max_middle_offset - middle_offset < items_block_size));
if (is_ready && (is_centered || is_full_start || is_full_end)) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
- sfile->smoothscroll_timer = NULL;
+ file_params_smoothscroll_timer_clear(wm, win, sfile);
/* Post-scroll (after rename has been validated by user) is done,
* rename process is totally finished, cleanup. */
if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE) != 0) {
- params->renamefile[0] = '\0';
- params->rename_flag = 0;
+ file_params_renamefile_clear(params);
}
return OPERATOR_FINISHED;
}
@@ -2346,21 +2336,20 @@ static int file_directory_new_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ eFileSel_Params_RenameFlag rename_flag = params->rename_flag;
+
/* If we don't enter the directory directly, remember file to jump into editing. */
if (do_diropen == false) {
+ BLI_assert(params->rename_id == NULL || !"File rename handling should immediately clear rename_id when done, because otherwise it will keep taking precedence over renamefile.");
BLI_strncpy(params->renamefile, name, FILE_MAXFILE);
- params->rename_flag = FILE_PARAMS_RENAME_PENDING;
+ rename_flag = FILE_PARAMS_RENAME_PENDING;
}
- /* Set timer to smoothly view newly generated file. */
- if (sfile->smoothscroll_timer != NULL) {
- WM_event_remove_timer(wm, CTX_wm_window(C), sfile->smoothscroll_timer);
- }
- sfile->smoothscroll_timer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER1, 1.0 / 1000.0);
- sfile->scroll_offset = 0;
+ file_params_invoke_rename_postscroll(wm, CTX_wm_window(C), sfile);
+ params->rename_flag = rename_flag;
/* reload dir to make sure we're seeing what's in the directory */
- ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
+ ED_fileselect_clear(wm, sfile);
if (do_diropen) {
BLI_strncpy(params->dir, path, sizeof(params->dir));
@@ -2400,7 +2389,7 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
/** \name Refresh File List Operator
* \{ */
-/* TODO This should go to BLI_path_utils. */
+/* TODO: This should go to BLI_path_utils. */
static void file_expand_directory(bContext *C)
{
Main *bmain = CTX_data_main(C);
@@ -2441,7 +2430,7 @@ static void file_expand_directory(bContext *C)
}
}
-/* TODO check we still need this, it's annoying to have OS-specific code here... :/ */
+/* TODO: check we still need this, it's annoying to have OS-specific code here... :/. */
#if defined(WIN32)
static bool can_create_dir(const char *dir)
{
@@ -2611,7 +2600,7 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
if (params) {
params->flag ^= FILE_HIDE_DOT;
- ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
+ ED_fileselect_clear(wm, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -2804,6 +2793,11 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+static bool file_rename_poll(bContext *C)
+{
+ return ED_operator_file_active(C) && !ED_fileselect_is_asset_browser(CTX_wm_space_file(C));
+}
+
void FILE_OT_rename(struct wmOperatorType *ot)
{
/* identifiers */
@@ -2814,7 +2808,7 @@ void FILE_OT_rename(struct wmOperatorType *ot)
/* api callbacks */
ot->invoke = file_rename_invoke;
ot->exec = file_rename_exec;
- ot->poll = ED_operator_file_active;
+ ot->poll = file_rename_poll;
}
/** \} */
@@ -2908,7 +2902,7 @@ static int file_delete_exec(bContext *C, wmOperator *op)
}
}
- ED_fileselect_clear(wm, CTX_data_scene(C), sfile);
+ ED_fileselect_clear(wm, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 40a7be0423e..492a189fc81 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -263,8 +263,7 @@ ListBase folder_history_list_duplicate(ListBase *listbase)
typedef struct FileListInternEntry {
struct FileListInternEntry *next, *prev;
- /** ASSET_UUID_LENGTH */
- char uuid[16];
+ FileUID uid;
/** eFileSel_File_Types */
int typeflag;
@@ -306,7 +305,7 @@ typedef struct FileListIntern {
ListBase entries;
FileListInternEntry **filtered;
- char curr_uuid[16]; /* Used to generate uuid during internal listing. */
+ FileUID curr_uid; /* Used to generate UID during internal listing. */
} FileListIntern;
#define FILELIST_ENTRYCACHESIZE_DEFAULT 1024 /* Keep it a power of two! */
@@ -315,7 +314,7 @@ typedef struct FileListEntryCache {
int flags;
- /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */
+ /* This one gathers all entries from both block and misc caches. Used for easy bulk-freeing. */
ListBase cached_entries;
/* Block cache: all entries between start and end index.
@@ -324,17 +323,18 @@ typedef struct FileListEntryCache {
int block_start_index, block_end_index, block_center_index, block_cursor;
/* Misc cache: random indices, FIFO behavior.
- * Note: Not 100% sure we actually need that, time will say. */
+ * NOTE: Not 100% sure we actually need that, time will say. */
int misc_cursor;
int *misc_entries_indices;
GHash *misc_entries;
- /* Allows to quickly get a cached entry from its UUID. */
- GHash *uuids;
+ /* Allows to quickly get a cached entry from its UID. */
+ GHash *uids;
/* Previews handling. */
TaskPool *previews_pool;
ThreadQueue *previews_done;
+ size_t previews_todo_count;
} FileListEntryCache;
/* FileListCache.flags */
@@ -1051,7 +1051,7 @@ static bool filelist_compare_asset_libraries(const FileSelectAssetLibraryUID *li
if (library_a->type != library_b->type) {
return false;
}
- if (library_a->type == FILE_ASSET_LIBRARY_CUSTOM) {
+ if (library_a->type == ASSET_LIBRARY_CUSTOM) {
/* Don't only check the index, also check that it's valid. */
bUserAssetLibrary *library_ptr_a = BKE_preferences_asset_library_find_from_index(
&U, library_a->custom_library_index);
@@ -1154,7 +1154,7 @@ ImBuf *filelist_file_getimage(const FileDirEntry *file)
return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL;
}
-static ImBuf *filelist_geticon_image_ex(FileDirEntry *file)
+ImBuf *filelist_geticon_image_ex(const FileDirEntry *file)
{
ImBuf *ibuf = NULL;
@@ -1383,40 +1383,6 @@ static void filelist_entry_clear(FileDirEntry *entry)
BKE_icon_delete(entry->preview_icon_id);
entry->preview_icon_id = 0;
}
- /* For now, consider FileDirEntryRevision::poin as not owned here,
- * so no need to do anything about it */
-
- if (!BLI_listbase_is_empty(&entry->variants)) {
- FileDirEntryVariant *var;
-
- for (var = entry->variants.first; var; var = var->next) {
- if (var->name) {
- MEM_freeN(var->name);
- }
- if (var->description) {
- MEM_freeN(var->description);
- }
-
- if (!BLI_listbase_is_empty(&var->revisions)) {
- FileDirEntryRevision *rev;
-
- for (rev = var->revisions.first; rev; rev = rev->next) {
- if (rev->comment) {
- MEM_freeN(rev->comment);
- }
- }
-
- BLI_freelistN(&var->revisions);
- }
- }
-
- /* TODO: tags! */
-
- BLI_freelistN(&entry->variants);
- }
- else if (entry->entry) {
- MEM_freeN(entry->entry);
- }
}
static void filelist_entry_free(FileDirEntry *entry)
@@ -1529,6 +1495,7 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
/* That way task freeing function won't free th preview, since it does not own it anymore. */
atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL);
BLI_thread_queue_push(cache->previews_done, preview);
+ atomic_fetch_and_sub_z(&cache->previews_todo_count, 1);
}
// printf("%s: End (%d)...\n", __func__, threadid);
@@ -1555,6 +1522,7 @@ static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
if (!cache->previews_pool) {
cache->previews_pool = BLI_task_pool_create_background(cache, TASK_PRIORITY_LOW);
cache->previews_done = BLI_thread_queue_init();
+ cache->previews_todo_count = 0;
IMB_thumb_locks_acquire();
}
@@ -1588,6 +1556,7 @@ static void filelist_cache_previews_free(FileListEntryCache *cache)
BLI_task_pool_free(cache->previews_pool);
cache->previews_pool = NULL;
cache->previews_done = NULL;
+ cache->previews_todo_count = 0;
IMB_thumb_locks_release();
}
@@ -1662,13 +1631,14 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
copy_vn_i(cache->misc_entries_indices, cache_size, -1);
cache->misc_cursor = 0;
- /* XXX This assumes uint is 32 bits and uuid is 128 bits (char[16]), be careful! */
- cache->uuids = BLI_ghash_new_ex(
- BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__, cache_size * 2);
+ cache->uids = BLI_ghash_new_ex(
+ BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__, cache_size * 2);
cache->size = cache_size;
cache->flags = FLC_IS_INIT;
+ cache->previews_todo_count = 0;
+
/* We cannot translate from non-main thread, so init translated strings once from here. */
IMB_thumb_ensure_translations();
}
@@ -1688,7 +1658,7 @@ static void filelist_cache_free(FileListEntryCache *cache)
BLI_ghash_free(cache->misc_entries, NULL, NULL);
MEM_freeN(cache->misc_entries_indices);
- BLI_ghash_free(cache->uuids, NULL, NULL);
+ BLI_ghash_free(cache->uids, NULL, NULL);
for (entry = cache->cached_entries.first; entry; entry = entry_next) {
entry_next = entry->next;
@@ -1721,7 +1691,7 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
}
copy_vn_i(cache->misc_entries_indices, new_size, -1);
- BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2);
+ BLI_ghash_clear_ex(cache->uids, NULL, NULL, new_size * 2);
cache->size = new_size;
@@ -1738,8 +1708,7 @@ FileList *filelist_new(short type)
filelist_cache_init(&p->filelist_cache, FILELIST_ENTRYCACHESIZE_DEFAULT);
- p->selection_state = BLI_ghash_new(
- BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+ p->selection_state = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET;
filelist_settype(p, type);
@@ -1798,7 +1767,7 @@ void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const boo
filelist_direntryarr_free(&filelist->filelist);
if (do_selection && filelist->selection_state) {
- BLI_ghash_clear(filelist->selection_state, MEM_freeN, NULL);
+ BLI_ghash_clear(filelist->selection_state, NULL, NULL);
}
}
@@ -1819,7 +1788,7 @@ void filelist_free(struct FileList *filelist)
filelist_cache_free(&filelist->filelist_cache);
if (filelist->selection_state) {
- BLI_ghash_free(filelist->selection_state, MEM_freeN, NULL);
+ BLI_ghash_free(filelist->selection_state, NULL, NULL);
filelist->selection_state = NULL;
}
@@ -1957,16 +1926,12 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
FileListInternEntry *entry = filelist->filelist_intern.filtered[index];
FileListEntryCache *cache = &filelist->filelist_cache;
FileDirEntry *ret;
- FileDirEntryRevision *rev;
ret = MEM_callocN(sizeof(*ret), __func__);
- rev = MEM_callocN(sizeof(*rev), __func__);
-
- rev->size = (uint64_t)entry->st.st_size;
- rev->time = (int64_t)entry->st.st_mtime;
+ ret->size = (uint64_t)entry->st.st_size;
+ ret->time = (int64_t)entry->st.st_mtime;
- ret->entry = rev;
ret->relpath = BLI_strdup(entry->relpath);
if (entry->free_name) {
ret->name = BLI_strdup(entry->name);
@@ -1976,7 +1941,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
ret->name = entry->name;
}
ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath);
- memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid));
+ ret->uid = entry->uid;
ret->blentype = entry->blentype;
ret->typeflag = entry->typeflag;
ret->attributes = entry->attributes;
@@ -2034,11 +1999,11 @@ FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const
ret = filelist_file_create_entry(filelist, index);
old_index = cache->misc_entries_indices[cache->misc_cursor];
if ((old = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(old_index), NULL))) {
- BLI_ghash_remove(cache->uuids, old->uuid, NULL, NULL);
+ BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(old->uid), NULL, NULL);
filelist_file_release_entry(filelist, old);
}
BLI_ghash_insert(cache->misc_entries, POINTER_FROM_INT(index), ret);
- BLI_ghash_insert(cache->uuids, ret->uuid, ret);
+ BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(ret->uid), ret);
cache->misc_entries_indices[cache->misc_cursor] = index;
cache->misc_cursor = (cache->misc_cursor + 1) % cache_size;
@@ -2057,19 +2022,21 @@ FileDirEntry *filelist_file(struct FileList *filelist, int index)
return filelist_file_ex(filelist, index, true);
}
-int filelist_file_findpath(struct FileList *filelist, const char *filename)
+/**
+ * Find a file from a file name, or more precisely, its file-list relative path, inside the
+ * filtered items. \return The index of the found file or -1.
+ */
+int filelist_file_find_path(struct FileList *filelist, const char *filename)
{
- int fidx = -1;
-
if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) {
- return fidx;
+ return -1;
}
- /* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though.
- * This is only used to find again renamed entry,
- * annoying but looks hairy to get rid of it currently. */
+ /* XXX TODO: Cache could probably use a ghash on paths too? Not really urgent though.
+ * This is only used to find again renamed entry,
+ * annoying but looks hairy to get rid of it currently. */
- for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
+ for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
if (STREQ(entry->relpath, filename)) {
return fidx;
@@ -2080,38 +2047,53 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename)
}
/**
- * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET.
+ * Find a file representing \a id.
+ * \return The index of the found file or -1.
*/
-ID *filelist_file_get_id(const FileDirEntry *file)
-{
- return file->id;
-}
-
-FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4])
+int filelist_file_find_id(const FileList *filelist, const ID *id)
{
if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) {
- return NULL;
+ return -1;
}
- if (filelist->filelist_cache.uuids) {
- FileDirEntry *entry = BLI_ghash_lookup(filelist->filelist_cache.uuids, uuid);
- if (entry) {
- return entry;
+ for (int fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
+ FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
+ if (entry->local_data.id == id) {
+ return fidx;
}
}
- {
- int fidx;
+ return -1;
+}
- for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
- FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
- if (memcmp(entry->uuid, uuid, sizeof(entry->uuid)) == 0) {
- return filelist_file(filelist, fidx);
- }
- }
- }
+/**
+ * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET.
+ */
+ID *filelist_file_get_id(const FileDirEntry *file)
+{
+ return file->id;
+}
- return NULL;
+#define FILE_UID_UNSET 0
+
+static FileUID filelist_uid_generate(FileList *filelist)
+{
+ /* Using an atomic operation to avoid having to lock thread...
+ * Note that we do not really need this here currently, since there is a single listing thread,
+ * but better remain consistent about threading! */
+ return atomic_add_and_fetch_uint32(&filelist->filelist_intern.curr_uid, 1);
+}
+
+bool filelist_uid_is_set(const FileUID uid)
+{
+ FileUID unset_uid;
+ filelist_uid_unset(&unset_uid);
+ return unset_uid != uid;
+}
+
+void filelist_uid_unset(FileUID *r_uid)
+{
+ *r_uid = FILE_UID_UNSET;
}
void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size)
@@ -2147,7 +2129,7 @@ static bool filelist_file_cache_block_create(FileList *filelist,
/* That entry might have already been requested and stored in misc cache... */
if ((entry = BLI_ghash_popkey(cache->misc_entries, POINTER_FROM_INT(idx), NULL)) == NULL) {
entry = filelist_file_create_entry(filelist, idx);
- BLI_ghash_insert(cache->uuids, entry->uuid, entry);
+ BLI_ghash_insert(cache->uids, POINTER_FROM_UINT(entry->uid), entry);
}
cache->block_entries[cursor] = entry;
}
@@ -2173,7 +2155,7 @@ static void filelist_file_cache_block_release(struct FileList *filelist,
__func__,
cursor /*, cache->block_entries[cursor], cache->block_entries[cursor]->relpath*/);
#endif
- BLI_ghash_remove(cache->uuids, entry->uuid, NULL, NULL);
+ BLI_ghash_remove(cache->uids, POINTER_FROM_UINT(entry->uid), NULL, NULL);
filelist_file_release_entry(filelist, entry);
#ifndef NDEBUG
cache->block_entries[cursor] = NULL;
@@ -2305,7 +2287,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index)
if (start_index < cache->block_start_index) {
/* Add (request) needed entries before already cached ones. */
- /* Note: We need some index black magic to wrap around (cycle)
+ /* NOTE: We need some index black magic to wrap around (cycle)
* inside our cache_size array... */
int size1 = cache->block_start_index - start_index;
int size2 = 0;
@@ -2337,7 +2319,7 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index)
// printf("\tstart-extended...\n");
if (end_index > cache->block_end_index) {
/* Add (request) needed entries after already cached ones. */
- /* Note: We need some index black magic to wrap around (cycle)
+ /* NOTE: We need some index black magic to wrap around (cycle)
* inside our cache_size array... */
int size1 = end_index - cache->block_end_index;
int size2 = 0;
@@ -2408,7 +2390,8 @@ void filelist_cache_previews_set(FileList *filelist, const bool use_previews)
if (use_previews && (filelist->flags & FL_IS_READY)) {
cache->flags |= FLC_PREVIEWS_ACTIVE;
- BLI_assert((cache->previews_pool == NULL) && (cache->previews_done == NULL));
+ BLI_assert((cache->previews_pool == NULL) && (cache->previews_done == NULL) &&
+ (cache->previews_todo_count == 0));
// printf("%s: Init Previews...\n", __func__);
@@ -2481,6 +2464,18 @@ bool filelist_cache_previews_running(FileList *filelist)
return (cache->previews_pool != NULL);
}
+bool filelist_cache_previews_done(FileList *filelist)
+{
+ FileListEntryCache *cache = &filelist->filelist_cache;
+ if ((cache->flags & FLC_PREVIEWS_ACTIVE) == 0) {
+ /* There are no previews. */
+ return false;
+ }
+
+ return (cache->previews_pool == NULL) || (cache->previews_done == NULL) ||
+ (cache->previews_todo_count == (size_t)BLI_thread_queue_len(cache->previews_done));
+}
+
/* would recognize .blend as well */
static bool file_is_blend_backup(const char *str)
{
@@ -2635,7 +2630,7 @@ uint filelist_entry_select_set(const FileList *filelist,
FileCheckType check)
{
/* Default NULL pointer if not found is fine here! */
- void **es_p = BLI_ghash_lookup_p(filelist->selection_state, entry->uuid);
+ void **es_p = BLI_ghash_lookup_p(filelist->selection_state, POINTER_FROM_UINT(entry->uid));
uint entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0;
const uint org_entry_flag = entry_flag;
@@ -2663,13 +2658,12 @@ uint filelist_entry_select_set(const FileList *filelist,
*es_p = POINTER_FROM_UINT(entry_flag);
}
else {
- BLI_ghash_remove(filelist->selection_state, entry->uuid, MEM_freeN, NULL);
+ BLI_ghash_remove(filelist->selection_state, POINTER_FROM_UINT(entry->uid), NULL, NULL);
}
}
else if (entry_flag) {
- void *key = MEM_mallocN(sizeof(entry->uuid), __func__);
- memcpy(key, entry->uuid, sizeof(entry->uuid));
- BLI_ghash_insert(filelist->selection_state, key, POINTER_FROM_UINT(entry_flag));
+ BLI_ghash_insert(
+ filelist->selection_state, POINTER_FROM_UINT(entry->uid), POINTER_FROM_UINT(entry_flag));
}
}
@@ -2707,7 +2701,8 @@ uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileChec
if (((check == CHECK_ALL)) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) {
/* Default NULL pointer if not found is fine here! */
- return POINTER_AS_UINT(BLI_ghash_lookup(filelist->selection_state, entry->uuid));
+ return POINTER_AS_UINT(
+ BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid)));
}
return 0;
@@ -2732,7 +2727,7 @@ bool filelist_entry_is_selected(FileList *filelist, const int index)
/* BLI_ghash_lookup returns NULL if not found, which gets mapped to 0, which gets mapped to
* "not selected". */
const uint selection_state = POINTER_AS_UINT(
- BLI_ghash_lookup(filelist->selection_state, intern_entry->uuid));
+ BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid)));
return selection_state != 0;
}
@@ -2967,7 +2962,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist)
ListBase *lb;
int a, fake, idcode, ok, totlib, totbl;
- // filelist->type = FILE_MAIN; /* XXX TODO: add modes to filebrowser */
+ // filelist->type = FILE_MAIN; /* XXX TODO: add modes to file-browser */
BLI_assert(filelist->filelist.entries == NULL);
@@ -3073,7 +3068,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist)
files->entry->relpath = BLI_strdup(relname);
}
// files->type |= S_IFREG;
-# if 0 /* XXX TODO show the selection status of the objects */
+# if 0 /* XXX TODO: show the selection status of the objects. */
if (!filelist->has_func) { /* F4 DATA BROWSE */
if (idcode == ID_OB) {
if ( ((Object *)id)->flag & SELECT) {
@@ -3202,14 +3197,7 @@ static void filelist_readjob_do(const bool do_lib,
for (entry = entries.first; entry; entry = entry->next) {
BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath);
- /* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here,
- * things would crash way before we overflow that counter!
- * Using an atomic operation to avoid having to lock thread...
- * Note that we do not really need this here currently,
- * since there is a single listing thread, but better
- * remain consistent about threading! */
- *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32(
- (uint32_t *)filelist->filelist_intern.curr_uuid, 1);
+ entry->uid = filelist_uid_generate(filelist);
/* Only thing we change in direntry here, so we need to free it first. */
MEM_freeN(entry->relpath);
@@ -3334,8 +3322,7 @@ static void filelist_readjob_main_assets(Main *current_main,
entry->free_name = false;
entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET;
entry->blentype = GS(id_iter->name);
- *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32(
- (uint32_t *)filelist->filelist_intern.curr_uuid, 1);
+ entry->uid = filelist_uid_generate(filelist);
entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data,
id_iter);
entry->local_data.id = id_iter;
@@ -3381,9 +3368,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update
flrj->tmp_filelist->filelist_intern.filtered = NULL;
BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries);
- memset(flrj->tmp_filelist->filelist_intern.curr_uuid,
- 0,
- sizeof(flrj->tmp_filelist->filelist_intern.curr_uuid));
+ filelist_uid_unset(&flrj->tmp_filelist->filelist_intern.curr_uid);
flrj->tmp_filelist->libfiledata = NULL;
memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
@@ -3423,7 +3408,7 @@ static void filelist_readjob_update(void *flrjv)
BLI_mutex_unlock(&flrj->lock);
if (new_nbr_entries) {
- /* Do not clear selection cache, we can assume already 'selected' uuids are still valid! */
+ /* Do not clear selection cache, we can assume already 'selected' UIDs are still valid! */
filelist_clear_ex(flrj->filelist, true, false);
flrj->filelist->flags |= (FL_NEED_SORTING | FL_NEED_FILTERING);
@@ -3466,7 +3451,7 @@ static void filelist_readjob_free(void *flrjv)
MEM_freeN(flrj);
}
-void filelist_readjob_start(FileList *filelist, const bContext *C)
+void filelist_readjob_start(FileList *filelist, const int space_notifier, const bContext *C)
{
Main *bmain = CTX_data_main(C);
wmJob *wm_job;
@@ -3498,22 +3483,19 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
filelist_readjob_endjob(flrj);
filelist_readjob_free(flrj);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED, NULL);
+ WM_event_add_notifier(C, space_notifier | NA_JOB_FINISHED, NULL);
return;
}
/* setup job */
wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
- CTX_data_scene(C),
+ filelist,
"Listing Dirs...",
WM_JOB_PROGRESS,
WM_JOB_TYPE_FILESEL_READDIR);
WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free);
- WM_jobs_timer(wm_job,
- 0.01,
- NC_SPACE | ND_SPACE_FILE_LIST,
- NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED);
+ WM_jobs_timer(wm_job, 0.01, space_notifier, space_notifier | NA_JOB_FINISHED);
WM_jobs_callbacks(
wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob);
@@ -3521,12 +3503,12 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene)
+void filelist_readjob_stop(FileList *filelist, wmWindowManager *wm)
{
- WM_jobs_kill_type(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
+ WM_jobs_kill_type(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR);
}
-int filelist_readjob_running(wmWindowManager *wm, Scene *owner_scene)
+int filelist_readjob_running(FileList *filelist, wmWindowManager *wm)
{
- return WM_jobs_test(wm, owner_scene, WM_JOB_TYPE_FILESEL_READDIR);
+ return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_READDIR);
}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 9eb70dd8437..cb98cf6e74a 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -35,6 +35,8 @@ struct wmWindowManager;
struct FileDirEntry;
+typedef uint32_t FileUID;
+
typedef enum FileSelType {
FILE_SEL_REMOVE = 0,
FILE_SEL_ADD = 1,
@@ -77,6 +79,7 @@ void filelist_init_icons(void);
void filelist_free_icons(void);
struct ImBuf *filelist_getimage(struct FileList *filelist, const int index);
struct ImBuf *filelist_file_getimage(const FileDirEntry *file);
+struct ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);
struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index);
int filelist_geticon(struct FileList *filelist, const int index, const bool is_main);
@@ -95,9 +98,11 @@ int filelist_needs_reading(struct FileList *filelist);
FileDirEntry *filelist_file(struct FileList *filelist, int index);
FileDirEntry *filelist_file_ex(struct FileList *filelist, int index, bool use_request);
-int filelist_file_findpath(struct FileList *filelist, const char *file);
+int filelist_file_find_path(struct FileList *filelist, const char *file);
+int filelist_file_find_id(const struct FileList *filelist, const struct ID *id);
struct ID *filelist_file_get_id(const struct FileDirEntry *file);
-FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]);
+bool filelist_uid_is_set(const FileUID uid);
+void filelist_uid_unset(FileUID *r_uid);
void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size);
bool filelist_file_cache_block(struct FileList *filelist, const int index);
@@ -140,13 +145,16 @@ struct BlendHandle *filelist_lib(struct FileList *filelist);
bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group);
void filelist_freelib(struct FileList *filelist);
-void filelist_readjob_start(struct FileList *filelist, const struct bContext *C);
-void filelist_readjob_stop(struct wmWindowManager *wm, struct Scene *owner_scene);
-int filelist_readjob_running(struct wmWindowManager *wm, struct Scene *owner_scene);
+void filelist_readjob_start(struct FileList *filelist,
+ int space_notifier,
+ const struct bContext *C);
+void filelist_readjob_stop(struct FileList *filelist, struct wmWindowManager *wm);
+int filelist_readjob_running(struct FileList *filelist, struct wmWindowManager *wm);
bool filelist_cache_previews_update(struct FileList *filelist);
void filelist_cache_previews_set(struct FileList *filelist, const bool use_previews);
bool filelist_cache_previews_running(struct FileList *filelist);
+bool filelist_cache_previews_done(struct FileList *filelist);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 8e3fc36aa71..7bc83e8fc79 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -118,7 +118,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
asset_params = sfile->asset_params = MEM_callocN(sizeof(*asset_params),
"FileAssetSelectParams");
asset_params->base_params.details_flags = U_default.file_space_data.details_flags;
- asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL;
+ asset_params->asset_library.type = ASSET_LIBRARY_LOCAL;
asset_params->asset_library.custom_library_index = -1;
asset_params->import_type = FILE_ASSET_IMPORT_APPEND;
}
@@ -126,7 +126,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
FileSelectParams *base_params = &asset_params->base_params;
base_params->file[0] = '\0';
base_params->filter_glob[0] = '\0';
- /* TODO this way of using filters to form categories is notably slower than specifying a
+ /* TODO: this way of using filters to form categories is notably slower than specifying a
* "group" to read. That's because all types are read and filtering is applied afterwards. Would
* be nice if we could lazy-read individual groups. */
base_params->flag |= U_default.file_space_data.flag | FILE_ASSETS_ONLY | FILE_FILTER;
@@ -378,7 +378,7 @@ FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile)
return &sfile->asset_params->base_params;
}
- BLI_assert(!"Invalid browse mode set in file space.");
+ BLI_assert_msg(0, "Invalid browse mode set in file space.");
return NULL;
}
@@ -399,7 +399,7 @@ FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile)
return (FileSelectParams *)sfile->asset_params;
}
- BLI_assert(!"Invalid browse mode set in file space.");
+ BLI_assert_msg(0, "Invalid browse mode set in file space.");
return NULL;
}
@@ -420,26 +420,26 @@ static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params)
bUserAssetLibrary *user_library = NULL;
/* Ensure valid repository, or fall-back to local one. */
- if (library->type == FILE_ASSET_LIBRARY_CUSTOM) {
+ if (library->type == ASSET_LIBRARY_CUSTOM) {
BLI_assert(library->custom_library_index >= 0);
user_library = BKE_preferences_asset_library_find_from_index(&U,
library->custom_library_index);
if (!user_library) {
- library->type = FILE_ASSET_LIBRARY_LOCAL;
+ library->type = ASSET_LIBRARY_LOCAL;
}
}
switch (library->type) {
- case FILE_ASSET_LIBRARY_LOCAL:
+ case ASSET_LIBRARY_LOCAL:
base_params->dir[0] = '\0';
break;
- case FILE_ASSET_LIBRARY_CUSTOM:
+ case ASSET_LIBRARY_CUSTOM:
BLI_assert(user_library);
BLI_strncpy(base_params->dir, user_library->path, sizeof(base_params->dir));
break;
}
- base_params->type = (library->type == FILE_ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB;
+ base_params->type = (library->type == ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB;
}
void fileselect_refresh_params(SpaceFile *sfile)
@@ -1047,7 +1047,7 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *region)
* Support updating the directory even when this isn't the active space
* needed so RNA properties update function isn't context sensitive, see T70255.
*/
-void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
+void ED_file_change_dir_ex(bContext *C, ScrArea *area)
{
/* May happen when manipulating non-active spaces. */
if (UNLIKELY(area->spacetype != SPACE_FILE)) {
@@ -1057,10 +1057,7 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
if (params) {
wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
- if (LIKELY(scene != NULL)) {
- ED_fileselect_clear(wm, scene, sfile);
- }
+ ED_fileselect_clear(wm, sfile);
/* Clear search string, it is very rare to want to keep that filter while changing dir,
* and usually very annoying to keep it actually! */
@@ -1085,9 +1082,17 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area)
void ED_file_change_dir(bContext *C)
{
- bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
- ED_file_change_dir_ex(C, screen, area);
+ ED_file_change_dir_ex(C, area);
+}
+
+void file_select_deselect_all(SpaceFile *sfile, uint flag)
+{
+ FileSelection sel;
+ sel.first = 0;
+ sel.last = filelist_files_ensure(sfile->files) - 1;
+
+ filelist_entries_select_index_range_set(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
}
int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file)
@@ -1183,11 +1188,11 @@ int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
return match;
}
-void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
+void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile)
{
/* only NULL in rare cases - T29734. */
if (sfile->files) {
- filelist_readjob_stop(wm, owner_scene);
+ filelist_readjob_stop(sfile->files, wm);
filelist_freelib(sfile->files);
filelist_clear(sfile->files);
}
@@ -1197,7 +1202,7 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi
WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfile)
+void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile)
{
if (!sfile) {
return;
@@ -1224,13 +1229,72 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil
folder_history_list_free(sfile);
if (sfile->files) {
- ED_fileselect_clear(wm, owner_scene, sfile);
+ ED_fileselect_clear(wm, sfile);
filelist_free(sfile->files);
MEM_freeN(sfile->files);
sfile->files = NULL;
}
}
+void file_params_smoothscroll_timer_clear(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile)
+{
+ WM_event_remove_timer(wm, win, sfile->smoothscroll_timer);
+ sfile->smoothscroll_timer = NULL;
+}
+
+/**
+ * Set the renaming-state to #FILE_PARAMS_RENAME_POSTSCROLL_PENDING and trigger the smooth-scroll
+ * timer. To be used right after a file was renamed.
+ * Note that the caller is responsible for setting the correct rename-file info
+ * (#FileSelectParams.renamefile or #FileSelectParams.rename_id).
+ */
+void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile)
+{
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+
+ params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING;
+
+ if (sfile->smoothscroll_timer != NULL) {
+ file_params_smoothscroll_timer_clear(wm, win, sfile);
+ }
+ sfile->smoothscroll_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 1000.0);
+ sfile->scroll_offset = 0;
+}
+
+/**
+ * To be executed whenever renaming ends (successfully or not).
+ */
+void file_params_rename_end(wmWindowManager *wm,
+ wmWindow *win,
+ SpaceFile *sfile,
+ FileDirEntry *rename_file)
+{
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+
+ filelist_entry_select_set(
+ sfile->files, rename_file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
+
+ /* Ensure smooth-scroll timer is active, even if not needed, because that way rename state is
+ * handled properly. */
+ file_params_invoke_rename_postscroll(wm, win, sfile);
+ /* Also always activate the rename file, even if renaming was cancelled. */
+ file_params_renamefile_activate(sfile, params);
+}
+
+void file_params_renamefile_clear(FileSelectParams *params)
+{
+ params->renamefile[0] = '\0';
+ params->rename_id = NULL;
+ params->rename_flag = 0;
+}
+
+static int file_params_find_renamed(const FileSelectParams *params, struct FileList *filelist)
+{
+ /* Find the file either through the local ID/asset it represents or its relative path. */
+ return (params->rename_id != NULL) ? filelist_file_find_id(filelist, params->rename_id) :
+ filelist_file_find_path(filelist, params->renamefile);
+}
+
/**
* Helper used by both main update code, and smooth-scroll timer,
* to try to enable rename editing from #FileSelectParams.renamefile name.
@@ -1244,28 +1308,33 @@ void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params)
return;
}
- BLI_assert(params->renamefile[0] != '\0');
+ BLI_assert(params->renamefile[0] != '\0' || params->rename_id != NULL);
- const int idx = filelist_file_findpath(sfile->files, params->renamefile);
+ const int idx = file_params_find_renamed(params, sfile->files);
if (idx >= 0) {
FileDirEntry *file = filelist_file(sfile->files, idx);
BLI_assert(file != NULL);
+ params->active_file = idx;
+ filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+
if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) {
filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL);
params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
}
else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) {
- filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_HIGHLIGHTED, CHECK_ALL);
- params->renamefile[0] = '\0';
+ file_select_deselect_all(sfile, FILE_SEL_SELECTED);
+ filelist_entry_select_set(
+ sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED | FILE_SEL_HIGHLIGHTED, CHECK_ALL);
+ params->active_file = idx;
+ file_params_renamefile_clear(params);
params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE;
}
}
/* File listing is now async, only reset renaming if matching entry is not found
* when file listing is not done. */
else if (filelist_is_ready(sfile->files)) {
- params->renamefile[0] = '\0';
- params->rename_flag = 0;
+ file_params_renamefile_clear(params);
}
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 0418bb87768..31c7dee294b 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -32,6 +32,7 @@
#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "RNA_access.h"
@@ -206,7 +207,7 @@ static void file_exit(wmWindowManager *wm, ScrArea *area)
sfile->previews_timer = NULL;
}
- ED_fileselect_exit(wm, NULL, sfile);
+ ED_fileselect_exit(wm, sfile);
}
static SpaceLink *file_duplicate(SpaceLink *sl)
@@ -360,13 +361,13 @@ static void file_refresh(const bContext *C, ScrArea *area)
sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
if (filelist_needs_force_reset(sfile->files)) {
- filelist_readjob_stop(wm, CTX_data_scene(C));
+ filelist_readjob_stop(sfile->files, wm);
filelist_clear(sfile->files);
}
if (filelist_needs_reading(sfile->files)) {
if (!filelist_pending(sfile->files)) {
- filelist_readjob_start(sfile->files, C);
+ filelist_readjob_start(sfile->files, NC_SPACE | ND_SPACE_FILE_LIST, C);
}
}
@@ -429,10 +430,10 @@ static void file_reset_filelist_showing_main_data(ScrArea *area, SpaceFile *sfil
}
}
-static void file_listener(const wmSpaceTypeListenerParams *params)
+static void file_listener(const wmSpaceTypeListenerParams *listener_params)
{
- ScrArea *area = params->area;
- wmNotifier *wmn = params->notifier;
+ ScrArea *area = listener_params->area;
+ wmNotifier *wmn = listener_params->notifier;
SpaceFile *sfile = (SpaceFile *)area->spacedata.first;
/* context changes */
@@ -469,10 +470,19 @@ static void file_listener(const wmSpaceTypeListenerParams *params)
break;
case NC_ID: {
switch (wmn->action) {
- case NA_RENAME:
+ case NA_RENAME: {
+ const ID *active_file_id = ED_fileselect_active_asset_get(sfile);
+ /* If a renamed ID is active in the file browser, update scrolling to keep it in view. */
+ if (active_file_id && (wmn->reference == active_file_id)) {
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ params->rename_id = active_file_id;
+ file_params_invoke_rename_postscroll(G_MAIN->wm.first, listener_params->window, sfile);
+ }
+
/* Force list to update sorting (with a full reset for now). */
file_reset_filelist_showing_main_data(area, sfile);
break;
+ }
}
break;
}
@@ -508,10 +518,10 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *region)
WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
}
-static void file_main_region_listener(const wmRegionListenerParams *params)
+static void file_main_region_listener(const wmRegionListenerParams *listener_params)
{
- ARegion *region = params->region;
- wmNotifier *wmn = params->notifier;
+ ARegion *region = listener_params->region;
+ wmNotifier *wmn = listener_params->notifier;
/* context changes */
switch (wmn->category) {
@@ -716,14 +726,14 @@ static void file_tools_region_draw(const bContext *C, ARegion *region)
ED_region_panels(C, region);
}
-static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(params))
+static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(listener_params))
{
}
-static void file_tool_props_region_listener(const wmRegionListenerParams *params)
+static void file_tool_props_region_listener(const wmRegionListenerParams *listener_params)
{
- const wmNotifier *wmn = params->notifier;
- ARegion *region = params->region;
+ const wmNotifier *wmn = listener_params->notifier;
+ ARegion *region = listener_params->region;
switch (wmn->category) {
case NC_ID:
@@ -789,10 +799,10 @@ static void file_execution_region_draw(const bContext *C, ARegion *region)
ED_region_panels(C, region);
}
-static void file_ui_region_listener(const wmRegionListenerParams *params)
+static void file_ui_region_listener(const wmRegionListenerParams *listener_params)
{
- ARegion *region = params->region;
- wmNotifier *wmn = params->notifier;
+ ARegion *region = listener_params->region;
+ wmNotifier *wmn = listener_params->notifier;
/* context changes */
switch (wmn->category) {
@@ -858,7 +868,12 @@ static void file_space_subtype_item_extend(bContext *UNUSED(C),
}
}
-static const char *file_context_dir[] = {"active_file", "id", NULL};
+static const char *file_context_dir[] = {
+ "active_file",
+ "asset_library",
+ "id",
+ NULL,
+};
static int /*eContextResult*/ file_context(const bContext *C,
const char *member,
@@ -889,6 +904,23 @@ static int /*eContextResult*/ file_context(const bContext *C,
CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file);
return CTX_RESULT_OK;
}
+ if (CTX_data_equals(member, "asset_library")) {
+ FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
+ if (!asset_params) {
+ return CTX_RESULT_NO_DATA;
+ }
+
+ BLI_STATIC_ASSERT(offsetof(FileSelectAssetLibraryUID, type) ==
+ offsetof(AssetLibraryReference, type),
+ "Expected FileSelectAssetLibraryUID to match AssetLibraryReference");
+ BLI_STATIC_ASSERT(offsetof(FileSelectAssetLibraryUID, custom_library_index) ==
+ offsetof(AssetLibraryReference, custom_library_index),
+ "Expected FileSelectAssetLibraryUID to match AssetLibraryReference");
+
+ CTX_data_pointer_set(
+ result, &screen->id, &RNA_AssetLibraryReference, &asset_params->asset_library);
+ return CTX_RESULT_OK;
+ }
if (CTX_data_equals(member, "id")) {
const FileDirEntry *file = filelist_file(sfile->files, params->active_file);
if (file == NULL) {
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 0d2a436902a..af88bbced9c 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -414,7 +414,7 @@ static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu)
}
/* draw lines for F-Curve handles only (this is only done in EditMode)
- * note: draw_fcurve_handles_check must be checked before running this. */
+ * NOTE: draw_fcurve_handles_check must be checked before running this. */
static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
{
int sel, b;
@@ -1259,14 +1259,15 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
immUniformColor3f(0.9f, 0.9f, 0.9f);
immUniform1f("dash_width", 10.0f);
immUniform1f("dash_factor", 0.5f);
+ GPU_line_width(1.0f);
- immBegin(GPU_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
+ immBegin(GPU_PRIM_LINES, (y <= v2d->cur.ymax) ? 4 : 2);
/* x-axis lookup */
co[0] = x;
- if (y >= v2d->cur.ymin) {
- co[1] = v2d->cur.ymin - 1.0f;
+ if (y <= v2d->cur.ymax) {
+ co[1] = v2d->cur.ymax + 1.0f;
immVertex2fv(shdr_pos, co);
co[1] = y;
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index be577e9ab13..6f1b0bb0d7d 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1481,7 +1481,7 @@ static void setipo_graph_keys(bAnimContext *ac, short mode)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting BezTriple interpolation
- * Note: we do not supply KeyframeEditData to the looper yet.
+ * NOTE: we do not supply KeyframeEditData to the looper yet.
* Currently that's not necessary here.
*/
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -1558,7 +1558,7 @@ static void seteasing_graph_keys(bAnimContext *ac, short mode)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting BezTriple easing.
- * Note: we do not supply KeyframeEditData to the looper yet.
+ * NOTE: we do not supply KeyframeEditData to the looper yet.
* Currently that's not necessary here.
*/
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -1636,7 +1636,7 @@ static void sethandles_graph_keys(bAnimContext *ac, short mode)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting flags for handles.
- * Note: we do not supply KeyframeEditData to the looper yet.
+ * NOTE: we do not supply KeyframeEditData to the looper yet.
* Currently that's not necessary here.
*/
for (ale = anim_data.first; ale; ale = ale->next) {
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 2f4e1c1abbe..a853efb1ace 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -167,7 +167,7 @@ static void nearest_fcurve_vert_store(ListBase *matches,
}
}
else if (fpt) {
- /* TODO... */
+ /* TODO: support #FPoint. */
}
}
@@ -257,7 +257,7 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
}
}
else if (fcu->fpt) {
- /* TODO; do this for samples too */
+ /* TODO: do this for samples too. */
}
/* un-apply NLA mapping from all the keyframes */
@@ -736,7 +736,7 @@ static bool rectf_curve_intersection(
* to select a curve by sampling it at various points instead of trying to select the
* keyframes directly.
* The selection actions done to a curve are actually done on all the keyframes of the curve.
- * Note: This function is only called if no keyframe is in the selection area.
+ * NOTE: This function is only called if no keyframe is in the selection area.
*/
static void box_select_graphcurves(bAnimContext *ac,
const rctf *rectf_view,
@@ -859,7 +859,7 @@ static int graphkeys_box_select_exec(bContext *C, wmOperator *op)
* as frame-range one is often used for tweaking timing when "blocking",
* while channels is not that useful.
*/
- if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) {
+ if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) {
mode = BEZT_OK_FRAMERANGE;
}
else {
@@ -1131,8 +1131,8 @@ static const EnumPropertyItem prop_column_select_types[] = {
/* ------------------- */
/* Selects all visible keyframes between the specified markers */
-/* TODO, this is almost an _exact_ duplicate of a function of the same name in action_select.c
- * should de-duplicate - campbell */
+/* TODO(campbell): this is almost an _exact_ duplicate of a function of the same name in
+ * action_select.c should de-duplicate. */
static void markers_selectkeys_between(bAnimContext *ac)
{
ListBase anim_data = {NULL, NULL};
diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c
index ca14f7c5942..31c53cde62c 100644
--- a/source/blender/editors/space_graph/graph_view.c
+++ b/source/blender/editors/space_graph/graph_view.c
@@ -51,7 +51,7 @@
/* *************************** Calculate Range ************************** */
/* Get the min/max keyframes. */
-/* Note: it should return total boundbox, filter for selection only can be argument... */
+/* NOTE: it should return total boundbox, filter for selection only can be argument... */
void get_graph_keyframe_extents(bAnimContext *ac,
float *xmin,
float *xmax,
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 32496cb8f1f..49966e880d3 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -229,7 +229,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *region)
graph_draw_curves(&ac, sipo, region, 0);
graph_draw_curves(&ac, sipo, region, 1);
- /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */
+ /* XXX(ton): the slow way to set tot rect... but for nice sliders needed. */
get_graph_keyframe_extents(
&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true);
/* extra offset so that these items are visible */
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index d909bfd1864..4779a82948d 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -511,7 +511,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt
return false;
}
- /* note, this looks reversed, but matches menu direction */
+ /* NOTE: this looks reversed, but matches menu direction. */
if (direction == -1) {
RenderPass *rp;
int rp_index = iuser->pass + 1;
@@ -1013,14 +1013,14 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma
uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
/* only display depth setting if multiple depths can be used */
- if ((ELEM(depth_ok,
- R_IMF_CHAN_DEPTH_1,
- R_IMF_CHAN_DEPTH_8,
- R_IMF_CHAN_DEPTH_10,
- R_IMF_CHAN_DEPTH_12,
- R_IMF_CHAN_DEPTH_16,
- R_IMF_CHAN_DEPTH_24,
- R_IMF_CHAN_DEPTH_32)) == 0) {
+ if (ELEM(depth_ok,
+ R_IMF_CHAN_DEPTH_1,
+ R_IMF_CHAN_DEPTH_8,
+ R_IMF_CHAN_DEPTH_10,
+ R_IMF_CHAN_DEPTH_12,
+ R_IMF_CHAN_DEPTH_16,
+ R_IMF_CHAN_DEPTH_24,
+ R_IMF_CHAN_DEPTH_32) == 0) {
uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index c26f92c5463..169dafcb8d0 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -51,7 +51,7 @@
#include "WM_api.h"
#include "WM_types.h"
-/* note; image_panel_properties() uses pointer to sima->image directly */
+/* NOTE: image_panel_properties() uses pointer to sima->image directly. */
Image *ED_space_image(SpaceImage *sima)
{
return sima->image;
@@ -64,8 +64,6 @@ void ED_space_image_set(Main *bmain, SpaceImage *sima, Object *obedit, Image *im
sima->pin = true;
}
- /* change the space ima after because uvedit_face_visible_test uses the space ima
- * to check if the face is displayed in UV-localview */
sima->image = ima;
if (ima == NULL || ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE) {
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 193c35d10a2..dad354ba8ee 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1995,7 +1995,7 @@ static bool image_save_as_draw_check_prop(PointerRNA *ptr,
return !(STREQ(prop_id, "filepath") || STREQ(prop_id, "directory") ||
STREQ(prop_id, "filename") ||
/* when saving a copy, relative path has no effect */
- ((STREQ(prop_id, "relative_path")) && RNA_boolean_get(ptr, "copy")));
+ (STREQ(prop_id, "relative_path") && RNA_boolean_get(ptr, "copy")));
}
static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
@@ -2712,10 +2712,10 @@ static int image_flip_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- const bool flip_horizontal = RNA_boolean_get(op->ptr, "use_flip_horizontal");
- const bool flip_vertical = RNA_boolean_get(op->ptr, "use_flip_vertical");
+ const bool use_flip_x = RNA_boolean_get(op->ptr, "use_flip_x");
+ const bool use_flip_y = RNA_boolean_get(op->ptr, "use_flip_y");
- if (!flip_horizontal && !flip_vertical) {
+ if (!use_flip_x && !use_flip_y) {
BKE_image_release_ibuf(ima, ibuf, NULL);
return OPERATOR_FINISHED;
}
@@ -2734,11 +2734,12 @@ static int image_flip_exec(bContext *C, wmOperator *op)
float *orig_float_pixels = MEM_dupallocN(float_pixels);
for (int x = 0; x < size_x; x++) {
+ const int source_pixel_x = use_flip_x ? size_x - x - 1 : x;
for (int y = 0; y < size_y; y++) {
- const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x;
- const int source_pixel_y = flip_vertical ? size_y - y - 1 : y;
+ const int source_pixel_y = use_flip_y ? size_y - y - 1 : y;
- float *source_pixel = &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)];
+ const float *source_pixel =
+ &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)];
float *target_pixel = &float_pixels[4 * (x + y * size_x)];
copy_v4_v4(target_pixel, source_pixel);
@@ -2754,11 +2755,12 @@ static int image_flip_exec(bContext *C, wmOperator *op)
char *char_pixels = (char *)ibuf->rect;
char *orig_char_pixels = MEM_dupallocN(char_pixels);
for (int x = 0; x < size_x; x++) {
+ const int source_pixel_x = use_flip_x ? size_x - x - 1 : x;
for (int y = 0; y < size_y; y++) {
- const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x;
- const int source_pixel_y = flip_vertical ? size_y - y - 1 : y;
+ const int source_pixel_y = use_flip_y ? size_y - y - 1 : y;
- char *source_pixel = &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)];
+ const char *source_pixel =
+ &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)];
char *target_pixel = &char_pixels[4 * (x + y * size_x)];
copy_v4_v4_char(target_pixel, source_pixel);
@@ -2804,10 +2806,9 @@ void IMAGE_OT_flip(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
prop = RNA_def_boolean(
- ot->srna, "use_flip_horizontal", false, "Horizontal", "Flip the image horizontally");
+ ot->srna, "use_flip_x", false, "Horizontal", "Flip the image horizontally");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(
- ot->srna, "use_flip_vertical", false, "Vertical", "Flip the image vertically");
+ prop = RNA_def_boolean(ot->srna, "use_flip_y", false, "Vertical", "Flip the image vertically");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
/* flags */
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index 082f66b57af..cc6effd0f71 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -1006,7 +1006,7 @@ void ED_image_undosys_type(UndoType *ut)
* specific case, see `image_undosys_step_encode` code. We cannot specify
* `UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE` though, as it can be called with a NULL context by
* current code. */
- ut->flags = 0;
+ ut->flags = UNDOTYPE_FLAG_DECODE_ACTIVE_STEP;
ut->step_size = sizeof(ImageUndoStep);
}
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index aaf9852e212..94e53958524 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -564,12 +564,11 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
/** \name Report Box Operator
* \{ */
-/* Hard to decide whether to keep this as an operator,
- * or turn it into a hardcoded ui control feature,
- * handling TIMER events for all regions in interface_handlers.c
+/* NOTE(matt): Hard to decide whether to keep this as an operator,
+ * or turn it into a hard_coded UI control feature,
+ * handling TIMER events for all regions in `interface_handlers.c`.
* Not sure how good that is to be accessing UI data from
- * inactive regions, so use this for now. --matt
- */
+ * inactive regions, so use this for now. */
#define INFO_TIMEOUT 5.0f
#define ERROR_TIMEOUT 10.0f
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index a3da50709df..1062b76b1df 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -102,7 +102,7 @@ int info_report_mask(const SpaceInfo *UNUSED(sinfo))
static int report_replay_exec(bContext *C, wmOperator *UNUSED(op))
{
- /* TODO, get this working again! */
+ /* TODO: get this working again! */
#if 0
SpaceInfo *sc = CTX_wm_space_info(C);
ReportList *reports = CTX_wm_reports(C);
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 9e0973f5fde..d7671a372c6 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -96,7 +96,7 @@ typedef struct SceneStatsFmt {
char totgpstroke[MAX_INFO_NUM_LEN], totgppoint[MAX_INFO_NUM_LEN];
} SceneStatsFmt;
-static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats)
+static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *stats)
{
if (me_eval == NULL) {
return false;
@@ -149,8 +149,8 @@ static void stats_object(Object *ob,
switch (ob->type) {
case OB_MESH: {
/* we assume evaluated mesh is already built, this strictly does stats now. */
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
- if (!BLI_gset_add(objects_gset, me_eval)) {
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
+ if (!BLI_gset_add(objects_gset, (void *)me_eval)) {
break;
}
stats_mesheval(me_eval, is_selected, stats);
@@ -165,8 +165,8 @@ static void stats_object(Object *ob,
case OB_SURF:
case OB_CURVE:
case OB_FONT: {
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
- if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) {
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
+ if ((me_eval != NULL) && !BLI_gset_add(objects_gset, (void *)me_eval)) {
break;
}
@@ -179,7 +179,7 @@ static void stats_object(Object *ob,
int totv = 0, totf = 0, tottri = 0;
if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
- /* Note: We only get the same curve_cache for instances of the same curve/font/...
+ /* NOTE: We only get the same curve_cache for instances of the same curve/font/...
* For simple linked duplicated objects, each has its own dispList. */
if (!BLI_gset_add(objects_gset, ob->runtime.curve_cache)) {
break;
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index aef59e89325..e656155fb13 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -353,7 +353,7 @@ int textview_draw(TextViewContext *tvc,
tds.lheight = tvc->lheight;
tds.row_vpadding = tvc->row_vpadding;
tds.lofs = -BLF_descender(font_id);
- /* Note, scroll bar must be already subtracted. */
+ /* NOTE: scroll bar must be already subtracted. */
tds.columns = (tvc->draw_rect.xmax - tvc->draw_rect.xmin) / tds.cwidth;
/* Avoid divide by zero on small windows. */
if (tds.columns < 1) {
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index f2cea23af76..0498964c549 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -288,14 +288,14 @@ static int mouse_nla_channels(
/* button region... */
if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
if (nlaedit_is_tweakmode_on(ac) == 0) {
- /* 'push-down' action - only usable when not in TweakMode */
+ /* 'push-down' action - only usable when not in tweak-mode */
/* TODO: make this use the operator instead of calling the function directly
* however, calling the operator requires that we supply the args,
* and that works with proper buttons only */
BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id));
}
else {
- /* when in tweakmode, this button becomes the toggle for mapped editing */
+ /* When in tweak-mode, this button becomes the toggle for mapped editing. */
adt->flag ^= ADT_NLA_EDIT_NOMAP;
}
@@ -308,13 +308,13 @@ static int mouse_nla_channels(
/* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
* - this is useful when there's no clear divider, and makes more sense in
* the case of users trying to use this to change actions
- * - in tweakmode, clicking here gets us out of tweakmode, as changing selection
- * while in tweakmode is really evil!
+ * - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection
+ * while in tweak-mode is really evil!
* - we disable "solo" flags too, to make it easier to work with stashed actions
* with less trouble
*/
if (nlaedit_is_tweakmode_on(ac)) {
- /* exit tweakmode immediately */
+ /* Exit tweak-mode immediately. */
nlaedit_disable_tweakmode(ac, true);
/* changes to NLA-Action occurred */
@@ -515,7 +515,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- /* 'push-down' action - only usable when not in TweakMode */
+ /* 'push-down' action - only usable when not in Tweak-mode. */
BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id));
struct Main *bmain = CTX_data_main(C);
@@ -874,7 +874,7 @@ static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op))
/* operate on selected objects... */
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
/* ensure that object has AnimData... that's all */
- BKE_animdata_add_id(&ob->id);
+ BKE_animdata_ensure_id(&ob->id);
}
CTX_DATA_END;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 0fd1a1318e8..f9fb386095d 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -127,8 +127,8 @@ static void nla_action_draw_keyframes(
immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
immUnbindProgram();
- /* count keys before drawing */
- /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
+ /* Count keys before drawing. */
+ /* NOTE: It's safe to cast #DLRBT_Tree, as it's designed to degrade down to a #ListBase. */
uint key_len = BLI_listbase_count((ListBase *)&keys);
if (key_len > 0) {
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 3ca3aa15cd3..56efcd8571f 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -65,7 +65,7 @@
#include "UI_view2d.h"
#include "nla_intern.h" /* own include */
-#include "nla_private.h" /* FIXME... maybe this shouldn't be included? */
+#include "nla_private.h" /* FIXME: maybe this shouldn't be included? */
/* -------------------------------------------------------------------- */
/** \name Public Utilities
@@ -135,7 +135,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ale->data;
- /* try entering tweakmode if valid */
+ /* Try entering tweak-mode if valid. */
ok |= BKE_nla_tweakmode_enter(adt);
/* mark the active track as being "solo"? */
@@ -154,9 +154,8 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
- /* if we managed to enter tweakmode on at least one AnimData block,
- * set the flag for this in the active scene and send notifiers
- */
+ /* If we managed to enter tweak-mode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers. */
if (ac.scene && ok) {
/* set editing flag */
ac.scene->flag |= SCE_NLA_EDIT_ON;
@@ -206,7 +205,7 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot)
/** \name Disable Tweak-Mode Operator
* \{ */
-/* NLA Editor internal API function for exiting tweakmode */
+/* NLA Editor internal API function for exiting tweak-mode. */
bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
{
ListBase anim_data = {NULL, NULL};
@@ -232,7 +231,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
BKE_nlatrack_solo_toggle(adt, NULL);
}
- /* to be sure that we're doing everything right, just exit tweakmode... */
+ /* To be sure that we're doing everything right, just exit tweak-mode. */
BKE_nla_tweakmode_exit(adt);
ale->update |= ANIM_UPDATE_DEPS;
@@ -242,7 +241,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
- /* if we managed to enter tweakmode on at least one AnimData block,
+ /* if we managed to enter tweak-mode on at least one AnimData block,
* set the flag for this in the active scene and send notifiers
*/
if (ac->scene) {
@@ -257,7 +256,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
return true;
}
-/* exit tweakmode operator callback */
+/* Exit tweak-mode operator callback. */
static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -1157,7 +1156,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
NlaStrip *strip, *nstrip, *next;
NlaTrack *track;
- /* Note: We allow this operator in override context because it is almost always (from possible
+ /* NOTE: We allow this operator in override context because it is almost always (from possible
* default user interactions) paired with the transform one, which will ensure that the new
* strip ends up in a valid (local) track. */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 631dc2e550c..28f194877fa 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -39,17 +39,16 @@
/* ************************** poll callbacks for operators **********************************/
-/* tweakmode is NOT enabled */
+/* Tweak-mode is NOT enabled. */
bool nlaop_poll_tweakmode_off(bContext *C)
{
Scene *scene;
/* for now, we check 2 things:
* 1) active editor must be NLA
- * 2) tweakmode is currently set as a 'per-scene' flag
+ * 2) tweak-mode is currently set as a 'per-scene' flag
* so that it will affect entire NLA data-sets,
- * but not all AnimData blocks will be in tweakmode for
- * various reasons
+ * but not all AnimData blocks will be in tweak-mode for various reasons.
*/
if (ED_operator_nla_active(C) == 0) {
return 0;
@@ -63,17 +62,16 @@ bool nlaop_poll_tweakmode_off(bContext *C)
return 1;
}
-/* tweakmode IS enabled */
+/* Tweak-mode IS enabled. */
bool nlaop_poll_tweakmode_on(bContext *C)
{
Scene *scene;
/* for now, we check 2 things:
* 1) active editor must be NLA
- * 2) tweakmode is currently set as a 'per-scene' flag
+ * 2) tweak-mode is currently set as a 'per-scene' flag
* so that it will affect entire NLA data-sets,
- * but not all AnimData blocks will be in tweakmode for
- * various reasons
+ * but not all AnimData blocks will be in tweak-mode for various reasons.
*/
if (ED_operator_nla_active(C) == 0) {
return 0;
@@ -87,7 +85,7 @@ bool nlaop_poll_tweakmode_on(bContext *C)
return 1;
}
-/* is tweakmode enabled - for use in NLA operator code */
+/* is tweak-mode enabled - for use in NLA operator code */
bool nlaedit_is_tweakmode_on(bAnimContext *ac)
{
if (ac && ac->scene) {
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index dc95a01a021..246c3e0156a 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -453,7 +453,7 @@ static void nlaedit_select_leftright(bContext *C,
Scene *scene = ac->scene;
float xmin, xmax;
- /* if currently in tweakmode, exit tweakmode first */
+ /* if currently in tweak-mode, exit tweak-mode first */
if (scene->flag & SCE_NLA_EDIT_ON) {
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
}
@@ -612,7 +612,7 @@ static int mouse_nla_strips(bContext *C,
nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip);
- /* if currently in tweakmode, exit tweakmode before changing selection states
+ /* if currently in tweak-mode, exit tweak-mode before changing selection states
* now that we've found our target...
*/
if (scene->flag & SCE_NLA_EDIT_ON) {
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 6e234c5b2ce..80d3b43bf6b 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../compositor
../../depsgraph
../../draw
+ ../../functions
../../gpu
../../imbuf
../../makesdna
@@ -39,7 +40,6 @@ set(INC
set(SRC
drawnode.cc
node_add.cc
- node_buttons.c
node_draw.cc
node_edit.cc
node_geometry_attribute_search.cc
@@ -78,4 +78,20 @@ if(WITH_OPENSUBDIV)
add_definitions(-DWITH_OPENSUBDIV)
endif()
+if(WITH_TBB)
+ add_definitions(-DWITH_TBB)
+ if(WIN32)
+ # TBB includes Windows.h which will define min/max macros
+ # that will collide with the stl versions.
+ add_definitions(-DNOMINMAX)
+ endif()
+ list(APPEND INC_SYS
+ ${TBB_INCLUDE_DIRS}
+ )
+
+ list(APPEND LIB
+ ${TBB_LIBRARIES}
+ )
+endif()
+
blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index d99433b47a8..8da67bbd21b 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -758,7 +758,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
uiItemR(layout, ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE);
- /* note: image user properties used directly here, unlike compositor image node,
+ /* NOTE: image user properties used directly here, unlike compositor image node,
* which redefines them in the node struct RNA to get proper updates.
*/
node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false, true);
@@ -1953,8 +1953,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
0,
0,
0,
- false,
- false);
+ UI_TEMPLATE_LIST_FLAG_NONE);
RNA_property_collection_lookup_int(
ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr);
}
@@ -1972,8 +1971,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
0,
0,
0,
- false,
- false);
+ UI_TEMPLATE_LIST_FLAG_NONE);
RNA_property_collection_lookup_int(
ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr);
}
@@ -4029,8 +4027,10 @@ static struct {
GPUVertBuf *inst_vbo;
uint p0_id, p1_id, p2_id, p3_id;
uint colid_id, muted_id;
+ uint dim_factor_id;
GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
GPUVertBufRaw colid_step, muted_step;
+ GPUVertBufRaw dim_factor_step;
uint count;
bool enabled;
} g_batch_link;
@@ -4045,6 +4045,8 @@ static void nodelink_batch_reset()
g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
GPU_vertbuf_attr_get_raw_data(
g_batch_link.inst_vbo, g_batch_link.muted_id, &g_batch_link.muted_step);
+ GPU_vertbuf_attr_get_raw_data(
+ g_batch_link.inst_vbo, g_batch_link.dim_factor_id, &g_batch_link.dim_factor_step);
g_batch_link.count = 0;
}
@@ -4162,6 +4164,8 @@ static void nodelink_batch_init()
&format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT);
g_batch_link.muted_id = GPU_vertformat_attr_add(
&format_inst, "domuted", GPU_COMP_U8, 2, GPU_FETCH_INT);
+ g_batch_link.dim_factor_id = GPU_vertformat_attr_add(
+ &format_inst, "dim_factor", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM);
/* Alloc max count but only draw the range we need. */
GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE);
@@ -4237,7 +4241,8 @@ static void nodelink_batch_add_link(const SpaceNode *snode,
int th_col2,
int th_col3,
bool drawarrow,
- bool drawmuted)
+ bool drawmuted,
+ float dim_factor)
{
/* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
@@ -4256,6 +4261,7 @@ static void nodelink_batch_add_link(const SpaceNode *snode,
colid[3] = drawarrow;
char *muted = (char *)GPU_vertbuf_raw_step(&g_batch_link.muted_step);
muted[0] = drawmuted;
+ *(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = dim_factor;
if (g_batch_link.count == NODELINK_GROUP_SIZE) {
nodelink_batch_draw(snode);
@@ -4270,6 +4276,8 @@ void node_draw_link_bezier(const View2D *v2d,
int th_col2,
int th_col3)
{
+ const float dim_factor = node_link_dim_factor(v2d, link);
+
float vec[4][2];
const bool highlighted = link->flag & NODE_LINK_TEMP_HIGHLIGHT;
if (node_link_bezier_handles(v2d, snode, link, vec)) {
@@ -4282,8 +4290,17 @@ void node_draw_link_bezier(const View2D *v2d,
if (g_batch_link.enabled && !highlighted) {
/* Add link to batch. */
- nodelink_batch_add_link(
- snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow, drawmuted);
+ nodelink_batch_add_link(snode,
+ vec[0],
+ vec[1],
+ vec[2],
+ vec[3],
+ th_col1,
+ th_col2,
+ th_col3,
+ drawarrow,
+ drawmuted,
+ dim_factor);
}
else {
/* Draw single link. */
@@ -4308,12 +4325,13 @@ void node_draw_link_bezier(const View2D *v2d,
GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
GPU_batch_uniform_1i(batch, "doArrow", drawarrow);
GPU_batch_uniform_1i(batch, "doMuted", drawmuted);
+ GPU_batch_uniform_1f(batch, "dim_factor", dim_factor);
GPU_batch_draw(batch);
}
}
}
-/* note; this is used for fake links in groups too */
+/* NOTE: this is used for fake links in groups too. */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
{
int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc
index 6143af8ed70..9264c9d3572 100644
--- a/source/blender/editors/space_node/node_add.cc
+++ b/source/blender/editors/space_node/node_add.cc
@@ -90,7 +90,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
nodeSetSelected(node, true);
ntreeUpdateTree(bmain, snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node, nullptr);
+ ED_node_set_active(bmain, snode, snode->edittree, node, nullptr);
snode_update(snode, node);
@@ -260,7 +260,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
BLI_listbase_clear(&input_links);
for (link = (bNodeLink *)ntree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link)) {
continue;
}
if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
deleted file mode 100644
index 336b0c46a81..00000000000
--- a/source/blender/editors/space_node/node_buttons.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup spnode
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_node_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-
-#include "BLT_translation.h"
-
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_node.h"
-#include "BKE_screen.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-
-#include "ED_screen.h"
-
-#include "UI_resources.h"
-
-#include "node_intern.h" /* own include */
-
-/* ******************* node space & buttons ************** */
-
-#if 0
-/* poll for active nodetree */
-static bool active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- return (snode && snode->nodetree);
-}
-#endif
-
-static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- return (snode && snode->nodetree && G.debug_value == 777);
-}
-
-static void node_sockets_panel(const bContext *C, Panel *panel)
-{
- SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */
- bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */
- bNode *node = nodeGetActive(ntree);
- if (node == NULL) {
- return;
- }
-
- LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
- char name[UI_MAX_NAME_STR];
- BLI_snprintf(name, sizeof(name), "%s:", socket->name);
-
- uiLayout *split = uiLayoutSplit(panel->layout, 0.35f, false);
- uiItemL(split, name, ICON_NONE);
- uiTemplateNodeLink(split, (bContext *)C, ntree, node, socket);
- }
-}
-
-static bool node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- return (snode && snode->edittree &&
- (snode->edittree->inputs.first || snode->edittree->outputs.first));
-}
-
-static bNodeSocket *node_tree_find_active_socket(bNodeTree *ntree, const eNodeSocketInOut in_out)
-{
- ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
- LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
- if (socket->flag & SELECT) {
- return socket;
- }
- }
- return NULL;
-}
-
-static void draw_socket_list(const bContext *C,
- uiLayout *layout,
- bNodeTree *ntree,
- const eNodeSocketInOut in_out)
-{
- PointerRNA tree_ptr;
- RNA_id_pointer_create((ID *)ntree, &tree_ptr);
-
- uiLayout *split = uiLayoutRow(layout, false);
- uiLayout *list_col = uiLayoutColumn(split, true);
- uiTemplateList(list_col,
- (bContext *)C,
- "NODE_UL_interface_sockets",
- (in_out == SOCK_IN) ? "inputs" : "outputs",
- &tree_ptr,
- (in_out == SOCK_IN) ? "inputs" : "outputs",
- &tree_ptr,
- (in_out == SOCK_IN) ? "active_input" : "active_output",
- NULL,
- 0,
- 0,
- 0,
- 0,
- false,
- false);
- PointerRNA opptr;
- uiLayout *ops_col = uiLayoutColumn(split, false);
- uiLayout *add_remove_col = uiLayoutColumn(ops_col, true);
- wmOperatorType *ot = WM_operatortype_find("NODE_OT_tree_socket_add", false);
- uiItemFullO_ptr(add_remove_col, ot, "", ICON_ADD, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "in_out", in_out);
- ot = WM_operatortype_find("NODE_OT_tree_socket_remove", false);
- uiItemFullO_ptr(add_remove_col, ot, "", ICON_REMOVE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "in_out", in_out);
-
- uiItemS(ops_col);
-
- uiLayout *up_down_col = uiLayoutColumn(ops_col, true);
- ot = WM_operatortype_find("NODE_OT_tree_socket_move", false);
- uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "direction", 1);
- RNA_enum_set(&opptr, "in_out", in_out);
- uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "direction", 2);
- RNA_enum_set(&opptr, "in_out", in_out);
-
- bNodeSocket *socket = node_tree_find_active_socket(ntree, in_out);
- if (socket != NULL) {
- uiLayoutSetPropSep(layout, true);
- uiLayoutSetPropDecorate(layout, false);
- PointerRNA socket_ptr;
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, socket, &socket_ptr);
- uiItemR(layout, &socket_ptr, "name", 0, NULL, ICON_NONE);
-
- /* Display descriptions only for Geometry Nodes, since it's only used in the modifier panel. */
- if (ntree->type == NTREE_GEOMETRY) {
- uiItemR(layout, &socket_ptr, "description", 0, NULL, ICON_NONE);
- }
-
- if (socket->typeinfo->interface_draw) {
- socket->typeinfo->interface_draw((bContext *)C, layout, &socket_ptr);
- }
- }
-}
-
-static void node_tree_interface_inputs_panel(const bContext *C, Panel *panel)
-{
- SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */
- bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */
-
- draw_socket_list(C, panel->layout, ntree, SOCK_IN);
-}
-
-static void node_tree_interface_outputs_panel(const bContext *C, Panel *panel)
-{
- SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */
- bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */
-
- draw_socket_list(C, panel->layout, ntree, SOCK_OUT);
-}
-
-/* ******************* node buttons registration ************** */
-
-void node_buttons_register(ARegionType *art)
-{
- {
- PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
- strcpy(pt->idname, "NODE_PT_sockets");
- strcpy(pt->category, N_("Node"));
- strcpy(pt->label, N_("Sockets"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = node_sockets_panel;
- pt->poll = node_sockets_poll;
- pt->flag |= PANEL_TYPE_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
- }
-
- {
- PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
- strcpy(pt->idname, "NODE_PT_node_tree_interface_inputs");
- strcpy(pt->category, N_("Group"));
- strcpy(pt->label, N_("Inputs"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = node_tree_interface_inputs_panel;
- pt->poll = node_tree_interface_poll;
- BLI_addtail(&art->paneltypes, pt);
- }
- {
- PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
- strcpy(pt->idname, "NODE_PT_node_tree_interface_outputs");
- strcpy(pt->category, N_("Group"));
- strcpy(pt->label, N_("Outputs"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = node_tree_interface_outputs_panel;
- pt->poll = node_tree_interface_poll;
- BLI_addtail(&art->paneltypes, pt);
- }
-}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 8599b159cca..ed88489c63e 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -45,10 +45,10 @@
#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
-#include "BKE_node_ui_storage.hh"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
@@ -76,6 +76,8 @@
#include "RNA_access.h"
+#include "NOD_geometry_nodes_eval_log.hh"
+
#include "node_intern.h" /* own include */
#ifdef WITH_COMPOSITOR
@@ -86,6 +88,9 @@ using blender::Map;
using blender::Set;
using blender::Span;
using blender::Vector;
+using blender::fn::CPPType;
+using blender::fn::GPointer;
+namespace geo_log = blender::nodes::geometry_nodes_eval_log;
extern "C" {
/* XXX interface.h */
@@ -833,6 +838,149 @@ void node_socket_color_get(bContext *C,
}
}
+struct SocketTooltipData {
+ bNodeTree *ntree;
+ bNode *node;
+ bNodeSocket *socket;
+};
+
+static void create_inspection_string_for_generic_value(const geo_log::GenericValueLog &value_log,
+ std::stringstream &ss)
+{
+ auto id_to_inspection_string = [&](ID *id) {
+ ss << (id ? id->name + 2 : TIP_("None")) << " (" << BKE_idtype_idcode_to_name(GS(id->name))
+ << ")";
+ };
+
+ const GPointer value = value_log.value();
+ if (value.is_type<int>()) {
+ ss << *value.get<int>() << TIP_(" (Integer)");
+ }
+ else if (value.is_type<float>()) {
+ ss << *value.get<float>() << TIP_(" (Float)");
+ }
+ else if (value.is_type<blender::float3>()) {
+ ss << *value.get<blender::float3>() << TIP_(" (Vector)");
+ }
+ else if (value.is_type<bool>()) {
+ ss << (*value.get<bool>() ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)");
+ }
+ else if (value.is_type<std::string>()) {
+ ss << *value.get<std::string>() << TIP_(" (String)");
+ }
+ else if (value.is_type<Object *>()) {
+ id_to_inspection_string((ID *)*value.get<Object *>());
+ }
+ else if (value.is_type<Material *>()) {
+ id_to_inspection_string((ID *)*value.get<Material *>());
+ }
+ else if (value.is_type<Tex *>()) {
+ id_to_inspection_string((ID *)*value.get<Tex *>());
+ }
+ else if (value.is_type<Collection *>()) {
+ id_to_inspection_string((ID *)*value.get<Collection *>());
+ }
+}
+
+static void create_inspection_string_for_geometry(const geo_log::GeometryValueLog &value_log,
+ std::stringstream &ss)
+{
+ Span<GeometryComponentType> component_types = value_log.component_types();
+ if (component_types.is_empty()) {
+ ss << TIP_("Empty Geometry");
+ return;
+ }
+
+ auto to_string = [](int value) {
+ char str[16];
+ BLI_str_format_int_grouped(str, value);
+ return std::string(str);
+ };
+
+ ss << TIP_("Geometry:\n");
+ for (GeometryComponentType type : component_types) {
+ const char *line_end = (type == component_types.last()) ? "" : ".\n";
+ switch (type) {
+ case GEO_COMPONENT_TYPE_MESH: {
+ const geo_log::GeometryValueLog::MeshInfo &mesh_info = *value_log.mesh_info;
+ char line[256];
+ BLI_snprintf(line,
+ sizeof(line),
+ TIP_("\u2022 Mesh: %s vertices, %s edges, %s faces"),
+ to_string(mesh_info.tot_verts).c_str(),
+ to_string(mesh_info.tot_edges).c_str(),
+ to_string(mesh_info.tot_faces).c_str());
+ ss << line << line_end;
+ break;
+ }
+ case GEO_COMPONENT_TYPE_POINT_CLOUD: {
+ const geo_log::GeometryValueLog::PointCloudInfo &pointcloud_info =
+ *value_log.pointcloud_info;
+ char line[256];
+ BLI_snprintf(line,
+ sizeof(line),
+ TIP_("\u2022 Point Cloud: %s points"),
+ to_string(pointcloud_info.tot_points).c_str());
+ ss << line << line_end;
+ break;
+ }
+ case GEO_COMPONENT_TYPE_CURVE: {
+ const geo_log::GeometryValueLog::CurveInfo &curve_info = *value_log.curve_info;
+ char line[256];
+ BLI_snprintf(line,
+ sizeof(line),
+ TIP_("\u2022 Curve: %s splines"),
+ to_string(curve_info.tot_splines).c_str());
+ ss << line << line_end;
+ break;
+ }
+ case GEO_COMPONENT_TYPE_INSTANCES: {
+ const geo_log::GeometryValueLog::InstancesInfo &instances_info = *value_log.instances_info;
+ char line[256];
+ BLI_snprintf(line,
+ sizeof(line),
+ TIP_("\u2022 Instances: %s"),
+ to_string(instances_info.tot_instances).c_str());
+ ss << line << line_end;
+ break;
+ }
+ case GEO_COMPONENT_TYPE_VOLUME: {
+ ss << TIP_("\u2022 Volume") << line_end;
+ break;
+ }
+ }
+ }
+}
+
+static std::optional<std::string> create_socket_inspection_string(bContext *C,
+ bNodeTree &UNUSED(ntree),
+ bNode &node,
+ bNodeSocket &socket)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const geo_log::SocketLog *socket_log = geo_log::ModifierLog::find_socket_by_node_editor_context(
+ *snode, node, socket);
+ if (socket_log == nullptr) {
+ return {};
+ }
+ const geo_log::ValueLog *value_log = socket_log->value();
+ if (value_log == nullptr) {
+ return {};
+ }
+
+ std::stringstream ss;
+ if (const geo_log::GenericValueLog *generic_value_log =
+ dynamic_cast<const geo_log::GenericValueLog *>(value_log)) {
+ create_inspection_string_for_generic_value(*generic_value_log, ss);
+ }
+ else if (const geo_log::GeometryValueLog *geo_value_log =
+ dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) {
+ create_inspection_string_for_geometry(*geo_value_log, ss);
+ }
+
+ return ss.str();
+}
+
static void node_socket_draw_nested(const bContext *C,
bNodeTree *ntree,
PointerRNA *node_ptr,
@@ -863,6 +1011,55 @@ static void node_socket_draw_nested(const bContext *C,
shape_id,
size_id,
outline_col_id);
+
+ if (ntree->type != NTREE_GEOMETRY) {
+ /* Only geometry nodes has socket value tooltips currently. */
+ return;
+ }
+
+ bNode *node = (bNode *)node_ptr->data;
+ uiBlock *block = node->block;
+
+ /* Ideally sockets themselves should be buttons, but they aren't currently. So add an invisible
+ * button on top of them for the tooltip. */
+ const eUIEmbossType old_emboss = UI_block_emboss_get(block);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiBut *but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_NONE,
+ sock->locx - size / 2,
+ sock->locy - size / 2,
+ size,
+ size,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+
+ SocketTooltipData *data = (SocketTooltipData *)MEM_mallocN(sizeof(SocketTooltipData), __func__);
+ data->ntree = ntree;
+ data->node = (bNode *)node_ptr->data;
+ data->socket = sock;
+
+ UI_but_func_tooltip_set(
+ but,
+ [](bContext *C, void *argN, const char *UNUSED(tip)) {
+ SocketTooltipData *data = (SocketTooltipData *)argN;
+ std::optional<std::string> str = create_socket_inspection_string(
+ C, *data->ntree, *data->node, *data->socket);
+ if (str.has_value()) {
+ return BLI_strdup(str->c_str());
+ }
+ return BLI_strdup(TIP_("The socket value has not been computed yet"));
+ },
+ data,
+ MEM_freeN);
+ /* Disable the button so that clicks on it are ignored the the link operator still works. */
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ UI_block_emboss_set(block, old_emboss);
}
/**
@@ -1203,14 +1400,14 @@ void node_draw_sockets(const View2D *v2d,
}
}
-static int node_error_type_to_icon(const NodeWarningType type)
+static int node_error_type_to_icon(const geo_log::NodeWarningType type)
{
switch (type) {
- case NodeWarningType::Error:
+ case geo_log::NodeWarningType::Error:
return ICON_ERROR;
- case NodeWarningType::Warning:
+ case geo_log::NodeWarningType::Warning:
return ICON_ERROR;
- case NodeWarningType::Info:
+ case geo_log::NodeWarningType::Info:
return ICON_INFO;
}
@@ -1218,14 +1415,14 @@ static int node_error_type_to_icon(const NodeWarningType type)
return ICON_ERROR;
}
-static uint8_t node_error_type_priority(const NodeWarningType type)
+static uint8_t node_error_type_priority(const geo_log::NodeWarningType type)
{
switch (type) {
- case NodeWarningType::Error:
+ case geo_log::NodeWarningType::Error:
return 3;
- case NodeWarningType::Warning:
+ case geo_log::NodeWarningType::Warning:
return 2;
- case NodeWarningType::Info:
+ case geo_log::NodeWarningType::Info:
return 1;
}
@@ -1233,11 +1430,11 @@ static uint8_t node_error_type_priority(const NodeWarningType type)
return 0;
}
-static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings)
+static geo_log::NodeWarningType node_error_highest_priority(Span<geo_log::NodeWarning> warnings)
{
uint8_t highest_priority = 0;
- NodeWarningType highest_priority_type = NodeWarningType::Info;
- for (const NodeWarning &warning : warnings) {
+ geo_log::NodeWarningType highest_priority_type = geo_log::NodeWarningType::Info;
+ for (const geo_log::NodeWarning &warning : warnings) {
const uint8_t priority = node_error_type_priority(warning.type);
if (priority > highest_priority) {
highest_priority = priority;
@@ -1247,15 +1444,17 @@ static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings)
return highest_priority_type;
}
+struct NodeErrorsTooltipData {
+ Span<geo_log::NodeWarning> warnings;
+};
+
static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
{
- const NodeUIStorage **storage_pointer_alloc = static_cast<const NodeUIStorage **>(argN);
- const NodeUIStorage *node_ui_storage = *storage_pointer_alloc;
- Span<NodeWarning> warnings = node_ui_storage->warnings;
+ NodeErrorsTooltipData &data = *(NodeErrorsTooltipData *)argN;
std::string complete_string;
- for (const NodeWarning &warning : warnings.drop_back(1)) {
+ for (const geo_log::NodeWarning &warning : data.warnings.drop_back(1)) {
complete_string += warning.message;
/* Adding the period is not ideal for multi-line messages, but it is consistent
* with other tooltip implementations in Blender, so it is added here. */
@@ -1264,7 +1463,7 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char
}
/* Let the tooltip system automatically add the last period. */
- complete_string += warnings.last().message;
+ complete_string += data.warnings.last().message;
return BLI_strdupn(complete_string.c_str(), complete_string.size());
}
@@ -1272,20 +1471,26 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char
#define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit)
static void node_add_error_message_button(
- const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset)
+ const bContext *C, bNodeTree &UNUSED(ntree), bNode &node, const rctf &rect, float &icon_offset)
{
- const NodeUIStorage *node_ui_storage = BKE_node_tree_ui_storage_get_from_context(C, ntree, node);
- if (node_ui_storage == nullptr || node_ui_storage->warnings.is_empty()) {
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(*snode,
+ node);
+ if (node_log == nullptr) {
+ return;
+ }
+
+ Span<geo_log::NodeWarning> warnings = node_log->warnings();
+
+ if (warnings.is_empty()) {
return;
}
- /* The UI API forces us to allocate memory for each error button, because the
- * ownership of #UI_but_func_tooltip_set's argument is transferred to the button. */
- const NodeUIStorage **storage_pointer_alloc = (const NodeUIStorage **)MEM_mallocN(
- sizeof(NodeUIStorage *), __func__);
- *storage_pointer_alloc = node_ui_storage;
+ NodeErrorsTooltipData *tooltip_data = (NodeErrorsTooltipData *)MEM_mallocN(
+ sizeof(NodeErrorsTooltipData), __func__);
+ tooltip_data->warnings = warnings;
- const NodeWarningType display_type = node_error_highest_priority(node_ui_storage->warnings);
+ const geo_log::NodeWarningType display_type = node_error_highest_priority(warnings);
icon_offset -= NODE_HEADER_ICON_SIZE;
UI_block_emboss_set(node.block, UI_EMBOSS_NONE);
@@ -1303,7 +1508,7 @@ static void node_add_error_message_button(
0,
0,
nullptr);
- UI_but_func_tooltip_set(but, node_errors_tooltip_fn, storage_pointer_alloc, MEM_freeN);
+ UI_but_func_tooltip_set(but, node_errors_tooltip_fn, tooltip_data, MEM_freeN);
UI_block_emboss_set(node.block, UI_EMBOSS);
}
@@ -1423,28 +1628,6 @@ static void node_draw_basis(const bContext *C,
"");
UI_block_emboss_set(node->block, UI_EMBOSS);
}
- if (ntree->type == NTREE_GEOMETRY) {
- /* Active preview toggle. */
- iconofs -= iconbutw;
- UI_block_emboss_set(node->block, UI_EMBOSS_NONE);
- int icon = (node->flag & NODE_ACTIVE_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON;
- uiBut *but = uiDefIconBut(node->block,
- UI_BTYPE_BUT_TOGGLE,
- 0,
- icon,
- iconofs,
- rct->ymax - NODE_DY,
- iconbutw,
- UI_UNIT_Y,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- "Show this node's geometry output in the spreadsheet");
- UI_but_func_set(but, node_toggle_button_cb, node, (void *)"NODE_OT_active_preview_toggle");
- UI_block_emboss_set(node->block, UI_EMBOSS);
- }
node_add_error_message_button(C, *ntree, *node, *rct, iconofs);
diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc
index 0cf47ed35fa..af9c888cbf7 100644
--- a/source/blender/editors/space_node/node_edit.cc
+++ b/source/blender/editors/space_node/node_edit.cc
@@ -21,6 +21,8 @@
* \ingroup spnode
*/
+#include <algorithm>
+
#include "MEM_guardedalloc.h"
#include "DNA_light_types.h"
@@ -54,6 +56,7 @@
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
+#include "ED_spreadsheet.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -662,7 +665,8 @@ void snode_update(SpaceNode *snode, bNode *node)
}
}
-void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
+void ED_node_set_active(
+ Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
{
const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
if (r_active_texture_changed) {
@@ -782,6 +786,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
}
#endif
}
+ else if (ntree->type == NTREE_GEOMETRY) {
+ if (node->type == GEO_NODE_VIEWER) {
+ if ((node->flag & NODE_DO_OUTPUT) == 0) {
+ LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
+ if (node_iter->type == GEO_NODE_VIEWER) {
+ node_iter->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ node->flag |= NODE_DO_OUTPUT;
+ ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node);
+ }
+ }
+ }
}
}
@@ -1211,6 +1228,32 @@ int node_find_indicated_socket(
return 0;
}
+/* ****************** Link Dimming *********************** */
+
+float node_link_dim_factor(const View2D *v2d, const bNodeLink *link)
+{
+ if (link->fromsock == nullptr || link->tosock == nullptr) {
+ return 1.0f;
+ }
+
+ const float min_endpoint_distance = std::min(
+ std::max(BLI_rctf_length_x(&v2d->cur, link->fromsock->locx),
+ BLI_rctf_length_y(&v2d->cur, link->fromsock->locy)),
+ std::max(BLI_rctf_length_x(&v2d->cur, link->tosock->locx),
+ BLI_rctf_length_y(&v2d->cur, link->tosock->locy)));
+
+ if (min_endpoint_distance == 0.0f) {
+ return 1.0f;
+ }
+ const float viewport_width = BLI_rctf_size_x(&v2d->cur);
+ return std::clamp(1.0f - min_endpoint_distance / viewport_width * 10.0f, 0.05f, 1.0f);
+}
+
+bool node_link_is_hidden_or_dimmed(const View2D *v2d, const bNodeLink *link)
+{
+ return nodeLinkIsHidden(link) || node_link_dim_factor(v2d, link) < 0.5f;
+}
+
/* ****************** Duplicate *********************** */
static void node_duplicate_reparent_recursive(bNode *node)
@@ -1318,7 +1361,6 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
nodeSetSelected(node, false);
node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE);
nodeSetSelected(newnode, true);
- newnode->flag &= ~NODE_ACTIVE_PREVIEW;
do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode));
}
@@ -2313,7 +2355,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
// nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);
}
else {
- /* XXX TODO define default socket type for a tree! */
+ /* XXX TODO: define default socket type for a tree! */
sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
}
@@ -2400,6 +2442,109 @@ void NODE_OT_tree_socket_remove(wmOperatorType *ot)
RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
}
+/********************** Change interface socket type operator *********************/
+
+static int ntree_socket_change_type_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out");
+ const bNodeSocketType *socket_type = rna_node_socket_type_from_enum(
+ RNA_enum_get(op->ptr, "socket_type"));
+ ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
+
+ Main *main = CTX_data_main(C);
+
+ bNodeSocket *iosock = ntree_get_active_interface_socket(sockets);
+ if (iosock == nullptr) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* The type remains the same, so we don't need to change anything. */
+ if (iosock->typeinfo == socket_type) {
+ return OPERATOR_FINISHED;
+ }
+
+ /* Don't handle subtypes for now. */
+ nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname);
+
+ /* Need the extra update here because the loop above does not check for valid links in the node
+ * group we're currently editing. */
+ ntree->update |= NTREE_UPDATE_GROUP | NTREE_UPDATE_LINKS;
+
+ /* Deactivate sockets. */
+ LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) {
+ socket_iter->flag &= ~SELECT;
+ }
+ /* Make the new socket active. */
+ iosock->flag |= SELECT;
+
+ ntreeUpdateTree(main, ntree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool socket_change_poll_type(void *userdata, bNodeSocketType *socket_type)
+{
+ /* Check if the node tree supports the socket type. */
+ bNodeTreeType *ntreetype = (bNodeTreeType *)userdata;
+ if (ntreetype->valid_socket_type && !ntreetype->valid_socket_type(ntreetype, socket_type)) {
+ return false;
+ }
+
+ /* Only use basic socket types for this enum. */
+ if (socket_type->subtype != PROP_NONE) {
+ return false;
+ }
+
+ return true;
+}
+
+static const EnumPropertyItem *socket_change_type_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ if (!C) {
+ return DummyRNA_NULL_items;
+ }
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+ if (!snode || !snode->edittree) {
+ return DummyRNA_NULL_items;
+ }
+
+ return rna_node_socket_type_itemf(snode->edittree->typeinfo, socket_change_poll_type, r_free);
+}
+
+void NODE_OT_tree_socket_change_type(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Change Node Tree Interface Socket Type";
+ ot->description = "Change the type of a socket of the current node tree";
+ ot->idname = "NODE_OT_tree_socket_change_type";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = ntree_socket_change_type_exec;
+ ot->poll = ED_operator_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
+ prop = RNA_def_enum(ot->srna, "socket_type", DummyRNA_DEFAULT_items, 0, "Socket Type", "");
+ RNA_def_enum_funcs(prop, socket_change_type_itemf);
+ ot->prop = prop;
+}
+
/********************** Move interface socket operator *********************/
static const EnumPropertyItem move_direction_items[] = {
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index e92449e3535..af35f9692ae 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -27,7 +27,6 @@
#include "DNA_space_types.h"
#include "BKE_context.h"
-#include "BKE_node_ui_storage.hh"
#include "BKE_object.h"
#include "RNA_access.h"
@@ -40,17 +39,21 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "NOD_geometry_nodes_eval_log.hh"
+
#include "node_intern.h"
using blender::IndexRange;
using blender::Map;
using blender::Set;
using blender::StringRef;
+namespace geo_log = blender::nodes::geometry_nodes_eval_log;
+using geo_log::GeometryAttributeInfo;
struct AttributeSearchData {
- AvailableAttributeInfo &dummy_info_for_search;
- const NodeUIStorage &ui_storage;
- bNodeSocket &socket;
+ const bNodeTree *tree;
+ const bNode *node;
+ bNodeSocket *socket;
};
/* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
@@ -73,7 +76,7 @@ static StringRef attribute_domain_string(const AttributeDomain domain)
/* Unicode arrow. */
#define MENU_SEP "\xe2\x96\xb6"
-static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttributeInfo &item)
+static bool attribute_search_item_add(uiSearchItems *items, const GeometryAttributeInfo &item)
{
const StringRef data_type_name = attribute_data_type_string(item.data_type);
const StringRef domain_name = attribute_domain_string(item.domain);
@@ -84,31 +87,47 @@ static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttri
items, search_item_text.c_str(), (void *)&item, ICON_NONE, UI_BUT_HAS_SEP_CHAR, 0);
}
-static void attribute_search_update_fn(const bContext *UNUSED(C),
- void *arg,
- const char *str,
- uiSearchItems *items,
- const bool is_first)
+static GeometryAttributeInfo &get_dummy_item_info()
+{
+ static GeometryAttributeInfo info;
+ return info;
+}
+
+static void attribute_search_update_fn(
+ const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
{
AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
- const Set<AvailableAttributeInfo> &attribute_hints = data->ui_storage.attribute_hints;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
+ *snode, *data->node);
+ if (node_log == nullptr) {
+ return;
+ }
+ blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes();
+
+ GeometryAttributeInfo &dummy_info = get_dummy_item_info();
/* Any string may be valid, so add the current search string along with the hints. */
if (str[0] != '\0') {
- /* Note that the attribute domain and data type are dummies, since
- * #AvailableAttributeInfo equality is only based on the string. */
- if (!attribute_hints.contains(AvailableAttributeInfo{str, ATTR_DOMAIN_AUTO, CD_PROP_BOOL})) {
- data->dummy_info_for_search.name = std::string(str);
- UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_ADD, 0, 0);
+ bool contained = false;
+ for (const GeometryAttributeInfo *attribute_info : infos) {
+ if (attribute_info->name == str) {
+ contained = true;
+ break;
+ }
+ }
+ if (!contained) {
+ dummy_info.name = str;
+ UI_search_item_add(items, str, &dummy_info, ICON_ADD, 0, 0);
}
}
if (str[0] == '\0' && !is_first) {
/* Allow clearing the text field when the string is empty, but not on the first pass,
* or opening an attribute field for the first time would show this search item. */
- data->dummy_info_for_search.name = std::string(str);
- UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_X, 0, 0);
+ dummy_info.name = str;
+ UI_search_item_add(items, str, &dummy_info, ICON_X, 0, 0);
}
/* Don't filter when the menu is first opened, but still run the search
@@ -116,15 +135,15 @@ static void attribute_search_update_fn(const bContext *UNUSED(C),
const char *string = is_first ? "" : str;
StringSearch *search = BLI_string_search_new();
- for (const AvailableAttributeInfo &item : attribute_hints) {
- BLI_string_search_add(search, item.name.c_str(), (void *)&item);
+ for (const GeometryAttributeInfo *item : infos) {
+ BLI_string_search_add(search, item->name.c_str(), (void *)item);
}
- AvailableAttributeInfo **filtered_items;
+ GeometryAttributeInfo **filtered_items;
const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items);
for (const int i : IndexRange(filtered_amount)) {
- const AvailableAttributeInfo *item = filtered_items[i];
+ const GeometryAttributeInfo *item = filtered_items[i];
if (!attribute_search_item_add(items, *item)) {
break;
}
@@ -136,10 +155,13 @@ static void attribute_search_update_fn(const bContext *UNUSED(C),
static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
{
+ if (item_v == nullptr) {
+ return;
+ }
AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v);
- AvailableAttributeInfo *item = static_cast<AvailableAttributeInfo *>(item_v);
+ GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v;
- bNodeSocket &socket = data->socket;
+ bNodeSocket &socket = *data->socket;
switch (socket.type) {
case SOCK_STRING: {
bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value);
@@ -157,23 +179,13 @@ static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
ED_undo_push(C, "Assign Attribute Name");
}
-void node_geometry_add_attribute_search_button(const bContext *C,
+void node_geometry_add_attribute_search_button(const bContext *UNUSED(C),
const bNodeTree *node_tree,
const bNode *node,
PointerRNA *socket_ptr,
const char *propname,
uiLayout *layout)
{
- const NodeUIStorage *ui_storage = BKE_node_tree_ui_storage_get_from_context(
- C, *node_tree, *node);
-
- if (ui_storage == nullptr) {
- uiItemR(layout, socket_ptr, propname, 0, "", 0);
- return;
- }
-
- const NodeTreeUIStorage *tree_ui_storage = node_tree->ui_storage;
-
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but = uiDefIconTextButR(block,
UI_BTYPE_SEARCH_MENU,
@@ -193,10 +205,8 @@ void node_geometry_add_attribute_search_button(const bContext *C,
0.0f,
"");
- AttributeSearchData *data = OBJECT_GUARDED_NEW(AttributeSearchData,
- {tree_ui_storage->dummy_info_for_search,
- *ui_storage,
- *static_cast<bNodeSocket *>(socket_ptr->data)});
+ AttributeSearchData *data = OBJECT_GUARDED_NEW(
+ AttributeSearchData, {node_tree, node, (bNodeSocket *)socket_ptr->data});
UI_but_func_search_set_results_are_suggestions(but, true);
UI_but_func_search_set_sep_string(but, MENU_SEP);
diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c
index 8547c825230..e1deca54890 100644
--- a/source/blender/editors/space_node/node_gizmo.c
+++ b/source/blender/editors/space_node/node_gizmo.c
@@ -155,7 +155,7 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *
WM_gizmo_set_matrix_location(cage, origin);
WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false);
- /* need to set property here for undo. TODO would prefer to do this in _init */
+ /* Need to set property here for undo. TODO: would prefer to do this in _init. */
SpaceNode *snode = CTX_wm_space_node(C);
#if 0
PointerRNA nodeptr;
@@ -492,7 +492,7 @@ static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgr
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node = nodeGetActive(snode->edittree);
- /* need to set property here for undo. TODO would prefer to do this in _init */
+ /* Need to set property here for undo. TODO: would prefer to do this in _init. */
PointerRNA nodeptr;
RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr);
WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1);
@@ -604,7 +604,7 @@ static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node = nodeGetActive(snode->edittree);
- /* need to set property here for undo. TODO would prefer to do this in _init */
+ /* need to set property here for undo. TODO: would prefer to do this in _init. */
int i = 0;
for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
if (sock->type == SOCK_VECTOR) {
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 73de87b8c14..385bf8ab4a8 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -52,7 +52,7 @@ typedef struct bNodeLinkDrag {
struct bNodeLinkDrag *next, *prev;
/* List of links dragged by the operator.
- * Note: This is a list of LinkData structs on top of the actual bNodeLinks.
+ * NOTE: This is a list of LinkData structs on top of the actual bNodeLinks.
* This way the links can be added to the node tree while being stored in this list.
*/
ListBase links;
@@ -141,9 +141,6 @@ void node_to_view(const struct bNode *node, float x, float y, float *rx, float *
void node_to_updated_rect(const struct bNode *node, rctf *r_rect);
void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry);
-/* node_buttons.c */
-void node_buttons_register(struct ARegionType *art);
-
/* node_toolbar.c */
void node_toolbar_register(struct ARegionType *art);
@@ -269,6 +266,8 @@ int node_find_indicated_socket(struct SpaceNode *snode,
struct bNodeSocket **sockp,
const float cursor[2],
int in_out);
+float node_link_dim_factor(const struct View2D *v2d, const struct bNodeLink *link);
+bool node_link_is_hidden_or_dimmed(const struct View2D *v2d, const struct bNodeLink *link);
void NODE_OT_duplicate(struct wmOperatorType *ot);
void NODE_OT_delete(struct wmOperatorType *ot);
@@ -280,7 +279,6 @@ void NODE_OT_hide_toggle(struct wmOperatorType *ot);
void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot);
void NODE_OT_preview_toggle(struct wmOperatorType *ot);
void NODE_OT_options_toggle(struct wmOperatorType *ot);
-void NODE_OT_active_preview_toggle(struct wmOperatorType *ot);
void NODE_OT_node_copy_color(struct wmOperatorType *ot);
void NODE_OT_read_viewlayers(struct wmOperatorType *ot);
@@ -292,12 +290,13 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
void NODE_OT_switch_view_update(struct wmOperatorType *ot);
-/* Note: clipboard_cut is a simple macro of copy + delete */
+/* NOTE: clipboard_cut is a simple macro of copy + delete. */
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
void NODE_OT_tree_socket_add(struct wmOperatorType *ot);
void NODE_OT_tree_socket_remove(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot);
void NODE_OT_tree_socket_move(struct wmOperatorType *ot);
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index e35b444aa11..610c2889e7a 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -119,6 +119,7 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_tree_socket_add);
WM_operatortype_append(NODE_OT_tree_socket_remove);
+ WM_operatortype_append(NODE_OT_tree_socket_change_type);
WM_operatortype_append(NODE_OT_tree_socket_move);
WM_operatortype_append(NODE_OT_cryptomatte_layer_add);
@@ -157,7 +158,7 @@ void ED_operatormacros_node(void)
WM_operatortype_macro_define(ot, "NODE_OT_attach");
WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
- /* Note: Currently not in a default keymap or menu due to messy keymaps
+ /* NOTE: Currently not in a default keymap or menu due to messy keymaps
* and tricky invoke functionality.
* Kept around in case users want to make own shortcuts.
*/
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index 5c251b47746..4e6e8937bb4 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -36,15 +36,19 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_screen.h"
#include "ED_node.h" /* own include */
#include "ED_render.h"
#include "ED_screen.h"
+#include "ED_spreadsheet.h"
#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -160,6 +164,11 @@ bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node)
return true;
}
}
+ if (current_node->type == GEO_NODE_VIEWER) {
+ if (ntree_check_nodes_connected(ntree, node, current_node)) {
+ return true;
+ }
+ }
}
return false;
}
@@ -610,14 +619,14 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (tonode == nullptr || BLI_listbase_is_empty(&tonode->outputs)) {
return OPERATOR_CANCELLED;
}
- if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
return OPERATOR_CANCELLED;
}
/* get viewer */
bNode *viewer_node = nullptr;
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
if (node->flag & NODE_DO_OUTPUT) {
viewer_node = node;
break;
@@ -627,7 +636,7 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
/* no viewer, we make one active */
if (viewer_node == nullptr) {
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER)) {
node->flag |= NODE_DO_OUTPUT;
viewer_node = node;
break;
@@ -686,7 +695,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
/* add a new viewer if none exists yet */
if (!viewer_node) {
/* XXX location is a quick hack, just place it next to the linked socket */
- viewer_node = node_add_node(C, nullptr, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
+ const int viewer_type = ED_node_is_compositor(snode) ? CMP_NODE_VIEWER : GEO_NODE_VIEWER;
+ viewer_node = node_add_node(C, nullptr, viewer_type, sock->locx + 100, sock->locy);
if (!viewer_node) {
return OPERATOR_CANCELLED;
}
@@ -712,8 +722,13 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
/* make sure the dependency sorting is updated */
snode->edittree->update |= NTREE_UPDATE_LINKS;
}
+ if (ED_node_is_geometry(snode)) {
+ ED_spreadsheet_context_paths_set_geometry_node(CTX_data_main(C), snode, viewer_node);
+ }
+
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_update(snode, viewer_node);
+ DEG_id_tag_update(&snode->edittree->id, 0);
}
return OPERATOR_FINISHED;
@@ -739,6 +754,15 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+static bool node_active_link_viewer_poll(bContext *C)
+{
+ if (!ED_operator_node_editable(C)) {
+ return false;
+ }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ return ED_node_is_compositor(snode) || ED_node_is_geometry(snode);
+}
+
void NODE_OT_link_viewer(wmOperatorType *ot)
{
/* identifiers */
@@ -748,7 +772,7 @@ void NODE_OT_link_viewer(wmOperatorType *ot)
/* api callbacks */
ot->exec = node_active_link_viewer_exec;
- ot->poll = composite_node_editable;
+ ot->poll = node_active_link_viewer_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1309,7 +1333,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode->edittree->links) {
- if (nodeLinkIsHidden(link)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link)) {
continue;
}
@@ -1406,7 +1430,7 @@ static int mute_links_exec(bContext *C, wmOperator *op)
/* Count intersected links and clear test flag. */
int tot = 0;
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
- if (nodeLinkIsHidden(link)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link)) {
continue;
}
link->flag &= ~NODE_LINK_TEST;
@@ -1420,7 +1444,7 @@ static int mute_links_exec(bContext *C, wmOperator *op)
/* Mute links. */
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
- if (nodeLinkIsHidden(link) || (link->flag & NODE_LINK_TEST)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link) || (link->flag & NODE_LINK_TEST)) {
continue;
}
@@ -1435,7 +1459,7 @@ static int mute_links_exec(bContext *C, wmOperator *op)
/* Clear remaining test flags. */
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
- if (nodeLinkIsHidden(link)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link)) {
continue;
}
link->flag &= ~NODE_LINK_TEST;
@@ -1871,9 +1895,11 @@ static bool ed_node_link_conditions(ScrArea *area,
return false;
}
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+
/* test node for links */
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
- if (nodeLinkIsHidden(link)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link)) {
continue;
}
@@ -1904,13 +1930,15 @@ void ED_node_link_intersect_test(ScrArea *area, int test)
return;
}
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+
/* find link to select/highlight */
bNodeLink *selink = nullptr;
float dist_best = FLT_MAX;
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
float coord_array[NODE_LINK_RESOL + 1][2];
- if (nodeLinkIsHidden(link)) {
+ if (node_link_is_hidden_or_dimmed(&region->v2d, link)) {
continue;
}
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc
index 41820cd813c..a081cc83481 100644
--- a/source/blender/editors/space_node/node_select.cc
+++ b/source/blender/editors/space_node/node_select.cc
@@ -44,6 +44,7 @@
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_select_utils.h"
+#include "ED_spreadsheet.h"
#include "ED_view3d.h"
#include "RNA_access.h"
@@ -330,7 +331,7 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo
pref_len_act = BLI_str_partition_ex_utf8(
node_act->name, nullptr, delims, &sep, &suf_act, from_right);
- /* Note: in case we are searching for suffix, and found none, use whole name as suffix. */
+ /* NOTE: in case we are searching for suffix, and found none, use whole name as suffix. */
if (from_right && !(sep && suf_act)) {
pref_len_act = 0;
suf_act = node_act->name;
@@ -469,7 +470,7 @@ void node_select_single(bContext *C, bNode *node)
}
nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed);
+ ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed);
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
@@ -606,12 +607,18 @@ static int node_mouse_select(bContext *C,
/* update node order */
if (ret_value != OPERATOR_CANCELLED) {
bool active_texture_changed = false;
+ bool viewer_node_changed = false;
if (node != nullptr && ret_value != OPERATOR_RUNNING_MODAL) {
- ED_node_set_active(bmain, snode->edittree, node, &active_texture_changed);
+ viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER;
+ ED_node_set_active(bmain, snode, snode->edittree, node, &active_texture_changed);
+ }
+ else if (node != nullptr && node->type == GEO_NODE_VIEWER) {
+ ED_spreadsheet_context_paths_set_geometry_node(bmain, snode, node);
}
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
- if (active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) {
+ if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) ||
+ viewer_node_changed) {
DEG_id_tag_update(&snode->edittree->id, ID_RECALC_COPY_ON_WRITE);
}
diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc
index 93599bc3c2a..10ad83e4fe9 100644
--- a/source/blender/editors/space_node/node_templates.cc
+++ b/source/blender/editors/space_node/node_templates.cc
@@ -364,7 +364,7 @@ static void ui_node_link_items(NodeLinkArg *arg,
NodeLinkItem *item = &items[i];
item->socket_index = index;
- /* note: int stemp->type is not fully reliable, not used for node group
+ /* NOTE: int stemp->type is not fully reliable, not used for node group
* interface sockets. use the typeinfo->type instead.
*/
item->socket_type = stemp->typeinfo->type;
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index f20a9409d90..ff848a7bb95 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -345,7 +345,7 @@ static void node_area_listener(const wmSpaceTypeListenerParams *params)
ScrArea *area = params->area;
wmNotifier *wmn = params->notifier;
- /* note, ED_area_tag_refresh will re-execute compositor */
+ /* NOTE: #ED_area_tag_refresh will re-execute compositor. */
SpaceNode *snode = area->spacedata.first;
/* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
short shader_type = snode->shaderfrom;
@@ -563,7 +563,7 @@ static SpaceLink *node_duplicate(SpaceLink *sl)
BLI_listbase_clear(&snoden->runtime->linkdrag);
}
- /* Note: no need to set node tree user counts,
+ /* NOTE: no need to set node tree user counts,
* the editor only keeps at least 1 (id_us_ensure_real),
* which is already done by the original SpaceNode.
*/
@@ -651,6 +651,10 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *region)
lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW);
WM_event_add_dropbox_handler(&region->handlers, lb);
+
+ /* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on
+ * region size changes. */
+ WM_gizmomap_tag_refresh(region->gizmo_map);
}
static void node_main_region_draw(const bContext *C, ARegion *region)
@@ -1094,8 +1098,6 @@ void ED_spacetype_node(void)
art->draw = node_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
- node_buttons_register(art);
-
/* regions: toolbar */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
art->regionid = RGN_TYPE_TOOLS;
diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c
index 4293d8da73e..d61bb17f661 100644
--- a/source/blender/editors/space_outliner/outliner_context.c
+++ b/source/blender/editors/space_outliner/outliner_context.c
@@ -64,7 +64,7 @@ int /*eContextResult*/ outliner_context(const bContext *C,
outliner_context_selected_ids(space_outliner, result);
return CTX_RESULT_OK;
}
- /* Note: Querying non-ID selection could also work if tree elements stored their matching RNA
+ /* NOTE: Querying non-ID selection could also work if tree elements stored their matching RNA
* struct type. */
return CTX_RESULT_MEMBER_NOT_FOUND;
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index 8021b45ac77..86aab86db10 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -1325,7 +1325,7 @@ static TreeElement *outliner_item_drag_element_find(SpaceOutliner *space_outline
ARegion *region,
const wmEvent *event)
{
- /* note: using EVT_TWEAK_ events to trigger dragging is fine,
+ /* NOTE: using EVT_TWEAK_ events to trigger dragging is fine,
* it sends coordinates from where dragging was started */
const float my = UI_view2d_region_to_view_y(&region->v2d, event->mval[1]);
return outliner_find_item_at_y(space_outliner, &space_outliner->tree, my);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 4fe29d4e9bd..db37c8c1c8c 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -355,7 +355,7 @@ static void outliner_base_or_object_pointer_create(
}
}
-/* Note: Collection is only valid when we want to change the collection data, otherwise we get it
+/* NOTE: Collection is only valid when we want to change the collection data, otherwise we get it
* from layer collection. Layer collection is valid whenever we are looking at a view layer. */
static void outliner_collection_set_flag_recursive(Scene *scene,
ViewLayer *view_layer,
@@ -374,7 +374,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene,
/* Set the same flag for the nested objects as well. */
if (base_or_object_prop) {
- /* Note: We can't use BKE_collection_object_cache_get()
+ /* NOTE: We can't use BKE_collection_object_cache_get()
* otherwise we would not take collection exclusion into account. */
LISTBASE_FOREACH (CollectionObject *, cob, &layer_collection->collection->gobject) {
@@ -414,7 +414,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene,
* A collection is isolated if all its parents and children are "visible".
* All the other collections must be "invisible".
*
- * Note: We could/should boost performance by iterating over the tree twice.
+ * NOTE: We could/should boost performance by iterating over the tree twice.
* First tagging all the children/parent collections, then getting their values and comparing.
* To run BKE_collection_has_collection() so many times is silly and slow.
*/
@@ -2356,6 +2356,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case eGpencilModifierType_Texture:
data.icon = ICON_TEXTURE;
break;
+ case eGpencilModifierType_Weight:
+ data.icon = ICON_MOD_VERTEX_WEIGHT;
+ break;
/* Default */
default:
@@ -2961,7 +2964,8 @@ static void outliner_draw_iconrow(bContext *C,
te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED);
/* object hierarchy always, further constrained on level */
- if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) {
+ if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) ||
+ ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL)) {
/* active blocks get white circle */
if (tselem->type == TSE_SOME_ID) {
if (te->idcode == ID_OB) {
@@ -3728,7 +3732,7 @@ static void outliner_update_viewable_area(ARegion *region,
}
/* ****************************************************** */
-/* Main Entrypoint - Draw contents of Outliner editor */
+/* Main Entry-point - Draw contents of Outliner editor */
void draw_outliner(const bContext *C)
{
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 4a070590d55..5be6c69363e 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -966,7 +966,7 @@ void OUTLINER_OT_lib_relocate(wmOperatorType *ot)
/* XXX This does not work with several items
* (it is only called once in the end, due to the 'deferred'
- * filebrowser invocation through event system...). */
+ * file-browser invocation through event system...). */
void lib_relocate_fn(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index fea5ddae16b..5336376b576 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -191,7 +191,7 @@ typedef enum {
#define OL_RNA_COL_SPACEX (UI_UNIT_X * 2.5f)
/* The outliner display modes that support the filter system.
- * Note: keep it synced with space_outliner.py */
+ * NOTE: keep it synced with `space_outliner.py`. */
#define SUPPORT_FILTER_OUTLINER(space_outliner_) \
(ELEM((space_outliner_)->outlinevis, SO_VIEW_LAYER, SO_OVERRIDES_LIBRARY))
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index b14a3cdb91d..35015356f0b 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -42,6 +42,7 @@
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_layer.h"
@@ -450,7 +451,7 @@ static void tree_element_defgroup_activate(bContext *C, TreeElement *te, TreeSto
/* id in tselem is object */
Object *ob = (Object *)tselem->id;
BLI_assert(te->index + 1 >= 0);
- ob->actdef = te->index + 1;
+ BKE_object_defgroup_active_index_set(ob, te->index + 1);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
@@ -830,7 +831,7 @@ static eOLDrawState tree_element_defgroup_state_get(const ViewLayer *view_layer,
{
const Object *ob = (const Object *)tselem->id;
if (ob == OBACT(view_layer)) {
- if (ob->actdef == te->index + 1) {
+ if (BKE_object_defgroup_active_index_get(ob) == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
}
@@ -1654,7 +1655,7 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
return OPERATOR_FINISHED;
}
-/* event can enterkey, then it opens/closes */
+/* Event can enter-key, then it opens/closes. */
static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const bool extend = RNA_boolean_get(op->ptr, "extend");
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index d59d04b6ac2..8a3ba9a24c2 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -168,7 +168,7 @@ static void get_element_operation_type(
case ID_WM:
case ID_SCR:
/* Those are ignored here. */
- /* Note: while Screens should be manageable here, deleting a screen used by a workspace
+ /* NOTE: while Screens should be manageable here, deleting a screen used by a workspace
* will cause crashes when trying to use that workspace, so for now let's play minimal,
* safe change. */
break;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ae455d957cf..c5ec656080a 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1,4 +1,4 @@
-/*
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -62,6 +62,7 @@
#include "BLT_translation.h"
#include "BKE_armature.h"
+#include "BKE_deform.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -552,17 +553,20 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
}
/* vertex groups */
- if (!BLI_listbase_is_empty(&ob->defbase)) {
- TreeElement *tenla = outliner_add_element(
- space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
- tenla->name = IFACE_("Vertex Groups");
+ if (ELEM(ob->type, OB_MESH, OB_GPENCIL, OB_LATTICE)) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ if (!BLI_listbase_is_empty(defbase)) {
+ TreeElement *tenla = outliner_add_element(
+ space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
+ tenla->name = IFACE_("Vertex Groups");
- int index;
- LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, &ob->defbase, index) {
- TreeElement *ten = outliner_add_element(
- space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index);
- ten->name = defgroup->name;
- ten->directdata = defgroup;
+ int index;
+ LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, defbase, index) {
+ TreeElement *ten = outliner_add_element(
+ space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index);
+ ten->name = defgroup->name;
+ ten->directdata = defgroup;
+ }
}
}
@@ -588,7 +592,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
switch (GS(id->name)) {
case ID_LI:
case ID_SCE:
- BLI_assert(!"ID type expected to be expanded through new tree-element design");
+ BLI_assert_msg(0, "ID type expected to be expanded through new tree-element design");
break;
case ID_OB: {
outliner_add_object_contents(space_outliner, te, tselem, (Object *)id);
@@ -901,12 +905,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
}
else if (type == TSE_SOME_ID) {
if (!te->type) {
- BLI_assert(!"Expected this ID type to be ported to new Outliner tree-element design");
+ BLI_assert_msg(0, "Expected this ID type to be ported to new Outliner tree-element design");
}
}
else if (ELEM(type, TSE_LIBRARY_OVERRIDE_BASE, TSE_LIBRARY_OVERRIDE)) {
if (!te->type) {
- BLI_assert(!"Expected override types to be ported to new Outliner tree-element design");
+ BLI_assert_msg(0,
+ "Expected override types to be ported to new Outliner tree-element design");
}
}
else {
@@ -1320,7 +1325,7 @@ static void outliner_sort(ListBase *lb)
}
TreeStoreElem *tselem = TREESTORE(te);
- /* sorting rules; only object lists, ID lists, or deformgroups */
+ /* Sorting rules; only object lists, ID lists, or deform-groups. */
if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) ||
((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) {
int totelem = BLI_listbase_count(lb);
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index a2032fa1dc0..205f0117e6a 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -179,7 +179,7 @@ static void outliner_main_region_listener(const wmRegionListenerParams *params)
}
break;
case NC_GROUP:
- /* all actions now, todo: check outliner view mode? */
+ /* All actions now, TODO: check outliner view mode? */
ED_region_tag_redraw(region);
break;
case NC_LAMP:
diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh
index f089a149805..96af8258010 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.hh
+++ b/source/blender/editors/space_outliner/tree/tree_display.hh
@@ -86,7 +86,7 @@ class TreeDisplayViewLayer final : public AbstractTreeDisplay {
ListBase buildTree(const TreeSourceData &source_data) override;
private:
- void add_view_layer(ListBase &, TreeElement &);
+ void add_view_layer(Scene &, ListBase &, TreeElement *);
void add_layer_collections_recursive(ListBase &, ListBase &, TreeElement &);
void add_layer_collection_objects(ListBase &, LayerCollection &, TreeElement &);
void add_layer_collection_objects_children(TreeElement &);
diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc
index 3059f8bfe0c..a17bf174a74 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc
@@ -150,27 +150,25 @@ TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar,
}
/* Create data-block list parent element on demand. */
- if (id != nullptr) {
- TreeElement *ten;
+ TreeElement *ten;
- if (filter_id_type) {
- ten = tenlib;
- }
- else {
- ten = outliner_add_element(
- &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
- ten->name = outliner_idcode_to_plural(GS(id->name));
- }
+ if (filter_id_type) {
+ ten = tenlib;
+ }
+ else {
+ ten = outliner_add_element(
+ &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
- for (ID *id : List<ID>(lbarray[a])) {
- if (override_library_id_filter_poll(lib, id)) {
- TreeElement *override_tree_element = outliner_add_element(
- &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0);
+ for (ID *id : List<ID>(lbarray[a])) {
+ if (override_library_id_filter_poll(lib, id)) {
+ TreeElement *override_tree_element = outliner_add_element(
+ &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0);
- if (BLI_listbase_is_empty(&override_tree_element->subtree)) {
- outliner_free_tree_element(override_tree_element, &ten->subtree);
- }
+ if (BLI_listbase_is_empty(&override_tree_element->subtree)) {
+ outliner_free_tree_element(override_tree_element, &ten->subtree);
}
}
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
index 402526bbe8d..c3d0aecd3cb 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
@@ -70,74 +70,69 @@ TreeDisplayViewLayer::TreeDisplayViewLayer(SpaceOutliner &space_outliner)
ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
-
Scene *scene = source_data.scene;
show_objects_ = !(space_outliner_.filter & SO_FILTER_NO_OBJECT);
- const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0;
-
for (auto *view_layer : ListBaseWrapper<ViewLayer>(scene->view_layers)) {
+ view_layer_ = view_layer;
+
if (space_outliner_.filter & SO_FILTER_NO_VIEW_LAYERS) {
if (view_layer != source_data.view_layer) {
continue;
}
- }
- TreeElement &te_view_layer = *outliner_add_element(
- &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0);
- TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED;
- te_view_layer.name = view_layer->name;
- te_view_layer.directdata = view_layer;
- view_layer_ = view_layer;
-
- if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) {
- /* Show objects in the view layer. */
- for (Base *base : List<Base>(view_layer_->object_bases)) {
- TreeElement *te_object = outliner_add_element(&space_outliner_,
- &te_view_layer.subtree,
- base->object,
- &te_view_layer,
- TSE_SOME_ID,
- 0);
- te_object->directdata = base;
- }
-
- if (show_children) {
- outliner_make_object_parent_hierarchy(&tree);
- }
+ add_view_layer(*scene, tree, (TreeElement *)nullptr);
}
else {
- /* Show collections in the view layer. */
- TreeElement &ten = *outliner_add_element(&space_outliner_,
- &te_view_layer.subtree,
- source_data.scene,
- &te_view_layer,
- TSE_VIEW_COLLECTION_BASE,
- 0);
- ten.name = IFACE_("Scene Collection");
- TREESTORE(&ten)->flag &= ~TSE_CLOSED;
-
- add_view_layer(ten.subtree, ten);
- if (show_children) {
- add_layer_collection_objects_children(ten);
- }
+ TreeElement &te_view_layer = *outliner_add_element(
+ &space_outliner_, &tree, scene, nullptr, TSE_R_LAYER, 0);
+ TREESTORE(&te_view_layer)->flag &= ~TSE_CLOSED;
+ te_view_layer.name = view_layer->name;
+ te_view_layer.directdata = view_layer;
+
+ add_view_layer(*scene, te_view_layer.subtree, &te_view_layer);
}
}
return tree;
}
-void TreeDisplayViewLayer::add_view_layer(ListBase &tree, TreeElement &parent)
+void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElement *parent)
{
- /* First layer collection is for master collection, don't show it. */
- LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first);
- if (lc == nullptr) {
- return;
+ const bool show_children = (space_outliner_.filter & SO_FILTER_NO_CHILDREN) == 0;
+
+ if (space_outliner_.filter & SO_FILTER_NO_COLLECTION) {
+ /* Show objects in the view layer. */
+ for (Base *base : List<Base>(view_layer_->object_bases)) {
+ TreeElement *te_object = outliner_add_element(
+ &space_outliner_, &tree, base->object, parent, TSE_SOME_ID, 0);
+ te_object->directdata = base;
+ }
+
+ if (show_children) {
+ outliner_make_object_parent_hierarchy(&tree);
+ }
}
+ else {
+ /* Show collections in the view layer. */
+ TreeElement &ten = *outliner_add_element(
+ &space_outliner_, &tree, &scene, parent, TSE_VIEW_COLLECTION_BASE, 0);
+ ten.name = IFACE_("Scene Collection");
+ TREESTORE(&ten)->flag &= ~TSE_CLOSED;
+
+ /* First layer collection is for master collection, don't show it. */
+ LayerCollection *lc = static_cast<LayerCollection *>(view_layer_->layer_collections.first);
+ if (lc == nullptr) {
+ return;
+ }
- add_layer_collections_recursive(tree, lc->layer_collections, parent);
- if (show_objects_) {
- add_layer_collection_objects(tree, *lc, parent);
+ add_layer_collections_recursive(ten.subtree, lc->layer_collections, ten);
+ if (show_objects_) {
+ add_layer_collection_objects(ten.subtree, *lc, ten);
+ }
+ if (show_children) {
+ add_layer_collection_objects_children(ten);
+ }
}
}
diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.cc b/source/blender/editors/space_outliner/tree/tree_element_id.cc
index ce99b954204..7ff5a3285f1 100644
--- a/source/blender/editors/space_outliner/tree/tree_element_id.cc
+++ b/source/blender/editors/space_outliner/tree/tree_element_id.cc
@@ -85,7 +85,7 @@ TreeElementID *TreeElementID::createFromID(TreeElement &legacy_te, ID &id)
return new TreeElementID(legacy_te, id);
/* Deprecated */
case ID_IP:
- BLI_assert(!"Outliner trying to build tree-element for deprecated ID type");
+ BLI_assert_msg(0, "Outliner trying to build tree-element for deprecated ID type");
return nullptr;
}
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index 897af9ae931..11bee36e914 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -156,7 +156,7 @@ static void script_header_region_draw(const bContext *C, ARegion *region)
static void script_main_region_listener(const wmRegionListenerParams *UNUSED(params))
{
-/* XXX - Todo, need the ScriptSpace accessible to get the python script to run. */
+/* XXX: Todo, need the ScriptSpace accessible to get the python script to run. */
#if 0
BPY_run_script_space_listener()
#endif
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index ac31e0e7c37..1239286d4da 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -260,7 +260,7 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm
RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
BLI_strncpy(load_data->name, filename, sizeof(load_data->name));
- BLI_snprintf(load_data->path, sizeof(load_data->path), "%s%s", directory, filename);
+ BLI_join_dirfile(load_data->path, sizeof(load_data->path), directory, filename);
MEM_freeN(filename);
break;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 8341dbe6014..cdbe5bc63ce 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -101,7 +101,7 @@
#define SEQ_SCROLLER_TEXT_OFFSET 8
#define MUTE_ALPHA 120
-/* Note, Don't use SEQ_ALL_BEGIN/SEQ_ALL_END while drawing!
+/* NOTE: Don't use SEQ_ALL_BEGIN/SEQ_ALL_END while drawing!
* it messes up transform. */
#undef SEQ_ALL_BEGIN
#undef SEQ_ALL_END
@@ -453,13 +453,13 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
GPU_blend(GPU_BLEND_NONE);
}
-/* Get handle width in pixels. */
+/* Get handle width in 2d-View space. */
float sequence_handle_size_get_clamped(Sequence *seq, const float pixelx)
{
const float maxhandle = (pixelx * SEQ_HANDLE_SIZE) * U.pixelsize;
- /* Ensure that handle is not wider, than half of strip. */
- return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx);
+ /* Ensure that handle is not wider, than quarter of strip. */
+ return min_ff(maxhandle, ((float)(seq->enddisp - seq->startdisp) / 4.0f));
}
/* Draw a handle, on left or right side of strip. */
@@ -1556,7 +1556,7 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C,
*r_format = GPU_RGB16F;
}
else {
- BLI_assert(!"Incompatible number of channels for float buffer in sequencer");
+ BLI_assert_msg(0, "Incompatible number of channels for float buffer in sequencer");
*r_format = GPU_RGBA16F;
display_buffer = NULL;
}
@@ -2479,10 +2479,12 @@ void draw_timeline_seq_display(const bContext *C, ARegion *region)
const SpaceSeq *sseq = CTX_wm_space_seq(C);
View2D *v2d = &region->v2d;
- if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
+ if (scene->ed != NULL) {
UI_view2d_view_ortho(v2d);
draw_cache_view(C);
- draw_overlap_frame_indicator(scene, v2d);
+ if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
+ draw_overlap_frame_indicator(scene, v2d);
+ }
UI_view2d_view_restore(C);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 48b8a1b87a3..4b26469aad3 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -2258,7 +2258,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
break;
}
- /* XXX - Should be a generic function. */
+ /* XXX: Should be a generic function. */
for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) {
if ((iseq->type & SEQ_TYPE_EFFECT) &&
(seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
@@ -2414,6 +2414,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
(LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_MAIN));
seqbase_clipboard_frame = scene->r.cfra;
+ SEQ_clipboard_active_seq_name_store(scene);
/* Remove anything that references the current scene. */
LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) {
@@ -2504,6 +2505,10 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
BLI_movelisttolist(ed->seqbasep, &nseqbase);
for (iseq = iseq_first; iseq; iseq = iseq->next) {
+ if (SEQ_clipboard_pasted_seq_was_active(iseq)) {
+ SEQ_select_active_set(scene, iseq);
+ }
+
/* Make sure, that pasted strips have unique names. */
SEQ_ensure_unique_name(iseq, scene);
/* Translate after name has been changed, otherwise this will affect animdata of original
@@ -2804,9 +2809,9 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "directory", directory);
if (is_relative_path) {
- /* TODO, shouldn't this already be relative from the filesel?
+ /* TODO(campbell): shouldn't this already be relative from the filesel?
* (as the 'filepath' is) for now just make relative here,
- * but look into changing after 2.60 - campbell */
+ * but look into changing after 2.60. */
BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
}
BLI_strncpy(seq->strip->dir, directory, sizeof(seq->strip->dir));
@@ -2929,6 +2934,23 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
/** \name Export Subtitles Operator
* \{ */
+/** Comparison function suitable to be used with BLI_listbase_sort(). */
+static int seq_cmp_time_startdisp_channel(const void *a, const void *b)
+{
+ Sequence *seq_a = (Sequence *)a;
+ Sequence *seq_b = (Sequence *)b;
+
+ int seq_a_start = SEQ_transform_get_left_handle_frame(seq_a);
+ int seq_b_start = SEQ_transform_get_left_handle_frame(seq_b);
+
+ /** If strips have the same start frame favor the one with a higher channel. **/
+ if (seq_a_start == seq_b_start) {
+ return seq_a->machine > seq_b->machine;
+ }
+
+ return (seq_a_start > seq_b_start);
+}
+
static int sequencer_export_subtitles_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
@@ -2998,7 +3020,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BLI_listbase_sort(&text_seq, SEQ_time_cmp_time_startdisp);
+ BLI_listbase_sort(&text_seq, seq_cmp_time_startdisp_channel);
/* Open and write file. */
file = BLI_fopen(filepath, "w");
@@ -3008,7 +3030,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
char timecode_str_start[32];
char timecode_str_end[32];
- /* Write timecode relative to start frame of scene. Don't allow negative timecodes. */
+ /* Write time-code relative to start frame of scene. Don't allow negative time-codes. */
BLI_timecode_string_from_time(timecode_str_start,
sizeof(timecode_str_start),
-2,
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 16768e09cb8..5d857f62b47 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -32,8 +32,8 @@
#include "sequencer_intern.h"
-/* XXX, why is this function better than BLI_math version?
- * only difference is it does some normalize after, need to double check on this - campbell */
+/* XXX(campbell): why is this function better than BLI_math version?
+ * only difference is it does some normalize after, need to double check on this. */
static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
{
yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
@@ -624,8 +624,6 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i
{
float rgb[3], yuv[3];
char *p;
- int x = 0;
- int y = 0;
rgb[0] = (float)r / 255.0f;
rgb[1] = (float)g / 255.0f;
@@ -638,8 +636,8 @@ static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, i
r = 255;
}
- for (y = -size; y <= size; y++) {
- for (x = -size; x <= size; x++) {
+ for (int y = -size; y <= size; y++) {
+ for (int x = -size; x <= size; x++) {
char *q = p + 4 * (y * w + x);
q[0] = r;
q[1] = g;
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 7e515271b13..5980bfe37cd 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -534,7 +534,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
seq = find_nearest_seq(scene, v2d, &hand, mval);
- /* XXX - not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip */
+ /* XXX: not nice, Ctrl+RMB needs to do side_of_frame only when not over a strip. */
if (seq && linked_time) {
side_of_frame = false;
}
diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index 1ea6593588a..e903feeec1b 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
../../gpu
../../makesdna
../../makesrna
+ ../../nodes
../../windowmanager
../../../../intern/glew-mx
../../../../intern/guardedalloc
@@ -34,8 +35,8 @@ set(INC
set(SRC
space_spreadsheet.cc
- spreadsheet_context.cc
spreadsheet_column.cc
+ spreadsheet_context.cc
spreadsheet_data_source.cc
spreadsheet_data_source_geometry.cc
spreadsheet_dataset_draw.cc
@@ -46,10 +47,10 @@ set(SRC
spreadsheet_row_filter.cc
spreadsheet_row_filter_ui.cc
- spreadsheet_context.hh
spreadsheet_cell_value.hh
spreadsheet_column.hh
spreadsheet_column_values.hh
+ spreadsheet_context.hh
spreadsheet_data_source.hh
spreadsheet_data_source_geometry.hh
spreadsheet_dataset_draw.hh
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index 07517f9e60f..fcc92345bea 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -222,24 +222,11 @@ ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet)
static void update_pinned_context_path_if_outdated(const bContext *C)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
-
- /* Currently, this only checks if the object has been deleted. In the future we can have a more
- * sophisticated check for the entire context (including modifier and nodes). */
- LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
- if (context->type == SPREADSHEET_CONTEXT_OBJECT) {
- SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context;
- if (object_context->object == nullptr) {
- ED_spreadsheet_context_path_clear(sspreadsheet);
- break;
- }
- }
- }
- if (BLI_listbase_is_empty(&sspreadsheet->context_path)) {
- Object *active_object = CTX_data_active_object(C);
- if (active_object != nullptr) {
- SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT);
- ((SpreadsheetContextObject *)new_context)->object = active_object;
- BLI_addtail(&sspreadsheet->context_path, new_context);
+ Main *bmain = CTX_data_main(C);
+ if (!ED_spreadsheet_context_path_exists(bmain, sspreadsheet)) {
+ ED_spreadsheet_context_path_guess(C, sspreadsheet);
+ if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
}
}
@@ -252,25 +239,12 @@ static void update_pinned_context_path_if_outdated(const bContext *C)
static void update_context_path_from_context(const bContext *C)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
- Object *active_object = CTX_data_active_object(C);
- if (active_object == nullptr) {
- ED_spreadsheet_context_path_clear(sspreadsheet);
- return;
- }
- if (!BLI_listbase_is_empty(&sspreadsheet->context_path)) {
- SpreadsheetContext *root_context = (SpreadsheetContext *)sspreadsheet->context_path.first;
- if (root_context->type == SPREADSHEET_CONTEXT_OBJECT) {
- SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)root_context;
- if (object_context->object != active_object) {
- ED_spreadsheet_context_path_clear(sspreadsheet);
- }
+ if (!ED_spreadsheet_context_path_is_active(C, sspreadsheet)) {
+ ED_spreadsheet_context_path_guess(C, sspreadsheet);
+ if (ED_spreadsheet_context_path_update_tag(sspreadsheet)) {
+ ED_area_tag_redraw(CTX_wm_area(C));
}
}
- if (BLI_listbase_is_empty(&sspreadsheet->context_path)) {
- SpreadsheetContext *new_context = spreadsheet_context_new(SPREADSHEET_CONTEXT_OBJECT);
- ((SpreadsheetContextObject *)new_context)->object = active_object;
- BLI_addtail(&sspreadsheet->context_path, new_context);
- }
}
void spreadsheet_update_context_path(const bContext *C)
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
index c9b73aabf96..680da9b6794 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
@@ -22,8 +22,8 @@
#include "BLI_float2.hh"
#include "BLI_float3.hh"
-struct Object;
struct Collection;
+struct Object;
namespace blender::ed::spreadsheet {
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
index af6ab5d1b92..1ac2075e281 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
@@ -24,16 +24,28 @@
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
+#include "ED_screen.h"
#include "ED_spreadsheet.h"
#include "DEG_depsgraph.h"
+#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_workspace.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_windowmanager_types.h"
#include "spreadsheet_context.hh"
+using blender::IndexRange;
+using blender::Span;
+using blender::StringRef;
+using blender::Vector;
+
namespace blender::ed::spreadsheet {
static SpreadsheetContextObject *spreadsheet_context_object_new()
@@ -206,28 +218,30 @@ void spreadsheet_context_free(SpreadsheetContext *context)
/**
* Tag any data relevant to the spreadsheet's context for recalculation in order to collect
* information to display in the editor, which may be cached during evaluation.
+ * \return True when any data has been tagged for update.
*/
-static void spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet)
+static bool spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet)
{
using namespace blender;
Vector<const SpreadsheetContext *> context_path = sspreadsheet->context_path;
if (context_path.is_empty()) {
- return;
+ return false;
}
if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
- return;
+ return false;
}
SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0];
Object *object = object_context->object;
if (object == nullptr) {
- return;
+ return false;
}
if (context_path.size() == 1) {
/* No need to reevaluate, when the final or original object is viewed. */
- return;
+ return false;
}
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ return true;
}
} // namespace blender::ed::spreadsheet
@@ -250,9 +264,9 @@ void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet)
BLI_listbase_clear(&sspreadsheet->context_path);
}
-void ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet)
+bool ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet)
{
- blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet);
+ return blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet);
}
uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet)
@@ -265,15 +279,32 @@ uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet)
return BLI_hash_mm2a_end(&mm2);
}
-void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet,
- struct SpaceNode *snode,
- struct bNode *node)
+void ED_spreadsheet_context_path_set_geometry_node(struct SpaceSpreadsheet *sspreadsheet,
+ struct SpaceNode *snode,
+ struct bNode *node)
{
using namespace blender::ed::spreadsheet;
- ED_spreadsheet_context_path_clear(sspreadsheet);
Object *object = (Object *)snode->id;
+ /* Try to find the modifier the node tree belongs to. */
ModifierData *modifier = BKE_object_active_modifier(object);
+ if (modifier && modifier->type != eModifierType_Nodes) {
+ modifier = nullptr;
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ if (md->type == eModifierType_Nodes) {
+ NodesModifierData *nmd = (NodesModifierData *)md;
+ if (nmd->node_group == snode->nodetree) {
+ modifier = md;
+ break;
+ }
+ }
+ }
+ }
+ if (modifier == nullptr) {
+ return;
+ }
+
+ ED_spreadsheet_context_path_clear(sspreadsheet);
{
SpreadsheetContextObject *context = spreadsheet_context_object_new();
@@ -302,5 +333,251 @@ void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsh
BLI_addtail(&sspreadsheet->context_path, context);
}
- sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED;
+ sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE;
+}
+
+void ED_spreadsheet_context_paths_set_geometry_node(Main *bmain, SpaceNode *snode, bNode *node)
+{
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ if (wm == nullptr) {
+ return;
+ }
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
+ if (sl->spacetype == SPACE_SPREADSHEET) {
+ SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
+ if ((sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) == 0) {
+ const uint64_t context_hash_before = ED_spreadsheet_context_path_hash(sspreadsheet);
+ ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node);
+ const uint64_t context_hash_after = ED_spreadsheet_context_path_hash(sspreadsheet);
+ if (context_hash_before != context_hash_after) {
+ ED_spreadsheet_context_path_update_tag(sspreadsheet);
+ }
+ ED_area_tag_redraw(area);
+ }
+ }
+ }
+ }
+}
+
+void ED_spreadsheet_context_path_set_evaluated_object(SpaceSpreadsheet *sspreadsheet,
+ Object *object)
+{
+ using namespace blender::ed::spreadsheet;
+ ED_spreadsheet_context_path_clear(sspreadsheet);
+
+ SpreadsheetContextObject *context = spreadsheet_context_object_new();
+ context->object = object;
+ BLI_addtail(&sspreadsheet->context_path, context);
+}
+
+void ED_spreadsheet_context_path_guess(const bContext *C, SpaceSpreadsheet *sspreadsheet)
+{
+ ED_spreadsheet_context_path_clear(sspreadsheet);
+
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ if (wm == nullptr) {
+ return;
+ }
+
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) {
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
+ if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ if (snode->edittree != nullptr) {
+ if (snode->edittree->type == NTREE_GEOMETRY) {
+ LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
+ if (node->type == GEO_NODE_VIEWER) {
+ if (node->flag & NODE_DO_OUTPUT) {
+ ED_spreadsheet_context_path_set_geometry_node(sspreadsheet, snode, node);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Object *active_object = CTX_data_active_object(C);
+ if (active_object != nullptr) {
+ ED_spreadsheet_context_path_set_evaluated_object(sspreadsheet, active_object);
+ return;
+ }
+}
+
+bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet *sspreadsheet)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+ if (wm == nullptr) {
+ return false;
+ }
+ Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path;
+ if (context_path.is_empty()) {
+ return false;
+ }
+ if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
+ return false;
+ }
+ Object *object = ((SpreadsheetContextObject *)context_path[0])->object;
+ if (object == nullptr) {
+ return false;
+ }
+ if (context_path.size() == 1) {
+ if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) {
+ return false;
+ }
+ Object *active_object = CTX_data_active_object(C);
+ return object == active_object;
+ }
+ if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) {
+ return false;
+ }
+ if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) {
+ return false;
+ }
+ const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name;
+ const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name);
+ if (modifier == nullptr) {
+ return false;
+ }
+ if (!(modifier->flag & eModifierFlag_Active)) {
+ return false;
+ }
+ if (modifier->type != eModifierType_Nodes) {
+ return false;
+ }
+ bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group;
+ if (root_node_tree == nullptr) {
+ return false;
+ }
+ const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2);
+ if (node_context_path.is_empty()) {
+ return false;
+ }
+
+ LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
+ bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ SpaceLink *sl = (SpaceLink *)area->spacedata.first;
+ if (sl->spacetype != SPACE_NODE) {
+ continue;
+ }
+ SpaceNode *snode = (SpaceNode *)sl;
+ if (snode->nodetree != root_node_tree) {
+ continue;
+ }
+ if (snode->id != &object->id) {
+ continue;
+ }
+ Vector<bNodeTreePath *> tree_path = snode->treepath;
+ if (node_context_path.size() != tree_path.size()) {
+ continue;
+ }
+ int valid_count = 0;
+ for (const int i : IndexRange(tree_path.size() - 1)) {
+ if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) {
+ break;
+ }
+ SpreadsheetContextNode *node_context = (SpreadsheetContextNode *)node_context_path[i];
+ if (!STREQ(node_context->node_name, tree_path[i]->node_name)) {
+ break;
+ }
+ valid_count++;
+ }
+ if (valid_count != tree_path.size() - 1) {
+ continue;
+ }
+ SpreadsheetContext *last_context = node_context_path.last();
+ if (last_context->type != SPREADSHEET_CONTEXT_NODE) {
+ return false;
+ }
+ const char *node_name = ((SpreadsheetContextNode *)last_context)->node_name;
+ bNode *node = nodeFindNodebyName(snode->edittree, node_name);
+ if (node == nullptr) {
+ return false;
+ }
+ if (node->type != GEO_NODE_VIEWER) {
+ return false;
+ }
+ if (!(node->flag & NODE_DO_OUTPUT)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ED_spreadsheet_context_path_exists(Main *UNUSED(bmain), SpaceSpreadsheet *sspreadsheet)
+{
+ Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path;
+ if (context_path.is_empty()) {
+ return false;
+ }
+ if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
+ return false;
+ }
+ Object *object = ((SpreadsheetContextObject *)context_path[0])->object;
+ if (object == nullptr) {
+ return false;
+ }
+ if (context_path.size() == 1) {
+ return true;
+ }
+ if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) {
+ return false;
+ }
+ const char *modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name;
+ const ModifierData *modifier = BKE_modifiers_findby_name(object, modifier_name);
+ if (modifier == nullptr) {
+ return false;
+ }
+ if (modifier->type != eModifierType_Nodes) {
+ return false;
+ }
+ bNodeTree *root_node_tree = ((NodesModifierData *)modifier)->node_group;
+ if (root_node_tree == nullptr) {
+ return false;
+ }
+ const Span<SpreadsheetContext *> node_context_path = context_path.as_span().drop_front(2);
+ if (node_context_path.is_empty()) {
+ return false;
+ }
+ bNodeTree *node_tree = root_node_tree;
+ for (const int i : node_context_path.index_range()) {
+ if (node_context_path[i]->type != SPREADSHEET_CONTEXT_NODE) {
+ return false;
+ }
+ const char *node_name = ((SpreadsheetContextNode *)node_context_path[i])->node_name;
+ bNode *node = nodeFindNodebyName(node_tree, node_name);
+ if (node == nullptr) {
+ return false;
+ }
+ if (node->type == GEO_NODE_VIEWER) {
+ if (i == node_context_path.index_range().last()) {
+ return true;
+ }
+ return false;
+ }
+ if (node->id != nullptr) {
+ if (GS(node->id->name) != ID_NT) {
+ return false;
+ }
+ node_tree = (bNodeTree *)node->id;
+ }
+ else {
+ return false;
+ }
+ }
+ return false;
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
index 6d244a1bda6..e38c70afd0f 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -31,11 +31,15 @@
#include "ED_spreadsheet.h"
+#include "NOD_geometry_nodes_eval_log.hh"
+
#include "bmesh.h"
#include "spreadsheet_data_source_geometry.hh"
#include "spreadsheet_intern.hh"
+namespace geo_log = blender::nodes::geometry_nodes_eval_log;
+
namespace blender::ed::spreadsheet {
void GeometryDataSource::foreach_default_column_ids(
@@ -410,7 +414,6 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
Mesh *mesh = (Mesh *)object_orig->data;
mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
}
- mesh_component.copy_vertex_group_names_from_object(*object_orig);
}
else if (object_orig->type == OB_POINTCLOUD) {
PointCloud *pointcloud = (PointCloud *)object_orig->data;
@@ -419,7 +422,7 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly);
}
}
- else if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED) {
+ else {
if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
if (mesh == nullptr) {
@@ -428,7 +431,6 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
BKE_mesh_wrapper_ensure_mdata(mesh);
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
- mesh_component.copy_vertex_group_names_from_object(*object_eval);
}
else {
if (BLI_listbase_count(&sspreadsheet->context_path) == 1) {
@@ -438,13 +440,18 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
}
}
else {
- if (object_eval->runtime.geometry_set_previews != nullptr) {
- GHash *ghash = (GHash *)object_eval->runtime.geometry_set_previews;
- const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet);
- GeometrySet *geometry_set_preview = (GeometrySet *)BLI_ghash_lookup_default(
- ghash, POINTER_FROM_UINT(key), nullptr);
- if (geometry_set_preview != nullptr) {
- geometry_set = *geometry_set_preview;
+ const geo_log::NodeLog *node_log =
+ geo_log::ModifierLog::find_node_by_spreadsheet_editor_context(*sspreadsheet);
+ if (node_log != nullptr) {
+ for (const geo_log::SocketLog &input_log : node_log->input_logs()) {
+ if (const geo_log::GeometryValueLog *geo_value_log =
+ dynamic_cast<const geo_log::GeometryValueLog *>(input_log.value())) {
+ const GeometrySet *full_geometry = geo_value_log->full_geometry();
+ if (full_geometry != nullptr) {
+ geometry_set = *full_geometry;
+ break;
+ }
+ }
}
}
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
index d9e6d882c2a..19906d73e7f 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
@@ -23,9 +23,9 @@
#include "spreadsheet_dataset_layout.hh"
struct ARegion;
-struct uiBlock;
struct View2D;
struct bContext;
+struct uiBlock;
namespace blender::ed::spreadsheet {
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
index 5b5c5ed0b04..abbad8c7088 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
@@ -38,9 +38,9 @@ namespace blender::ed::spreadsheet {
* Definition for the component->attribute-domain hierarchy.
* Constructed at compile time.
*
- * \warning: Order of attribute-domains matters! It __must__ match the #AttributeDomain definition
- * and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use array
- * designators for this (which C++ doesn't support).
+ * \warning Order of attribute-domains matters! It __must__ match the #AttributeDomain
+ * definition and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use
+ * array designators for this (which C++ doesn't support).
*/
constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = {
{
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh
index 647587ec8b0..9accd1d3d09 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_draw.hh
@@ -18,9 +18,9 @@
#include "BLI_vector.hh"
-struct uiBlock;
-struct bContext;
struct ARegion;
+struct bContext;
+struct uiBlock;
namespace blender::ed::spreadsheet {
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
index dbd2ef157af..219d03c1dcd 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter_ui.cc
@@ -267,20 +267,20 @@ static void spreadsheet_row_filters_layout(const bContext *C, Panel *panel)
}
else {
/* Assuming there's only one group of instanced panels, update the custom data pointers. */
- Panel *panel = (Panel *)region->panels.first;
+ Panel *panel_iter = (Panel *)region->panels.first;
LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, row_filters) {
/* Move to the next instanced panel corresponding to the next filter. */
- while ((panel->type == nullptr) || !(panel->type->flag & PANEL_TYPE_INSTANCED)) {
- panel = panel->next;
- BLI_assert(panel != nullptr); /* There shouldn't be fewer panels than filters. */
+ while ((panel_iter->type == nullptr) || !(panel_iter->type->flag & PANEL_TYPE_INSTANCED)) {
+ panel_iter = panel_iter->next;
+ BLI_assert(panel_iter != nullptr); /* There shouldn't be fewer panels than filters. */
}
PointerRNA *filter_ptr = (PointerRNA *)MEM_mallocN(sizeof(PointerRNA), "panel customdata");
RNA_pointer_create(&screen->id, &RNA_SpreadsheetRowFilter, row_filter, filter_ptr);
- UI_panel_custom_data_set(panel, filter_ptr);
+ UI_panel_custom_data_set(panel_iter, filter_ptr);
- panel = panel->next;
+ panel_iter = panel_iter->next;
}
}
}
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
index 16eb66624ce..0cd2d9baa0b 100644
--- a/source/blender/editors/space_text/text_format_lua.c
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -165,9 +165,9 @@ static char txtfmt_lua_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_lua_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
- } else if ((txtfmt_lua_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
- } else { fmt = FMT_TYPE_DEFAULT;
+ if (txtfmt_lua_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL;
+ } else if (txtfmt_lua_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD;
+ } else { fmt = FMT_TYPE_DEFAULT;
}
/* clang-format on */
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
index 1a024779a83..97d9ec546ca 100644
--- a/source/blender/editors/space_text/text_format_osl.c
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -189,11 +189,11 @@ static char txtfmt_osl_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_osl_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
- } else if ((txtfmt_osl_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
- } else if ((txtfmt_osl_find_reserved(str)) != -1) { fmt = FMT_TYPE_RESERVED;
- } else if ((txtfmt_osl_find_preprocessor(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE;
- } else { fmt = FMT_TYPE_DEFAULT;
+ if (txtfmt_osl_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL;
+ } else if (txtfmt_osl_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD;
+ } else if (txtfmt_osl_find_reserved(str) != -1) { fmt = FMT_TYPE_RESERVED;
+ } else if (txtfmt_osl_find_preprocessor(str) != -1) { fmt = FMT_TYPE_DIRECTIVE;
+ } else { fmt = FMT_TYPE_DEFAULT;
}
/* clang-format on */
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
index 1200dda7533..ea3d0ec1478 100644
--- a/source/blender/editors/space_text/text_format_pov.c
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -762,11 +762,11 @@ static char txtfmt_pov_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_pov_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
- } else if ((txtfmt_pov_find_keyword(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
- } else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) { fmt = FMT_TYPE_RESERVED;
- } else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) { fmt = FMT_TYPE_DIRECTIVE;
- } else { fmt = FMT_TYPE_DEFAULT;
+ if (txtfmt_pov_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL;
+ } else if (txtfmt_pov_find_keyword(str) != -1) { fmt = FMT_TYPE_KEYWORD;
+ } else if (txtfmt_pov_find_reserved_keywords(str) != -1) { fmt = FMT_TYPE_RESERVED;
+ } else if (txtfmt_pov_find_reserved_builtins(str) != -1) { fmt = FMT_TYPE_DIRECTIVE;
+ } else { fmt = FMT_TYPE_DEFAULT;
}
/* clang-format on */
diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c
index 1c6a93d2d7a..259ad02a6b7 100644
--- a/source/blender/editors/space_text/text_format_pov_ini.c
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -347,10 +347,10 @@ static int txtfmt_ini_find_bool(const char *string)
static char txtfmt_pov_ini_format_identifier(const char *str)
{
char fmt;
- if ((txtfmt_ini_find_keyword(str)) != -1) {
+ if (txtfmt_ini_find_keyword(str) != -1) {
fmt = FMT_TYPE_KEYWORD;
}
- else if ((txtfmt_ini_find_reserved(str)) != -1) {
+ else if (txtfmt_ini_find_reserved(str) != -1) {
fmt = FMT_TYPE_RESERVED;
}
else {
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 31177c53d6a..e2a01a8d85d 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -290,7 +290,7 @@ static int txtfmt_py_literal_numeral(const char *string, char prev_fmt)
return 1 + txtfmt_py_find_numeral_inner(string + 1);
}
/* Previous was a number; if immediately followed by '.' it's a floating point decimal number.
- * Note: keep the decimal point, it's needed to allow leading zeros. */
+ * NOTE: keep the decimal point, it's needed to allow leading zeros. */
if (first == '.') {
return txtfmt_py_find_numeral_inner(string);
}
@@ -315,10 +315,10 @@ static char txtfmt_py_format_identifier(const char *str)
/* Keep aligned args for readability. */
/* clang-format off */
- if ((txtfmt_py_find_specialvar(str)) != -1) { fmt = FMT_TYPE_SPECIAL;
- } else if ((txtfmt_py_find_builtinfunc(str)) != -1) { fmt = FMT_TYPE_KEYWORD;
- } else if ((txtfmt_py_find_decorator(str)) != -1) { fmt = FMT_TYPE_RESERVED;
- } else { fmt = FMT_TYPE_DEFAULT;
+ if (txtfmt_py_find_specialvar(str) != -1) { fmt = FMT_TYPE_SPECIAL;
+ } else if (txtfmt_py_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD;
+ } else if (txtfmt_py_find_decorator(str) != -1) { fmt = FMT_TYPE_RESERVED;
+ } else { fmt = FMT_TYPE_DEFAULT;
}
/* clang-format on */
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 6ca89250cd7..b98dae0cd57 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -745,7 +745,7 @@ void TEXT_OT_save_as(wmOperatorType *ot)
FILE_SAVE,
WM_FILESEL_FILEPATH,
FILE_DEFAULTDISPLAY,
- FILE_SORT_DEFAULT); /* XXX TODO, relative_path. */
+ FILE_SORT_DEFAULT); /* XXX TODO: relative_path. */
}
/** \} */
@@ -3468,7 +3468,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int ret;
- /* Note, the "text" property is always set from key-map,
+ /* NOTE: the "text" property is always set from key-map,
* so we can't use #RNA_struct_property_is_set, check the length instead. */
if (!RNA_string_length(op->ptr, "text")) {
/* if alt/ctrl/super are pressed pass through except for utf8 character event
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
index f55db8c3cc9..80af7d8c9f6 100644
--- a/source/blender/editors/space_text/text_undo.c
+++ b/source/blender/editors/space_text/text_undo.c
@@ -265,7 +265,7 @@ void ED_text_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref;
- ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
+ ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE | UNDOTYPE_FLAG_DECODE_ACTIVE_STEP;
ut->step_size = sizeof(TextUndoStep);
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 660ae9da506..6b9da431510 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -117,10 +117,10 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
return;
}
- Mesh *me = ob->data;
+ const Mesh *me = ob->data;
{
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (me_eval != NULL) {
me = me_eval;
}
@@ -160,7 +160,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
const MPoly *mp;
int i;
if (me->runtime.looptris.array) {
- MLoopTri *mlt = me->runtime.looptris.array;
+ const MLoopTri *mlt = me->runtime.looptris.array;
for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
if (facemap_data[i] == facemap) {
for (int j = 2; j < mp->totloop; j++) {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6ce13f83cf3..54f10e259f9 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1096,7 +1096,7 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP
ScrArea *area = params->area;
ARegion *region = params->region;
- /* Developer note: there are many properties that impact 3D view drawing,
+ /* Developer NOTE: there are many properties that impact 3D view drawing,
* so instead of subscribing to individual properties, just subscribe to types
* accepting some redundant redraws.
*
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 60e1c780b9e..3428a738dde 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -39,6 +39,8 @@
#include "BLT_translation.h"
+#include "BLI_array_utils.h"
+#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -112,10 +114,94 @@ typedef struct {
float ob_dims[3];
/* Floats only (treated as an array). */
TransformMedian ve_median, median;
+ bool tag_for_update;
} TransformProperties;
#define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float))
+static TransformProperties *v3d_transform_props_ensure(View3D *v3d);
+
+/* -------------------------------------------------------------------- */
+/** \name Edit Mesh Partial Updates
+ * \{ */
+
+static void *editmesh_partial_update_begin_fn(struct bContext *UNUSED(C),
+ const struct uiBlockInteraction_Params *params,
+ void *arg1)
+{
+ const int retval_test = B_TRANSFORM_PANEL_MEDIAN;
+ if (BLI_array_findindex(
+ params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1) {
+ return NULL;
+ }
+
+ BMEditMesh *em = arg1;
+
+ int verts_mask_count = 0;
+ BMIter iter;
+ BMVert *eve;
+ int i;
+
+ BLI_bitmap *verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ continue;
+ }
+ BLI_BITMAP_ENABLE(verts_mask, i);
+ verts_mask_count += 1;
+ }
+
+ BMPartialUpdate *bmpinfo = BM_mesh_partial_create_from_verts_group_single(
+ em->bm,
+ &(BMPartialUpdate_Params){
+ .do_tessellate = true,
+ .do_normals = true,
+ },
+ verts_mask,
+ verts_mask_count);
+
+ MEM_freeN(verts_mask);
+
+ return bmpinfo;
+}
+
+static void editmesh_partial_update_end_fn(struct bContext *UNUSED(C),
+ const struct uiBlockInteraction_Params *UNUSED(params),
+ void *UNUSED(arg1),
+ void *user_data)
+{
+ BMPartialUpdate *bmpinfo = user_data;
+ if (bmpinfo == NULL) {
+ return;
+ }
+ BM_mesh_partial_destroy(bmpinfo);
+}
+
+static void editmesh_partial_update_update_fn(
+ struct bContext *C,
+ const struct uiBlockInteraction_Params *UNUSED(params),
+ void *arg1,
+ void *user_data)
+{
+ BMPartialUpdate *bmpinfo = user_data;
+ if (bmpinfo == NULL) {
+ return;
+ }
+
+ View3D *v3d = CTX_wm_view3d(C);
+ TransformProperties *tfp = v3d_transform_props_ensure(v3d);
+ if (tfp->tag_for_update == false) {
+ return;
+ }
+ tfp->tag_for_update = false;
+
+ BMEditMesh *em = arg1;
+
+ BKE_editmesh_looptri_and_normals_calc_with_partial(em, bmpinfo);
+}
+
+/** \} */
+
/* Helper function to compute a median changed value,
* when the value should be clamped in [0.0, 1.0].
* Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor
@@ -840,6 +926,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
UI_block_align_end(block);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ if (em != NULL) {
+ UI_block_interaction_set(block,
+ &(uiBlockInteraction_CallbackData){
+ .begin_fn = editmesh_partial_update_begin_fn,
+ .end_fn = editmesh_partial_update_end_fn,
+ .update_fn = editmesh_partial_update_update_fn,
+ .arg1 = em,
+ });
+ }
+ }
}
else { /* apply */
memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median));
@@ -927,9 +1027,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
if (apply_vcos) {
- /* TODO: use the #BKE_editmesh_looptri_and_normals_calc_with_partial
- * This requires begin/end states for UI interaction (which currently aren't supported). */
- BKE_editmesh_looptri_and_normals_calc(em);
+ /* Tell the update callback to run. */
+ tfp->tag_for_update = true;
}
/* Edges */
@@ -1152,7 +1251,7 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = view_layer->basact->object;
ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
}
@@ -1211,7 +1310,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel)
vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
ob, subset_type, &vgroup_tot, &subset_count);
- for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
+ for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) {
bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0;
if (vgroup_validmap[i]) {
MDeformWeight *dw = BKE_defvert_find_index(dv, i);
@@ -1237,7 +1338,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *panel)
but_ptr = UI_but_operator_ptr_get(but);
RNA_int_set(but_ptr, "weight_group", i);
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
- if (ob->actdef != i + 1) {
+ if (BKE_object_defgroup_active_index_get(ob) != i + 1) {
UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
xco += x;
@@ -1464,7 +1565,7 @@ static void v3d_posearmature_buts(uiLayout *layout, Object *ob)
/* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.)
* but old-school UI shows in eulers always. Do we want to be able to still display in Eulers?
- * Maybe needs RNA/ui options to display rotations as different types... */
+ * Maybe needs RNA/UI options to display rotations as different types. */
v3d_transform_butsR(col, &pchanptr);
}
@@ -1568,7 +1669,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event
case B_TRANSFORM_PANEL_MEDIAN:
if (ob) {
v3d_editvertex_buts(NULL, v3d, ob, 1.0);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
}
break;
case B_TRANSFORM_PANEL_DIMS:
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 2e46deea0e8..c97ba7ba7e9 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -140,7 +140,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)region->winx;
rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)region->winy;
}
- /* note: calls BKE_object_where_is_calc for camera... */
+ /* NOTE: calls BKE_object_where_is_calc for camera... */
view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL);
}
/* update utility matrices */
@@ -167,7 +167,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
/* Calculate pixel-size factor once, this is used for lights and object-centers. */
{
- /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
+ /* NOTE: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
* because of float point precision problems at large values T23908. */
float v1[3], v2[3];
float len_px, len_sc;
@@ -563,10 +563,10 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
/* apply offsets so the real 3D camera shows through */
- /* note: quite un-scientific but without this bit extra
+ /* NOTE: quite un-scientific but without this bit extra
* 0.0001 on the lower left the 2D border sometimes
* obscures the 3D camera border */
- /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
+ /* NOTE: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
* but keep it here in case we need to remove the workaround */
x1i = (int)(x1 - 1.0001f);
y1i = (int)(y1 - 1.0001f);
@@ -780,7 +780,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
/* draw */
immUniformThemeColorShadeAlpha(TH_VIEW_OVERLAY, 100, 255);
- /* TODO Was using:
+ /* TODO: Was using:
* UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color);
* We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the
* 2.0f round corner effect was nearly not visible anyway... */
@@ -1159,7 +1159,7 @@ static void view3d_draw_border(const bContext *C, ARegion *region)
*/
static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
{
- /* TODO viewport */
+ /* TODO: viewport. */
}
/**
@@ -1404,7 +1404,7 @@ static void draw_selected_name(
/* color depends on whether there is a keyframe */
if (id_frame_has_keyframe(
- (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) {
+ (ID *)ob, /* BKE_scene_ctime_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) {
UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
}
else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) {
@@ -2262,7 +2262,7 @@ void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d)
}
}
-/* Note, with nouveau drivers the glReadPixels() is very slow. T24339. */
+/* NOTE: with nouveau drivers the glReadPixels() is very slow. T24339. */
static ViewDepths *view3d_depths_create(ARegion *region)
{
ViewDepths *d = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 50e9a9fb805..651ae8a3000 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -392,9 +392,9 @@ enum eViewOpsFlag {
/** When enabled, use the depth under the cursor for navigation. */
VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
/**
- * When enabled run #ED_view3d_persp_ensure this may switch out of
- * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
- * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
+ * When enabled run #ED_view3d_persp_ensure this may switch out of camera view
+ * when orbiting or switch from orthographic to perspective when auto-perspective is enabled.
+ * Some operations don't require this (view zoom/pan or NDOF where subtle rotation is common
* so we don't want it to trigger auto-perspective). */
VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
/** When set, ignore any options that depend on initial cursor location. */
@@ -813,7 +813,6 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
}
else {
- /* New turntable view code by John Aughey */
float quat_local_x[4], quat_global_z[4];
float m[3][3];
float m_inv[3][3];
@@ -894,8 +893,8 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
* rotation back into the view we calculate with */
copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
- /* check for view snap,
- * note: don't apply snap to vod->viewquat so the view won't jam up */
+ /* Check for view snap,
+ * NOTE: don't apply snap to `vod->viewquat` so the view won't jam up. */
if (vod->axis_snap) {
viewrotate_apply_snap(vod);
}
@@ -1201,7 +1200,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
if (U.ndof_flag & NDOF_TURNTABLE) {
float rot[3];
- /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
+ /* Turntable view code adapted for 3D mouse use. */
float angle, quat[4];
float xvec[3] = {1, 0, 0};
@@ -1506,7 +1505,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
}
else {
- /* Note: based on feedback from T67579, users want to have pan and orbit enabled at once.
+ /* NOTE: based on feedback from T67579, users want to have pan and orbit enabled at once.
* It's arguable that orbit shouldn't pan (since we have a pan only operator),
* so if there are users who like to separate orbit/pan operations - it can be a preference. */
const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) ||
@@ -2955,7 +2954,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
if (!changed) {
ED_region_tag_redraw(region);
- /* TODO - should this be cancel?
+ /* TODO: should this be cancel?
* I think no, because we always move the cursor, with or without
* object, but in this case there is no change in the scene,
* only the cursor so I choice a ED_region_tag like
@@ -3604,7 +3603,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
float depth_close = FLT_MAX;
float cent[2], p[3];
- /* note; otherwise opengl won't work */
+ /* NOTE: otherwise opengl won't work. */
view3d_operator_needs_opengl(C);
/* get box select values using rna */
@@ -4788,7 +4787,7 @@ static bool background_image_add_poll(bContext *C)
void VIEW3D_OT_background_image_add(wmOperatorType *ot)
{
/* identifiers */
- /* note: having key shortcut here is bad practice,
+ /* NOTE: having key shortcut here is bad practice,
* but for now keep because this displays when dragging an image over the 3D viewport */
ot->name = "Add Background Image";
ot->description = "Add a new background image";
@@ -4957,7 +4956,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
* \{ */
/* cursor position in vec, result in vec, mval in region coords */
-/* note: cannot use event->mval here (called by object_add() */
+/* NOTE: cannot use `event->mval` here, called by #object_add(). */
void ED_view3d_cursor3d_position(bContext *C,
const int mval[2],
const bool use_depth,
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
index 16c83b45924..83d3286c8b3 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c
@@ -199,7 +199,7 @@ static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup
mul_m4_m4m4(mat, ob->obmat, (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 */
+ /* need to set property here for undo. TODO: would prefer to do this in _init. */
WM_gizmo_target_property_def_func(gz,
"offset",
&(const struct wmGizmoPropertyFnParams){
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 20d766357e8..e1d439bef15 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -153,7 +153,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize);
WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false);
- /* Need to set property here for undo. TODO would prefer to do this in _init */
+ /* Need to set property here for undo. TODO: would prefer to do this in _init. */
PointerRNA camera_dof_ptr;
RNA_pointer_create(&ca->id, &RNA_CameraDOFSettings, &ca->dof, &camera_dof_ptr);
WM_gizmo_target_property_def_rna(
@@ -163,7 +163,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
}
- /* TODO - make focal length/ortho ob_scale_inv widget optional */
+ /* TODO: make focal length/ortho ob_scale_inv widget optional. */
const Scene *scene = CTX_data_scene(C);
const float aspx = (float)scene->r.xsch * scene->r.xasp;
const float aspy = (float)scene->r.ysch * scene->r.yasp;
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c
index 5bf105b6775..d92ebfd57a8 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_light.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c
@@ -99,7 +99,7 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr
WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir);
WM_gizmo_set_matrix_location(gz, ob->obmat[3]);
- /* need to set property here for undo. TODO would prefer to do this in _init */
+ /* need to set property here for undo. TODO: would prefer to do this in _init. */
PointerRNA lamp_ptr;
const char *propname = "spot_size";
RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
@@ -212,7 +212,7 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr
}
RNA_enum_set(gz->ptr, "transform", flag);
- /* need to set property here for undo. TODO would prefer to do this in _init */
+ /* need to set property here for undo. TODO: would prefer to do this in _init. */
WM_gizmo_target_property_def_func(gz,
"matrix",
&(const struct wmGizmoPropertyFnParams){
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 0d568363b00..49299d73337 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -580,7 +580,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
UI_GetThemeColor3ubv(TH_TEXT, color_text);
UI_GetThemeColor3ubv(TH_WIRE, color_wire);
- /* Avoid white on white text. (TODO Fix by using theme) */
+ /* Avoid white on white text. (TODO: Fix by using theme). */
if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) {
copy_v3_fl(color_back, 0.0f);
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c
index e2fa0fdc6a5..5752837c40f 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_fly.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c
@@ -122,7 +122,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
{FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
{FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"},
- {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"},
+ {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction (toggle)"},
{FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""},
{FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""},
diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c
index 33cb6aad400..09936b41a74 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_walk.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c
@@ -98,9 +98,10 @@ enum {
WALK_MODAL_JUMP,
WALK_MODAL_JUMP_STOP,
WALK_MODAL_TELEPORT,
- WALK_MODAL_TOGGLE,
+ WALK_MODAL_GRAVITY_TOGGLE,
WALK_MODAL_ACCELERATE,
WALK_MODAL_DECELERATE,
+ WALK_MODAL_AXIS_LOCK_Z,
};
enum {
@@ -129,6 +130,18 @@ typedef enum eWalkGravityState {
WALK_GRAVITY_STATE_ON,
} eWalkGravityState;
+/* Relative view axis z axis locking. */
+typedef enum eWalkLockState {
+ /* Disabled. */
+ WALK_AXISLOCK_STATE_OFF = 0,
+
+ /* Moving. */
+ WALK_AXISLOCK_STATE_ACTIVE = 2,
+
+ /* Done moving, it cannot be activated again. */
+ WALK_AXISLOCK_STATE_DONE = 3,
+} eWalkLockState;
+
/* Called in transform_ops.c, on each regeneration of key-maps. */
void walk_modal_keymap(wmKeyConfig *keyconf)
{
@@ -164,7 +177,9 @@ void walk_modal_keymap(wmKeyConfig *keyconf)
{WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
{WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"},
- {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
+ {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
+
+ {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"},
{0, NULL, 0, NULL, NULL},
};
@@ -292,6 +307,10 @@ typedef struct WalkInfo {
/** To use for fast/slow speeds. */
float speed_factor;
+ eWalkLockState zlock;
+ /** Nicer dynamics. */
+ float zlock_momentum;
+
struct SnapObjectContext *snap_context;
struct View3DCameraControl *v3d_camera_control;
@@ -540,6 +559,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->jump_height = U.walk_navigation.jump_height;
walk->speed = U.walk_navigation.walk_speed;
walk->speed_factor = U.walk_navigation.walk_speed_factor;
+ walk->zlock = WALK_AXISLOCK_STATE_OFF;
walk->gravity_state = WALK_GRAVITY_STATE_OFF;
@@ -694,7 +714,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
walk->is_cursor_first = false;
}
else {
- /* note, its possible the system isn't giving us the warp event
+ /* NOTE: its possible the system isn't giving us the warp event
* ideally we shouldn't have to worry about this, see: T45361 */
wmWindow *win = CTX_wm_window(C);
WM_cursor_warp(win,
@@ -708,8 +728,6 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
walk->is_cursor_absolute = true;
copy_v2_v2_int(walk->prev_mval, event->mval);
copy_v2_v2_int(walk->center_mval, event->mval);
- /* Without this we can't turn 180d with the default speed of 1.0. */
- walk->mouse_speed *= 4.0f;
}
#endif /* USE_TABLET_SUPPORT */
@@ -941,7 +959,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
#undef JUMP_TIME_MAX
#undef JUMP_SPEED_MIN
- case WALK_MODAL_TOGGLE:
+ case WALK_MODAL_GRAVITY_TOGGLE:
if (walk->navigation_mode == WALK_MODE_GRAVITY) {
walk_navigation_mode_set(walk, WALK_MODE_FREE);
}
@@ -949,6 +967,13 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
walk_navigation_mode_set(walk, WALK_MODE_GRAVITY);
}
break;
+
+ case WALK_MODAL_AXIS_LOCK_Z:
+ if (walk->zlock != WALK_AXISLOCK_STATE_DONE) {
+ walk->zlock = WALK_AXISLOCK_STATE_ACTIVE;
+ walk->zlock_momentum = 0.0f;
+ }
+ break;
}
}
}
@@ -982,12 +1007,14 @@ static float getVelocityZeroTime(const float gravity, const float velocity)
static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
{
-#define WALK_ROTATE_RELATIVE_FAC 2.2f /* More is faster, relative to region size. */
-#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* More is faster, radians per-pixel. */
+#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */
+#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* Higher is faster, radians per-pixel. */
#define WALK_TOP_LIMIT DEG2RADF(85.0f)
#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
#define WALK_MOVE_SPEED base_speed
#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)
+#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */
+#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */
RegionView3D *rv3d = walk->rv3d;
ARegion *region = walk->region;
@@ -1022,20 +1049,25 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
/* Should we redraw? */
if ((walk->active_directions) || moffset[0] || moffset[1] ||
- walk->teleport.state == WALK_TELEPORT_STATE_ON ||
- walk->gravity_state != WALK_GRAVITY_STATE_OFF || is_confirm) {
+ walk->zlock == WALK_AXISLOCK_STATE_ACTIVE ||
+ walk->gravity_state != WALK_GRAVITY_STATE_OFF ||
+ walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm) {
float dvec_tmp[3];
/* time how fast it takes for us to redraw,
* this is so simple scenes don't walk too fast */
double time_current;
float time_redraw;
+ float time_redraw_clamped;
#ifdef NDOF_WALK_DRAW_TOOMUCH
walk->redraw = 1;
#endif
time_current = PIL_check_seconds_timer();
time_redraw = (float)(time_current - walk->time_lastdraw);
+ /* Clamp redraw time to avoid jitter in roll correction. */
+ time_redraw_clamped = min_ff(0.05f, time_redraw);
+
walk->time_lastdraw = time_current;
/* base speed in m/s */
@@ -1064,7 +1096,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
#ifdef USE_TABLET_SUPPORT
if (walk->is_cursor_absolute) {
y /= region->winy;
- y *= WALK_ROTATE_RELATIVE_FAC;
+ y *= WALK_ROTATE_TABLET_FAC;
}
else
#endif
@@ -1113,7 +1145,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
#ifdef USE_TABLET_SUPPORT
if (walk->is_cursor_absolute) {
x /= region->winx;
- x *= WALK_ROTATE_RELATIVE_FAC;
+ x *= WALK_ROTATE_TABLET_FAC;
}
else
#endif
@@ -1128,6 +1160,32 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
axis_angle_to_quat_single(tmp_quat, 'Z', x);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
}
+
+ if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) {
+ float upvec[3];
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+
+ /* Make sure we have some z rolling. */
+ if (fabsf(upvec[2]) > 0.00001f) {
+ float roll = upvec[2] * 5.0f;
+ /* Rotate the view about this axis. */
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
+ mul_m3_v3(mat, upvec);
+ /* Rotate about the relative up vec. */
+ axis_angle_to_quat(tmp_quat,
+ upvec,
+ roll * time_redraw_clamped * walk->zlock_momentum *
+ WALK_ZUP_CORRECT_FAC);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+
+ walk->zlock_momentum += WALK_ZUP_CORRECT_ACCEL;
+ }
+ else {
+ /* Lock fixed, don't need to check it ever again. */
+ walk->zlock = WALK_AXISLOCK_STATE_DONE;
+ }
+ }
}
/* WASD - 'move' translation code */
@@ -1318,7 +1376,8 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
add_v3_v3(rv3d->ofs, dvec_tmp);
if (rv3d->persp == RV3D_CAMOB) {
- walk->need_rotation_keyframe |= (moffset[0] || moffset[1]);
+ walk->need_rotation_keyframe |= (moffset[0] || moffset[1] ||
+ walk->zlock == WALK_AXISLOCK_STATE_ACTIVE);
walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON);
walkMoveCamera(
C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
@@ -1333,7 +1392,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
}
return OPERATOR_FINISHED;
-#undef WALK_ROTATE_RELATIVE_FAC
+#undef WALK_ROTATE_TABLET_FAC
#undef WALK_TOP_LIMIT
#undef WALK_BOTTOM_LIMIT
#undef WALK_MOVE_SPEED
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 1ea7993572d..aa3bf46d2e5 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -1610,7 +1610,7 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
ot->cancel = view3d_interactive_add_cancel;
ot->poll = view3d_interactive_add_poll;
- /* Note, let the operator we call handle undo and registering itself. */
+ /* NOTE: let the operator we call handle undo and registering itself. */
/* flags */
ot->flag = 0;
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 8a900a4e898..d926ea84e0f 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -561,7 +561,7 @@ void ED_view3d_win_to_3d(const View3D *v3d,
copy_v3_v3(ray_origin, rv3d->viewinv[3]);
ED_view3d_win_to_vector(region, mval, ray_direction);
- /* Note: we could use #isect_line_plane_v3()
+ /* NOTE: we could use #isect_line_plane_v3()
* however we want the intersection to be in front of the view no matter what,
* so apply the unsigned factor instead. */
plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 0e5df3a0cdd..ecf43c734e2 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1378,7 +1378,7 @@ static bool view3d_lasso_select(bContext *C,
changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op);
break;
default:
- BLI_assert(!"lasso select on incorrect object type");
+ BLI_assert_msg(0, "lasso select on incorrect object type");
break;
}
@@ -2291,7 +2291,7 @@ static bool ed_object_select_pick(bContext *C,
/* In edit-mode do not activate. */
if (obcenter) {
- /* note; shift+alt goes to group-flush-selecting */
+ /* NOTE: shift+alt goes to group-flush-selecting. */
if (enumerate) {
basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend, deselect, toggle);
}
@@ -2354,10 +2354,10 @@ static bool ed_object_select_pick(bContext *C,
// TIMEIT_END(select_time);
if (hits > 0) {
- /* note: bundles are handling in the same way as bones */
+ /* NOTE: bundles are handling in the same way as bones. */
const bool has_bones = object ? false : selectbuffer_has_bones(buffer, hits);
- /* note; shift+alt goes to group-flush-selecting */
+ /* NOTE: shift+alt goes to group-flush-selecting. */
if (enumerate) {
if (has_bones &&
bone_mouse_select_menu(C, buffer, hits, false, extend, deselect, toggle)) {
@@ -3604,7 +3604,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
break;
default:
- BLI_assert(!"box select on incorrect object type");
+ BLI_assert_msg(0, "box select on incorrect object type");
break;
}
changed_multi |= changed;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 6dec3cc818a..4482e5897ca 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -511,47 +511,47 @@ static int snap_selected_to_location(bContext *C,
for (int ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob = objects[ob_index];
+ if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) {
+ continue;
+ }
- if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
-
- float cursor_parent[3]; /* parent-relative */
-
- if (use_offset) {
- add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
- }
- else {
- copy_v3_v3(cursor_parent, snap_target_global);
- }
+ float cursor_parent[3]; /* parent-relative */
- sub_v3_v3(cursor_parent, ob->obmat[3]);
+ if (use_offset) {
+ add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
+ }
+ else {
+ copy_v3_v3(cursor_parent, snap_target_global);
+ }
- if (ob->parent) {
- float originmat[3][3], parentmat[4][4];
- /* Use the evaluated object here because sometimes
- * `ob->parent->runtime.curve_cache` is required. */
- BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ sub_v3_v3(cursor_parent, ob->obmat[3]);
- BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat);
- mul_m3_m4m4(originmat, parentmat, ob->parentinv);
- invert_m3_m3(imat, originmat);
- mul_m3_v3(imat, cursor_parent);
- }
- if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
- ob->loc[0] += cursor_parent[0];
- }
- if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
- ob->loc[1] += cursor_parent[1];
- }
- if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
- ob->loc[2] += cursor_parent[2];
- }
+ if (ob->parent) {
+ float originmat[3][3], parentmat[4][4];
+ /* Use the evaluated object here because sometimes
+ * `ob->parent->runtime.curve_cache` is required. */
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
+ BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat);
+ mul_m3_m4m4(originmat, parentmat, ob->parentinv);
+ invert_m3_m3(imat, originmat);
+ mul_m3_v3(imat, cursor_parent);
+ }
+ if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
+ ob->loc[0] += cursor_parent[0];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
+ ob->loc[1] += cursor_parent[1];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
+ ob->loc[2] += cursor_parent[2];
+ }
- /* auto-keyframing */
- ED_autokeyframe_object(C, scene, ob, ks);
+ /* auto-keyframing */
+ ED_autokeyframe_object(C, scene, ob, ks);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
if (objects) {
@@ -895,7 +895,7 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
/**
* Calculates the center position of the active object in global space.
*
- * Note: this could be exported to be a generic function.
+ * NOTE: this could be exported to be a generic function.
* see: #calculateCenterActive
*/
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 4f8b0fa4685..8bcc05c1e55 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -530,7 +530,7 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph,
}
/**
* Action to take when rotating the view,
- * handle auto-persp and logic for switching out of views.
+ * handle auto-perspective and logic for switching out of views.
*
* shared with NDOF.
*/
@@ -1699,7 +1699,7 @@ bool ED_view3d_depth_read_cached_normal(const ARegion *region,
const int mval[2],
float r_normal[3])
{
- /* Note: we could support passing in a radius.
+ /* NOTE: we could support passing in a radius.
* For now just read 9 pixels. */
/* pixels surrounding */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index a2d50c43bd2..86a610f8dd9 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -392,7 +392,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b
view3d_boxview_copy(CTX_wm_area(C), region);
}
- /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
+ /* NOTE: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
* when switching camera in quad-view the other ortho views would zoom & reset.
*
* For now only redraw all regions when smooth-view finishes.
@@ -1565,7 +1565,7 @@ static uint free_localcollection_bit(Main *bmain, ushort local_collections_uuid,
ushort local_view_bits = 0;
- /* Check all areas: which localviews are in use? */
+ /* Check all areas: which local-views are in use? */
for (screen = bmain->screens.first; screen; screen = screen->id.next) {
for (area = screen->areabase.first; area; area = area->next) {
SpaceLink *sl = area->spacedata.first;
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 88f91d477b5..efcf7d587e1 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -78,7 +78,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2]);
bool transdata_check_local_islands(TransInfo *t, short around)
{
- return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH, OB_GPENCIL))));
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) && (ELEM(t->obedit_type, OB_MESH, OB_GPENCIL)));
}
/* ************************** SPACE DEPENDENT CODE **************************** */
@@ -536,7 +536,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
- /* XXX temp, first hack to get auto-render in compositor work (ton) */
+ /* XXX(ton): temp, first hack to get auto-render in compositor work. */
WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
}
@@ -1937,7 +1937,7 @@ int transformEnd(bContext *C, TransInfo *t)
return exit_code;
}
-/* TODO, move to: transform_query.c */
+/* TODO: move to: `transform_query.c`. */
bool checkUseAxisMatrix(TransInfo *t)
{
/* currently only checks for editmode */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index bd0ee1a51c6..1a61a594f37 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -353,7 +353,7 @@ typedef struct TransCon {
eTConstraint mode;
void (*drawExtra)(struct TransInfo *t);
- /* Note: if 'tc' is NULL, 'td' must also be NULL.
+ /* NOTE: if 'tc' is NULL, 'td' must also be NULL.
* For constraints that needs to draw differently from the other
* uses this instead of the generic draw function. */
@@ -802,7 +802,7 @@ struct Object *transform_object_deform_pose_armature_get(const TransInfo *t, str
void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
-/* TODO. transform_query.c */
+/* TODO: `transform_query.c`. */
bool checkUseAxisMatrix(TransInfo *t);
#define TRANSFORM_SNAP_MAX_PX 100.0f
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 99368a40225..00fd008151d 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -849,10 +849,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
/* Copy Transforms constraint only does this in the Before mode. */
bTransLikeConstraint *data = (bTransLikeConstraint *)con->data;
- if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE) &&
+ if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE, TRANSLIKE_MIX_BEFORE_FULL) &&
ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
return true;
}
+ if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) {
+ return true;
+ }
}
else if (con->type == CONSTRAINT_TYPE_ACTION) {
/* The Action constraint only does this in the Before mode. */
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
index 575e0da21a4..255af3feca2 100644
--- a/source/blender/editors/transform/transform_convert_curve.c
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -277,7 +277,7 @@ void createTransCurveVerts(TransInfo *t)
}
td->ext = NULL;
- /* TODO - make points scale */
+ /* TODO: make points scale. */
if (t->mode == TFM_CURVE_SHRINKFATTEN /* `|| t->mode == TFM_RESIZE` */) {
td->val = &(bezt->radius);
td->ival = bezt->radius;
@@ -423,7 +423,7 @@ void createTransCurveVerts(TransInfo *t)
calc_distanceCurveVerts(head, tail, cyclic);
}
- /* TODO - in the case of tilt and radius we can also avoid allocating the
+ /* TODO: in the case of tilt and radius we can also avoid allocating the
* initTransDataCurveHandles but for now just don't change handle types */
if ((nu->type == CU_BEZIER) &&
ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c
index d57f7fffe0b..111f81ff87b 100644
--- a/source/blender/editors/transform/transform_convert_graph.c
+++ b/source/blender/editors/transform/transform_convert_graph.c
@@ -939,8 +939,8 @@ static void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
if (fcu->bezt) {
BeztMap *bezm;
- /* adjust transform-data pointers */
- /* note, none of these functions use 'use_handle', it could be removed */
+ /* Adjust transform-data pointers. */
+ /* NOTE: none of these functions use 'use_handle', it could be removed. */
bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert);
sort_time_beztmaps(bezm, fcu->totvert);
beztmap_to_data(t, fcu, bezm, fcu->totvert);
@@ -1082,7 +1082,7 @@ void special_aftertrans_update__graph(bContext *C, TransInfo *t)
/* Make sure all F-Curves are set correctly, but not if transform was
* canceled, since then curves were already restored to initial state.
- * Note: if the refresh is really needed after cancel then some way
+ * NOTE: if the refresh is really needed after cancel then some way
* has to be added to not update handle types (see bug 22289).
*/
if (!canceled) {
diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c
index 45dc6df4fde..54df8270702 100644
--- a/source/blender/editors/transform/transform_convert_mask.c
+++ b/source/blender/editors/transform/transform_convert_mask.c
@@ -330,7 +330,7 @@ void createTransMaskingData(bContext *C, TransInfo *t)
}
}
- /* note: in prop mode we need at least 1 selected */
+ /* NOTE: in prop mode we need at least 1 selected. */
if (countsel == 0) {
return;
}
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index de2f96c0f97..383f9870714 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1337,7 +1337,7 @@ void transform_convert_mesh_crazyspace_detect(TransInfo *t,
* correction with \a quats, relative to the coordinates after
* the modifiers that support deform matrices \a defcos. */
-#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */
+#if 0 /* TODO(campbell): fix crazy-space & extrude so it can be enabled for general use. */
if ((totleft > 0) || (totleft == -1))
#else
if (totleft > 0)
@@ -2067,6 +2067,27 @@ static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc)
}
}
+static bool tc_mesh_is_deform_only_update(TransInfo *t, TransDataContainer *tc)
+{
+ if (tc->custom.type.data &&
+ ((struct TransCustomDataMesh *)tc->custom.type.data)->cd_layer_correct) {
+ return false;
+ }
+
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(t->depsgraph, (ID *)tc->obedit->data);
+ Mesh *mesh_eval_cage = me_eval->edit_mesh->mesh_eval_cage;
+ Mesh *mesh_eval_final = me_eval->edit_mesh->mesh_eval_final;
+ if (mesh_eval_cage && !mesh_eval_cage->runtime.is_original) {
+ return false;
+ }
+ if (mesh_eval_final && mesh_eval_final != mesh_eval_cage &&
+ !mesh_eval_final->runtime.is_original) {
+ return false;
+ }
+
+ return me_eval->runtime.deformed_only;
+}
+
void recalcData_mesh(TransInfo *t)
{
bool is_canceling = t->state == TRANS_CANCEL;
@@ -2094,7 +2115,10 @@ void recalcData_mesh(TransInfo *t)
tc_mesh_partial_types_calc(t, &partial_state);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
+ const bool is_deform_only = tc_mesh_is_deform_only_update(t, tc);
+
+ DEG_id_tag_update(tc->obedit->data,
+ is_deform_only ? ID_RECALC_GEOMETRY_DEFORM : ID_RECALC_GEOMETRY);
tc_mesh_partial_update(t, tc, &partial_state);
}
diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c
index 3b1191a3401..2db3e259153 100644
--- a/source/blender/editors/transform/transform_convert_mesh_edge.c
+++ b/source/blender/editors/transform/transform_convert_mesh_edge.c
@@ -28,6 +28,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c
index d91a2a8be4b..61397b6ef4b 100644
--- a/source/blender/editors/transform/transform_convert_mesh_uv.c
+++ b/source/blender/editors/transform/transform_convert_mesh_uv.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c
index c217478bd04..ee6cb391fdc 100644
--- a/source/blender/editors/transform/transform_convert_object.c
+++ b/source/blender/editors/transform/transform_convert_object.c
@@ -153,7 +153,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
float rot[3][3], scale[3];
- float ctime = BKE_scene_frame_get(scene);
+ float ctime = BKE_scene_ctime_get(scene);
/* only use rigid body transform if simulation is running,
* avoids problems with initial setup of rigid bodies */
@@ -978,7 +978,7 @@ void special_aftertrans_update__object(bContext *C, TransInfo *t)
/* restore rigid body transform */
if (ob->rigidbody_object && canceled) {
- float ctime = BKE_scene_frame_get(t->scene);
+ float ctime = BKE_scene_ctime_get(t->scene);
if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) {
BKE_rigidbody_aftertrans_update(ob,
td->ext->oloc,
diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c
index cb4df28d94b..681d6aea774 100644
--- a/source/blender/editors/transform/transform_convert_particle.c
+++ b/source/blender/editors/transform/transform_convert_particle.c
@@ -91,7 +91,7 @@ void createTransParticleVerts(TransInfo *t)
}
}
- /* note: in prop mode we need at least 1 selected */
+ /* NOTE: in prop mode we need at least 1 selected. */
if (hasselected == 0) {
return;
}
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 51914004e70..17512c79d03 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -262,8 +262,16 @@ static void free_transform_custom_data(TransCustomData *custom_data)
/* Canceled, need to update the strips display. */
static void seq_transform_cancel(TransInfo *t, SeqCollection *transformed_strips)
{
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false));
+
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
+ /* Handle pre-existing overlapping strips even when operator is canceled.
+ * This is necessary for SEQUENCER_OT_duplicate_move macro for example. */
+ if (SEQ_transform_test_overlap(seqbase, seq)) {
+ SEQ_transform_seqbase_shuffle(seqbase, seq, t->scene);
+ }
+
SEQ_time_update_sequence_bounds(t->scene, seq);
}
}
@@ -281,7 +289,7 @@ static bool seq_transform_check_overlap(SeqCollection *transformed_strips)
static SeqCollection *extract_standalone_strips(SeqCollection *transformed_strips)
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
if ((seq->type & SEQ_TYPE_EFFECT) == 0 || seq->seq1 == NULL) {
@@ -302,7 +310,7 @@ static SeqCollection *query_right_side_strips(ListBase *seqbase, SeqCollection *
}
}
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT) == 0 && seq->startdisp >= minframe) {
SEQ_collection_append_strip(seq, collection);
@@ -407,7 +415,7 @@ static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transforme
static SeqCollection *seq_transform_collection_from_transdata(TransDataContainer *tc)
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
TransData *td = tc->data;
for (int a = 0; a < tc->data_len; a++, td++) {
Sequence *seq = ((TransDataSeq *)td->extra)->seq;
@@ -428,6 +436,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
if (t->state == TRANS_CANCEL) {
seq_transform_cancel(t, transformed_strips);
+ SEQ_collection_free(transformed_strips);
free_transform_custom_data(custom_data);
return;
}
diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h
index 606453e356b..15e40ec466b 100644
--- a/source/blender/editors/transform/transform_data.h
+++ b/source/blender/editors/transform/transform_data.h
@@ -170,7 +170,7 @@ enum {
TD_BEZTRIPLE = 1 << 8,
/** when this is set, don't apply translation changes to this element */
TD_NO_LOC = 1 << 9,
- /** For Graph Editor autosnap, indicates that point should not undergo autosnapping */
+ /** For Graph Editor auto-snap, indicates that point should not undergo auto-snapping. */
TD_NOTIMESNAP = 1 << 10,
/** For Graph Editor - curves that can only have int-values
* need their keyframes tagged with this. */
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 9e048a0ca1d..aaac8e21cb9 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -856,8 +856,8 @@ void calculateCenter2D(TransInfo *t)
void calculateCenterLocal(TransInfo *t, const float center_global[3])
{
- /* setting constraint center */
- /* note, init functions may over-ride t->center */
+ /* Setting constraint center. */
+ /* NOTE: init functions may over-ride `t->center`. */
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
if (tc->use_local_mat) {
mul_v3_m4v3(tc->center_local, tc->imat, center_global);
@@ -910,7 +910,7 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
}
else {
- BLI_assert(!"Shall not happen");
+ BLI_assert_msg(0, "Shall not happen");
}
r_center[0] = co[0] * t->aspect[0];
diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
index fe853440c96..a8f7fc43b5e 100644
--- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
@@ -129,7 +129,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
transform_convert_sequencer_channel_clamp(t, values_final);
if (t->con.mode & CON_APPLY) {
- t->con.applyVec(t, NULL, NULL, t->values, values_final);
+ t->con.applyVec(t, NULL, NULL, values_final, values_final);
}
}
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c
index 6134c8a98f5..066a2853dc7 100644
--- a/source/blender/editors/transform/transform_mode_edge_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_slide.c
@@ -107,7 +107,7 @@ static TransDataContainer *edge_slide_container_first_ok(TransInfo *t)
return tc;
}
}
- BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid");
+ BLI_assert_msg(0, "Should never happen, at least one EdgeSlideData should be valid");
return NULL;
}
@@ -565,7 +565,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- /* note, any edge with loops can work, but we won't get predictable results, so bail out */
+ /* NOTE: any edge with loops can work, but we won't get predictable results, so bail out. */
if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) {
/* can edges with at least once face user */
MEM_freeN(sld);
@@ -818,7 +818,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo
/* if there are non-contiguous faces, we can still recover
* the loops of the new edges faces */
- /* note!, the behavior in this case means edges may move in opposite directions,
+ /* NOTE:, the behavior in this case means edges may move in opposite directions,
* this could be made to work more usefully. */
if (l_a_ok_prev) {
diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c
index e16aa636872..def5f911c6f 100644
--- a/source/blender/editors/transform/transform_mode_vert_slide.c
+++ b/source/blender/editors/transform/transform_mode_vert_slide.c
@@ -158,7 +158,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]
TransDataVertSlideVert *sv;
int i;
- /* note: we could save a matrix-multiply for each vertex
+ /* NOTE: we could save a matrix-multiply for each vertex
* by finding the closest edge in local-space.
* However this skews the outcome with non-uniform-scale. */
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index d97bcba161f..155250261de 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -455,7 +455,7 @@ void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3]
/* Updates all `BONE_TRANSFORM` flags.
* Returns total number of bones with `BONE_TRANSFORM`.
- * Note: `transform_convert_pose_transflags_update` has a similar logic. */
+ * NOTE: `transform_convert_pose_transflags_update` has a similar logic. */
static int armature_bone_transflags_update_recursive(bArmature *arm,
ListBase *lb,
const bool do_it)
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 9a33dc1218d..2619fdf3403 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -303,10 +303,15 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2f(pos, t->tsnap.snapPoint[0], region->v2d.cur.ymin);
- immVertex2f(pos, t->tsnap.snapPoint[0], region->v2d.cur.ymax);
- immEnd();
+ UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
+ col[3] = 128;
+ immUniformColor4ubv(col);
+ float pixelx = BLI_rctf_size_x(&region->v2d.cur) / BLI_rcti_size_x(&region->v2d.mask);
+ immRectf(pos,
+ t->tsnap.snapPoint[0] - pixelx,
+ region->v2d.cur.ymax,
+ t->tsnap.snapPoint[0] + pixelx,
+ region->v2d.cur.ymin);
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
}
@@ -405,7 +410,7 @@ void applyProject(TransInfo *t)
transform_data_ext_rotate(td, mat, true);
- /* TODO support constraints for rotation too? see ElementRotation */
+ /* TODO: support constraints for rotation too? see #ElementRotation. */
}
}
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 4212045a33d..2d98d756dba 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -255,7 +255,7 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *
static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
Object *ob_eval,
- Mesh *me_eval,
+ const Mesh *me_eval,
bool use_hide)
{
SnapObjectData *sod;
@@ -535,7 +535,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
* \{ */
/* Store all ray-hits
- * Support for storing all depths, not just the first (raycast 'all') */
+ * Support for storing all depths, not just the first (ray-cast 'all'). */
struct RayCastAll_Data {
void *bvhdata;
@@ -626,7 +626,7 @@ static bool raycast_tri_backface_culling_test(
return dot_v3v3(no, dir) < 0.0f;
}
-/* Callback to raycast with backface culling (Mesh). */
+/* Callback to ray-cast with back-face culling (#Mesh). */
static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
int index,
const BVHTreeRay *ray,
@@ -653,7 +653,7 @@ static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
}
}
-/* Callback to raycast with backface culling (EditMesh). */
+/* Callback to ray-cast with back-face culling (#EditMesh). */
static void editmesh_looptri_raycast_backface_culling_cb(void *userdata,
int index,
const BVHTreeRay *ray,
@@ -687,7 +687,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
const float ray_start[3],
const float ray_dir[3],
Object *ob_eval,
- Mesh *me_eval,
+ const Mesh *me_eval,
const float obmat[4][4],
const uint ob_index,
bool use_hide,
@@ -1088,7 +1088,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
case OB_SURF:
case OB_FONT: {
if (!is_object_active) {
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (mesh_eval) {
retval = raycastMesh(sctx,
dt->ray_start,
diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c
index 91bebc9c59d..d0b730383d5 100644
--- a/source/blender/editors/transform/transform_snap_sequencer.c
+++ b/source/blender/editors/transform/transform_snap_sequencer.c
@@ -108,7 +108,7 @@ static SeqCollection *query_snap_targets(const TransInfo *t)
{
const ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene, false));
const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene);
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT)) {
continue; /* Selected are being transformed. */
@@ -236,6 +236,11 @@ void transform_snap_sequencer_data_free(TransSeqSnapData *data)
bool transform_snap_sequencer_calc(TransInfo *t)
{
+ /* Prevent snapping when constrained to Y axis. */
+ if (t->con.mode & CON_APPLY && t->con.mode & CON_AXIS1) {
+ return false;
+ }
+
const TransSeqSnapData *snap_data = t->tsnap.seq_context;
int best_dist = MAXFRAME, best_target_frame = 0, best_source_frame = 0;
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index df4e6f893ec..3e0029156c1 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -50,6 +50,7 @@
#include "BLO_blend_validate.h"
+#include "ED_asset.h"
#include "ED_gpencil.h"
#include "ED_object.h"
#include "ED_outliner.h"
@@ -202,7 +203,7 @@ static void ed_undo_step_pre(bContext *C,
/* App-Handlers (pre). */
{
- /* Note: ignore grease pencil for now. */
+ /* NOTE: ignore grease pencil for now. */
wm->op_undo_depth++;
BKE_callback_exec_id(
bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE);
@@ -268,6 +269,8 @@ static void ed_undo_step_post(bContext *C,
WM_toolsystem_refresh_active(C);
WM_toolsystem_refresh_screen_all(bmain);
+ ED_assetlist_storage_tag_main_data_dirty();
+
if (CLOG_CHECK(&LOG, 1)) {
BKE_undosys_print(wm->undo_stack);
}
@@ -321,7 +324,7 @@ static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *
/* FIXME: See comments in `ed_undo_step_direction`. */
if (ED_gpencil_session_active()) {
- BLI_assert(!"Not implemented currently.");
+ BLI_assert_msg(0, "Not implemented currently.");
}
wmWindowManager *wm = CTX_wm_manager(C);
@@ -369,7 +372,7 @@ static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList *
/* FIXME: See comments in `ed_undo_step_direction`. */
if (ED_gpencil_session_active()) {
- BLI_assert(!"Not implemented currently.");
+ BLI_assert_msg(0, "Not implemented currently.");
}
wmWindowManager *wm = CTX_wm_manager(C);
@@ -528,7 +531,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op)
{
if (G.background) {
/* Exception for background mode, see: T60934.
- * Note: since the undo stack isn't initialized on startup, background mode behavior
+ * NOTE: since the undo stack isn't initialized on startup, background mode behavior
* won't match regular usage, this is just for scripts to do explicit undo pushes. */
wmWindowManager *wm = CTX_wm_manager(C);
if (wm->undo_stack == NULL) {
@@ -692,12 +695,12 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
CTX_wm_region_set(C, region_win);
}
- if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) &&
- /* note, undo/redo can't run if there are jobs active,
+ if (WM_operator_repeat_check(C, op) && WM_operator_poll(C, op->type) &&
+ /* NOTE: undo/redo can't run if there are jobs active,
* check for screen jobs only so jobs like material/texture/world preview
* (which copy their data), won't stop redo, see T29579],
*
- * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */
+ * NOTE: WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this. */
(WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) {
int retval;
@@ -829,7 +832,7 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
return OPERATOR_CANCELLED;
}
-/* note: also check ed_undo_step() in top if you change notifiers */
+/* NOTE: also check #ed_undo_step() in top if you change notifiers. */
static int undo_history_exec(bContext *C, wmOperator *op)
{
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item");
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 7bbdc58474f..73f328f85d7 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -46,6 +46,7 @@
#include "DEG_depsgraph.h"
#include "ED_armature.h"
+#include "ED_asset.h"
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_object.h"
@@ -169,6 +170,8 @@ void ED_editors_init(bContext *C)
ED_space_image_paint_update(bmain, wm, scene);
}
+ ED_assetlist_storage_tag_main_data_dirty();
+
SWAP(int, reports->flag, reports_flag_prev);
wm->op_undo_depth--;
}
diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c
index 0f2e280251f..9e05efca3df 100644
--- a/source/blender/editors/util/ed_util_imbuf.c
+++ b/source/blender/editors/util/ed_util_imbuf.c
@@ -244,7 +244,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
}
if (ibuf->zbuf) {
- /* TODO, blend depth (not urgent). */
+ /* TODO: blend depth (not urgent). */
info->z = ibuf->zbuf[y * ibuf->x + x];
info->zp = &info->z;
if (ibuf->zbuf == (int *)ibuf->rect) {
@@ -252,7 +252,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
}
}
if (ibuf->zbuf_float) {
- /* TODO, blend depth (not urgent). */
+ /* TODO: blend depth (not urgent). */
info->zf = ibuf->zbuf_float[y * ibuf->x + x];
info->zfp = &info->zf;
if (ibuf->zbuf_float == ibuf->rect_float) {
diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc
index 462f7768f81..7d32d252718 100644
--- a/source/blender/editors/util/ed_util_ops.cc
+++ b/source/blender/editors/util/ed_util_ops.cc
@@ -36,6 +36,7 @@
#include "BLT_translation.h"
+#include "ED_asset.h"
#include "ED_render.h"
#include "ED_undo.h"
#include "ED_util.h"
@@ -131,9 +132,11 @@ static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op))
if (preview) {
BKE_previewimg_clear(preview);
}
+
UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true);
WM_event_add_notifier(C, NC_ASSET | NA_EDITED, nullptr);
+ ED_assetlist_storage_tag_main_data_dirty();
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c
index 4e8cf1e92e6..5681edd2f5c 100644
--- a/source/blender/editors/util/select_utils.c
+++ b/source/blender/editors/util/select_utils.c
@@ -41,7 +41,7 @@ int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool
case SEL_OP_XOR:
return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
}
- BLI_assert(!"invalid sel_op");
+ BLI_assert_msg(0, "invalid sel_op");
return -1;
}
/**
@@ -67,7 +67,7 @@ int ED_select_op_action_deselected(const eSelectOp sel_op,
case SEL_OP_XOR:
return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
}
- BLI_assert(!"invalid sel_op");
+ BLI_assert_msg(0, "invalid sel_op");
return -1;
}
diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c
index 93948b5ae1b..56bcbc63de1 100644
--- a/source/blender/editors/uvedit/uvedit_islands.c
+++ b/source/blender/editors/uvedit/uvedit_islands.c
@@ -36,6 +36,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 2f88e50492f..0757e177235 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1496,7 +1496,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
}
if (hide) {
- /* note, a special case for edges could be used,
+ /* NOTE: a special case for edges could be used,
* for now edges act like verts and get flushed */
if (use_face_center) {
if (em->selectmode == SCE_SELECT_FACE) {
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index eb4ca2e13b2..f97403a0919 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -2154,7 +2154,7 @@ static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine
static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
{
- /* move to collapsed_ */
+ /* Move to `collapsed_*`. */
PVert *v, *nextv = NULL, *verts = chart->verts;
PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL;
@@ -2224,7 +2224,7 @@ static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
static void p_chart_post_split_flush(PChart *chart)
{
- /* move from collapsed_ */
+ /* Move from `collapsed_*`. */
PVert *v, *nextv = NULL;
PEdge *e, *nexte = NULL;
@@ -2259,7 +2259,7 @@ static void p_chart_post_split_flush(PChart *chart)
static void p_chart_simplify_compute(PChart *chart)
{
/* Computes a list of edge collapses / vertex splits. The collapsed
- * simplices go in the chart->collapsed_* lists, The original and
+ * simplices go in the `chart->collapsed_*` lists, The original and
* collapsed may then be view as stacks, where the next collapse/split
* is at the top of the respective lists. */
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index 0a7cd579a0a..7709b76290f 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -1351,7 +1351,7 @@ static void uv_select_linked_multi(Scene *scene,
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
- /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
+ /* NOTE: we had 'use winding' so we don't consider overlapping islands as connected, see T44320
* this made *every* projection split the island into front/back islands.
* Keep 'use_winding' to false, see: T50970.
*
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 71656784947..535a0e00347 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1746,7 +1746,8 @@ static void stitch_draw_vbo(GPUVertBuf *vbo, GPUPrimType prim_type, const float
GPU_batch_discard(batch);
}
-/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */
+/* TODO: make things pretier : store batches inside StitchPreviewer instead of the bare verts pos
+ */
static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
{
@@ -1927,6 +1928,11 @@ static StitchState *stitch_init(bContext *C,
state->obedit = obedit;
state->em = em;
+ /* Workaround for sync-select & face-select mode which implies all selected faces are detached,
+ * for stitch this isn't useful behavior, see T86924. */
+ const int selectmode_orig = scene->toolsettings->selectmode;
+ scene->toolsettings->selectmode = SCE_SELECT_VERTEX;
+
/* in uv synch selection, all uv's are visible */
if (ts->uv_flag & UV_SYNC_SELECTION) {
state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, false, true, true);
@@ -1934,6 +1940,9 @@ static StitchState *stitch_init(bContext *C,
else {
state->element_map = BM_uv_element_map_create(state->em->bm, scene, true, false, true, true);
}
+
+ scene->toolsettings->selectmode = selectmode_orig;
+
if (!state->element_map) {
state_delete(state);
return NULL;
@@ -1988,7 +1997,7 @@ static StitchState *stitch_init(bContext *C,
/* Now, on to generate our uv connectivity data */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!(ts->uv_flag & UV_SYNC_SELECTION) &&
- ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
continue;
}
@@ -2171,8 +2180,8 @@ static StitchState *stitch_init(bContext *C,
"uv_stitch_selection_stack");
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!(ts->uv_flag & UV_SYNC_SELECTION) && ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
- !BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ if (!(ts->uv_flag & UV_SYNC_SELECTION) &&
+ (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
continue;
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index ae02097707c..3d5dabda23d 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -315,7 +315,7 @@ static ParamHandle *construct_param_handle(const Scene *scene,
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
- if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ||
(options->only_selected_faces && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
continue;
}
@@ -404,7 +404,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
- if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ||
(options->only_selected_faces && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
continue;
}
@@ -2319,7 +2319,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
const bool use_orthographic = RNA_boolean_get(op->ptr, "orthographic");
- /* Note: objects that aren't touched are set to NULL (to skip clipping). */
+ /* NOTE: objects that aren't touched are set to NULL (to skip clipping). */
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
view_layer, v3d, &objects_len);
diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h
index ccb2c61fef5..c8ecbc9eadc 100644
--- a/source/blender/freestyle/intern/application/AppView.h
+++ b/source/blender/freestyle/intern/application/AppView.h
@@ -214,7 +214,7 @@ class AppView {
inline real GetFovyDegrees() const
{
- return _Fovy * 180.0 / M_PI; // TODO Use RAD2DEG here too?
+ return _Fovy * 180.0 / M_PI; // TODO: Use RAD2DEG here too?
}
BBox<Vec3r> scene3DBBox() const
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index a16479873e7..9c3270e788c 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -435,7 +435,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
transpose_m4(nmat);
// We count the number of triangles after the clipping by the near and far view
- // planes is applied (Note: mesh vertices are in the camera coordinate system).
+ // planes is applied (NOTE: mesh vertices are in the camera coordinate system).
unsigned numFaces = 0;
float v1[3], v2[3], v3[3];
float n1[3], n2[3], n3[3], facenormal[3];
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 4f6ffc451c8..e290b8a87a3 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -671,7 +671,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
visible = false;
- // Note: Mesh generation in the following loop assumes stroke strips
+ // NOTE: Mesh generation in the following loop assumes stroke strips
// to be triangle strips.
for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
svRep[0] = *(v[0]);
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h
index 9d8ffcfd7fb..949675e9d8d 100644
--- a/source/blender/freestyle/intern/geometry/normal_cycle.h
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.h
@@ -67,7 +67,7 @@ class NormalCycle {
void begin();
void end();
/**
- * Note: the specified edge vector needs to be pre-clipped by the neighborhood.
+ * NOTE: the specified edge vector needs to be pre-clipped by the neighborhood.
*/
void accumulate_dihedral_angle(const Vec3r &edge, real angle, real neigh_area = 1.0);
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
index 4c339a54bb3..959c5ec7074 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
@@ -122,7 +122,7 @@ static PyObject *FrsNoise_turbulence_smooth(BPy_FrsNoise *self, PyObject *args,
{
static const char *kwlist[] = {"v", "oct", nullptr};
- double x; // note: this has to be a double (not float)
+ double x; // NOTE: this has to be a double (not float)
unsigned nbOctaves = 8;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|I", (char **)kwlist, &x, &nbOctaves)) {
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
index 3c0ee9fd9a3..f63ad0d618b 100644
--- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
@@ -48,7 +48,7 @@ PyDoc_STRVAR(
" :arg svertex: An SVertex object.\n"
" :type svertex: :class:`SVertex`");
-/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */
+/* NOTE: No copy constructor in Python because the C++ copy constructor is 'protected'. */
static int NonTVertex_init(BPy_NonTVertex *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
index 9fe39b3e359..0e6d6766436 100644
--- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
@@ -49,7 +49,7 @@ PyDoc_STRVAR(TVertex_doc,
"\n"
" Default constructor.");
-/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */
+/* NOTE: No copy constructor in Python because the C++ copy constructor is 'protected'. */
static int TVertex_init(BPy_TVertex *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.h b/source/blender/freestyle/intern/scene_graph/NodeLight.h
index 1d92a96100c..7eb8fcd0029 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeLight.h
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.h
@@ -95,7 +95,7 @@ class NodeLight : public Node {
* Initially, 0.
*/
static int numberOfLights;
- /** The current lignt number */
+ /** The current light number */
int _number;
};
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
index 209ec86edef..cc4c0749ca8 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -514,7 +514,7 @@ class Stroke : public Interface1D {
return _id;
}
- /** The different blending modes available to similate the interaction media-medium. */
+ /** The different blending modes available to simulate the interaction media-medium. */
typedef enum {
DRY_MEDIUM, /**< To simulate a dry medium such as Pencil or Charcoal. */
HUMID_MEDIUM, /**< To simulate ink painting (color subtraction blending). */
diff --git a/source/blender/freestyle/intern/system/FreestyleConfig.h b/source/blender/freestyle/intern/system/FreestyleConfig.h
index 032da864e6c..92c207a1b7f 100644
--- a/source/blender/freestyle/intern/system/FreestyleConfig.h
+++ b/source/blender/freestyle/intern/system/FreestyleConfig.h
@@ -30,7 +30,7 @@ namespace Freestyle {
namespace Config {
// Directory separators
-// TODO Use Blender's stuff for such things!
+// TODO: Use Blender's stuff for such things!
#ifdef WIN32
static const string DIR_SEP("\\");
static const string PATH_SEP(";");
diff --git a/source/blender/freestyle/intern/system/RandGen.h b/source/blender/freestyle/intern/system/RandGen.h
index f54a0035b62..9d9697a2d34 100644
--- a/source/blender/freestyle/intern/system/RandGen.h
+++ b/source/blender/freestyle/intern/system/RandGen.h
@@ -21,7 +21,7 @@
* \brief Pseudo-random number generator
*/
-// TODO Check whether we could replace this with BLI rand stuff...
+// TODO: Check whether we could replace this with BLI rand stuff...
#include "../system/Precision.h"
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h
index 0ec9144595c..3709b0ae11a 100644
--- a/source/blender/freestyle/intern/view_map/Silhouette.h
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -1916,7 +1916,7 @@ class SShape {
return _LibraryPath;
}
- /* Modififers */
+ /* Modifiers */
/** Sets the Id of the shape. */
inline void setId(Id id)
{
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
index cd0059f3c21..afb23690a84 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -2285,7 +2285,7 @@ struct less_SVertex2D {
Vec3r A = x->point2D();
Vec3r B = y->point2D();
for (unsigned int i = 0; i < 3; i++) {
- if ((fabs(A[i] - B[i])) < epsilon) {
+ if (fabs(A[i] - B[i]) < epsilon) {
continue;
}
if (A[i] < B[i]) {
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
index 774751a2589..7cb06673811 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
@@ -813,7 +813,7 @@ static int save(ostream &out, SVertex *sv)
WRITE_IF_NON_NULL(sv->viewvertex());
// Normals (List)
- // Note: the 'size()' method of a set doesn't seem to return the actual size of the given set, so
+ // NOTE: the 'size()' method of a set doesn't seem to return the actual size of the given set, so
// we have to hack it...
set<Vec3r>::const_iterator i;
for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++) {
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
index 62d767fd2a1..478e48de66c 100644
--- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -98,7 +98,7 @@ static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2)
udotv = u * v;
denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
- /* Note: I assume this is what they mean by using atan2(). -Ray Jones */
+ /* NOTE(Ray Jones): I assume this is what they mean by using #atan2. */
/* tan = denom/udotv = y/x (see man page for atan2) */
return (fabs(atan2(denom, udotv)));
@@ -112,7 +112,7 @@ static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2)
* Computes the Discrete Mean Curvature Normal approximation at \a v.
* The mean curvature at \a v is half the magnitude of the vector \a Kh.
*
- * Note: the normal computed is not unit length, and may point either into or out of the surface,
+ * NOTE: the normal computed is not unit length, and may point either into or out of the surface,
* depending on the curvature at \a v. It is the responsibility of the caller of the function to
* use the mean curvature normal appropriately.
*
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
index bedf4192d64..cef1a8f8f77 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -37,7 +37,7 @@ unsigned int WXFaceLayer::Get0VertexIndex() const
int i = 0;
int nEdges = _pWXFace->numberOfEdges();
for (i = 0; i < nEdges; ++i) {
- if (_DotP[i] == 0.0f) { // TODO this comparison is weak, check if it actually works
+ if (_DotP[i] == 0.0f) { // TODO: this comparison is weak, check if it actually works
return i;
}
}
@@ -48,7 +48,7 @@ unsigned int WXFaceLayer::GetSmoothEdgeIndex() const
int i = 0;
int nEdges = _pWXFace->numberOfEdges();
for (i = 0; i < nEdges; ++i) {
- if ((_DotP[i] == 0.0f) && (_DotP[(i + 1) % nEdges] == 0.0f)) { // TODO ditto
+ if ((_DotP[i] == 0.0f) && (_DotP[(i + 1) % nEdges] == 0.0f)) { // TODO: ditto
return i;
}
}
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h
index f95913c23f3..b335a364365 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.h
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h
@@ -465,7 +465,7 @@ class WXFaceLayer {
if (iDotP > 0.0f) {
++_nPosDotP;
}
- if (iDotP == 0.0f) { // TODO this comparison is weak, check if it actually works
+ if (iDotP == 0.0f) { // TODO: this comparison is weak, check if it actually works
++_nNullDotP;
}
}
@@ -484,7 +484,7 @@ class WXFaceLayer {
if ((*d) > 0.0f) {
++_nPosDotP;
}
- if ((*d) == 0.0f) { // TODO ditto
+ if ((*d) == 0.0f) { // TODO: ditto
++_nNullDotP;
}
}
diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh
index 4de0533a46d..421e5f0018d 100644
--- a/source/blender/functions/FN_cpp_type.hh
+++ b/source/blender/functions/FN_cpp_type.hh
@@ -545,6 +545,13 @@ class CPPType : NonCopyable, NonMovable {
m_.print(value, ss);
}
+ std::string to_string(const void *value) const
+ {
+ std::stringstream ss;
+ this->print(value, ss);
+ return ss.str();
+ }
+
void print_or_default(const void *value, std::stringstream &ss, StringRef default_value) const
{
if (this->is_printable()) {
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index f39306ac9d0..ec965c9a29f 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -68,6 +68,7 @@ set(SRC
intern/MOD_gpencilthick.c
intern/MOD_gpenciltime.c
intern/MOD_gpenciltint.c
+ intern/MOD_gpencilweight.c
MOD_gpencil_lineart.h
MOD_gpencil_modifiertypes.h
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
index f8a28f2e5cb..18310bd5dff 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -44,6 +44,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Armature;
extern GpencilModifierTypeInfo modifierType_Gpencil_Time;
extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply;
extern GpencilModifierTypeInfo modifierType_Gpencil_Texture;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Weight;
extern GpencilModifierTypeInfo modifierType_Gpencil_Lineart;
/* MOD_gpencil_util.c */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
index 94285b5032e..a156fca5b7b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
@@ -203,20 +203,6 @@ void gpencil_modifier_curve_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiTemplateCurveMapping(layout, ptr, "curve", 0, false, false, false, false);
}
-void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel)
-{
- PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
-
- uiLayout *layout = panel->layout;
- uiLayoutSetPropSep(layout, true);
-
- uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE);
- uiLayout *sub = uiLayoutColumn(layout, true);
- uiItemR(sub, ptr, "fading_start", 0, NULL, ICON_NONE);
- uiItemR(sub, ptr, "fading_end", 0, IFACE_("End"), ICON_NONE);
- uiItemR(layout, ptr, "fading_end_factor", 0, NULL, ICON_NONE);
-}
-
/**
* Draw modifier error message.
*/
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
index 75907aaa781..782b36d47ed 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
@@ -37,8 +37,6 @@ void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool u
void gpencil_modifier_curve_header_draw(const bContext *C, Panel *panel);
void gpencil_modifier_curve_panel_draw(const bContext *C, Panel *panel);
-void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel);
-
void gpencil_modifier_panel_end(struct uiLayout *layout, PointerRNA *ptr);
struct PointerRNA *gpencil_modifier_panel_get_property_pointers(struct Panel *panel,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index b28a44a0521..6409c86b6e3 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -63,6 +63,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(Time);
INIT_GP_TYPE(Multiply);
INIT_GP_TYPE(Texture);
+ INIT_GP_TYPE(Weight);
INIT_GP_TYPE(Lineart);
#undef INIT_GP_TYPE
}
@@ -152,16 +153,16 @@ float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
if ((dvert != NULL) && (def_nr != -1)) {
MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
weight = dw ? dw->weight : -1.0f;
- if ((weight >= 0.0f) && (inverse == 1)) {
+ if ((weight >= 0.0f) && (inverse)) {
return -1.0f;
}
- if ((weight < 0.0f) && (inverse == 0)) {
+ if ((weight < 0.0f) && (!inverse)) {
return -1.0f;
}
/* if inverse, weight is always 1 */
- if ((weight < 0.0f) && (inverse == 1)) {
+ if ((weight < 0.0f) && (inverse)) {
return 1.0f;
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index d9f0fc9bddd..4e07827c940 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -112,7 +112,7 @@ static void gpf_clear_all_strokes(bGPDframe *gpf)
/* Reduce the number of points in the stroke
*
- * Note: This won't be called if all points are present/removed
+ * NOTE: This won't be called if all points are present/removed
*/
static void reduce_stroke_points(bGPdata *gpd,
bGPDstroke *gps,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
index 9593a1364e7..fcc44aab583 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
@@ -205,11 +205,18 @@ static void bakeModifier(Main *UNUSED(bmain),
}
if (!gpd->runtime.lineart_cache) {
+ /* Only calculate for this modifier, thus no need to get maximum values from all line art
+ * modifiers in the stack. */
+ lmd->edge_types_override = lmd->edge_types;
+ lmd->level_end_override = lmd->level_end;
+
MOD_lineart_compute_feature_lines(depsgraph, lmd, &gpd->runtime.lineart_cache);
MOD_lineart_destroy_render_data(lmd);
}
generate_strokes_actual(md, depsgraph, ob, gpl, gpf);
+
+ MOD_lineart_clear_cache(&gpd->runtime.lineart_cache);
}
static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
@@ -331,7 +338,7 @@ static void edge_types_panel_draw(const bContext *UNUSED(C), Panel *panel)
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
- const bool use_cache = RNA_boolean_get(ptr, "use_cached_result");
+ const bool use_cache = RNA_boolean_get(ptr, "use_cache");
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
uiLayoutSetEnabled(layout, !is_baked);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
index cd29a006aae..1a38b91a18b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -129,14 +129,6 @@ static void deformStroke(GpencilModifierData *md,
}
}
}
- /* Calculate Random matrix. */
- float mat_rnd[4][4];
- float rnd_loc[3], rnd_rot[3];
- float rnd_scale[3] = {1.0f, 1.0f, 1.0f};
- mul_v3_v3v3(rnd_loc, mmd->rnd_offset, rand[0]);
- mul_v3_v3v3(rnd_rot, mmd->rnd_rot, rand[1]);
- madd_v3_v3v3(rnd_scale, mmd->rnd_scale, rand[2]);
- loc_eul_size_to_mat4(mat_rnd, rnd_loc, rnd_rot, rnd_scale);
bGPdata *gpd = ob->data;
@@ -150,6 +142,21 @@ static void deformStroke(GpencilModifierData *md,
if (weight < 0.0f) {
continue;
}
+
+ /* Calculate Random matrix. */
+ float mat_rnd[4][4];
+ float rnd_loc[3], rnd_rot[3], rnd_scale_weight[3];
+ float rnd_scale[3] = {1.0f, 1.0f, 1.0f};
+
+ mul_v3_v3fl(rnd_loc, rand[0], weight);
+ mul_v3_v3fl(rnd_rot, rand[1], weight);
+ mul_v3_v3fl(rnd_scale_weight, rand[2], weight);
+
+ mul_v3_v3v3(rnd_loc, mmd->rnd_offset, rnd_loc);
+ mul_v3_v3v3(rnd_rot, mmd->rnd_rot, rnd_rot);
+ madd_v3_v3v3(rnd_scale, mmd->rnd_scale, rnd_scale_weight);
+
+ loc_eul_size_to_mat4(mat_rnd, rnd_loc, rnd_rot, rnd_scale);
/* Apply randomness matrix. */
mul_m4_v3(mat_rnd, &pt->x);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index 9f03e493ea8..fb75b1e99ac 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -47,8 +47,6 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -86,39 +84,6 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
-static float give_opacity_fading_factor(OpacityGpencilModifierData *mmd,
- Object *ob_this,
- float *pos,
- bool apply_obmat)
-{
- float factor_depth = 1.0f;
-
- if (((mmd->flag & GP_OPACITY_FADING) == 0) || ((mmd->object) == NULL)) {
- return factor_depth;
- }
-
- float gvert[3];
- if (apply_obmat) {
- mul_v3_m4v3(gvert, ob_this->obmat, pos);
- }
- float dist = len_v3v3(mmd->object->obmat[3], gvert);
- float fading_max = MAX2(mmd->fading_start, mmd->fading_end);
- float fading_min = MIN2(mmd->fading_start, mmd->fading_end);
-
- /* Better with ratiof() function from line art. */
- if (dist > fading_max) {
- factor_depth = 0.0f;
- }
- else if (dist <= fading_max && dist > fading_min) {
- factor_depth = (fading_max - dist) / (fading_max - fading_min);
- }
- else {
- factor_depth = 1.0f;
- }
-
- return factor_depth;
-}
-
/* opacity strokes */
static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
@@ -130,6 +95,9 @@ static void deformStroke(GpencilModifierData *md,
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
const bool use_curve = (mmd->flag & GP_OPACITY_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
+ const bool is_normalized = (mmd->flag & GP_OPACITY_NORMALIZE);
+ bool is_inverted = ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) == 0) &&
+ ((mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0);
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -161,11 +129,17 @@ static void deformStroke(GpencilModifierData *md,
/* Stroke using strength. */
if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
/* verify vertex group */
- float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
+ float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight < 0.0f) {
continue;
}
+
+ /* Apply weight directly. */
+ if ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) && (!is_normalized)) {
+ pt->strength *= ((mmd->flag & GP_OPACITY_INVERT_VGROUP) ? 1.0f - weight : weight);
+ continue;
+ }
+
/* Custom curve to modulate value. */
float factor_curve = mmd->factor;
if (use_curve) {
@@ -173,9 +147,6 @@ static void deformStroke(GpencilModifierData *md,
factor_curve *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
}
- float factor_depth = give_opacity_fading_factor(mmd, ob, &pt->x, true);
- factor_curve = interpf(factor_curve, mmd->fading_end_factor, factor_depth);
-
if (def_nr < 0) {
if (mmd->flag & GP_OPACITY_NORMALIZE) {
pt->strength = factor_curve;
@@ -204,9 +175,19 @@ static void deformStroke(GpencilModifierData *md,
/* Fill using opacity factor. */
if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- float factor_depth = give_opacity_fading_factor(mmd, ob, ob->obmat[3], true);
- gps->fill_opacity_fac = interpf(mmd->factor, mmd->fading_end_factor, factor_depth);
+ float fill_factor = mmd->factor;
+ if ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) && (!is_normalized)) {
+ /* Use first point for weight. */
+ MDeformVert *dvert = (gps->dvert != NULL) ? &gps->dvert[0] : NULL;
+ float weight = get_modifier_point_weight(
+ dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
+ if (weight >= 0.0f) {
+ fill_factor = ((mmd->flag & GP_OPACITY_INVERT_VGROUP) ? 1.0f - weight : weight);
+ }
+ }
+
+ gps->fill_opacity_fac = fill_factor;
CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f);
}
}
@@ -241,18 +222,6 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
- walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
-}
-
-static void updateDepsgraph(GpencilModifierData *md,
- const ModifierUpdateDepsgraphContext *ctx,
- const int UNUSED(mode))
-{
- OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
- if (mmd->object != NULL) {
- DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier");
- }
- DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier");
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -271,29 +240,25 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(layout, ptr, "hardness", 0, NULL, ICON_NONE);
}
else {
+ const bool is_normalized = RNA_boolean_get(ptr, "normalize_opacity");
+ const bool is_weighted = RNA_boolean_get(ptr, "use_weight_factor");
+
uiItemR(layout, ptr, "normalize_opacity", 0, NULL, ICON_NONE);
- const char *text = (RNA_boolean_get(ptr, "normalize_opacity")) ? IFACE_("Strength") :
- IFACE_("Opacity Factor");
- uiItemR(layout, ptr, "factor", 0, text, ICON_NONE);
+ const char *text = (is_normalized) ? IFACE_("Strength") : IFACE_("Opacity Factor");
+
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiLayoutSetActive(row, !is_weighted || is_normalized);
+ uiItemR(row, ptr, "factor", 0, text, ICON_NONE);
+ if (!is_normalized) {
+ uiLayout *sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, true);
+ uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT);
+ }
}
gpencil_modifier_panel_end(layout, ptr);
}
-static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
-{
- uiLayout *layout = panel->layout;
-
- PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
-
- uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE);
-}
-
-static void fading_panel_draw(const bContext *C, Panel *panel)
-{
- gpencil_modifier_fading_draw(C, panel);
-}
-
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
@@ -333,8 +298,6 @@ static void panelRegister(ARegionType *region_type)
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Opacity, panel_draw);
- gpencil_modifier_subpanel_register(
- region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
PanelType *mask_panel_type = gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
@@ -358,7 +321,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
/* initData */ initData,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepsgraph */ updateDepsgraph,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index 126949cd659..cac700e15f4 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -43,8 +43,6 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -118,42 +116,28 @@ static void deformStroke(GpencilModifierData *md,
}
float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1);
+ const bool is_normalized = (mmd->flag & GP_THICK_NORMALIZE);
+ bool is_inverted = ((mmd->flag & GP_THICK_WEIGHT_FACTOR) == 0) &&
+ ((mmd->flag & GP_THICK_INVERT_VGROUP) != 0);
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
/* Verify point is part of vertex group. */
- float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr);
+ float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight < 0.0f) {
continue;
}
- float curvef = 1.0f;
-
- float factor_depth = 1.0f;
-
- if (mmd->flag & GP_THICK_FADING) {
- if (mmd->object) {
- float gvert[3];
- mul_v3_m4v3(gvert, ob->obmat, &pt->x);
- float dist = len_v3v3(mmd->object->obmat[3], gvert);
- float fading_max = MAX2(mmd->fading_start, mmd->fading_end);
- float fading_min = MIN2(mmd->fading_start, mmd->fading_end);
-
- /* Better with ratiof() function from line art. */
- if (dist > fading_max) {
- factor_depth = 0.0f;
- }
- else if (dist <= fading_max && dist > fading_min) {
- factor_depth = (fading_max - dist) / (fading_max - fading_min);
- }
- else {
- factor_depth = 1.0f;
- }
- }
+ /* Apply weight directly. */
+ if ((!is_normalized) && (mmd->flag & GP_THICK_WEIGHT_FACTOR)) {
+ pt->pressure *= ((mmd->flag & GP_THICK_INVERT_VGROUP) ? 1.0f - weight : weight);
+ CLAMP_MIN(pt->pressure, 0.0f);
+ continue;
}
+ float curvef = 1.0f;
+
if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
/* Normalize value to evaluate curve. */
float value = (float)i / (gps->totpoints - 1);
@@ -161,7 +145,7 @@ static void deformStroke(GpencilModifierData *md,
}
float target;
- if (mmd->flag & GP_THICK_NORMALIZE) {
+ if (is_normalized) {
target = mmd->thickness * stroke_thickness_inv;
target *= curvef;
}
@@ -170,11 +154,6 @@ static void deformStroke(GpencilModifierData *md,
weight *= curvef;
}
- /* Apply distance fading. */
- if (mmd->flag & GP_THICK_FADING) {
- target = interpf(target, mmd->fading_end_factor, factor_depth);
- }
-
pt->pressure = interpf(target, pt->pressure, weight);
CLAMP_MIN(pt->pressure, 0.0f);
@@ -202,32 +181,6 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
- walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
-}
-
-static void updateDepsgraph(GpencilModifierData *md,
- const ModifierUpdateDepsgraphContext *ctx,
- const int UNUSED(mode))
-{
- ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
- if (mmd->object != NULL) {
- DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier");
- }
- DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier");
-}
-
-static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
-{
- uiLayout *layout = panel->layout;
-
- PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
-
- uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE);
-}
-
-static void fading_panel_draw(const bContext *C, Panel *panel)
-{
- gpencil_modifier_fading_draw(C, panel);
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -239,12 +192,17 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "normalize_thickness", 0, NULL, ICON_NONE);
-
if (RNA_boolean_get(ptr, "normalize_thickness")) {
uiItemR(layout, ptr, "thickness", 0, NULL, ICON_NONE);
}
else {
- uiItemR(layout, ptr, "thickness_factor", 0, NULL, ICON_NONE);
+ const bool is_weighted = !RNA_boolean_get(ptr, "use_weight_factor");
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiLayoutSetActive(row, is_weighted);
+ uiItemR(row, ptr, "thickness_factor", 0, NULL, ICON_NONE);
+ uiLayout *sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, true);
+ uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT);
}
gpencil_modifier_panel_end(layout, ptr);
@@ -259,8 +217,6 @@ static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Thick, panel_draw);
- gpencil_modifier_subpanel_register(
- region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
PanelType *mask_panel_type = gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
gpencil_modifier_subpanel_register(region_type,
@@ -288,7 +244,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = {
/* initData */ initData,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepsgraph */ updateDepsgraph,
+ /* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index 4a6e3df59c7..680f5ab05ec 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -127,6 +127,8 @@ static void deformStroke(GpencilModifierData *md,
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
const bool use_curve = (mmd->flag & GP_TINT_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
+ bool is_inverted = ((mmd->flag & GP_TINT_WEIGHT_FACTOR) == 0) &&
+ ((mmd->flag & GP_TINT_INVERT_VGROUP) != 0);
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -169,6 +171,17 @@ static void deformStroke(GpencilModifierData *md,
if (!fill_done) {
/* Apply to fill. */
if (mmd->mode != GPPAINT_MODE_STROKE) {
+ float fill_factor = mmd->factor;
+
+ /* Use weighted factor. */
+ if (mmd->flag & GP_TINT_WEIGHT_FACTOR) {
+ /* Use first point for weight. */
+ MDeformVert *dvert_fill = (gps->dvert != NULL) ? &gps->dvert[0] : NULL;
+ float weight = get_modifier_point_weight(dvert_fill, is_inverted, def_nr);
+ if (weight >= 0.0f) {
+ fill_factor = ((mmd->flag & GP_TINT_INVERT_VGROUP) ? 1.0f - weight : weight);
+ }
+ }
/* If not using Vertex Color, use the material color. */
if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
@@ -188,13 +201,13 @@ static void deformStroke(GpencilModifierData *md,
BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor);
- gps->vert_color_fill[3] = clamp_f(mmd->factor, 0.0f, 1.0f);
+ gps->vert_color_fill[3] = clamp_f(fill_factor, 0.0f, 1.0f);
}
else {
interp_v3_v3v3(gps->vert_color_fill,
gps->vert_color_fill,
mmd->rgb,
- clamp_f(mmd->factor, 0.0f, 1.0f));
+ clamp_f(fill_factor, 0.0f, 1.0f));
}
/* If no stroke, cancel loop. */
if (mmd->mode != GPPAINT_MODE_BOTH) {
@@ -207,11 +220,13 @@ static void deformStroke(GpencilModifierData *md,
/* Verify vertex group. */
if (mmd->mode != GPPAINT_MODE_FILL) {
- float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_TINT_INVERT_VGROUP) != 0, def_nr);
+ float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight < 0.0f) {
continue;
}
+
+ float factor = mmd->factor;
+
/* Custom curve to modulate value. */
if (use_curve) {
float value = (float)i / (gps->totpoints - 1);
@@ -224,6 +239,12 @@ static void deformStroke(GpencilModifierData *md,
pt->vert_color[3] = 1.0f;
}
+ /* Apply weight directly. */
+ if (mmd->flag & GP_TINT_WEIGHT_FACTOR) {
+ factor = ((mmd->flag & GP_TINT_INVERT_VGROUP) ? 1.0f - weight : weight);
+ weight = 1.0f;
+ }
+
if (is_gradient) {
/* Calc world position of point. */
float pt_loc[3];
@@ -237,11 +258,11 @@ static void deformStroke(GpencilModifierData *md,
interp_v3_v3v3(pt->vert_color,
pt->vert_color,
coba_res,
- clamp_f(mmd->factor, 0.0f, 1.0f) * weight * coba_res[3]);
+ clamp_f(factor, 0.0f, 1.0f) * weight * coba_res[3]);
}
else {
interp_v3_v3v3(
- pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(mmd->factor * weight, 0.0, 1.0f));
+ pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(factor * weight, 0.0, 1.0f));
}
}
}
@@ -338,7 +359,15 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "vertex_mode", 0, NULL, ICON_NONE);
- uiItemR(layout, ptr, "factor", 0, NULL, ICON_NONE);
+
+ const bool is_weighted = !RNA_boolean_get(ptr, "use_weight_factor");
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiLayoutSetActive(row, is_weighted);
+ uiItemR(row, ptr, "factor", 0, NULL, ICON_NONE);
+ uiLayout *sub = uiLayoutRow(row, true);
+ uiLayoutSetActive(sub, true);
+ uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT);
+
uiItemR(layout, ptr, "tint_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
if (tint_type == GP_TINT_UNIFORM) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c
new file mode 100644
index 00000000000..c7fe20edef7
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c
@@ -0,0 +1,335 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_defaults.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_lib_query.h"
+#include "BKE_modifier.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+
+#include "MOD_gpencil_modifiertypes.h"
+#include "MOD_gpencil_ui_common.h"
+#include "MOD_gpencil_util.h"
+
+static void initData(GpencilModifierData *md)
+{
+ WeightGpencilModifierData *gpmd = (WeightGpencilModifierData *)md;
+
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier));
+
+ MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(WeightGpencilModifierData), modifier);
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copydata_generic(md, target);
+}
+
+/* Calc distance between point and target object. */
+static float calc_point_weight_by_distance(Object *ob,
+ WeightGpencilModifierData *mmd,
+ const float dist_max,
+ const float dist_min,
+ bGPDspoint *pt)
+{
+ float weight;
+ float gvert[3];
+ mul_v3_m4v3(gvert, ob->obmat, &pt->x);
+ float dist = len_v3v3(mmd->object->obmat[3], gvert);
+
+ if (dist > dist_max) {
+ weight = 0.0f;
+ }
+ else if (dist <= dist_max && dist > dist_min) {
+ weight = (dist_max - dist) / max_ff((dist_max - dist_min), 0.0001f);
+ }
+ else {
+ weight = 1.0f;
+ }
+
+ return weight;
+}
+
+/* change stroke thickness */
+static void deformStroke(GpencilModifierData *md,
+ Depsgraph *UNUSED(depsgraph),
+ Object *ob,
+ bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps)
+{
+ WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
+ const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
+ const eWeightGpencilModifierMode mode = mmd->mode;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername,
+ mmd->material,
+ mmd->pass_index,
+ mmd->layer_pass,
+ 1,
+ gpl,
+ gps,
+ mmd->flag & GP_WEIGHT_INVERT_LAYER,
+ mmd->flag & GP_WEIGHT_INVERT_PASS,
+ mmd->flag & GP_WEIGHT_INVERT_LAYERPASS,
+ mmd->flag & GP_WEIGHT_INVERT_MATERIAL)) {
+ return;
+ }
+
+ const float dist_max = MAX2(mmd->dist_start, mmd->dist_end);
+ const float dist_min = MIN2(mmd->dist_start, mmd->dist_end);
+ const int target_def_nr = BKE_object_defgroup_name_index(ob, mmd->target_vgname);
+
+ if (target_def_nr == -1) {
+ return;
+ }
+
+ /* Use default Z up. */
+ float vec_axis[3] = {0.0f, 0.0f, 1.0f};
+ float axis[3] = {0.0f, 0.0f, 0.0f};
+ axis[mmd->axis] = 1.0f;
+ float vec_ref[3];
+ /* Apply modifier rotation (sub 90 degrees for Y axis due Z-Up vector). */
+ float rot_angle = mmd->angle - ((mmd->axis == 1) ? M_PI_2 : 0.0f);
+ rotate_normalized_v3_v3v3fl(vec_ref, vec_axis, axis, rot_angle);
+
+ /* Apply the rotation of the object. */
+ if (mmd->space == GP_SPACE_LOCAL) {
+ mul_mat3_m4_v3(ob->obmat, vec_ref);
+ }
+
+ /* Ensure there is a vertex group. */
+ BKE_gpencil_dvert_ensure(gps);
+
+ float weight_pt = 1.0f;
+ for (int i = 0; i < gps->totpoints; i++) {
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ /* Verify point is part of vertex group. */
+ float weight = get_modifier_point_weight(
+ dvert, (mmd->flag & GP_WEIGHT_INVERT_VGROUP) != 0, def_nr);
+ if (weight < 0.0f) {
+ continue;
+ }
+
+ switch (mode) {
+ case GP_WEIGHT_MODE_DISTANCE: {
+ if (mmd->object) {
+ bGPDspoint *pt = &gps->points[i];
+ weight_pt = calc_point_weight_by_distance(ob, mmd, dist_max, dist_min, pt);
+ }
+ break;
+ }
+ case GP_WEIGHT_MODE_ANGLE: {
+ /* Special case for single points. */
+ if (gps->totpoints == 1) {
+ weight_pt = 1.0f;
+ break;
+ }
+
+ 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);
+
+ float vec[3];
+ sub_v3_v3v3(vec, fpt1, fpt2);
+ float angle = angle_on_axis_v3v3_v3(vec_ref, vec, axis);
+ /* Use sin to get a value between 0 and 1. */
+ weight_pt = 1.0f - sin(angle);
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Invert weight if required. */
+ if (mmd->flag & GP_WEIGHT_INVERT_OUTPUT) {
+ weight_pt = 1.0f - weight_pt;
+ }
+ /* Assign weight. */
+ dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ if (dvert != NULL) {
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr);
+ if (dw) {
+ dw->weight = (mmd->flag & GP_WEIGHT_BLEND_DATA) ? dw->weight * weight_pt : weight_pt;
+ CLAMP(dw->weight, mmd->min_weight, 1.0f);
+ }
+ }
+ }
+}
+
+static void bakeModifier(struct Main *UNUSED(bmain),
+ Depsgraph *depsgraph,
+ GpencilModifierData *md,
+ Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ deformStroke(md, depsgraph, ob, gpl, gpf, gps);
+ }
+ }
+ }
+}
+
+static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
+
+ walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
+ walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
+}
+
+static void updateDepsgraph(GpencilModifierData *md,
+ const ModifierUpdateDepsgraphContext *ctx,
+ const int UNUSED(mode))
+{
+ WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
+ if (mmd->object != NULL) {
+ DEG_add_object_relation(
+ ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "GPencil Weight Modifier");
+ }
+ DEG_add_object_relation(
+ ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "GPencil Weight Modifier");
+}
+
+static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
+{
+ WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
+
+ return !(mmd->target_vgname && mmd->target_vgname[0] != '\0');
+}
+
+static void distance_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
+
+ uiLayout *layout = panel->layout;
+ uiLayoutSetPropSep(layout, true);
+
+ uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE);
+ uiLayout *sub = uiLayoutColumn(layout, true);
+ uiItemR(sub, ptr, "distance_start", 0, NULL, ICON_NONE);
+ uiItemR(sub, ptr, "distance_end", 0, "End", ICON_NONE);
+}
+
+static void panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ uiLayoutSetPropSep(layout, true);
+ uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
+
+ const eWeightGpencilModifierMode mode = RNA_enum_get(ptr, "mode");
+
+ uiItemPointerR(layout, ptr, "target_vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
+
+ uiItemR(layout, ptr, "minimum_weight", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_invert_output", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_blend", 0, NULL, ICON_NONE);
+
+ switch (mode) {
+ case GP_WEIGHT_MODE_DISTANCE:
+ distance_panel_draw(C, panel);
+ break;
+ case GP_WEIGHT_MODE_ANGLE:
+ uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "axis", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE);
+ break;
+ default:
+ break;
+ }
+
+ gpencil_modifier_panel_end(layout, ptr);
+}
+
+static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ gpencil_modifier_masking_panel_draw(panel, true, true);
+}
+
+static void panelRegister(ARegionType *region_type)
+{
+ PanelType *panel_type = gpencil_modifier_panel_register(
+ region_type, eGpencilModifierType_Weight, panel_draw);
+
+ gpencil_modifier_subpanel_register(
+ region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Weight = {
+ /* name */ "Vertex Weight",
+ /* structName */ "WeightGpencilModifierData",
+ /* structSize */ sizeof(WeightGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ 0,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+ /* remapTime */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ NULL,
+ /* panelRegister */ panelRegister,
+};
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index 247b0b3f57b..1d4370ed3a9 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -575,9 +575,9 @@ BLI_INLINE int lineart_LineIntersectTest2d(
}
struct Depsgraph;
-struct Scene;
-struct LineartRenderBuffer;
struct LineartGpencilModifierData;
+struct LineartRenderBuffer;
+struct Scene;
void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd);
@@ -602,8 +602,8 @@ LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *r
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y);
-struct bGPDlayer;
struct bGPDframe;
+struct bGPDlayer;
void MOD_lineart_gpencil_generate(LineartCache *cache,
struct Depsgraph *depsgraph,
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 52485648ee0..d86253e7fe0 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -635,7 +635,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
}
/**
- * Note: segment type (crease/material/contour...) is ambiguous after this.
+ * NOTE: segment type (crease/material/contour...) is ambiguous after this.
*/
static void lineart_chain_connect(LineartRenderBuffer *UNUSED(rb),
LineartEdgeChain *onto,
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index c05749061a9..82fd85f5c65 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -735,6 +735,7 @@ static void lineart_triangle_post(LineartTriangle *tri, LineartTriangle *orig)
copy_v3_v3_db(tri->gn, orig->gn);
tri->flags = LRT_CULL_GENERATED;
tri->material_mask_bits = orig->material_mask_bits;
+ tri->mat_occlusion = orig->mat_occlusion;
}
static void lineart_triangle_set_cull_flag(LineartTriangle *tri, uchar flag)
@@ -1695,7 +1696,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
}
if (rb->remove_doubles) {
- BMEditMesh *em = BKE_editmesh_create(bm, false);
+ BMEditMesh *em = BKE_editmesh_create(bm);
BMOperator findop, weldop;
/* See bmesh_opdefines.c and bmesh_operators.c for op names and argument formatting. */
@@ -3441,9 +3442,9 @@ static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb,
return true;
}
- if ((lineart_bounding_area_edge_intersect(fb, FBC1, FBC2, ba)) ||
- (lineart_bounding_area_edge_intersect(fb, FBC2, FBC3, ba)) ||
- (lineart_bounding_area_edge_intersect(fb, FBC3, FBC1, ba))) {
+ if (lineart_bounding_area_edge_intersect(fb, FBC1, FBC2, ba) ||
+ lineart_bounding_area_edge_intersect(fb, FBC2, FBC3, ba) ||
+ lineart_bounding_area_edge_intersect(fb, FBC3, FBC1, ba)) {
return true;
}
@@ -4216,9 +4217,6 @@ static void lineart_gpencil_generate(LineartCache *cache,
/* (!orig_col && !orig_ob) means the whole scene is selected. */
- float mat[4][4];
- unit_m4(mat);
-
int enabled_types = cache->rb_edge_types;
bool invert_input = modifier_flags & LRT_GPENCIL_INVERT_SOURCE_VGROUP;
bool match_output = modifier_flags & LRT_GPENCIL_MATCH_OUTPUT_VGROUP;
@@ -4270,29 +4268,20 @@ static void lineart_gpencil_generate(LineartCache *cache,
/* Preserved: If we ever do asynchronous generation, this picked flag should be set here. */
// ec->picked = 1;
- int array_idx = 0;
- int count = MOD_lineart_chain_count(ec);
+ const int count = MOD_lineart_chain_count(ec);
bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, color_idx, count, thickness, false);
- float *stroke_data = MEM_callocN(sizeof(float) * count * GP_PRIM_DATABUF_SIZE,
- "line art add stroke");
-
- LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) {
- stroke_data[array_idx] = eci->gpos[0];
- stroke_data[array_idx + 1] = eci->gpos[1];
- stroke_data[array_idx + 2] = eci->gpos[2];
- mul_m4_v3(gp_obmat_inverse, &stroke_data[array_idx]);
- stroke_data[array_idx + 3] = 1; /* thickness. */
- stroke_data[array_idx + 4] = opacity; /* hardness?. */
- array_idx += 5;
+ int i;
+ LISTBASE_FOREACH_INDEX (LineartEdgeChainItem *, eci, &ec->chain, i) {
+ bGPDspoint *point = &gps->points[i];
+ mul_v3_m4v3(&point->x, gp_obmat_inverse, eci->gpos);
+ point->pressure = 1.0f;
+ point->strength = opacity;
}
- BKE_gpencil_stroke_add_points(gps, stroke_data, count, mat);
BKE_gpencil_dvert_ensure(gps);
gps->mat_nr = max_ii(material_nr, 0);
- MEM_freeN(stroke_data);
-
if (source_vgname && vgname) {
Object *eval_ob = DEG_get_evaluated_object(depsgraph, ec->object_ref);
int gpdg = -1;
@@ -4301,7 +4290,7 @@ static void lineart_gpencil_generate(LineartCache *cache,
int dindex = 0;
Mesh *me = (Mesh *)eval_ob->data;
if (me->dvert) {
- LISTBASE_FOREACH (bDeformGroup *, db, &eval_ob->defbase) {
+ LISTBASE_FOREACH (bDeformGroup *, db, &me->vertex_group_names) {
if ((!source_vgname) || strstr(db->name, source_vgname) == db->name) {
if (match_output) {
gpdg = BKE_object_defgroup_name_index(gpencil_object, db->name);
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h
index 9d109320f09..70ff4a373dd 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h
@@ -33,10 +33,10 @@
#include <math.h>
#include <string.h>
-struct LineartStaticMemPool;
-struct LineartStaticMemPoolNode;
struct LineartEdge;
struct LineartRenderBuffer;
+struct LineartStaticMemPool;
+struct LineartStaticMemPoolNode;
void *lineart_list_append_pointer_pool(ListBase *h, struct LineartStaticMemPool *smp, void *data);
void *lineart_list_append_pointer_pool_sized(ListBase *h,
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index abb7330d292..b7dc3210c41 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -82,8 +82,8 @@ set(SRC
intern/gpu_select_sample_query.cc
intern/gpu_shader.cc
intern/gpu_shader_builtin.c
- intern/gpu_shader_log.cc
intern/gpu_shader_interface.cc
+ intern/gpu_shader_log.cc
intern/gpu_state.cc
intern/gpu_texture.cc
intern/gpu_uniform_buffer.cc
@@ -103,8 +103,8 @@ set(SRC
opengl/gl_index_buffer.cc
opengl/gl_query.cc
opengl/gl_shader.cc
- opengl/gl_shader_log.cc
opengl/gl_shader_interface.cc
+ opengl/gl_shader_log.cc
opengl/gl_state.cc
opengl/gl_texture.cc
opengl/gl_uniform_buffer.cc
diff --git a/source/blender/gpu/GPU_primitive.h b/source/blender/gpu/GPU_primitive.h
index b1d70326b45..f64a673d461 100644
--- a/source/blender/gpu/GPU_primitive.h
+++ b/source/blender/gpu/GPU_primitive.h
@@ -57,7 +57,7 @@ typedef enum {
} GPUPrimClass;
/**
- * TODO Improve error checking by validating that the shader is suited for this primitive type.
+ * TODO: Improve error checking by validating that the shader is suited for this primitive type.
* GPUPrimClass GPU_primtype_class(GPUPrimType);
* bool GPU_primtype_belongs_to_class(GPUPrimType, GPUPrimClass);
*/
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 13d0139e406..43483916236 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -707,7 +707,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
float fno[3];
short no_short[3];
- /* Note: Clockwise indices ordering, that's why we invert order here. */
+ /* NOTE: Clockwise indices ordering, that's why we invert order here. */
normal_quad_v3(fno, co[3], co[2], co[1], co[0]);
normal_float_to_short_v3(no_short, fno);
@@ -916,7 +916,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
return;
}
- /* TODO, make mask layer optional for bmesh buffer */
+ /* TODO: make mask layer optional for bmesh buffer. */
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
/* Fill vertex buffer */
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index a2072e504fd..d12cecd129e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -810,7 +810,7 @@ static char *code_generate_geometry(GPUNodeGraph *graph,
}
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
- /* TODO let shader choose what to do depending on what the attribute is. */
+ /* TODO: let shader choose what to do depending on what the attribute is. */
BLI_dynstr_appendf(ds, "dataAttrOut.var%d = dataAttrIn[vert].var%d;\\\n", attr->id, attr->id);
}
BLI_dynstr_append(ds, "}\n\n");
@@ -938,9 +938,9 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
return pass;
}
-static int count_active_texture_sampler(GPUShader *shader, char *source)
+static int count_active_texture_sampler(GPUShader *shader, const char *source)
{
- char *code = source;
+ const char *code = source;
/* Remember this is per stage. */
GSet *sampler_ids = BLI_gset_int_new(__func__);
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index b5a437b46f7..943a6151ced 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -28,7 +28,7 @@
* - free can be called from any thread
*/
-/* TODO Create cmake option. */
+/* TODO: Create cmake option. */
#define WITH_OPENGL_BACKEND 1
#include "BLI_assert.h"
@@ -99,7 +99,7 @@ Context *Context::get()
GPUContext *GPU_context_create(void *ghost_window)
{
if (GPUBackend::get() == nullptr) {
- /* TODO move where it make sense. */
+ /* TODO: move where it make sense. */
GPU_backend_init(GPU_BACKEND_OPENGL);
}
@@ -182,7 +182,7 @@ void GPU_backend_init(eGPUBackendType backend_type)
void GPU_backend_exit(void)
{
- /* TODO assert no resource left. Currently UI textures are still not freed in their context
+ /* TODO: assert no resource left. Currently UI textures are still not freed in their context
* correctly. */
delete g_backend;
g_backend = nullptr;
diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc
index 1293cc0953d..4bb13d01c2d 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.cc
+++ b/source/blender/gpu/intern/gpu_framebuffer.cc
@@ -609,7 +609,13 @@ GPUOffScreen *GPU_offscreen_create(
}
if ((depth && !ofs->depth) || !ofs->color) {
- BLI_snprintf(err_out, 256, "GPUTexture: Texture allocation failed.");
+ const char error[] = "GPUTexture: Texture allocation failed.";
+ if (err_out) {
+ BLI_snprintf(err_out, 256, error);
+ }
+ else {
+ fprintf(stderr, error);
+ }
GPU_offscreen_free(ofs);
return nullptr;
}
diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c
index 3c216c1a991..73a80c62bdc 100644
--- a/source/blender/gpu/intern/gpu_material_library.c
+++ b/source/blender/gpu/intern/gpu_material_library.c
@@ -684,7 +684,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = {
static GHash *FUNCTION_HASH = NULL;
-char *gpu_str_skip_token(char *str, char *token, int max)
+const char *gpu_str_skip_token(const char *str, char *token, int max)
{
int len = 0;
@@ -752,7 +752,7 @@ static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library)
eGPUType type;
GPUFunctionQual qual;
int i;
- char *code = library->code;
+ const char *code = library->code;
while ((code = strstr(code, "void "))) {
function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h
index da7b1636fa3..782d89d6f2a 100644
--- a/source/blender/gpu/intern/gpu_material_library.h
+++ b/source/blender/gpu/intern/gpu_material_library.h
@@ -62,5 +62,5 @@ char *gpu_material_library_generate_code(struct GSet *used_libraries, const char
/* Code Parsing */
-char *gpu_str_skip_token(char *str, char *token, int max);
+const char *gpu_str_skip_token(const char *str, char *token, int max);
const char *gpu_data_type_to_string(const eGPUType type);
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index b220c60e979..585cb296bac 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -88,7 +88,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
name = outnode->name;
input = outnode->inputs.first;
- if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && (input->type == type)) {
+ if (STR_ELEM(name, "set_value", "set_rgb", "set_rgba") && (input->type == type)) {
input = MEM_dupallocN(outnode->inputs.first);
if (input->link) {
input->link->users++;
@@ -174,7 +174,7 @@ static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
case SOCK_RGBA:
return "set_rgba";
default:
- BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
+ BLI_assert_msg(0, "No gpu function for non-supported eNodeSocketDatatype");
return NULL;
}
}
@@ -259,7 +259,7 @@ static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **li
output->link->link_type = GPU_NODE_LINK_OUTPUT;
output->link->output = output;
- /* note: the caller owns the reference to the link, GPUOutput
+ /* NOTE: the caller owns the reference to the link, GPUOutput
* merely points to it, and if the node is destroyed it will
* set that pointer to NULL */
}
diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc
index 5c33066c720..9ee8a8b8d32 100644
--- a/source/blender/gpu/intern/gpu_state.cc
+++ b/source/blender/gpu/intern/gpu_state.cc
@@ -187,7 +187,7 @@ void GPU_point_size(float size)
/* Programmable point size
* - shaders set their own point size when enabled
* - use GPU_point_size when disabled */
-/* TODO remove and use program point size everywhere */
+/* TODO: remove and use program point size everywhere. */
void GPU_program_point_size(bool enable)
{
StateManager *stack = Context::get()->state_manager;
diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh
index b79350a6506..b96b71a7ac4 100644
--- a/source/blender/gpu/intern/gpu_state_private.hh
+++ b/source/blender/gpu/intern/gpu_state_private.hh
@@ -96,7 +96,7 @@ inline GPUState operator~(const GPUState &a)
union GPUStateMutable {
struct {
/* Viewport State */
- /** TODO remove */
+ /** TODO: remove. */
float depth_range[2];
/** Positive if using program point size. */
/* TODO(fclem): should be passed as uniform to all shaders. */
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index de5a9f95b65..6564cbda694 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -154,7 +154,7 @@ void Texture::attach_to(FrameBuffer *fb, GPUAttachmentType type)
return;
}
}
- BLI_assert(!"GPU: Error: Texture: Not enough attachment");
+ BLI_assert_msg(0, "GPU: Error: Texture: Not enough attachment");
}
void Texture::detach_from(FrameBuffer *fb)
@@ -166,7 +166,7 @@ void Texture::detach_from(FrameBuffer *fb)
return;
}
}
- BLI_assert(!"GPU: Error: Texture: Framebuffer is not attached");
+ BLI_assert_msg(0, "GPU: Error: Texture: Framebuffer is not attached");
}
void Texture::update(eGPUDataFormat format, const void *data)
@@ -600,7 +600,7 @@ void GPU_texture_py_reference_set(GPUTexture *tex, void **py_ref)
}
#endif
-/* TODO remove */
+/* TODO: remove. */
int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
return reinterpret_cast<const Texture *>(tex)->gl_bindcode_get();
diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh
index a8f2e482bdd..2b8a5a5cc12 100644
--- a/source/blender/gpu/intern/gpu_texture_private.hh
+++ b/source/blender/gpu/intern/gpu_texture_private.hh
@@ -155,7 +155,7 @@ class Texture {
void mip_size_get(int mip, int r_size[3]) const
{
- /* TODO assert if lvl is below the limit of 1px in each dimension. */
+ /* TODO: assert if lvl is below the limit of 1px in each dimension. */
int div = 1 << mip;
r_size[0] = max_ii(1, w_ / div);
@@ -559,7 +559,7 @@ static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format)
case GPU_COMP_I16:
return GPU_RGBA16I;
case GPU_COMP_U16:
- /* Note: Checking the fetch mode to select the right GPU texture format. This can be
+ /* NOTE: Checking the fetch mode to select the right GPU texture format. This can be
* added to other formats as well. */
switch (format->attrs[0].fetch_mode) {
case GPU_FETCH_INT:
diff --git a/source/blender/gpu/intern/gpu_uniform_buffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc
index 3edb090d81c..3a9269d1753 100644
--- a/source/blender/gpu/intern/gpu_uniform_buffer.cc
+++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc
@@ -114,11 +114,11 @@ static void buffer_from_list_inputs_sort(ListBase *inputs)
if (input->type == GPU_MAT3) {
/* Alignment for mat3 is not handled currently, so not supported */
- BLI_assert(!"mat3 not supported in UBO");
+ BLI_assert_msg(0, "mat3 not supported in UBO");
continue;
}
if (input->type > MAX_UBO_GPU_TYPE) {
- BLI_assert(!"GPU type not supported in UBO");
+ BLI_assert_msg(0, "GPU type not supported in UBO");
continue;
}
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc
index 2c21d2bf9af..7ff68242c17 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.cc
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc
@@ -28,8 +28,8 @@
#include "gpu_backend.hh"
#include "gpu_vertex_format_private.h"
-#include "gl_vertex_buffer.hh" /* TODO remove */
-#include "gpu_context_private.hh" /* TODO remove */
+#include "gl_vertex_buffer.hh" /* TODO: remove. */
+#include "gpu_context_private.hh" /* TODO: remove. */
#include "gpu_vertex_buffer_private.hh"
@@ -287,7 +287,7 @@ void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts_, uint a_idx, GPUVertBufRaw
/* NOTE: Be careful when using this. The data needs to match the expected format. */
void *GPU_vertbuf_get_data(const GPUVertBuf *verts)
{
- /* TODO Assert that the format has no padding. */
+ /* TODO: Assert that the format has no padding. */
return unwrap(verts)->data;
}
@@ -296,7 +296,7 @@ void *GPU_vertbuf_get_data(const GPUVertBuf *verts)
void *GPU_vertbuf_steal_data(GPUVertBuf *verts_)
{
VertBuf *verts = unwrap(verts_);
- /* TODO Assert that the format has no padding. */
+ /* TODO: Assert that the format has no padding. */
BLI_assert(verts->data);
void *data = verts->data;
verts->data = nullptr;
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index ddf31b6ffa7..96bf1ec40b0 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -248,7 +248,7 @@ void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
}
}
- BLI_assert(!"Too many draw engines enabled at the same time");
+ BLI_assert_msg(0, "Too many draw engines enabled at the same time");
return NULL;
}
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 1ae68d6813c..42b85da1f93 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -90,7 +90,7 @@ void GLBackend::platform_init()
device |= GPU_DEVICE_INTEL_UHD;
}
}
- else if ((strstr(renderer, "Mesa DRI R")) ||
+ else if (strstr(renderer, "Mesa DRI R") ||
(strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
(strstr(renderer, "AMD") && strstr(vendor, "X.Org")) ||
(strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
@@ -365,8 +365,8 @@ static void detect_workarounds()
(strstr(version, "Build 20.19.15.4285"))) {
GCaps.use_main_context_workaround = true;
}
- /* See T70187: merging vertices fail. This has been tested from 18.2.2 till 19.3.0~dev of the
- * Mesa driver */
+ /* See T70187: merging vertices fail. This has been tested from `18.2.2` till `19.3.0~dev`
+ * of the Mesa driver */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) &&
(strstr(version, "Mesa 18.") || strstr(version, "Mesa 19.0") ||
strstr(version, "Mesa 19.1") || strstr(version, "Mesa 19.2"))) {
diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc
index 6c9c6e10774..23654cb96f3 100644
--- a/source/blender/gpu/opengl/gl_context.cc
+++ b/source/blender/gpu/opengl/gl_context.cc
@@ -39,7 +39,7 @@
#include "gl_state.hh"
#include "gl_uniform_buffer.hh"
-#include "gl_backend.hh" /* TODO remove */
+#include "gl_backend.hh" /* TODO: remove. */
#include "gl_context.hh"
using namespace blender;
diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc
index ac42a950945..3e259235515 100644
--- a/source/blender/gpu/opengl/gl_debug.cc
+++ b/source/blender/gpu/opengl/gl_debug.cc
@@ -81,9 +81,11 @@ static void APIENTRY debug_callback(GLenum UNUSED(source),
return;
}
- if (TRIM_NVIDIA_BUFFER_INFO &&
- GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) &&
- STRPREFIX(message, "Buffer detailed info")) {
+ /* NOTE: callback function can be triggered during before the platform is initialized.
+ * In this case invoking `GPU_type_matches` would fail and
+ * therefore the message is checked before the platform matching. */
+ if (TRIM_NVIDIA_BUFFER_INFO && STRPREFIX(message, "Buffer detailed info") &&
+ GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) {
/** Suppress buffer infos flooding the output. */
return;
}
diff --git a/source/blender/gpu/opengl/gl_drawlist.hh b/source/blender/gpu/opengl/gl_drawlist.hh
index db4b9c03c3c..6f80fdd5a8a 100644
--- a/source/blender/gpu/opengl/gl_drawlist.hh
+++ b/source/blender/gpu/opengl/gl_drawlist.hh
@@ -72,7 +72,7 @@ class GLDrawList : public DrawList {
GLuint buffer_id_;
/** Length of whole the buffer (in byte). */
GLsizeiptr buffer_size_;
- /** Offset of data_ inside the whole buffer (in byte). */
+ /** Offset of `data_` inside the whole buffer (in byte). */
GLintptr data_offset_;
/** To free the buffer_id_. */
diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc
index e87b22985bd..8da114d9270 100644
--- a/source/blender/gpu/opengl/gl_framebuffer.cc
+++ b/source/blender/gpu/opengl/gl_framebuffer.cc
@@ -268,7 +268,7 @@ void GLFrameBuffer::bind(bool enabled_srgb)
}
if (context_ != GLContext::get()) {
- BLI_assert(!"Trying to use the same frame-buffer in multiple context");
+ BLI_assert_msg(0, "Trying to use the same frame-buffer in multiple context");
return;
}
@@ -379,7 +379,7 @@ void GLFrameBuffer::clear_attachment(GPUAttachmentType type,
glClearBufferfv(GL_DEPTH, 0, &depth);
}
else {
- BLI_assert(!"Unhandled data format");
+ BLI_assert_msg(0, "Unhandled data format");
}
}
else {
@@ -395,7 +395,7 @@ void GLFrameBuffer::clear_attachment(GPUAttachmentType type,
glClearBufferiv(GL_COLOR, slot, (GLint *)clear_value);
break;
default:
- BLI_assert(!"Unhandled data format");
+ BLI_assert_msg(0, "Unhandled data format");
break;
}
}
diff --git a/source/blender/gpu/opengl/gl_query.cc b/source/blender/gpu/opengl/gl_query.cc
index 8a42719c665..da9770b4cc1 100644
--- a/source/blender/gpu/opengl/gl_query.cc
+++ b/source/blender/gpu/opengl/gl_query.cc
@@ -41,7 +41,7 @@ void GLQueryPool::init(GPUQueryType type)
query_issued_ = 0;
}
-#if 0 /* TODO to avoid realloc of permanent query pool. */
+#if 0 /* TODO: to avoid realloc of permanent query pool. */
void GLQueryPool::reset(GPUQueryType type)
{
initialized_ = false;
@@ -50,7 +50,7 @@ void GLQueryPool::reset(GPUQueryType type)
void GLQueryPool::begin_query()
{
- /* TODO add assert about expected usage. */
+ /* TODO: add assert about expected usage. */
while (query_issued_ >= query_ids_.size()) {
int64_t prev_size = query_ids_.size();
query_ids_.resize(prev_size + QUERY_CHUNCK_LEN);
@@ -61,7 +61,7 @@ void GLQueryPool::begin_query()
void GLQueryPool::end_query()
{
- /* TODO add assert about expected usage. */
+ /* TODO: add assert about expected usage. */
glEndQuery(gl_type_);
}
@@ -70,7 +70,7 @@ void GLQueryPool::get_occlusion_result(MutableSpan<uint32_t> r_values)
BLI_assert(r_values.size() == query_issued_);
for (int i = 0; i < query_issued_; i++) {
- /* Note: This is a sync point. */
+ /* NOTE: This is a sync point. */
glGetQueryObjectuiv(query_ids_[i], GL_QUERY_RESULT, &r_values[i]);
}
}
diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc
index b837eae4871..1106e3dab50 100644
--- a/source/blender/gpu/opengl/gl_state.cc
+++ b/source/blender/gpu/opengl/gl_state.cc
@@ -131,7 +131,7 @@ void GLStateManager::set_state(const GPUState &state)
set_shadow_bias(state.shadow_bias);
}
- /* TODO remove */
+ /* TODO: remove. */
if (changed.polygon_smooth) {
if (state.polygon_smooth) {
glEnable(GL_POLYGON_SMOOTH);
@@ -156,7 +156,7 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state)
{
GPUStateMutable changed = state ^ current_mutable_;
- /* TODO remove, should be uniform. */
+ /* TODO: remove, should be uniform. */
if (float_as_uint(changed.point_size) != 0) {
if (state.point_size > 0.0f) {
glEnable(GL_PROGRAM_POINT_SIZE);
@@ -168,12 +168,12 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state)
}
if (changed.line_width != 0) {
- /* TODO remove, should use wide line shader. */
+ /* TODO: remove, should use wide line shader. */
glLineWidth(clamp_f(state.line_width, line_width_range_[0], line_width_range_[1]));
}
if (changed.depth_range[0] != 0 || changed.depth_range[1] != 0) {
- /* TODO remove, should modify the projection matrix instead. */
+ /* TODO: remove, should modify the projection matrix instead. */
glDepthRange(UNPACK2(state.depth_range));
}
diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc
index ddc45a6a904..db1fda63c28 100644
--- a/source/blender/gpu/opengl/gl_texture.cc
+++ b/source/blender/gpu/opengl/gl_texture.cc
@@ -32,7 +32,7 @@
#include "gl_backend.hh"
#include "gl_debug.hh"
#include "gl_state.hh"
-#include "gpu_vertex_buffer_private.hh" /* TODO should be `gl_vertex_buffer.hh` */
+#include "gpu_vertex_buffer_private.hh" /* TODO: should be `gl_vertex_buffer.hh`. */
#include "gl_texture.hh"
@@ -347,7 +347,7 @@ void GLTexture::copy_to(Texture *dst_)
BLI_assert((dst->w_ == src->w_) && (dst->h_ == src->h_) && (dst->d_ == src->d_));
BLI_assert(dst->format_ == src->format_);
BLI_assert(dst->type_ == src->type_);
- /* TODO support array / 3D textures. */
+ /* TODO: support array / 3D textures. */
BLI_assert(dst->d_ == 0);
if (GLContext::copy_image_support) {
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
index 9ce2a1be015..aae7f641af8 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
@@ -18,6 +18,7 @@ in vec2 P2;
in vec2 P3;
in ivec4 colid_doarrow;
in ivec2 domuted;
+in float dim_factor;
uniform vec4 colors[6];
@@ -39,6 +40,7 @@ uniform vec2 bezierPts[4];
uniform vec4 colors[3];
uniform bool doArrow;
uniform bool doMuted;
+uniform float dim_factor;
# define colShadow colors[0]
# define colStart colors[1]
@@ -98,6 +100,8 @@ void main(void)
}
}
+ finalColor[3] *= dim_factor;
+
/* Expand into a line */
gl_Position.xy += exp_axis * expandSize * expand_dist;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl
index d33465fa846..40e46bc250c 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl
@@ -1,4 +1,4 @@
-/* TODO : clean this ifdef mess */
+/* TODO: clean this `ifdef` mess. */
void world_normals_get(out vec3 N)
{
#ifndef VOLUMETRICS
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 051bc193a42..0ee8b3057d2 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -47,7 +47,7 @@
/* ********************** THE IK SOLVER ******************* */
/* allocates PoseTree, and links that to root bone/channel */
-/* Note: detecting the IK chain is duplicate code...
+/* NOTE: detecting the IK chain is duplicate code...
* in drawarmature.c and in transform_conversions.c */
static void initialize_posetree(struct Object *UNUSED(ob), bPoseChannel *pchan_tip)
{
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 2cfce7b1ba0..d527aca184c 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -69,8 +69,8 @@ extern "C" {
* \attention defined in ???
*/
struct ImBuf;
-struct rcti;
struct rctf;
+struct rcti;
/**
*
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index ad72f373d12..70bb70ec4fa 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -395,9 +395,8 @@ bool imb_savebmp(ImBuf *ibuf, const char *filepath, int UNUSED(flags))
}
}
}
- if (ofile) {
- fflush(ofile);
- fclose(ofile);
- }
+
+ fflush(ofile);
+ fclose(ofile);
return 1;
}
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 71e513fb405..2cc44ebc67b 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1542,7 +1542,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
rgba_uchar_to_float(fp, cp);
}
else {
- BLI_assert(!"Buffers of 3 or 4 channels are only supported here");
+ BLI_assert_msg(0, "Buffers of 3 or 4 channels are only supported here");
}
}
@@ -3437,7 +3437,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf,
pixel[0] = linear_buffer[linear_index];
}
else {
- BLI_assert(!"Unsupported number of channels in partial buffer update");
+ BLI_assert_msg(0, "Unsupported number of channels in partial buffer update");
}
}
else if (byte_buffer) {
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index e767cb14b1a..1729a9a64f8 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -44,7 +44,7 @@ extern "C" {
bool imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/)
{
- return false; /* todo: finish this function */
+ return false; /* TODO: finish this function. */
/* check image buffer */
if (ibuf == nullptr) {
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 71137a408d2..27195b294d6 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -357,7 +357,7 @@ int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size)
case IMB_PROXY_100:
return 3;
default:
- BLI_assert(!"Unhandled proxy size enum!");
+ BLI_assert_msg(0, "Unhandled proxy size enum!");
return -1;
}
}
@@ -376,7 +376,7 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
case IMB_TC_RECORD_RUN_NO_GAPS:
return 3;
default:
- BLI_assert(!"Unhandled timecode type enum!");
+ BLI_assert_msg(0, "Unhandled timecode type enum!");
return -1;
}
}
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index 65c25194477..0941338160d 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -156,7 +156,7 @@ static ImBuf *imb_oiio_load_image_float(
/* ImBuf always needs 4 channels */
fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f);
- /* Note: Photoshop 16 bit files never has alpha with it,
+ /* NOTE: Photoshop 16 bit files never has alpha with it,
* so no need to handle associated/unassociated alpha. */
return ibuf;
}
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 4a964c64917..79c2583f983 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1195,22 +1195,9 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx)
{
uchar *rect, *_newrect = NULL, *newrect;
float *rectf, *_newrectf = NULL, *newrectf;
- float sample, add;
- float val_a, nval_a, diff_a;
- float val_b, nval_b, diff_b;
- float val_g, nval_g, diff_g;
- float val_r, nval_r, diff_r;
- float val_af, nval_af, diff_af;
- float val_bf, nval_bf, diff_bf;
- float val_gf, nval_gf, diff_gf;
- float val_rf, nval_rf, diff_rf;
int x, y;
bool do_rect = false, do_float = false;
- val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
- val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
- val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
- val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
if (ibuf == NULL) {
return NULL;
}
@@ -1236,119 +1223,158 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx)
}
}
- add = (ibuf->x - 1.001) / (newx - 1.0);
-
rect = (uchar *)ibuf->rect;
rectf = (float *)ibuf->rect_float;
newrect = _newrect;
newrectf = _newrectf;
- for (y = ibuf->y; y > 0; y--) {
-
- sample = 0;
-
+ /* Special case, copy all columns, needed since the scaling logic assumes there is at least
+ * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */
+ if (UNLIKELY(ibuf->x == 1)) {
if (do_rect) {
- val_a = rect[0];
- nval_a = rect[4];
- diff_a = nval_a - val_a;
- val_a += 0.5f;
-
- val_b = rect[1];
- nval_b = rect[5];
- diff_b = nval_b - val_b;
- val_b += 0.5f;
-
- val_g = rect[2];
- nval_g = rect[6];
- diff_g = nval_g - val_g;
- val_g += 0.5f;
-
- val_r = rect[3];
- nval_r = rect[7];
- diff_r = nval_r - val_r;
- val_r += 0.5f;
-
- rect += 8;
+ for (y = ibuf->y; y > 0; y--) {
+ for (x = newx; x > 0; x--) {
+ memcpy(newrect, rect, sizeof(char[4]));
+ newrect += 4;
+ }
+ rect += 4;
+ }
}
if (do_float) {
- val_af = rectf[0];
- nval_af = rectf[4];
- diff_af = nval_af - val_af;
+ for (y = ibuf->y; y > 0; y--) {
+ for (x = newx; x > 0; x--) {
+ memcpy(newrectf, rectf, sizeof(float[4]));
+ newrectf += 4;
+ }
+ rectf += 4;
+ }
+ }
+ }
+ else {
+ const float add = (ibuf->x - 1.001) / (newx - 1.0);
+ float sample;
- val_bf = rectf[1];
- nval_bf = rectf[5];
- diff_bf = nval_bf - val_bf;
+ float val_a, nval_a, diff_a;
+ float val_b, nval_b, diff_b;
+ float val_g, nval_g, diff_g;
+ float val_r, nval_r, diff_r;
+ float val_af, nval_af, diff_af;
+ float val_bf, nval_bf, diff_bf;
+ float val_gf, nval_gf, diff_gf;
+ float val_rf, nval_rf, diff_rf;
- val_gf = rectf[2];
- nval_gf = rectf[6];
- diff_gf = nval_gf - val_gf;
+ val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
+ val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
+ val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
+ val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
- val_rf = rectf[3];
- nval_rf = rectf[7];
- diff_rf = nval_rf - val_rf;
+ for (y = ibuf->y; y > 0; y--) {
- rectf += 8;
- }
- for (x = newx; x > 0; x--) {
- if (sample >= 1.0f) {
- sample -= 1.0f;
+ sample = 0;
- if (do_rect) {
- val_a = nval_a;
- nval_a = rect[0];
- diff_a = nval_a - val_a;
- val_a += 0.5f;
-
- val_b = nval_b;
- nval_b = rect[1];
- diff_b = nval_b - val_b;
- val_b += 0.5f;
-
- val_g = nval_g;
- nval_g = rect[2];
- diff_g = nval_g - val_g;
- val_g += 0.5f;
-
- val_r = nval_r;
- nval_r = rect[3];
- diff_r = nval_r - val_r;
- val_r += 0.5f;
- rect += 4;
- }
- if (do_float) {
- val_af = nval_af;
- nval_af = rectf[0];
- diff_af = nval_af - val_af;
+ if (do_rect) {
+ val_a = rect[0];
+ nval_a = rect[4];
+ diff_a = nval_a - val_a;
+ val_a += 0.5f;
+
+ val_b = rect[1];
+ nval_b = rect[5];
+ diff_b = nval_b - val_b;
+ val_b += 0.5f;
+
+ val_g = rect[2];
+ nval_g = rect[6];
+ diff_g = nval_g - val_g;
+ val_g += 0.5f;
+
+ val_r = rect[3];
+ nval_r = rect[7];
+ diff_r = nval_r - val_r;
+ val_r += 0.5f;
+
+ rect += 8;
+ }
+ if (do_float) {
+ val_af = rectf[0];
+ nval_af = rectf[4];
+ diff_af = nval_af - val_af;
- val_bf = nval_bf;
- nval_bf = rectf[1];
- diff_bf = nval_bf - val_bf;
+ val_bf = rectf[1];
+ nval_bf = rectf[5];
+ diff_bf = nval_bf - val_bf;
- val_gf = nval_gf;
- nval_gf = rectf[2];
- diff_gf = nval_gf - val_gf;
+ val_gf = rectf[2];
+ nval_gf = rectf[6];
+ diff_gf = nval_gf - val_gf;
- val_rf = nval_rf;
- nval_rf = rectf[3];
- diff_rf = nval_rf - val_rf;
- rectf += 4;
- }
- }
- if (do_rect) {
- newrect[0] = val_a + sample * diff_a;
- newrect[1] = val_b + sample * diff_b;
- newrect[2] = val_g + sample * diff_g;
- newrect[3] = val_r + sample * diff_r;
- newrect += 4;
+ val_rf = rectf[3];
+ nval_rf = rectf[7];
+ diff_rf = nval_rf - val_rf;
+
+ rectf += 8;
}
- if (do_float) {
- newrectf[0] = val_af + sample * diff_af;
- newrectf[1] = val_bf + sample * diff_bf;
- newrectf[2] = val_gf + sample * diff_gf;
- newrectf[3] = val_rf + sample * diff_rf;
- newrectf += 4;
+ for (x = newx; x > 0; x--) {
+ if (sample >= 1.0f) {
+ sample -= 1.0f;
+
+ if (do_rect) {
+ val_a = nval_a;
+ nval_a = rect[0];
+ diff_a = nval_a - val_a;
+ val_a += 0.5f;
+
+ val_b = nval_b;
+ nval_b = rect[1];
+ diff_b = nval_b - val_b;
+ val_b += 0.5f;
+
+ val_g = nval_g;
+ nval_g = rect[2];
+ diff_g = nval_g - val_g;
+ val_g += 0.5f;
+
+ val_r = nval_r;
+ nval_r = rect[3];
+ diff_r = nval_r - val_r;
+ val_r += 0.5f;
+ rect += 4;
+ }
+ if (do_float) {
+ val_af = nval_af;
+ nval_af = rectf[0];
+ diff_af = nval_af - val_af;
+
+ val_bf = nval_bf;
+ nval_bf = rectf[1];
+ diff_bf = nval_bf - val_bf;
+
+ val_gf = nval_gf;
+ nval_gf = rectf[2];
+ diff_gf = nval_gf - val_gf;
+
+ val_rf = nval_rf;
+ nval_rf = rectf[3];
+ diff_rf = nval_rf - val_rf;
+ rectf += 4;
+ }
+ }
+ if (do_rect) {
+ newrect[0] = val_a + sample * diff_a;
+ newrect[1] = val_b + sample * diff_b;
+ newrect[2] = val_g + sample * diff_g;
+ newrect[3] = val_r + sample * diff_r;
+ newrect += 4;
+ }
+ if (do_float) {
+ newrectf[0] = val_af + sample * diff_af;
+ newrectf[1] = val_bf + sample * diff_bf;
+ newrectf[2] = val_gf + sample * diff_gf;
+ newrectf[3] = val_rf + sample * diff_rf;
+ newrectf += 4;
+ }
+ sample += add;
}
- sample += add;
}
}
@@ -1371,22 +1397,9 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
{
uchar *rect, *_newrect = NULL, *newrect;
float *rectf, *_newrectf = NULL, *newrectf;
- float sample, add;
- float val_a, nval_a, diff_a;
- float val_b, nval_b, diff_b;
- float val_g, nval_g, diff_g;
- float val_r, nval_r, diff_r;
- float val_af, nval_af, diff_af;
- float val_bf, nval_bf, diff_bf;
- float val_gf, nval_gf, diff_gf;
- float val_rf, nval_rf, diff_rf;
int x, y, skipx;
bool do_rect = false, do_float = false;
- val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
- val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
- val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
- val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
if (ibuf == NULL) {
return NULL;
}
@@ -1412,126 +1425,159 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
}
}
- add = (ibuf->y - 1.001) / (newy - 1.0);
- skipx = 4 * ibuf->x;
-
rect = (uchar *)ibuf->rect;
rectf = (float *)ibuf->rect_float;
newrect = _newrect;
newrectf = _newrectf;
- for (x = ibuf->x; x > 0; x--) {
+ skipx = 4 * ibuf->x;
- sample = 0;
+ /* Special case, copy all rows, needed since the scaling logic assumes there is at least
+ * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */
+ if (UNLIKELY(ibuf->y == 1)) {
if (do_rect) {
- rect = ((uchar *)ibuf->rect) + 4 * (x - 1);
- newrect = _newrect + 4 * (x - 1);
-
- val_a = rect[0];
- nval_a = rect[skipx];
- diff_a = nval_a - val_a;
- val_a += 0.5f;
-
- val_b = rect[1];
- nval_b = rect[skipx + 1];
- diff_b = nval_b - val_b;
- val_b += 0.5f;
-
- val_g = rect[2];
- nval_g = rect[skipx + 2];
- diff_g = nval_g - val_g;
- val_g += 0.5f;
-
- val_r = rect[3];
- nval_r = rect[skipx + 3];
- diff_r = nval_r - val_r;
- val_r += 0.5f;
-
- rect += 2 * skipx;
+ for (y = newy; y > 0; y--) {
+ memcpy(newrect, rect, sizeof(char) * skipx);
+ newrect += skipx;
+ }
}
if (do_float) {
- rectf = ibuf->rect_float + 4 * (x - 1);
- newrectf = _newrectf + 4 * (x - 1);
-
- val_af = rectf[0];
- nval_af = rectf[skipx];
- diff_af = nval_af - val_af;
+ for (y = newy; y > 0; y--) {
+ memcpy(newrectf, rectf, sizeof(float) * skipx);
+ newrectf += skipx;
+ }
+ }
+ }
+ else {
+ const float add = (ibuf->y - 1.001) / (newy - 1.0);
+ float sample;
+
+ float val_a, nval_a, diff_a;
+ float val_b, nval_b, diff_b;
+ float val_g, nval_g, diff_g;
+ float val_r, nval_r, diff_r;
+ float val_af, nval_af, diff_af;
+ float val_bf, nval_bf, diff_bf;
+ float val_gf, nval_gf, diff_gf;
+ float val_rf, nval_rf, diff_rf;
+
+ val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
+ val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
+ val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
+ val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
+
+ for (x = ibuf->x; x > 0; x--) {
+ sample = 0;
+ if (do_rect) {
+ rect = ((uchar *)ibuf->rect) + 4 * (x - 1);
+ newrect = _newrect + 4 * (x - 1);
+
+ val_a = rect[0];
+ nval_a = rect[skipx];
+ diff_a = nval_a - val_a;
+ val_a += 0.5f;
+
+ val_b = rect[1];
+ nval_b = rect[skipx + 1];
+ diff_b = nval_b - val_b;
+ val_b += 0.5f;
+
+ val_g = rect[2];
+ nval_g = rect[skipx + 2];
+ diff_g = nval_g - val_g;
+ val_g += 0.5f;
+
+ val_r = rect[3];
+ nval_r = rect[skipx + 3];
+ diff_r = nval_r - val_r;
+ val_r += 0.5f;
+
+ rect += 2 * skipx;
+ }
+ if (do_float) {
+ rectf = ibuf->rect_float + 4 * (x - 1);
+ newrectf = _newrectf + 4 * (x - 1);
- val_bf = rectf[1];
- nval_bf = rectf[skipx + 1];
- diff_bf = nval_bf - val_bf;
+ val_af = rectf[0];
+ nval_af = rectf[skipx];
+ diff_af = nval_af - val_af;
- val_gf = rectf[2];
- nval_gf = rectf[skipx + 2];
- diff_gf = nval_gf - val_gf;
+ val_bf = rectf[1];
+ nval_bf = rectf[skipx + 1];
+ diff_bf = nval_bf - val_bf;
- val_rf = rectf[3];
- nval_rf = rectf[skipx + 3];
- diff_rf = nval_rf - val_rf;
+ val_gf = rectf[2];
+ nval_gf = rectf[skipx + 2];
+ diff_gf = nval_gf - val_gf;
- rectf += 2 * skipx;
- }
+ val_rf = rectf[3];
+ nval_rf = rectf[skipx + 3];
+ diff_rf = nval_rf - val_rf;
- for (y = newy; y > 0; y--) {
- if (sample >= 1.0f) {
- sample -= 1.0f;
+ rectf += 2 * skipx;
+ }
+ for (y = newy; y > 0; y--) {
+ if (sample >= 1.0f) {
+ sample -= 1.0f;
+
+ if (do_rect) {
+ val_a = nval_a;
+ nval_a = rect[0];
+ diff_a = nval_a - val_a;
+ val_a += 0.5f;
+
+ val_b = nval_b;
+ nval_b = rect[1];
+ diff_b = nval_b - val_b;
+ val_b += 0.5f;
+
+ val_g = nval_g;
+ nval_g = rect[2];
+ diff_g = nval_g - val_g;
+ val_g += 0.5f;
+
+ val_r = nval_r;
+ nval_r = rect[3];
+ diff_r = nval_r - val_r;
+ val_r += 0.5f;
+ rect += skipx;
+ }
+ if (do_float) {
+ val_af = nval_af;
+ nval_af = rectf[0];
+ diff_af = nval_af - val_af;
+
+ val_bf = nval_bf;
+ nval_bf = rectf[1];
+ diff_bf = nval_bf - val_bf;
+
+ val_gf = nval_gf;
+ nval_gf = rectf[2];
+ diff_gf = nval_gf - val_gf;
+
+ val_rf = nval_rf;
+ nval_rf = rectf[3];
+ diff_rf = nval_rf - val_rf;
+ rectf += skipx;
+ }
+ }
if (do_rect) {
- val_a = nval_a;
- nval_a = rect[0];
- diff_a = nval_a - val_a;
- val_a += 0.5f;
-
- val_b = nval_b;
- nval_b = rect[1];
- diff_b = nval_b - val_b;
- val_b += 0.5f;
-
- val_g = nval_g;
- nval_g = rect[2];
- diff_g = nval_g - val_g;
- val_g += 0.5f;
-
- val_r = nval_r;
- nval_r = rect[3];
- diff_r = nval_r - val_r;
- val_r += 0.5f;
- rect += skipx;
+ newrect[0] = val_a + sample * diff_a;
+ newrect[1] = val_b + sample * diff_b;
+ newrect[2] = val_g + sample * diff_g;
+ newrect[3] = val_r + sample * diff_r;
+ newrect += skipx;
}
if (do_float) {
- val_af = nval_af;
- nval_af = rectf[0];
- diff_af = nval_af - val_af;
-
- val_bf = nval_bf;
- nval_bf = rectf[1];
- diff_bf = nval_bf - val_bf;
-
- val_gf = nval_gf;
- nval_gf = rectf[2];
- diff_gf = nval_gf - val_gf;
-
- val_rf = nval_rf;
- nval_rf = rectf[3];
- diff_rf = nval_rf - val_rf;
- rectf += skipx;
+ newrectf[0] = val_af + sample * diff_af;
+ newrectf[1] = val_bf + sample * diff_bf;
+ newrectf[2] = val_gf + sample * diff_gf;
+ newrectf[3] = val_rf + sample * diff_rf;
+ newrectf += skipx;
}
+ sample += add;
}
- if (do_rect) {
- newrect[0] = val_a + sample * diff_a;
- newrect[1] = val_b + sample * diff_b;
- newrect[2] = val_g + sample * diff_g;
- newrect[3] = val_r + sample * diff_r;
- newrect += skipx;
- }
- if (do_float) {
- newrectf[0] = val_af + sample * diff_af;
- newrectf[1] = val_bf + sample * diff_bf;
- newrectf[2] = val_gf + sample * diff_gf;
- newrectf[3] = val_rf + sample * diff_rf;
- newrectf += skipx;
- }
- sample += add;
}
}
@@ -1620,6 +1666,8 @@ static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy)
*/
bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
{
+ BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!");
+
if (ibuf == NULL) {
return false;
}
@@ -1666,6 +1714,8 @@ struct imbufRGBA {
*/
bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
{
+ BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!");
+
unsigned int *rect, *_newrect, *newrect;
struct imbufRGBA *rectf, *_newrectf, *newrectf;
int x, y;
@@ -1838,6 +1888,8 @@ static void *do_scale_thread(void *data_v)
void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy)
{
+ BLI_assert_msg(newx > 0 && newy > 0, "Images must be at least 1 on both dimensions!");
+
ScaleTreadInitData init_data = {NULL};
/* prepare initialization data */
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
index 2a7a189dd2b..8ed0b8b535c 100644
--- a/source/blender/imbuf/intern/targa.c
+++ b/source/blender/imbuf/intern/targa.c
@@ -117,7 +117,7 @@ static int tga_out4(unsigned int data, FILE *file)
uchar *p;
p = (uchar *)&data;
- /* order = bgra */
+ /* Order = BGRA. */
if (putc(p[2], file) == EOF) {
return EOF;
}
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index db80d168e53..19f34a6aacd 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -172,7 +172,7 @@ static const unsigned char acceptable[96] = {
static const char hex[17] = "0123456789abcdef";
-/* Note: This escape function works on file: URIs, but if you want to
+/* NOTE: This escape function works on file: URIs, but if you want to
* escape something else, please read RFC-2396 */
static void escape_uri_string(const char *string,
char *escaped_string,
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c
index eb518828913..759f96af7c8 100644
--- a/source/blender/imbuf/intern/thumbs_blend.c
+++ b/source/blender/imbuf/intern/thumbs_blend.c
@@ -56,7 +56,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const
return ima;
}
- /* Note: we should handle all previews for a same group at once, would avoid reopening
+ /* NOTE: we should handle all previews for a same group at once, would avoid reopening
* `.blend` file for each and every ID. However, this adds some complexity,
* so keep it for later. */
names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, false, &nnames);
diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h
index 5664a43233a..3d1391ac2a4 100644
--- a/source/blender/io/alembic/ABC_alembic.h
+++ b/source/blender/io/alembic/ABC_alembic.h
@@ -19,6 +19,8 @@
* \ingroup balembic
*/
+#include "DEG_depsgraph.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -54,7 +56,6 @@ struct AlembicExportParams {
bool curves_as_mesh;
bool flatten_hierarchy;
bool visible_objects_only;
- bool renderable_only;
bool face_sets;
bool use_subdiv_schema;
bool packuv;
@@ -63,6 +64,7 @@ struct AlembicExportParams {
bool export_particles;
bool export_custom_properties;
bool use_instancing;
+ enum eEvaluationMode evaluation_mode;
/* See MOD_TRIANGULATE_NGON_xxx and MOD_TRIANGULATE_QUAD_xxx
* in DNA_modifier_types.h */
diff --git a/source/blender/io/alembic/exporter/abc_custom_props.cc b/source/blender/io/alembic/exporter/abc_custom_props.cc
index f5593e7ee30..4ea2fd03fff 100644
--- a/source/blender/io/alembic/exporter/abc_custom_props.cc
+++ b/source/blender/io/alembic/exporter/abc_custom_props.cc
@@ -141,7 +141,7 @@ void CustomPropertiesExporter::write_idparray(const IDProperty *idp_array)
continue;
}
std::cerr << "Custom property " << idp_array->name << " has elements of varying type";
- BLI_assert(!"Mixed type IDP_ARRAY custom property found");
+ BLI_assert_msg(0, "Mixed type IDP_ARRAY custom property found");
}
#endif
diff --git a/source/blender/io/alembic/exporter/abc_export_capi.cc b/source/blender/io/alembic/exporter/abc_export_capi.cc
index 5b8998a0b1a..efe04d64cc3 100644
--- a/source/blender/io/alembic/exporter/abc_export_capi.cc
+++ b/source/blender/io/alembic/exporter/abc_export_capi.cc
@@ -213,8 +213,7 @@ bool ABC_export(Scene *scene,
job->export_ok = false;
BLI_strncpy(job->filename, filepath, sizeof(job->filename));
- job->depsgraph = DEG_graph_new(
- job->bmain, scene, view_layer, DAG_EVAL_RENDER /* TODO(Sybren): params->evaluation_mode */);
+ job->depsgraph = DEG_graph_new(job->bmain, scene, view_layer, params->evaluation_mode);
job->params = *params;
bool export_ok = false;
diff --git a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc
index e2be241c144..174b2abb90f 100644
--- a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc
+++ b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc
@@ -229,7 +229,7 @@ ABCAbstractWriter *ABCHierarchyIterator::create_data_writer_for_object_type(
case OB_GPENCIL:
return nullptr;
case OB_TYPE_MAX:
- BLI_assert(!"OB_TYPE_MAX should not be used");
+ BLI_assert_msg(0, "OB_TYPE_MAX should not be used");
return nullptr;
}
diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.cc b/source/blender/io/alembic/exporter/abc_writer_abstract.cc
index 27b5c2fa2a4..910e04f3bf5 100644
--- a/source/blender/io/alembic/exporter/abc_writer_abstract.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_abstract.cc
@@ -137,7 +137,7 @@ void ABCAbstractWriter::update_bounding_box(Object *object)
void ABCAbstractWriter::write_visibility(const HierarchyContext &context)
{
- const bool is_visible = context.is_object_visible(DAG_EVAL_RENDER);
+ const bool is_visible = context.is_object_visible(args_.export_params->evaluation_mode);
Alembic::Abc::OObject abc_object = get_alembic_object();
if (!abc_visibility_.valid()) {
diff --git a/source/blender/io/alembic/exporter/abc_writer_instance.cc b/source/blender/io/alembic/exporter/abc_writer_instance.cc
index 1737e8c091e..353705f2c1d 100644
--- a/source/blender/io/alembic/exporter/abc_writer_instance.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_instance.cc
@@ -59,7 +59,7 @@ Alembic::Abc::OCompoundProperty ABCInstanceWriter::abc_prop_for_custom_props()
OObject ABCInstanceWriter::get_alembic_object() const
{
/* There is no OObject for an instance. */
- BLI_assert(!"ABCInstanceWriter cannot return its Alembic OObject");
+ BLI_assert_msg(0, "ABCInstanceWriter cannot return its Alembic OObject");
return OObject();
}
diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
index fd7db005dd2..7ffb61e1d1b 100644
--- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
@@ -162,7 +162,7 @@ ModifierData *ABCGenericMeshWriter::get_liquid_sim_modifier(Scene *scene, Object
bool ABCGenericMeshWriter::is_supported(const HierarchyContext *context) const
{
if (args_.export_params->visible_objects_only) {
- return context->is_object_visible(DAG_EVAL_RENDER);
+ return context->is_object_visible(args_.export_params->evaluation_mode);
}
return true;
}
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc
index 79f34f671c7..c05df7f1ff5 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.cc
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc
@@ -565,7 +565,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec
Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr);
if (read_mesh != mesh) {
- /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */
+ /* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */
/* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */
short autosmooth = (read_mesh->flag & ME_AUTOSMOOTH);
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true);
diff --git a/source/blender/io/collada/AnimationExporter.cpp b/source/blender/io/collada/AnimationExporter.cpp
index 73952b06bc9..9ba59c0414d 100644
--- a/source/blender/io/collada/AnimationExporter.cpp
+++ b/source/blender/io/collada/AnimationExporter.cpp
@@ -135,7 +135,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler)
container_is_open = open_animation_container(container_is_open, ob);
/* Now take care of the Object Animations
- * Note: For Armatures the skeletal animation has already been exported (see above)
+ * NOTE: For Armatures the skeletal animation has already been exported (see above)
* However Armatures also can have Object animation.
*/
bool export_as_matrix = this->export_settings.get_animation_transformation_type() ==
@@ -168,7 +168,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler)
/*
* Export all animation FCurves of an Object.
*
- * Note: This uses the keyframes as sample points,
+ * NOTE: This uses the keyframes as sample points,
* and exports "baked keyframes" while keeping the tangent information
* of the FCurves intact. This works for simple cases, but breaks
* especially when negative scales are involved in the animation.
@@ -337,7 +337,7 @@ void AnimationExporter::export_curve_animation(Object *ob, BCAnimationCurve &cur
/*
* Some curves can not be exported as is and need some conversion
* For more information see implementation of get_modified_export_curve()
- * note: if mcurve is not NULL then it must be deleted at end of this method;
+ * NOTE: if mcurve is not NULL then it must be deleted at end of this method;
*/
int channel_index = curve.get_channel_index();
@@ -775,7 +775,7 @@ std::string AnimationExporter::get_collada_name(std::string channel_type) const
{
/*
* Translation table to map FCurve animation types to Collada animation.
- * Todo: Maybe we can keep the names from the fcurves here instead of
+ * TODO: Maybe we can keep the names from the fcurves here instead of
* mapping. However this is what i found in the old code. So keep
* this map for now.
*/
@@ -799,9 +799,9 @@ std::string AnimationExporter::get_collada_name(std::string channel_type) const
{"spot_size", "falloff_angle"},
{"fall_off_exponent", "falloff_exponent"},
{"spot_blend", "falloff_exponent"},
- /* Special blender profile (todo: make this more elegant). */
+ /* Special blender profile (TODO: make this more elegant). */
{"blender/blender_dist", "blender/blender_dist"},
- /* Special blender profile (todo: make this more elegant). */
+ /* Special blender profile (TODO: make this more elegant). */
{"distance", "blender/blender_dist"},
/* Cameras */
diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp
index 49f28325257..626e4258239 100644
--- a/source/blender/io/collada/AnimationImporter.cpp
+++ b/source/blender/io/collada/AnimationImporter.cpp
@@ -164,7 +164,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
{
for (unsigned int i = 0; i < cu->totvert; i++) {
- /* TODO convert handles too */
+ /* TODO: convert handles too. */
cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f);
cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f);
cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f);
@@ -174,7 +174,7 @@ void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
void AnimationImporter::fcurve_scale(FCurve *cu, int scale)
{
for (unsigned int i = 0; i < cu->totvert; i++) {
- /* TODO convert handles too */
+ /* TODO: convert handles too. */
cu->bezt[i].vec[1][1] *= scale;
cu->bezt[i].vec[0][1] *= scale;
cu->bezt[i].vec[2][1] *= scale;
@@ -305,7 +305,7 @@ bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim)
animation_to_fcurves(curve);
break;
default:
- /* TODO there are also CARDINAL, HERMITE, BSPLINE and STEP types. */
+ /* TODO: there are also CARDINAL, HERMITE, BSPLINE and STEP types. */
fprintf(stderr,
"CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n");
break;
@@ -624,7 +624,7 @@ void AnimationImporter::Assign_transform_animations(
}
} break;
case COLLADAFW::AnimationList::AXISANGLE:
- /* TODO convert axis-angle to quat? or XYZ? */
+ /* TODO: convert axis-angle to quat? or XYZ? */
default:
unused_fcurve(curves);
fprintf(stderr,
@@ -972,7 +972,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob,
/*
* This function returns the aspect ration from the Collada camera.
*
- * Note:COLLADA allows to specify either XFov, or YFov alone.
+ * NOTE:COLLADA allows to specify either XFov, or YFov alone.
* In that case the aspect ratio can be determined from
* the viewport aspect ratio (which is 1:1 ?)
* XXX: check this: its probably wrong!
@@ -1979,7 +1979,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm,
return false;
}
- /* TODO support other animclasses */
+ /* TODO: support other animclasses. */
if (animclass != COLLADAFW::AnimationList::ANGLE) {
report_class_type_unsupported(path, animclass, type);
return false;
diff --git a/source/blender/io/collada/BCAnimationCurve.h b/source/blender/io/collada/BCAnimationCurve.h
index a1597cd47be..36b2a5e8509 100644
--- a/source/blender/io/collada/BCAnimationCurve.h
+++ b/source/blender/io/collada/BCAnimationCurve.h
@@ -116,7 +116,7 @@ class BCAnimationCurve {
bool is_keyframe(int frame);
void adjust_range(int frame);
- std::string get_animation_name(Object *ob) const; /* xxx: this is collada specific */
+ std::string get_animation_name(Object *ob) const; /* XXX: this is COLLADA specific. */
std::string get_channel_target() const;
std::string get_channel_type() const;
std::string get_channel_posebone() const; /* returns "" if channel is not a bone channel */
diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp
index 6f0d422dbe2..e61ed47adee 100644
--- a/source/blender/io/collada/ControllerExporter.cpp
+++ b/source/blender/io/collada/ControllerExporter.cpp
@@ -29,6 +29,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lib_id.h"
@@ -194,9 +195,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
add_bind_shape_mat(ob);
- std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
- std::string inv_bind_mat_source_id = add_inv_bind_mats_source(
- ob_arm, &ob->defbase, controller_id);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ std::string joints_source_id = add_joints_source(ob_arm, defbase, controller_id);
+ std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, defbase, controller_id);
std::list<int> vcounts;
std::list<int> joints;
@@ -207,9 +208,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
/* def group index -> joint index */
std::vector<int> joint_index_by_def_index;
- bDeformGroup *def;
+ const bDeformGroup *def;
- for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
+ for (def = (const bDeformGroup *)defbase->first, i = 0, j = 0; def; def = def->next, i++) {
if (is_bone_defgroup(ob_arm, def)) {
joint_index_by_def_index.push_back(j++);
}
@@ -269,7 +270,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
}
std::string weights_source_id = add_weights_source(me, controller_id, weights);
- add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
+ add_joints_element(defbase, joints_source_id, inv_bind_mat_source_id);
add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
BKE_id_free(nullptr, me);
@@ -392,7 +393,7 @@ void ControllerExporter::add_weight_extras(Key *key)
}
}
-void ControllerExporter::add_joints_element(ListBase *defbase,
+void ControllerExporter::add_joints_element(const ListBase *defbase,
const std::string &joints_source_id,
const std::string &inv_bind_mat_source_id)
{
@@ -431,7 +432,7 @@ void ControllerExporter::add_bind_shape_mat(Object *ob)
}
std::string ControllerExporter::add_joints_source(Object *ob_arm,
- ListBase *defbase,
+ const ListBase *defbase,
const std::string &controller_id)
{
std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
@@ -468,7 +469,7 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm,
}
std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
- ListBase *defbase,
+ const ListBase *defbase,
const std::string &controller_id)
{
std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
@@ -568,13 +569,13 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
return source_id;
}
-Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
+Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, const bDeformGroup *def)
{
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
return pchan ? pchan->bone : nullptr;
}
-bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def)
+bool ControllerExporter::is_bone_defgroup(Object *ob_arm, const bDeformGroup *def)
{
return get_bone_from_defgroup(ob_arm, def) != nullptr;
}
diff --git a/source/blender/io/collada/ControllerExporter.h b/source/blender/io/collada/ControllerExporter.h
index 6a377a4119e..0aec9e8d179 100644
--- a/source/blender/io/collada/ControllerExporter.h
+++ b/source/blender/io/collada/ControllerExporter.h
@@ -97,7 +97,7 @@ class ControllerExporter : public COLLADASW::LibraryControllers,
void export_morph_controller(Object *ob, Key *key);
- void add_joints_element(ListBase *defbase,
+ void add_joints_element(const ListBase *defbase,
const std::string &joints_source_id,
const std::string &inv_bind_mat_source_id);
@@ -110,16 +110,16 @@ class ControllerExporter : public COLLADASW::LibraryControllers,
void add_weight_extras(Key *key);
std::string add_joints_source(Object *ob_arm,
- ListBase *defbase,
+ const ListBase *defbase,
const std::string &controller_id);
std::string add_inv_bind_mats_source(Object *ob_arm,
- ListBase *defbase,
+ const ListBase *defbase,
const std::string &controller_id);
- Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def);
+ Bone *get_bone_from_defgroup(Object *ob_arm, const bDeformGroup *def);
- bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def);
+ bool is_bone_defgroup(Object *ob_arm, const bDeformGroup *def);
std::string add_weights_source(Mesh *me,
const std::string &controller_id,
diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp
index beadfc98c74..35bdc0a4e06 100644
--- a/source/blender/io/collada/DocumentImporter.cpp
+++ b/source/blender/io/collada/DocumentImporter.cpp
@@ -145,7 +145,7 @@ bool DocumentImporter::import()
return false;
}
- /** TODO set up scene graph and such here */
+ /** TODO: set up scene graph and such here. */
mImportStage = Fetching_Controller_data;
COLLADASaxFWL::Loader loader2;
COLLADAFW::Root root2(&loader2, this);
@@ -189,7 +189,7 @@ void DocumentImporter::finish()
std::vector<Object *> *objects_to_scale = new std::vector<Object *>();
- /** TODO Break up and put into 2-pass parsing of DAE */
+ /** TODO: Break up and put into 2-pass parsing of DAE. */
std::vector<const COLLADAFW::VisualScene *>::iterator sit;
for (sit = vscenes.begin(); sit != vscenes.end(); sit++) {
PointerRNA sceneptr, unit_settings;
@@ -1122,7 +1122,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
switch (light->getLightType()) {
case COLLADAFW::Light::AMBIENT_LIGHT: {
- lamp->type = LA_SUN; /* TODO needs more thoughts */
+ lamp->type = LA_SUN; /* TODO: needs more thoughts. */
} break;
case COLLADAFW::Light::SPOT_LIGHT: {
lamp->type = LA_SPOT;
diff --git a/source/blender/io/collada/ImageExporter.cpp b/source/blender/io/collada/ImageExporter.cpp
index bb7b3bf0631..4dd7e617459 100644
--- a/source/blender/io/collada/ImageExporter.cpp
+++ b/source/blender/io/collada/ImageExporter.cpp
@@ -113,7 +113,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
/* This image is already located on the file system.
* But we want to create copies here.
* To move images into the same export directory.
- * Note: If an image is already located in the export folder,
+ * NOTE: If an image is already located in the export folder,
* then skip the copy (as it would result in a file copy error). */
if (BLI_path_cmp(source_path, export_path) != 0) {
diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp
index a33256f9a59..5aa57159328 100644
--- a/source/blender/io/collada/MeshImporter.cpp
+++ b/source/blender/io/collada/MeshImporter.cpp
@@ -170,7 +170,7 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: {
COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
if (values->empty() || values->getCount() <= (v_index * stride + 2)) {
- return; /* xxx need to create an error instead */
+ return; /* XXX: need to create an error instead. */
}
mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]);
@@ -181,7 +181,7 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: {
COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
if (values->empty() || values->getCount() <= (v_index * stride + 2)) {
- return; /* xxx need to create an error instead */
+ return; /* XXX: need to create an error instead. */
}
mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]);
@@ -967,7 +967,7 @@ static void bc_remove_materials_from_object(Object *ob, Mesh *me)
/**
* Returns the list of Users of the given Mesh object.
- * Note: This function uses the object user flag to control
+ * NOTE: This function uses the object user flag to control
* which objects have already been processed.
*/
std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp
index c2f17174d75..f0e1c5e4c26 100644
--- a/source/blender/io/collada/SkinInfo.cpp
+++ b/source/blender/io/collada/SkinInfo.cpp
@@ -36,6 +36,7 @@
#include "DNA_scene_types.h"
#include "BKE_action.h"
+#include "BKE_deform.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
@@ -289,7 +290,8 @@ void SkinInfo::link_armature(bContext *C,
/* -1 means "weight towards the bind shape", we just don't assign it to any group */
if (joint != -1) {
- bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *def = (bDeformGroup *)BLI_findlink(defbase, joint);
ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
}
diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp
index 787af933e8f..355aa5c22f0 100644
--- a/source/blender/io/collada/collada_internal.cpp
+++ b/source/blender/io/collada/collada_internal.cpp
@@ -71,7 +71,7 @@ void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v)
v[2] = vec.z;
}
-/* TODO need also for angle conversion, time conversion... */
+/* TODO: need also for angle conversion, time conversion... */
void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in)
{
diff --git a/source/blender/io/collada/collada_internal.h b/source/blender/io/collada/collada_internal.h
index 1d2ed11bfe6..e3894093507 100644
--- a/source/blender/io/collada/collada_internal.h
+++ b/source/blender/io/collada/collada_internal.h
@@ -62,7 +62,7 @@ class UnitConverter {
float getLinearMeter(void);
- /* TODO need also for angle conversion, time conversion... */
+ /* TODO: need also for angle conversion, time conversion... */
static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in);
static void mat4_to_dae(float out[4][4], float in[4][4]);
diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp
index d7855d69d99..9967a526971 100644
--- a/source/blender/io/collada/collada_utils.cpp
+++ b/source/blender/io/collada/collada_utils.cpp
@@ -159,7 +159,7 @@ std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool al
for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) {
bAction *act = (bAction *)id;
/* XXX This currently creates too many actions.
- * TODO Need to check if the action is compatible to the given object. */
+ * TODO: Need to check if the action is compatible to the given object. */
actions.push_back(act);
}
}
@@ -281,7 +281,7 @@ bool bc_has_object_type(LinkNode *export_set, short obtype)
for (node = export_set; node; node = node->next) {
Object *ob = (Object *)node->link;
- /* XXX - why is this checking for ob->data? - we could be looking for empties */
+ /* XXX: why is this checking for ob->data? - we could be looking for empties. */
if (ob->type == obtype && ob->data) {
return true;
}
@@ -728,7 +728,7 @@ void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
/**
* Stores a Float value as a custom bone property
*
- * Note: This function is currently not needed. Keep for future usage
+ * NOTE: This function is currently not needed. Keep for future usage
*/
static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
{
@@ -1018,7 +1018,7 @@ void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform,
* Check if custom information about bind matrix exists and modify the from_mat
* accordingly.
*
- * Note: This is old style for Blender <= 2.78 only kept for compatibility
+ * NOTE: This is old style for Blender <= 2.78 only kept for compatibility
*/
void bc_create_restpose_mat(BCExportSettings &export_settings,
Bone *bone,
diff --git a/source/blender/io/gpencil/gpencil_io.h b/source/blender/io/gpencil/gpencil_io.h
index 24b13479359..fab867b38b3 100644
--- a/source/blender/io/gpencil/gpencil_io.h
+++ b/source/blender/io/gpencil/gpencil_io.h
@@ -27,9 +27,9 @@ extern "C" {
#endif
struct ARegion;
-struct bContext;
struct Object;
struct View3D;
+struct bContext;
typedef struct GpencilIOParams {
bContext *C;
diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc
index 6c369382e0d..294f6bfccb7 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_base.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc
@@ -100,11 +100,9 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara
invert_m4_m4(viewmat, cam_ob->obmat);
mul_m4_m4m4(persmat_, params.winmat, viewmat);
- is_ortho_ = params.is_ortho;
}
else {
unit_m4(persmat_);
- is_ortho_ = false;
}
winx_ = params_.region->winx;
@@ -129,7 +127,6 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara
}
else {
is_camera_ = false;
- is_ortho_ = false;
/* Calc selected object boundbox. Need set initial value to some variables. */
camera_ratio_ = 1.0f;
offset_.x = 0.0f;
@@ -248,19 +245,14 @@ bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
}
/** Convert to render space. */
-float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho)
+float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co)
{
float3 parent_co = diff_mat_ * co;
- mul_m4_v3(persmat_, parent_co);
-
- if (!is_ortho) {
- parent_co.x = parent_co.x / max_ff(FLT_MIN, parent_co.z);
- parent_co.y = parent_co.y / max_ff(FLT_MIN, parent_co.z);
- }
float2 r_co;
- r_co.x = (parent_co.x + 1.0f) / 2.0f * (float)render_x_;
- r_co.y = (parent_co.y + 1.0f) / 2.0f * (float)render_y_;
+ mul_v2_project_m4_v3(&r_co.x, persmat_, &parent_co.x);
+ r_co.x = (r_co.x + 1.0f) / 2.0f * (float)render_x_;
+ r_co.y = (r_co.y + 1.0f) / 2.0f * (float)render_y_;
/* Invert X axis. */
if (invert_axis_[0]) {
@@ -279,7 +271,7 @@ float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co)
{
const bool is_camera = (bool)(rv3d_->persp == RV3D_CAMOB);
if (is_camera) {
- return gpencil_3D_point_to_render_space(co, is_orthographic());
+ return gpencil_3D_point_to_render_space(co);
}
float2 result;
gpencil_3D_point_to_screen_space(co, result);
@@ -346,11 +338,6 @@ bool GpencilIO::is_camera_mode()
return is_camera_;
}
-bool GpencilIO::is_orthographic()
-{
- return is_ortho_;
-}
-
/* Calculate selected strokes boundbox. */
void GpencilIO::selected_objects_boundbox_calc()
{
diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.hh b/source/blender/io/gpencil/intern/gpencil_io_base.hh
index c3c6f1156bb..02758883f19 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_base.hh
+++ b/source/blender/io/gpencil/intern/gpencil_io_base.hh
@@ -37,9 +37,9 @@ struct Object;
struct RegionView3D;
struct Scene;
-struct bGPdata;
struct bGPDlayer;
struct bGPDstroke;
+struct bGPdata;
using blender::Vector;
@@ -88,14 +88,13 @@ class GpencilIO {
/* Geometry functions. */
bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co);
- float2 gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho);
+ float2 gpencil_3D_point_to_render_space(const float3 co);
float2 gpencil_3D_point_to_2D(const float3 co);
float stroke_point_radius_get(struct bGPDlayer *gpl, struct bGPDstroke *gps);
void create_object_list();
bool is_camera_mode();
- bool is_orthographic();
float stroke_average_opacity_get();
@@ -109,7 +108,6 @@ class GpencilIO {
private:
float avg_opacity_;
bool is_camera_;
- bool is_ortho_;
rctf select_boundbox_;
/* Camera matrix. */
diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh
index 0e9271dd2c6..99e8b1ed4fd 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh
+++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh
@@ -24,10 +24,10 @@
#include "gpencil_io_import_base.hh"
struct GpencilIOParams;
-struct NSVGshape;
struct NSVGpath;
-struct bGPdata;
+struct NSVGshape;
struct bGPDframe;
+struct bGPdata;
#define SVG_IMPORTER_NAME "SVG Import for Grease Pencil"
#define SVG_IMPORTER_VERSION "v1.0"
diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc
index 66dfc21441e..a9cba7f36d9 100644
--- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc
+++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc
@@ -121,7 +121,7 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
case OB_GPENCIL:
return nullptr;
case OB_TYPE_MAX:
- BLI_assert(!"OB_TYPE_MAX should not be used");
+ BLI_assert_msg(0, "OB_TYPE_MAX should not be used");
return nullptr;
}
diff --git a/source/blender/io/usd/intern/usd_writer_abstract.cc b/source/blender/io/usd/intern/usd_writer_abstract.cc
index 5e66136abf1..6965ecf6249 100644
--- a/source/blender/io/usd/intern/usd_writer_abstract.cc
+++ b/source/blender/io/usd/intern/usd_writer_abstract.cc
@@ -128,7 +128,7 @@ bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const
if (context.export_path == context.original_export_path) {
printf("USD ref error: export path is reference path: %s\n", context.export_path.c_str());
- BLI_assert(!"USD reference error");
+ BLI_assert_msg(0, "USD reference error");
return false;
}
diff --git a/source/blender/io/usd/intern/usd_writer_camera.cc b/source/blender/io/usd/intern/usd_writer_camera.cc
index 677be9a7fc4..50d644241df 100644
--- a/source/blender/io/usd/intern/usd_writer_camera.cc
+++ b/source/blender/io/usd/intern/usd_writer_camera.cc
@@ -61,7 +61,7 @@ static void camera_sensor_size_for_render(const Camera *camera,
*r_sensor_y = camera->sensor_y;
break;
case CAMERA_SENSOR_FIT_AUTO:
- BLI_assert(!"Camera fit should be either horizontal or vertical");
+ BLI_assert_msg(0, "Camera fit should be either horizontal or vertical");
break;
}
}
diff --git a/source/blender/io/usd/intern/usd_writer_light.cc b/source/blender/io/usd/intern/usd_writer_light.cc
index f77c51c22ec..7ffae1dd398 100644
--- a/source/blender/io/usd/intern/usd_writer_light.cc
+++ b/source/blender/io/usd/intern/usd_writer_light.cc
@@ -87,7 +87,7 @@ void USDLightWriter::do_write(HierarchyContext &context)
usd_light = pxr::UsdLuxDistantLight::Define(stage, usd_path);
break;
default:
- BLI_assert(!"is_supported() returned true for unsupported light type");
+ BLI_assert_msg(0, "is_supported() returned true for unsupported light type");
}
/* Scale factor to get to somewhat-similar illumination. Since the USDViewer had similar
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 15a4f8817fd..43969bf0768 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -62,7 +62,7 @@ typedef struct DrawDataList {
typedef struct IDPropertyData {
void *pointer;
ListBase group;
- /** Note, we actually fit a double into these two ints. */
+ /** NOTE: we actually fit a double into these two 32bit integers. */
int val, val2;
} IDPropertyData;
@@ -76,7 +76,7 @@ typedef struct IDProperty {
/* saved is used to indicate if this struct has been saved yet.
* seemed like a good idea as a '_pad' var was needed anyway :) */
int saved;
- /** Note, alignment for 64 bits. */
+ /** NOTE: alignment for 64 bits. */
IDPropertyData data;
/* Array length, also (this is important!) string length + 1.
@@ -554,7 +554,7 @@ enum {
* Also used internally in readfile.c to mark data-blocks needing do_versions. */
LIB_TAG_NEW = 1 << 8,
/* RESET_BEFORE_USE free test flag.
- * TODO make it a RESET_AFTER_USE too. */
+ * TODO: make it a RESET_AFTER_USE too. */
LIB_TAG_DOIT = 1 << 10,
/* RESET_AFTER_USE tag existing data before linking so we know what is new. */
LIB_TAG_PRE_EXISTING = 1 << 11,
@@ -621,9 +621,9 @@ typedef enum IDRecalcFlag {
* When a collection gets tagged with this flag, all objects depending on the geometry and
* transforms on any of the objects in the collection are updated. */
ID_RECALC_GEOMETRY = (1 << 1),
-
- /* ** Animation or time changed and animation is to be re-evaluated. ** */
- ID_RECALC_ANIMATION = (1 << 2),
+ /* Same as #ID_RECALC_GEOMETRY, but instead of tagging the batch cache as `dirty_all`, just tags
+ what matches the deform cache. */
+ ID_RECALC_GEOMETRY_DEFORM = (1 << 2),
/* ** Particle system changed. ** */
/* Only do pathcache etc. */
@@ -683,6 +683,9 @@ typedef enum IDRecalcFlag {
* have to be copied on every update. */
ID_RECALC_PARAMETERS = (1 << 21),
+ /* ** Animation or time changed and animation is to be re-evaluated. ** */
+ ID_RECALC_ANIMATION = (1 << 22),
+
/* Input has changed and datablock is to be reload from disk.
* Applies to movie clips to inform that copy-on-written version is to be refreshed for the new
* input file or for color space changes. */
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index b6ffefb55e0..aba6ccfd3ba 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -135,7 +135,7 @@ typedef struct bAnimVizSettings {
/* bAnimVizSettings->recalc */
typedef enum eAnimViz_RecalcFlags {
- /* motionpaths need recalculating */
+ /* Motion-paths need recalculating. */
ANIMVIZ_RECALC_PATHS = (1 << 0),
} eAnimViz_RecalcFlags;
@@ -419,7 +419,7 @@ typedef enum ePchan_DrawFlag {
PCHAN_DRAW_NO_CUSTOM_BONE_SIZE = (1 << 0),
} ePchan_DrawFlag;
-/* Note: It doesn't take custom_scale_xyz into account */
+/* NOTE: It doesn't take custom_scale_xyz into account. */
#define PCHAN_CUSTOM_BONE_LENGTH(pchan) \
(((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length)
@@ -602,7 +602,7 @@ typedef struct bActionGroup {
struct bActionGroup *next, *prev;
/**
- * Note: this must not be touched by standard listbase functions
+ * NOTE: this must not be touched by standard listbase functions
* which would clear links to other channels.
*/
ListBase channels;
diff --git a/source/blender/makesdna/DNA_asset_defaults.h b/source/blender/makesdna/DNA_asset_defaults.h
index ff00ba79cf0..ce01563f619 100644
--- a/source/blender/makesdna/DNA_asset_defaults.h
+++ b/source/blender/makesdna/DNA_asset_defaults.h
@@ -32,6 +32,13 @@
0 \
}
+#define _DNA_DEFAULT_AssetLibraryReference \
+ { \
+ .type = ASSET_LIBRARY_LOCAL, \
+ /* Not needed really (should be ignored for #ASSET_LIBRARY_LOCAL), but helps debugging. */ \
+ .custom_library_index = -1, \
+ }
+
/** \} */
/* clang-format on */
diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h
index 697d25653f8..3907c158573 100644
--- a/source/blender/makesdna/DNA_asset_types.h
+++ b/source/blender/makesdna/DNA_asset_types.h
@@ -20,6 +20,7 @@
#pragma once
+#include "DNA_defs.h"
#include "DNA_listBase.h"
#ifdef __cplusplus
@@ -36,6 +37,16 @@ typedef struct AssetTag {
char name[64]; /* MAX_NAME */
} AssetTag;
+#
+#
+typedef struct AssetFilterSettings {
+ /** Tags to match against. These are newly allocated, and compared against the
+ * #AssetMetaData.tags.
+ * TODO not used and doesn't do anything yet. */
+ ListBase tags; /* AssetTag */
+ uint64_t id_types; /* rna_enum_id_type_filter_items */
+} AssetFilterSettings;
+
/**
* \brief The meta-data of an asset.
* By creating and giving this for a data-block (#ID.asset_data), the data-block becomes an asset.
@@ -62,6 +73,52 @@ typedef struct AssetMetaData {
char _pad[4];
} AssetMetaData;
+typedef enum eAssetLibraryType {
+ /* For the future. Display assets bundled with Blender by default. */
+ // ASSET_LIBRARY_BUNDLED = 0,
+ /** Display assets from the current session (current "Main"). */
+ ASSET_LIBRARY_LOCAL = 1,
+ /* For the future. Display assets for the current project. */
+ // ASSET_LIBRARY_PROJECT = 2,
+
+ /** Display assets from custom asset libraries, as defined in the preferences
+ * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname
+ * then.
+ * In RNA, we add the index of the custom library to this to identify it by index. So keep
+ * this last! */
+ ASSET_LIBRARY_CUSTOM = 100,
+} eAssetLibraryType;
+
+/* TODO copy of FileSelectAssetLibraryUID */
+/**
+ * Information to identify a asset library. May be either one of the predefined types (current
+ * 'Main', builtin library, project library), or a custom type as defined in the Preferences.
+ *
+ * If the type is set to #ASSET_LIBRARY_CUSTOM, `custom_library_index` must be set to identify the
+ * custom library. Otherwise it is not used.
+ */
+typedef struct AssetLibraryReference {
+ short type; /* eAssetLibraryType */
+ char _pad1[2];
+ /**
+ * If showing a custom asset library (#ASSET_LIBRARY_CUSTOM), this is the index of the
+ * #bUserAssetLibrary within #UserDef.asset_libraries.
+ * Should be ignored otherwise (but better set to -1 then, for sanity and debugging).
+ */
+ int custom_library_index;
+} AssetLibraryReference;
+
+/**
+ * Not part of the core design, we should try to get rid of it. Only needed to wrap FileDirEntry
+ * into a type with PropertyGroup as base, so we can have an RNA collection of #AssetHandle's to
+ * pass to the UI.
+ */
+#
+#
+typedef struct AssetHandle {
+ struct FileDirEntry *file_data;
+} AssetHandle;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 1e4fd2a70f2..34f50b23c77 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -316,8 +316,9 @@ typedef struct bSameVolumeConstraint {
/* Copy Transform Constraint */
typedef struct bTransLikeConstraint {
struct Object *tar;
+ int flag;
char mix_mode;
- char _pad[7];
+ char _pad[3];
/** MAX_ID_NAME-2. */
char subtarget[64];
} bTransLikeConstraint;
@@ -740,6 +741,8 @@ typedef enum eBConstraint_SpaceTypes {
CONSTRAINT_SPACE_POSE = 2,
/** For posechannels - local with parent. */
CONSTRAINT_SPACE_PARLOCAL = 3,
+ /** For posechannels - local converted to the owner bone orientation. */
+ CONSTRAINT_SPACE_OWNLOCAL = 6,
/** For files from between 2.43-2.46 (should have been parlocal). */
CONSTRAINT_SPACE_INVALID = 4, /* do not exchange for anything! */
} eBConstraint_SpaceTypes;
@@ -810,6 +813,12 @@ typedef enum eCopyScale_Flags {
SIZELIKE_UNIFORM = (1 << 5),
} eCopyScale_Flags;
+/* bTransLikeConstraint.flag */
+typedef enum eCopyTransforms_Flags {
+ /* Remove shear from the target matrix. */
+ TRANSLIKE_REMOVE_TARGET_SHEAR = (1 << 0),
+} eCopyTransforms_Flags;
+
/* bTransLikeConstraint.mix_mode */
typedef enum eCopyTransforms_MixMode {
/* Replace rotation channel values. */
@@ -818,6 +827,14 @@ typedef enum eCopyTransforms_MixMode {
TRANSLIKE_MIX_BEFORE = 1,
/* Multiply the copied transformation on the right, with anti-shear scale handling. */
TRANSLIKE_MIX_AFTER = 2,
+ /* Multiply the copied transformation on the left, handling loc/rot/scale separately. */
+ TRANSLIKE_MIX_BEFORE_SPLIT = 3,
+ /* Multiply the copied transformation on the right, handling loc/rot/scale separately. */
+ TRANSLIKE_MIX_AFTER_SPLIT = 4,
+ /* Multiply the copied transformation on the left, using simple matrix multiplication. */
+ TRANSLIKE_MIX_BEFORE_FULL = 5,
+ /* Multiply the copied transformation on the right, using simple matrix multiplication. */
+ TRANSLIKE_MIX_AFTER_FULL = 6,
} eCopyTransforms_MixMode;
/* bTransformConstraint.to/from */
@@ -1179,13 +1196,6 @@ typedef enum eStretchTo_Flags {
STRETCHTOCON_USE_BULGE_MAX = (1 << 1),
} eStretchTo_Flags;
-/* important: these defines need to match up with PHY_DynamicTypes headerfile */
-#define CONSTRAINT_RB_BALL 1
-#define CONSTRAINT_RB_HINGE 2
-#define CONSTRAINT_RB_CONETWIST 4
-#define CONSTRAINT_RB_VEHICLE 11
-#define CONSTRAINT_RB_GENERIC6DOF 12
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index f6242679808..520fc6c1b00 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -35,6 +35,7 @@ extern "C" {
#define MAXTEXTBOX 256 /* used in readfile.c and editfont.c */
struct AnimData;
+struct CurveEval;
struct CurveProfile;
struct EditFont;
struct GHash;
@@ -43,7 +44,6 @@ struct Key;
struct Material;
struct Object;
struct VFont;
-struct CurveEval;
/* These two Lines with # tell makesdna this struct can be excluded. */
#
@@ -598,7 +598,7 @@ typedef enum eBezTriple_KeyframeType {
/* CharInfo.flag */
enum {
- /* note: CU_CHINFO_WRAP, CU_CHINFO_SMALLCAPS_TEST and CU_CHINFO_TRUNCATE are set dynamically */
+ /* NOTE: CU_CHINFO_WRAP, CU_CHINFO_SMALLCAPS_TEST and CU_CHINFO_TRUNCATE are set dynamically. */
CU_CHINFO_BOLD = 1 << 0,
CU_CHINFO_ITALIC = 1 << 1,
CU_CHINFO_UNDERLINE = 1 << 2,
diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h
index 01ee954d0d2..ef476f21458 100644
--- a/source/blender/makesdna/DNA_defs.h
+++ b/source/blender/makesdna/DNA_defs.h
@@ -31,7 +31,7 @@
# ifdef __GNUC__
# define DNA_DEPRECATED __attribute__((deprecated))
# else
-/* TODO, msvc & others */
+/* TODO: MSVC & others. */
# define DNA_DEPRECATED
# endif
# endif
diff --git a/source/blender/makesdna/DNA_fileglobal_types.h b/source/blender/makesdna/DNA_fileglobal_types.h
index dc43524a325..a0285215ff9 100644
--- a/source/blender/makesdna/DNA_fileglobal_types.h
+++ b/source/blender/makesdna/DNA_fileglobal_types.h
@@ -32,7 +32,7 @@ extern "C" {
* the moment of saving, and the file-specific settings.
*/
typedef struct FileGlobal {
- /** Needs to be here, for human fileformat recognition (keep first!). */
+ /** Needs to be here, for human file-format recognition (keep first!). */
char subvstr[4];
short subversion;
diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h
index 5e36c5673a4..cec6eb0d044 100644
--- a/source/blender/makesdna/DNA_fluid_types.h
+++ b/source/blender/makesdna/DNA_fluid_types.h
@@ -544,7 +544,7 @@ typedef struct FluidDomainSettings {
int boundary_width; /* Usually this is just 1. */
float gravity_final[3]; /* Scene or domain gravity multiplied with gravity weight. */
- /* -- User-accesible fields (from here on). -- */
+ /* -- User-accessible fields (from here on). -- */
/* Adaptive domain options. */
int adapt_margin;
@@ -640,7 +640,7 @@ typedef struct FluidDomainSettings {
/* Fluid guiding options. */
float guide_alpha; /* Guiding weight scalar (determines strength). */
- int guide_beta; /* Guiding blur radius (affects size of vortices). */
+ int guide_beta; /* Guiding blur radius (affects size of vortices vortices). */
float guide_vel_factor; /* Multiply guiding velocity by this factor. */
int guide_res[3]; /* Res for velocity guide grids - independent from base res. */
short guide_source;
@@ -790,7 +790,7 @@ typedef struct FluidFlowSettings {
float vel_coord[3];
char _pad1[4];
- /* -- User-accesible fields (from here on). -- */
+ /* -- User-accessible fields (from here on). -- */
/* Emission. */
float density;
@@ -856,7 +856,7 @@ typedef struct FluidEffectorSettings {
float *verts_old;
int numverts;
- /* -- User-accesible fields (from here on). -- */
+ /* -- User-accessible fields (from here on). -- */
float surface_distance; /* Thickness of mesh surface, used in obstacle sdf. */
int flags;
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h
index a4ab38f6022..b9697beeea9 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h
@@ -184,8 +184,6 @@
.layer_pass = 0, \
.hardeness = 1.0f, \
.curve_intensity = NULL, \
- .fading_end = 10.0f, \
- .fading_end_factor = 0.2f, \
}
#define _DNA_DEFAULT_SimplifyGpencilModifierData \
@@ -253,8 +251,6 @@
.thickness_fac = 1.0f, \
.thickness = 30, \
.layer_pass = 0, \
- .fading_end = 10.0f, \
- .fading_end_factor = 0.2f, \
}
#define _DNA_DEFAULT_TimeGpencilModifierData \
@@ -287,6 +283,20 @@
.colorband = NULL, \
}
+#define _DNA_DEFAULT_WeightGpencilModifierData \
+ { \
+ .target_vgname = "", \
+ .material = NULL, \
+ .layername = "", \
+ .vgname = "", \
+ .pass_index = 0, \
+ .flag = 0, \
+ .axis = 1, \
+ .layer_pass = 0, \
+ .dist_start = 0.0f, \
+ .dist_end = 20.0f, \
+ }
+
#define _DNA_DEFAULT_LineartGpencilModifierData \
{ \
.edge_types = LRT_EDGE_FLAG_ALL_TYPE, \
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 40e4c65c4b8..fac5bd3d4f4 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -55,6 +55,7 @@ typedef enum GpencilModifierType {
eGpencilModifierType_Texture = 18,
eGpencilModifierType_Lineart = 19,
eGpencilModifierType_Length = 20,
+ eGpencilModifierType_Weight = 21,
/* Keep last. */
NUM_GREASEPENCIL_MODIFIER_TYPES,
} GpencilModifierType;
@@ -188,12 +189,7 @@ typedef struct ThickGpencilModifierData {
int thickness;
/** Custom index for passes. */
int layer_pass;
- /** Start/end distances of the fading effect. */
- float fading_start;
- float fading_end;
- float fading_end_factor;
- /** Fading reference object */
- struct Object *object;
+ char _pad[4];
struct CurveMapping *curve_thickness;
} ThickGpencilModifierData;
@@ -205,7 +201,7 @@ typedef enum eThickGpencil_Flag {
GP_THICK_NORMALIZE = (1 << 4),
GP_THICK_INVERT_LAYERPASS = (1 << 5),
GP_THICK_INVERT_MATERIAL = (1 << 6),
- GP_THICK_FADING = (1 << 7),
+ GP_THICK_WEIGHT_FACTOR = (1 << 7),
} eThickGpencil_Flag;
typedef struct TimeGpencilModifierData {
@@ -298,16 +294,9 @@ typedef struct OpacityGpencilModifierData {
int flag;
/** Main Opacity factor. */
float factor;
- /** Fading controlling object */
- int _pad0;
- struct Object *object;
- /** Start/end distances of the fading effect. */
- float fading_start;
- float fading_end;
- float fading_end_factor;
/** Modify stroke, fill or both. */
char modify_color;
- char _pad1[3];
+ char _pad[3];
/** Custom index for passes. */
int layer_pass;
@@ -323,7 +312,7 @@ typedef enum eOpacityGpencil_Flag {
GP_OPACITY_INVERT_MATERIAL = (1 << 5),
GP_OPACITY_CUSTOM_CURVE = (1 << 6),
GP_OPACITY_NORMALIZE = (1 << 7),
- GP_OPACITY_FADING = (1 << 8),
+ GP_OPACITY_WEIGHT_FACTOR = (1 << 8),
} eOpacityGpencil_Flag;
typedef struct ArrayGpencilModifierData {
@@ -814,6 +803,7 @@ typedef enum eTintGpencil_Flag {
GP_TINT_INVERT_LAYERPASS = (1 << 4),
GP_TINT_INVERT_MATERIAL = (1 << 5),
GP_TINT_CUSTOM_CURVE = (1 << 6),
+ GP_TINT_WEIGHT_FACTOR = (1 << 7),
} eTintGpencil_Flag;
typedef struct TextureGpencilModifierData {
@@ -867,6 +857,61 @@ typedef enum eTextureGpencil_Mode {
STROKE_AND_FILL = 2,
} eTextureGpencil_Mode;
+typedef struct WeightGpencilModifierData {
+ GpencilModifierData modifier;
+ /** Target vertexgroup name, MAX_VGROUP_NAME. */
+ char target_vgname[64];
+ /** Material for filtering. */
+ struct Material *material;
+ /** Layer name. */
+ char layername[64];
+ /** Optional vertexgroup filter name, MAX_VGROUP_NAME. */
+ char vgname[64];
+ /** Custom index for passes. */
+ int pass_index;
+ /** Flags. */
+ int flag;
+ /** Minimum valid weight (clamp value). */
+ float min_weight;
+ /** Custom index for passes. */
+ int layer_pass;
+ /** Calculation Mode. */
+ short mode;
+ /** Axis. */
+ short axis;
+ /** Angle */
+ float angle;
+ /** Start/end distances. */
+ float dist_start;
+ float dist_end;
+ /** Space (Local/World). */
+ short space;
+ char _pad[6];
+
+ /** Reference object */
+ struct Object *object;
+} WeightGpencilModifierData;
+
+typedef enum eWeightGpencil_Flag {
+ GP_WEIGHT_INVERT_LAYER = (1 << 0),
+ GP_WEIGHT_INVERT_PASS = (1 << 1),
+ GP_WEIGHT_INVERT_VGROUP = (1 << 2),
+ GP_WEIGHT_INVERT_LAYERPASS = (1 << 3),
+ GP_WEIGHT_INVERT_MATERIAL = (1 << 4),
+ GP_WEIGHT_BLEND_DATA = (1 << 5),
+ GP_WEIGHT_INVERT_OUTPUT = (1 << 6),
+} eWeightGpencil_Flag;
+
+typedef enum eWeightGpencilModifierMode {
+ GP_WEIGHT_MODE_DISTANCE = 0,
+ GP_WEIGHT_MODE_ANGLE = 1,
+} eWeightGpencilModifierMode;
+
+typedef enum eGpencilModifierSpace {
+ GP_SPACE_LOCAL = 0,
+ GP_SPACE_WORLD = 1,
+} eGpencilModifierSpace;
+
typedef enum eLineartGpencilModifierSource {
LRT_SOURCE_COLLECTION = 0,
LRT_SOURCE_OBJECT = 1,
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index d0ae50d09ef..380d8ad1249 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -33,8 +33,8 @@ extern "C" {
struct AnimData;
struct Curve;
-struct MDeformVert;
struct Curve;
+struct MDeformVert;
#define GP_DEFAULT_PIX_FACTOR 1.0f
#define GP_DEFAULT_GRID_LINES 4
@@ -246,11 +246,11 @@ typedef struct bGPDstroke_Runtime {
/** Runtime falloff factor (only for transform). */
float multi_frame_falloff;
- /** Vertex offset in the vbo where this stroke starts. */
+ /** Vertex offset in the VBO where this stroke starts. */
int stroke_start;
/** Triangle offset in the ibo where this fill starts. */
int fill_start;
- /** Curve Handles offset in the ibo where this handle starts. */
+ /** Curve Handles offset in the IBO where this handle starts. */
int curve_start;
/** Original stroke (used to dereference evaluated data) */
@@ -666,6 +666,9 @@ typedef struct bGPdata {
/** List of bGPDpalette's - Deprecated (2.78 - 2.79 only). */
ListBase palettes DNA_DEPRECATED;
+ /** List of bDeformGroup names and flag only. */
+ ListBase vertex_group_names;
+
/* 3D Viewport/Appearance Settings */
/** Factor to define pixel size conversion. */
float pixfactor;
@@ -715,7 +718,8 @@ typedef struct bGPdata {
/** Stroke selection last index. Used to generate a unique selection index. */
int select_last_index;
- char _pad3[4];
+
+ int vertex_group_active_index;
bGPgrid grid;
diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h
index 48eb8d90702..361893db893 100644
--- a/source/blender/makesdna/DNA_lattice_types.h
+++ b/source/blender/makesdna/DNA_lattice_types.h
@@ -72,6 +72,11 @@ typedef struct Lattice {
struct MDeformVert *dvert;
/** Multiply the influence, MAX_VGROUP_NAME. */
char vgroup[64];
+ /** List of bDeformGroup names and flag only. */
+ ListBase vertex_group_names;
+ int vertex_group_active_index;
+
+ char _pad0[4];
struct EditLatt *editlatt;
void *batch_cache;
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 144e4594c98..c54c086affd 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -164,8 +164,10 @@ typedef struct Mesh {
struct MVert *mvert;
/** Array of edges. */
struct MEdge *medge;
- /** Deformgroup vertices. */
+ /** Deform-group vertices. */
struct MDeformVert *dvert;
+ /** List of bDeformGroup names and flag only. */
+ ListBase vertex_group_names;
/* array of colors for the tessellated faces, must be number of tessellated
* faces * 4 in length */
@@ -189,7 +191,7 @@ typedef struct Mesh {
/* END BMESH ONLY */
int attributes_active_index;
- int _pad3;
+ int vertex_group_active_index;
/* the last selected vertex/edge/face are used for the active face however
* this means the active face must always be selected, this is to keep track
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 346e65f0fa1..bc6b35c8e43 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -151,7 +151,7 @@ enum {
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Loop Tesselation Runtime Data
+/** \name Loop Tessellation Runtime Data
* \{ */
/**
diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h
index f6dac88051b..1b3dbd148df 100644
--- a/source/blender/makesdna/DNA_modifier_defaults.h
+++ b/source/blender/makesdna/DNA_modifier_defaults.h
@@ -647,7 +647,8 @@
.target = NULL, \
.verts = NULL, \
.falloff = 4.0f, \
- .numverts = 0, \
+ .num_mesh_verts = 0, \
+ .num_bind_verts = 0, \
.numpoly = 0, \
.flags = 0, \
.mat = _DNA_DEFAULT_UNIT_M4, \
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index dfe49452636..401b49f2ee8 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1840,7 +1840,7 @@ typedef struct CorrectiveSmoothModifierData {
* use for MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND */
float (*bind_coords)[3];
- /* note: -1 is used to bind */
+ /* NOTE: -1 is used to bind. */
unsigned int bind_coords_num;
float lambda, scale;
@@ -2180,7 +2180,7 @@ typedef struct SDefBind {
typedef struct SDefVert {
SDefBind *binds;
unsigned int numbinds;
- char _pad[4];
+ unsigned int vertex_idx;
} SDefVert;
typedef struct SurfaceDeformModifierData {
@@ -2192,11 +2192,10 @@ typedef struct SurfaceDeformModifierData {
/** Vertex bind data. */
SDefVert *verts;
float falloff;
- unsigned int numverts, numpoly;
+ unsigned int num_mesh_verts, num_bind_verts, numpoly;
int flags;
float mat[4][4];
float strength;
- char _pad[4];
char defgrp_name[64];
} SurfaceDeformModifierData;
@@ -2204,10 +2203,9 @@ typedef struct SurfaceDeformModifierData {
enum {
/* This indicates "do bind on next modifier evaluation" as well as "is bound". */
MOD_SDEF_BIND = (1 << 0),
- MOD_SDEF_INVERT_VGROUP = (1 << 1)
-
- /* MOD_SDEF_USES_LOOPTRI = (1 << 1), */ /* UNUSED */
- /* MOD_SDEF_HAS_CONCAVE = (1 << 2), */ /* UNUSED */
+ MOD_SDEF_INVERT_VGROUP = (1 << 1),
+ /* Only store bind data for nonzero vgroup weights at the time of bind. */
+ MOD_SDEF_SPARSE_BIND = (1 << 2),
};
/* Surface Deform vertex bind modes */
@@ -2256,6 +2254,10 @@ typedef struct NodesModifierData {
ModifierData modifier;
struct bNodeTree *node_group;
struct NodesModifierSettings settings;
+
+ /* Contains logged information from the last evaluation. This can be used to help the user to
+ * debug a node tree. */
+ void *runtime_eval_log;
} NodesModifierData;
typedef struct MeshToVolumeModifierData {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 4e0fb64cf1f..d05fb6b4168 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -37,7 +37,8 @@ struct Collection;
struct ID;
struct Image;
struct ListBase;
-struct NodeTreeUIStorage;
+struct Material;
+struct Tex;
struct bGPdata;
struct bNodeInstanceHash;
struct bNodeLink;
@@ -45,8 +46,6 @@ struct bNodePreview;
struct bNodeTreeExec;
struct bNodeType;
struct uiBlock;
-struct Tex;
-struct Material;
#define NODE_MAXSTR 64
@@ -326,6 +325,7 @@ typedef struct bNode {
#define NODE_HIDDEN 8
#define NODE_ACTIVE 16
#define NODE_ACTIVE_ID 32
+/* Used to indicate which group output node is used and which viewer node is active. */
#define NODE_DO_OUTPUT 64
#define __NODE_GROUP_EDIT 128 /* DEPRECATED */
/* free test flag, undefined */
@@ -341,7 +341,7 @@ typedef struct bNode {
#define NODE_TRANSFORM (1 << 13)
/* node is active texture */
-/* note: take care with this flag since its possible it gets
+/* NOTE: take care with this flag since its possible it gets
* `stuck` inside/outside the active group - which makes buttons
* window texture not update, we try to avoid it by clearing the
* flag when toggling group editing - Campbell */
@@ -360,7 +360,7 @@ typedef struct bNode {
*/
#define NODE_DO_OUTPUT_RECALC (1 << 17)
/* A preview for the data in this node can be displayed in the spreadsheet editor. */
-#define NODE_ACTIVE_PREVIEW (1 << 18)
+#define __NODE_ACTIVE_PREVIEW (1 << 18) /* deprecated */
/* node->update */
/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates
@@ -516,8 +516,6 @@ typedef struct bNodeTree {
int (*test_break)(void *);
void (*update_draw)(void *);
void *tbh, *prh, *sdh, *udh;
-
- struct NodeTreeUIStorage *ui_storage;
} bNodeTree;
/* ntree->type, index */
@@ -1380,6 +1378,11 @@ typedef struct NodeSwitch {
uint8_t input_type;
} NodeSwitch;
+typedef struct NodeGeometryCurvePrimitiveLine {
+ /* GeometryNodeCurvePrimitiveLineMode. */
+ uint8_t mode;
+} NodeGeometryCurvePrimitiveLine;
+
typedef struct NodeGeometryCurvePrimitiveBezierSegment {
/* GeometryNodeCurvePrimitiveBezierSegmentMode. */
uint8_t mode;
@@ -1390,6 +1393,11 @@ typedef struct NodeGeometryCurvePrimitiveCircle {
uint8_t mode;
} NodeGeometryCurvePrimitiveCircle;
+typedef struct NodeGeometryCurvePrimitiveQuad {
+ /* GeometryNodeCurvePrimitiveQuadMode. */
+ uint8_t mode;
+} NodeGeometryCurvePrimitiveQuad;
+
typedef struct NodeGeometryCurveResample {
/* GeometryNodeCurveSampleMode. */
uint8_t mode;
@@ -1710,6 +1718,14 @@ typedef enum FloatCompareOperation {
NODE_FLOAT_COMPARE_NOT_EQUAL = 5,
} FloatCompareOperation;
+/* Float to Int node operations. */
+typedef enum FloatToIntRoundingMode {
+ FN_NODE_FLOAT_TO_INT_ROUND = 0,
+ FN_NODE_FLOAT_TO_INT_FLOOR = 1,
+ FN_NODE_FLOAT_TO_INT_CEIL = 2,
+ FN_NODE_FLOAT_TO_INT_TRUNCATE = 3,
+} FloatToIntRoundingMode;
+
/* Clamp node types. */
enum {
NODE_CLAMP_MINMAX = 0,
@@ -1927,6 +1943,19 @@ typedef enum GeometryNodeMeshLineCountMode {
GEO_NODE_MESH_LINE_COUNT_RESOLUTION = 1,
} GeometryNodeMeshLineCountMode;
+typedef enum GeometryNodeCurvePrimitiveLineMode {
+ GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS = 0,
+ GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION = 1
+} GeometryNodeCurvePrimitiveLineMode;
+
+typedef enum GeometryNodeCurvePrimitiveQuadMode {
+ GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE = 0,
+ GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM = 1,
+ GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID = 2,
+ GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE = 3,
+ GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS = 4,
+} GeometryNodeCurvePrimitiveQuadMode;
+
typedef enum GeometryNodeCurvePrimitiveBezierSegmentMode {
GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT_POSITION = 0,
GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT_OFFSET = 1,
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 8d861647bd2..dd31e85647d 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -172,12 +172,6 @@ typedef struct Object_Runtime {
struct GeometrySet *geometry_set_eval;
/**
- * A GHash that contains geometry sets for intermediate stages of evaluation. The keys are just a
- * hash and are not owned by the map. The geometry sets are owned.
- */
- void *geometry_set_previews;
-
- /**
* Mesh structure created during object evaluation.
* It has deformation only modifiers applied on it.
*/
@@ -278,8 +272,7 @@ typedef struct Object {
ListBase constraintChannels DNA_DEPRECATED; /* XXX deprecated... old animation system */
ListBase effect DNA_DEPRECATED; /* XXX deprecated... keep for readfile */
- /** List of bDeformGroup (vertex groups) names and flag only. */
- ListBase defbase;
+ ListBase defbase DNA_DEPRECATED; /* Only for versioning, moved to object data. */
/** List of ModifierData structures. */
ListBase modifiers;
/** List of GpencilModifierData structures. */
@@ -335,12 +328,6 @@ typedef struct Object {
*/
float imat[4][4];
- /* Previously 'imat' was used at render time, but as other places use it too
- * the interactive ui of 2.5 creates problems. So now only 'imat_ren' should
- * be used when ever the inverse of ob->obmat * re->viewmat is needed! - jahka
- */
- float imat_ren[4][4];
-
/** Copy of Base's layer in the scene. */
unsigned int lay DNA_DEPRECATED;
@@ -386,9 +373,9 @@ typedef struct Object {
/** Custom index, for renderpasses. */
short index;
- /** Current deformation group, note: index starts at 1. */
- unsigned short actdef;
- /** Current face map, note: index starts at 1. */
+ /** Current deformation group, NOTE: index starts at 1. */
+ unsigned short actdef DNA_DEPRECATED;
+ /** Current face map, NOTE: index starts at 1. */
unsigned short actfmap;
char _pad2[2];
/** Object color (in most cases the material color is used for drawing). */
@@ -711,7 +698,7 @@ enum {
/* OB_ADS_SHOWCONS = 1 << 12, */ /* UNUSED */
/* object's material channels */
/* OB_ADS_SHOWMATS = 1 << 13, */ /* UNUSED */
- /* object's marticle channels */
+ /* object's particle channels */
/* OB_ADS_SHOWPARTS = 1 << 14, */ /* UNUSED */
};
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 7a39e0caef3..ebf3d4a248c 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -106,7 +106,7 @@ typedef enum eTreeStoreElemType {
TSE_R_LAYER = 20,
/* TSE_R_PASS = 21, */ /* UNUSED */
/* TSE_LINKED_MAT = 22, */
- /* NOTE, is used for light group */
+ /* NOTE: is used for light group. */
/* TSE_LINKED_LAMP = 23, */
TSE_POSEGRP_BASE = 24,
TSE_POSEGRP = 25,
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 0253de9f9d1..a51c532dfb3 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -74,8 +74,9 @@ typedef struct ParticleSpring {
/* Child particles are created around or between parent particles */
typedef struct ChildParticle {
- /** Num is face index on the final derived mesh. */
- int num, parent;
+ /** Face index on the final derived mesh. */
+ int num;
+ int parent;
/** Nearest particles to the child, used for the interpolation. */
int pa[4];
/** Interpolation weights for the above particles. */
diff --git a/source/blender/makesdna/DNA_pointcache_types.h b/source/blender/makesdna/DNA_pointcache_types.h
index ad5f386bf2b..7de0bb29c46 100644
--- a/source/blender/makesdna/DNA_pointcache_types.h
+++ b/source/blender/makesdna/DNA_pointcache_types.h
@@ -131,32 +131,34 @@ typedef struct PointCache {
void (*free_edit)(struct PTCacheEdit *edit);
} PointCache;
-/* pointcache->flag */
-#define PTCACHE_BAKED (1 << 0)
-#define PTCACHE_OUTDATED (1 << 1)
-#define PTCACHE_SIMULATION_VALID (1 << 2)
-#define PTCACHE_BAKING (1 << 3)
-//#define PTCACHE_BAKE_EDIT (1 << 4)
-//#define PTCACHE_BAKE_EDIT_ACTIVE (1 << 5)
-#define PTCACHE_DISK_CACHE (1 << 6)
-///* removed since 2.64 - T30974, could be added back in a more useful way */
-//#define PTCACHE_QUICK_CACHE (1 << 7)
-#define PTCACHE_FRAMES_SKIPPED (1 << 8)
-#define PTCACHE_EXTERNAL (1 << 9)
-#define PTCACHE_READ_INFO (1 << 10)
-/** don't use the filename of the blendfile the data is linked from (write a local cache) */
-#define PTCACHE_IGNORE_LIBPATH (1 << 11)
-/**
- * High resolution cache is saved for smoke for backwards compatibility,
- * so set this flag to know it's a "fake" cache.
- */
-#define PTCACHE_FAKE_SMOKE (1 << 12)
-#define PTCACHE_IGNORE_CLEAR (1 << 13)
+enum {
+ /* pointcache->flag */
+ PTCACHE_BAKED = 1 << 0,
+ PTCACHE_OUTDATED = 1 << 1,
+ PTCACHE_SIMULATION_VALID = 1 << 2,
+ PTCACHE_BAKING = 1 << 3,
+ // PTCACHE_BAKE_EDIT = 1 << 4,
+ // PTCACHE_BAKE_EDIT_ACTIVE = 1 << 5,
+ PTCACHE_DISK_CACHE = 1 << 6,
+ /* removed since 2.64 - T30974, could be added back in a more useful way */
+ // PTCACHE_QUICK_CACHE = 1 << 7,
+ PTCACHE_FRAMES_SKIPPED = 1 << 8,
+ PTCACHE_EXTERNAL = 1 << 9,
+ PTCACHE_READ_INFO = 1 << 10,
+ /** Don't use the filename of the blend-file the data is linked from (write a local cache). */
+ PTCACHE_IGNORE_LIBPATH = 1 << 11,
+ /**
+ * High resolution cache is saved for smoke for backwards compatibility,
+ * so set this flag to know it's a "fake" cache.
+ */
+ PTCACHE_FAKE_SMOKE = 1 << 12,
+ PTCACHE_IGNORE_CLEAR = 1 << 13,
-#define PTCACHE_FLAG_INFO_DIRTY (1 << 14)
+ PTCACHE_FLAG_INFO_DIRTY = 1 << 14,
-/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
-#define PTCACHE_REDO_NEEDED 258
+ PTCACHE_REDO_NEEDED = PTCACHE_OUTDATED | PTCACHE_FRAMES_SKIPPED,
+ PTCACHE_FLAGS_COPY = PTCACHE_DISK_CACHE | PTCACHE_EXTERNAL | PTCACHE_IGNORE_LIBPATH,
+};
#define PTCACHE_COMPRESS_NO 0
#define PTCACHE_COMPRESS_LZO 1
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
index 740dc35517a..1d5e5eeed31 100644
--- a/source/blender/makesdna/DNA_rigidbody_types.h
+++ b/source/blender/makesdna/DNA_rigidbody_types.h
@@ -206,12 +206,12 @@ typedef enum eRigidBody_Shape {
RB_SHAPE_SPHERE = 1,
/** Rounded "pill" shape (i.e. calcium tablets). */
RB_SHAPE_CAPSULE = 2,
- /** Cylinder (i.e. pringles can). */
+ /** Cylinder (i.e. tin of beans). */
RB_SHAPE_CYLINDER = 3,
/** Cone (i.e. party hat). */
RB_SHAPE_CONE = 4,
- /** Convex hull (minimal shrinkwrap encompassing all verts). */
+ /** Convex hull (minimal shrink-wrap encompassing all verts). */
RB_SHAPE_CONVEXH = 5,
/** Triangulated mesh. */
RB_SHAPE_TRIMESH = 6,
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index d40de4184b6..cd752b220a3 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -25,7 +25,7 @@
#include "DNA_defs.h"
-/* XXX, temp feature - campbell */
+/* XXX(campbell): temp feature. */
#define DURIAN_CAMERA_SWITCH
/* check for cyclic set-scene,
@@ -397,7 +397,7 @@ typedef enum eStereo3dInterlaceType {
/* Generic image format settings,
* this is used for NodeImageFile and IMAGE_OT_save_as operator too.
*
- * note: its a bit strange that even though this is an image format struct
+ * NOTE: its a bit strange that even though this is an image format struct
* the imtype can still be used to select video formats.
* RNA ensures these enum's are only selectable for render output.
*/
@@ -2069,6 +2069,7 @@ enum {
/** #SequencerToolSettings.snap_flag */
#define SEQ_SNAP_IGNORE_MUTED (1 << 0)
#define SEQ_SNAP_IGNORE_SOUND (1 << 1)
+#define SEQ_SNAP_CURRENT_FRAME_TO_STRIPS (1 << 2)
/** #ToolSettings.snap_node_mode */
#define SCE_SNAP_MODE_NODE_X (1 << 0)
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index ce25f8e40b7..5bd9cc7a999 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -43,23 +43,25 @@ struct SpaceLink;
struct SpaceType;
struct uiBlock;
struct uiLayout;
+struct uiList;
struct wmDrawBuffer;
struct wmTimer;
struct wmTooltipState;
-/* TODO Doing this is quite ugly :)
+/* TODO: Doing this is quite ugly :)
* Once the top-bar is merged bScreen should be refactored to use ScrAreaMap. */
#define AREAMAP_FROM_SCREEN(screen) ((ScrAreaMap *)&(screen)->vertbase)
typedef struct bScreen {
ID id;
- /* TODO Should become ScrAreaMap now.
- * ** NOTE: KEEP ORDER IN SYNC WITH ScrAreaMap! (see AREAMAP_FROM_SCREEN macro above) ** */
+ /* TODO: Should become ScrAreaMap now.
+ * NOTE: KEEP ORDER IN SYNC WITH #ScrAreaMap! (see AREAMAP_FROM_SCREEN macro above). */
/** Screens have vertices/edges to define areas. */
ListBase vertbase;
ListBase edgebase;
ListBase areabase;
+ /* End variables that must be in sync with #ScrAreaMap. */
/** Screen level regions (menus), runtime only. */
ListBase regionbase;
@@ -245,11 +247,16 @@ typedef struct PanelCategoryStack {
char idname[64];
} PanelCategoryStack;
+typedef void (*uiListFreeRuntimeDataFunc)(struct uiList *ui_list);
+
/* uiList dynamic data... */
/* These two Lines with # tell makesdna this struct can be excluded. */
#
#
typedef struct uiListDyn {
+ /** Callback to free UI data when freeing UI-Lists in BKE. */
+ uiListFreeRuntimeDataFunc free_runtime_data_fn;
+
/** Number of rows needed to draw all elements. */
int height;
/** Actual visual height of the list (in rows). */
@@ -257,6 +264,9 @@ typedef struct uiListDyn {
/** Minimal visual height of the list (in rows). */
int visual_height_min;
+ /** Number of columns drawn for grid layouts. */
+ int columns;
+
/** Number of items in collection. */
int items_len;
/** Number of items actually visible after filtering. */
@@ -269,11 +279,19 @@ typedef struct uiListDyn {
int resize;
int resize_prev;
+ /** Allocated custom data. Freed together with the #uiList (and when re-assigning). */
+ void *customdata;
+
/* Filtering data. */
/** Items_len length. */
int *items_filter_flags;
/** Org_idx -> new_idx, items_len length. */
int *items_filter_neworder;
+
+ struct wmOperatorType *custom_drag_optype;
+ struct PointerRNA *custom_drag_opptr;
+ struct wmOperatorType *custom_activate_optype;
+ struct PointerRNA *custom_activate_opptr;
} uiListDyn;
typedef struct uiList { /* some list UI data need to be saved in file */
@@ -300,6 +318,12 @@ typedef struct uiList { /* some list UI data need to be saved in file */
int filter_flag;
int filter_sort_flag;
+ /** Operator executed when activating an item. */
+ const char *custom_activate_opname;
+ /** Operator executed when dragging an item (item gets activated too, without running
+ * custom_activate_opname above). */
+ const char *custom_drag_opname;
+
/* Custom sub-classes properties. */
IDProperty *properties;
@@ -583,6 +607,7 @@ enum {
UILST_LAYOUT_DEFAULT = 0,
UILST_LAYOUT_COMPACT = 1,
UILST_LAYOUT_GRID = 2,
+ UILST_LAYOUT_BIG_PREVIEW_GRID = 3,
};
/** #uiList.flag */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 1bd4c9233e3..55dc51e0632 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -43,9 +43,9 @@ extern "C" {
struct Ipo;
struct MovieClip;
struct Scene;
+struct SequenceLookup;
struct VFont;
struct bSound;
-struct SequenceLookup;
/* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 556a9e48de5..b990de29ff3 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -448,7 +448,7 @@ typedef struct SpaceGraph {
/** Mode for the Graph editor (eGraphEdit_Mode). */
short mode;
/**
- * Time-transform autosnapping settings for Graph editor
+ * Time-transform auto-snapping settings for Graph editor
* (eAnimEdit_AutoSnap in DNA_action_types.h).
*/
short autosnap;
@@ -700,14 +700,14 @@ typedef enum eSpaceSeq_OverlayType {
* Information to identify a asset library. May be either one of the predefined types (current
* 'Main', builtin library, project library), or a custom type as defined in the Preferences.
*
- * If the type is set to #FILE_ASSET_LIBRARY_CUSTOM, idname must have the name to identify the
+ * If the type is set to #ASSET_LIBRARY_CUSTOM, idname must have the name to identify the
* custom library. Otherwise idname is not used.
*/
typedef struct FileSelectAssetLibraryUID {
short type; /* eFileAssetLibrary_Type */
char _pad[2];
/**
- * If showing a custom asset library (#FILE_ASSET_LIBRARY_CUSTOM), this is the index of the
+ * If showing a custom asset library (#ASSET_LIBRARY_CUSTOM), this is the index of the
* #bUserAssetLibrary within #UserDef.asset_libraries.
* Should be ignored otherwise (but better set to -1 then, for sanity and debugging).
*/
@@ -727,6 +727,12 @@ typedef struct FileSelectParams {
char renamefile[256];
short rename_flag;
+ char _pad[4];
+ /** An ID that was just renamed. Used to identify a renamed asset file over re-reads, similar to
+ * `renamefile` but for local IDs (takes precedence). Don't keep this stored across handlers!
+ * Would break on undo. */
+ const ID *rename_id;
+ void *_pad3;
/** List of filetypes to filter (FILE_MAXFILE). */
char filter_glob[256];
@@ -734,7 +740,6 @@ typedef struct FileSelectParams {
/** Text items name must match to be shown. */
char filter_search[64];
/** Same as filter, but for ID types (aka library groups). */
- int _pad0;
uint64_t filter_id;
/** Active file used for keyboard navigation. */
@@ -880,22 +885,6 @@ typedef enum eFileBrowse_Mode {
FILE_BROWSE_MODE_ASSETS = 1,
} eFileBrowse_Mode;
-typedef enum eFileAssetLibrary_Type {
- /* For the future. Display assets bundled with Blender by default. */
- // FILE_ASSET_LIBRARY_BUNDLED = 0,
- /** Display assets from the current session (current "Main"). */
- FILE_ASSET_LIBRARY_LOCAL = 1,
- /* For the future. Display assets for the current project. */
- // FILE_ASSET_LIBRARY_PROJECT = 2,
-
- /** Display assets from custom asset libraries, as defined in the preferences
- * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname
- * then.
- * In RNA, we add the index of the custom library to this to identify it by index. So keep
- * this last! */
- FILE_ASSET_LIBRARY_CUSTOM = 100,
-} eFileAssetLibrary_Type;
-
/* FileSelectParams.display */
enum eFileDisplayType {
/** Internal (not exposed to users): Keep whatever display type was used during the last File
@@ -987,7 +976,7 @@ typedef enum eFileSel_Params_Flag {
} eFileSel_Params_Flag;
/* sfile->params->rename_flag */
-/* Note: short flag. Defined as bitflags, but currently only used as exclusive status markers... */
+/* NOTE: short flag. Defined as bitflags, but currently only used as exclusive status markers... */
typedef enum eFileSel_Params_RenameFlag {
/** Used when we only have the name of the entry we want to rename,
* but not yet access to its matching file entry. */
@@ -1043,82 +1032,25 @@ typedef enum eDirEntry_SelectFlag {
/* ***** Related to file browser, but never saved in DNA, only here to help with RNA. ***** */
-/**
- * About Unique identifier.
- *
- * Stored in a CustomProps once imported.
- * Each engine is free to use it as it likes - it will be the only thing passed to it by blender to
- * identify asset/variant/version (concatenating the three into a single 48 bytes one).
- * Assumed to be 128bits, handled as four integers due to lack of real bytes proptype in RNA :|.
- */
-#define ASSET_UUID_LENGTH 16
-
-/* Used to communicate with asset engines outside of 'import' context. */
-#
-#
-typedef struct AssetUUID {
- int uuid_asset[4];
- int uuid_variant[4];
- int uuid_revision[4];
-} AssetUUID;
-
-#
-#
-typedef struct AssetUUIDList {
- AssetUUID *uuids;
- int nbr_uuids;
- char _pad[4];
-} AssetUUIDList;
-
-/* Container for a revision, only relevant in asset context. */
-#
-#
-typedef struct FileDirEntryRevision {
- struct FileDirEntryRevision *next, *prev;
-
- char *comment;
- void *_pad;
-
- int uuid[4];
-
- uint64_t size;
- int64_t time;
- /* Temp caching of UI-generated strings... */
- char size_str[16];
- char datetime_str[16 + 8];
-} FileDirEntryRevision;
-
-/* Container for a variant, only relevant in asset context.
- * In case there are no variants, a single one shall exist, with NULL name/description. */
-#
-#
-typedef struct FileDirEntryVariant {
- struct FileDirEntryVariant *next, *prev;
-
- int uuid[4];
- char *name;
- char *description;
-
- ListBase revisions;
- int nbr_revisions;
- int act_revision;
-} FileDirEntryVariant;
-
-/* Container for mere direntry, with additional asset-related data. */
#
#
typedef struct FileDirEntry {
struct FileDirEntry *next, *prev;
- int uuid[4];
+ uint32_t uid; /* FileUID */
/* Name needs freeing if FILE_ENTRY_NAME_FREE is set. Otherwise this is a direct pointer to a
* name buffer. */
char *name;
char *description;
- /* Either point to active variant/revision if available, or own entry
- * (in mere filebrowser case). */
- FileDirEntryRevision *entry;
+ uint64_t size;
+ int64_t time;
+
+ struct {
+ /* Temp caching of UI-generated strings. */
+ char size_str[16];
+ char datetime_str[16 + 8];
+ } draw_data;
/** #eFileSel_File_Types. */
int typeflag;
@@ -1141,32 +1073,16 @@ typedef struct FileDirEntry {
/* The icon_id for the preview image. */
int preview_icon_id;
- /* Tags are for info only, most of filtering is done in asset engine. */
- char **tags;
- int nbr_tags;
-
- short status;
short flags;
/* eFileAttributes defined in BLI_fileops.h */
int attributes;
-
- ListBase variants;
- int nbr_variants;
- int act_variant;
} FileDirEntry;
/**
- * Array of direntries.
- *
- * This struct is used in various, different contexts.
- *
- * In Filebrowser UI, it stores the total number of available entries, the number of visible
- * (filtered) entries, and a subset of those in 'entries' ListBase, from idx_start (included)
- * to idx_end (excluded).
+ * Array of directory entries.
*
- * In AssetEngine context (i.e. outside of 'browsing' context), entries contain all needed data,
- * there is no filtering, so nbr_entries_filtered, entry_idx_start and entry_idx_end
- * should all be set to -1.
+ * Stores the total number of available entries, the number of visible (filtered) entries, and a
+ * subset of those in 'entries' ListBase, from idx_start (included) to idx_end (excluded).
*/
#
#
@@ -1180,14 +1096,6 @@ typedef struct FileDirEntryArr {
char root[1024];
} FileDirEntryArr;
-#if 0 /* UNUSED */
-/* FileDirEntry.status */
-enum {
- ASSET_STATUS_LOCAL = 1 << 0, /* If active uuid is available locally/immediately. */
- ASSET_STATUS_LATEST = 1 << 1, /* If active uuid is latest available version. */
-};
-#endif
-
/* FileDirEntry.flags */
enum {
FILE_ENTRY_INVALID_PREVIEW = 1 << 0, /* The preview for this entry could not be generated. */
@@ -2003,6 +1911,7 @@ typedef enum eSpreadsheetFilterOperation {
typedef enum eSpaceSpreadsheet_ObjectEvalState {
SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED = 0,
SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1,
+ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE = 2,
} eSpaceSpreadsheet_Context;
typedef enum eSpaceSpreadsheet_ContextType {
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 60c255e8637..2308f04c4c7 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -219,10 +219,12 @@ typedef struct Tex {
} Tex;
-/* used for mapping and texture nodes. note: rot is now in radians */
-
+/** Used for mapping and texture nodes. */
typedef struct TexMapping {
- float loc[3], rot[3], size[3];
+ float loc[3];
+ /** Rotation in radians. */
+ float rot[3];
+ float size[3];
int flag;
char projx, projy, projz, mapping;
int type;
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 7abd960c467..629aa191890 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -261,7 +261,7 @@ typedef struct ThemeSpace {
/** Region background. */
unsigned char execution_buts[4];
- /* note, cannot use name 'panel' because of DNA mapping old files */
+ /* NOTE: cannot use name 'panel' because of DNA mapping old files. */
uiPanelColors panelcolors;
unsigned char shade1[4];
diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h
index bc1a71102da..e782f7914b5 100644
--- a/source/blender/makesdna/DNA_vfont_types.h
+++ b/source/blender/makesdna/DNA_vfont_types.h
@@ -45,7 +45,7 @@ typedef struct VFont {
struct PackedFile *packedfile;
/* runtime only, holds memory for freetype to read from
- * TODO, replace this with blf_font_new() style loading */
+ * TODO: replace this with #blf_font_new() style loading. */
struct PackedFile *temp_pf;
} VFont;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 80de5ae3b7c..08b29c82707 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -69,7 +69,7 @@ typedef struct RegionView3D {
float clip_local[6][4];
struct BoundBox *clipbb;
- /** Allocated backup of its self while in localview. */
+ /** Allocated backup of its self while in local-view. */
struct RegionView3D *localvd;
struct RenderEngine *render_engine;
@@ -257,7 +257,7 @@ typedef struct View3D_Runtime {
int flag;
char _pad1[4];
- /* Only used for overlay stats while in localview. */
+ /* Only used for overlay stats while in local-view. */
struct SceneStats *local_stats;
} View3D_Runtime;
@@ -295,7 +295,7 @@ typedef struct View3D {
struct Object *camera, *ob_center;
rctf render_border;
- /** Allocated backup of its self while in localview. */
+ /** Allocated backup of its self while in local-view. */
struct View3D *localvd;
/** Optional string for armature bone to define center, MAXBONENAME. */
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 59091fec4b8..94e89944f08 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -217,8 +217,8 @@ enum {
#define WM_KEYCONFIG_STR_DEFAULT "Blender"
-/* IME is win32 only! */
-#if !defined(WIN32) && !defined(DNA_DEPRECATED)
+/* IME is win32 and apple only! */
+#if !(defined(WIN32) || defined(__APPLE__)) && !defined(DNA_DEPRECATED)
# ifdef __GNUC__
# define ime_data ime_data __attribute__((deprecated))
# endif
@@ -302,7 +302,7 @@ typedef struct wmWindow {
struct wmGesture *tweak;
/* Input Method Editor data - complex character input (especially for Asian character input)
- * Currently WIN32, runtime-only data. */
+ * Currently WIN32 and APPLE, runtime-only data. */
struct wmIMEData *ime_data;
/** All events #wmEvent (ghost level events were handled). */
@@ -366,7 +366,7 @@ typedef struct wmKeyMapItem {
short type;
/** KM_ANY, KM_PRESS, KM_NOTHING etc. */
short val;
- /** Oskey is apple or windowskey, value denotes order of pressed. */
+ /** `oskey` also known as apple, windows-key or super, value denotes order of pressed. */
short shift, ctrl, alt, oskey;
/** Raw-key modifier. */
short keymodifier;
@@ -553,7 +553,7 @@ enum {
/* in case operator got executed outside WM code... like via fileselect */
OPERATOR_HANDLED = (1 << 4),
/* used for operators that act indirectly (eg. popup menu)
- * note: this isn't great design (using operators to trigger UI) avoid where possible. */
+ * NOTE: this isn't great design (using operators to trigger UI) avoid where possible. */
OPERATOR_INTERFACE = (1 << 5),
};
#define OPERATOR_FLAGS_ALL \
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index c5c2351c718..9ed01a7dbcc 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -23,6 +23,7 @@
#pragma once
#include "DNA_ID.h"
+#include "DNA_asset_types.h"
#ifdef __cplusplus
extern "C" {
@@ -135,6 +136,10 @@ typedef struct WorkSpace {
/** Info text from modal operators (runtime). */
char *status_text;
+
+ /** Workspace-wide active asset library, for asset UIs to use (e.g. asset view UI template). The
+ * Asset Browser has its own and doesn't use this. */
+ AssetLibraryReference active_asset_library;
} WorkSpace;
/**
@@ -165,7 +170,7 @@ typedef struct WorkSpaceDataRelation {
/** The data used to identify the relation
* (e.g. to find screen-layout (= value) from/for a hook).
- * Note: Now runtime only. */
+ * NOTE: Now runtime only. */
void *parent;
/** The value for this parent-data/workspace relation. */
void *value;
diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c
index 2d55ea05867..a573e2f9e8c 100644
--- a/source/blender/makesdna/intern/dna_defaults.c
+++ b/source/blender/makesdna/intern/dna_defaults.c
@@ -152,6 +152,7 @@
/* DNA_asset_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(AssetMetaData);
+SDNA_DEFAULT_DECL_STRUCT(AssetLibraryReference);
/* DNA_armature_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(bArmature);
@@ -315,6 +316,7 @@ SDNA_DEFAULT_DECL_STRUCT(TextureGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(ThickGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(TimeGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(TintGpencilModifierData);
+SDNA_DEFAULT_DECL_STRUCT(WeightGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(LineartGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(LengthGpencilModifierData);
@@ -347,6 +349,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
/* DNA_asset_defaults.h */
SDNA_DEFAULT_DECL(AssetMetaData),
+ SDNA_DEFAULT_DECL(AssetLibraryReference),
/* DNA_armature_defaults.h */
SDNA_DEFAULT_DECL(bArmature),
@@ -541,6 +544,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
SDNA_DEFAULT_DECL(ThickGpencilModifierData),
SDNA_DEFAULT_DECL(TimeGpencilModifierData),
SDNA_DEFAULT_DECL(TintGpencilModifierData),
+ SDNA_DEFAULT_DECL(WeightGpencilModifierData),
SDNA_DEFAULT_DECL(LineartGpencilModifierData),
SDNA_DEFAULT_DECL(LengthGpencilModifierData),
};
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 2a4bf53702f..d23b9441822 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -47,7 +47,7 @@
/**
* \section dna_genfile Overview
*
- * - please note: no builtin security to detect input of double structs
+ * - please NOTE: no builtin security to detect input of double structs
* - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`.
*
* Structure DNA data is added to each blender file and to each executable, this to detect
@@ -1060,7 +1060,7 @@ void DNA_struct_switch_endian(const SDNA *sdna, int struct_nr, char *data)
}
case SDNA_TYPE_INT:
case SDNA_TYPE_FLOAT: {
- /* Note, intentionally ignore long/ulong, because these could be 4 or 8 bytes.
+ /* NOTE: intentionally ignore long/ulong, because these could be 4 or 8 bytes.
* Fortunately, we only use these types for runtime variables and only once for a
* struct type that is no longer used. */
BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length);
@@ -1398,7 +1398,7 @@ static void init_reconstruct_step_for_member(const SDNA *oldsdna,
r_step->data.cast_pointer.array_len = shared_array_length;
}
else {
- BLI_assert(!"invalid pointer size");
+ BLI_assert_msg(0, "invalid pointer size");
r_step->type = RECONSTRUCT_STEP_INIT_ZERO;
}
break;
diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h
index 735be0c10bf..d363e40e4f0 100644
--- a/source/blender/makesdna/intern/dna_rename_defs.h
+++ b/source/blender/makesdna/intern/dna_rename_defs.h
@@ -136,4 +136,5 @@ DNA_STRUCT_RENAME_ELEM(wmWindow, global_area_map, global_areas)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits)
+DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, num_bind_verts)
DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits)
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 24cfc1d84f6..f2a75a60a44 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -43,6 +43,7 @@
#define DNA_DEPRECATED_ALLOW
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -272,6 +273,37 @@ void print_struct_sizes(void);
* Make DNA string (write to file).
* \{ */
+static bool match_identifier_with_len(const char *str,
+ const char *identifier,
+ const size_t identifier_len)
+{
+ if (strncmp(str, identifier, identifier_len) == 0) {
+ /* Check `str` isn't a prefix to a longer identifier. */
+ if (isdigit(str[identifier_len]) || isalpha(str[identifier_len]) ||
+ (str[identifier_len] == '_')) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+static bool match_identifier(const char *str, const char *identifier)
+{
+ const size_t identifier_len = strlen(identifier);
+ return match_identifier_with_len(str, identifier, identifier_len);
+}
+
+static bool match_identifier_and_advance(char **str_ptr, const char *identifier)
+{
+ const size_t identifier_len = strlen(identifier);
+ if (match_identifier_with_len(*str_ptr, identifier, identifier_len)) {
+ (*str_ptr) += identifier_len;
+ return true;
+ }
+ return false;
+}
+
static const char *version_struct_static_from_alias(const char *str)
{
const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_static_from_alias, str);
@@ -360,7 +392,7 @@ static int add_type(const char *str, int size)
return -1;
}
if (strchr(str, '*')) {
- /* note: this is valid C syntax but we can't parse, complain!
+ /* NOTE: this is valid C syntax but we can't parse, complain!
* `struct SomeStruct* some_var;` <-- correct but we can't handle right now. */
return -1;
}
@@ -422,7 +454,7 @@ static int add_name(const char *str)
int isfuncptr = (strchr(str + 1, '(')) != NULL;
DEBUG_PRINTF(3, "\t\t\t\t*** Function pointer or multidim array pointer found\n");
- /* functionpointer: transform the type (sometimes) */
+ /* function-pointer: transform the type (sometimes). */
int i = 0;
while (str[i] != ')') {
@@ -567,7 +599,7 @@ static short *add_struct(int namecode)
static int preprocess_include(char *maindata, const int maindata_len)
{
- /* note: len + 1, last character is a dummy to prevent
+ /* NOTE: len + 1, last character is a dummy to prevent
* comparisons using uninitialized memory */
char *temp = MEM_mallocN(maindata_len + 1, "preprocess_include");
temp[maindata_len] = ' ';
@@ -619,7 +651,7 @@ static int preprocess_include(char *maindata, const int maindata_len)
else if (cp[-1] == '*' && cp[0] == ' ') {
/* pointers with a space */
} /* skip special keywords */
- else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) {
+ else if (match_identifier(cp, "DNA_DEPRECATED")) {
/* single values are skipped already, so decrement 1 less */
a -= 13;
cp += 13;
@@ -721,7 +753,7 @@ static int convert_include(const char *filename)
md1++;
/* we've got a struct name when... */
- if (strncmp(md1 - 7, "struct", 6) == 0) {
+ if (match_identifier(md1 - 7, "struct")) {
const int strct = add_type(md1, 0);
if (strct == -1) {
@@ -756,14 +788,22 @@ static int convert_include(const char *filename)
/* skip when it says 'struct' or 'unsigned' or 'const' */
if (*md1) {
- if (strncmp(md1, "struct", 6) == 0) {
- md1 += 7;
- }
- if (strncmp(md1, "unsigned", 8) == 0) {
- md1 += 9;
- }
- if (strncmp(md1, "const", 5) == 0) {
- md1 += 6;
+ const char *md1_prev = md1;
+ while (match_identifier_and_advance(&md1, "struct") ||
+ match_identifier_and_advance(&md1, "unsigned") ||
+ match_identifier_and_advance(&md1, "const")) {
+ if (UNLIKELY(!ELEM(*md1, '\0', ' '))) {
+ /* This will happen with: `unsigned(*value)[3]` which isn't supported. */
+ fprintf(stderr,
+ "File '%s' contains non white space character "
+ "\"%c\" after identifier \"%s\"\n",
+ filename,
+ *md1,
+ md1_prev);
+ return 1;
+ }
+ /* Skip ' ' or '\0'. */
+ md1++;
}
/* we've got a type! */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 876229411e0..97615016016 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -71,6 +71,8 @@ extern StructRNA RNA_ArrayGpencilModifier;
extern StructRNA RNA_ArrayModifier;
extern StructRNA RNA_Attribute;
extern StructRNA RNA_AttributeGroup;
+extern StructRNA RNA_AssetHandle;
+extern StructRNA RNA_AssetLibraryReference;
extern StructRNA RNA_AssetMetaData;
extern StructRNA RNA_AssetTag;
extern StructRNA RNA_BackgroundImage;
@@ -450,6 +452,7 @@ extern StructRNA RNA_NodeOutputFileSlotFile;
extern StructRNA RNA_NodeOutputFileSlotLayer;
extern StructRNA RNA_NodeSocket;
extern StructRNA RNA_NodeSocketInterface;
+extern StructRNA RNA_NodeSocketStandard;
extern StructRNA RNA_NodeTree;
extern StructRNA RNA_NoiseGpencilModifier;
extern StructRNA RNA_NoiseTexture;
@@ -810,6 +813,7 @@ void RNA_struct_py_type_set(StructRNA *srna, void *py_type);
void *RNA_struct_blender_type_get(StructRNA *srna);
void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type);
+struct IDProperty **RNA_struct_idprops_p(PointerRNA *ptr);
struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create);
bool RNA_struct_idprops_check(StructRNA *srna);
bool RNA_struct_idprops_register_check(const StructRNA *type);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 71af69f77a1..d544083a749 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -204,6 +204,7 @@ extern const EnumPropertyItem rna_enum_node_vec_math_items[];
extern const EnumPropertyItem rna_enum_node_boolean_math_items[];
extern const EnumPropertyItem rna_enum_node_float_compare_items[];
extern const EnumPropertyItem rna_enum_node_filter_items[];
+extern const EnumPropertyItem rna_enum_node_float_to_int_items[];
extern const EnumPropertyItem rna_enum_node_map_range_items[];
extern const EnumPropertyItem rna_enum_node_clamp_items[];
@@ -244,6 +245,22 @@ extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id, bo
extern const EnumPropertyItem rna_enum_collection_color_items[];
+/**
+ * For ID filters (#FILTER_ID_AC, #FILTER_ID_AR, ...) an int isn't enough. This version allows 64
+ * bit integers. So can't use the regular #EnumPropertyItem. Would be nice if RNA supported this
+ * itself.
+ *
+ * Meant to be used with #RNA_def_property_boolean_sdna() which supports 64 bit flags as well.
+ */
+struct IDFilterEnumPropertyItem {
+ const uint64_t flag;
+ const char *identifier;
+ const int icon;
+ const char *name;
+ const char *description;
+};
+extern const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[];
+
/* API calls */
int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
int rna_node_tree_idname_to_enum(const char *idname);
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 96604b8a5fe..c2335b82fca 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -271,7 +271,7 @@ typedef enum PropertyFlag {
/**
* flag contains multiple enums.
- * note: not to be confused with prop->enumbitflags
+ * NOTE: not to be confused with prop->enumbitflags
* this exposes the flag as multiple options in python and the UI.
*
* \note These can't be animated so use with care.
@@ -443,7 +443,7 @@ typedef struct CollectionListBase {
typedef enum RawPropertyType {
PROP_RAW_UNSET = -1,
- PROP_RAW_INT, /* XXX - abused for types that are not set, eg. MFace.verts, needs fixing. */
+ PROP_RAW_INT, /* XXX: abused for types that are not set, eg. MFace.verts, needs fixing. */
PROP_RAW_SHORT,
PROP_RAW_CHAR,
PROP_RAW_BOOLEAN,
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 5bf16baa1e8..719b0f73a9d 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -2140,7 +2140,7 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property
return;
}
- /* disabled for now to avoid msvc compiler error due to large file size */
+ /* Disabled for now to avoid MSVC compiler error due to large file size. */
#if 0
if (prop->name && prop->description && prop->description[0] != '\0') {
fprintf(f, "\t/* %s: %s */\n", prop->name, prop->description);
@@ -2407,7 +2407,7 @@ static void rna_def_struct_function_prototype_cpp(FILE *f,
static void rna_def_struct_function_header_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc)
{
if (dfunc->call) {
- /* disabled for now to avoid msvc compiler error due to large file size */
+ /* Disabled for now to avoid MSVC compiler error due to large file size. */
#if 0
FunctionRNA *func = dfunc->func;
fprintf(f, "\n\t/* %s */\n", func->description);
@@ -4449,7 +4449,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
fprintf(f, "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n");
#endif
- fprintf(f, "/* Autogenerated Functions */\n\n");
+ fprintf(f, "/* Auto-generated Functions. */\n\n");
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) {
if (!filename || ds->filename == filename) {
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 43b65b087bf..6df03d19538 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -126,6 +126,97 @@ static const EnumPropertyItem rna_enum_override_library_property_operation_items
{0, NULL, 0, NULL, NULL},
};
+/**
+ * \note Uses #IDFilterEnumPropertyItem, not EnumPropertyItem, to support 64 bit items.
+ */
+const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[] = {
+ /* Datablocks */
+ {FILTER_ID_AC, "filter_action", ICON_ANIM_DATA, "Actions", "Show Action data-blocks"},
+ {FILTER_ID_AR,
+ "filter_armature",
+ ICON_ARMATURE_DATA,
+ "Armatures",
+ "Show Armature data-blocks"},
+ {FILTER_ID_BR, "filter_brush", ICON_BRUSH_DATA, "Brushes", "Show Brushes data-blocks"},
+ {FILTER_ID_CA, "filter_camera", ICON_CAMERA_DATA, "Cameras", "Show Camera data-blocks"},
+ {FILTER_ID_CF, "filter_cachefile", ICON_FILE, "Cache Files", "Show Cache File data-blocks"},
+ {FILTER_ID_CU, "filter_curve", ICON_CURVE_DATA, "Curves", "Show Curve data-blocks"},
+ {FILTER_ID_GD,
+ "filter_grease_pencil",
+ ICON_GREASEPENCIL,
+ "Grease Pencil",
+ "Show Grease pencil data-blocks"},
+ {FILTER_ID_GR,
+ "filter_group",
+ ICON_OUTLINER_COLLECTION,
+ "Collections",
+ "Show Collection data-blocks"},
+ {FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"},
+ {FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"},
+ {FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"},
+ {FILTER_ID_LP,
+ "filter_light_probe",
+ ICON_OUTLINER_DATA_LIGHTPROBE,
+ "Light Probes",
+ "Show Light Probe data-blocks"},
+ {FILTER_ID_LS,
+ "filter_linestyle",
+ ICON_LINE_DATA,
+ "Freestyle Linestyles",
+ "Show Freestyle's Line Style data-blocks"},
+ {FILTER_ID_LT, "filter_lattice", ICON_LATTICE_DATA, "Lattices", "Show Lattice data-blocks"},
+ {FILTER_ID_MA,
+ "filter_material",
+ ICON_MATERIAL_DATA,
+ "Materials",
+ "Show Material data-blocks"},
+ {FILTER_ID_MB, "filter_metaball", ICON_META_DATA, "Metaballs", "Show Metaball data-blocks"},
+ {FILTER_ID_MC,
+ "filter_movie_clip",
+ ICON_TRACKER_DATA,
+ "Movie Clips",
+ "Show Movie Clip data-blocks"},
+ {FILTER_ID_ME, "filter_mesh", ICON_MESH_DATA, "Meshes", "Show Mesh data-blocks"},
+ {FILTER_ID_MSK, "filter_mask", ICON_MOD_MASK, "Masks", "Show Mask data-blocks"},
+ {FILTER_ID_NT, "filter_node_tree", ICON_NODETREE, "Node Trees", "Show Node Tree data-blocks"},
+ {FILTER_ID_OB, "filter_object", ICON_OBJECT_DATA, "Objects", "Show Object data-blocks"},
+ {FILTER_ID_PA,
+ "filter_particle_settings",
+ ICON_PARTICLE_DATA,
+ "Particles Settings",
+ "Show Particle Settings data-blocks"},
+ {FILTER_ID_PAL, "filter_palette", ICON_COLOR, "Palettes", "Show Palette data-blocks"},
+ {FILTER_ID_PC,
+ "filter_paint_curve",
+ ICON_CURVE_BEZCURVE,
+ "Paint Curves",
+ "Show Paint Curve data-blocks"},
+ {FILTER_ID_PT,
+ "filter_pointcloud",
+ ICON_POINTCLOUD_DATA,
+ "Point Clouds",
+ "Show/hide Point Cloud data-blocks"},
+ {FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"},
+ {FILTER_ID_SIM,
+ "filter_simulation",
+ ICON_PHYSICS,
+ "Simulations",
+ "Show Simulation data-blocks"}, /* TODO: Use correct icon. */
+ {FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"},
+ {FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"},
+ {FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"},
+ {FILTER_ID_TXT, "filter_text", ICON_TEXT, "Texts", "Show Text data-blocks"},
+ {FILTER_ID_VF, "filter_font", ICON_FONT_DATA, "Fonts", "Show Font data-blocks"},
+ {FILTER_ID_VO, "filter_volume", ICON_VOLUME_DATA, "Volumes", "Show/hide Volume data-blocks"},
+ {FILTER_ID_WO, "filter_world", ICON_WORLD_DATA, "Worlds", "Show World data-blocks"},
+ {FILTER_ID_WS,
+ "filter_work_space",
+ ICON_WORKSPACE,
+ "Workspaces",
+ "Show workspace data-blocks"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "DNA_anim_types.h"
@@ -384,7 +475,7 @@ short RNA_type_to_ID_code(const StructRNA *type)
StructRNA *ID_code_to_RNA_type(short idcode)
{
- /* Note, this switch doesn't use a 'default',
+ /* NOTE: this switch doesn't use a 'default',
* so adding new ID's causes a warning. */
switch ((ID_Type)idcode) {
case ID_AC:
@@ -493,9 +584,10 @@ StructRNA *rna_ID_refine(PointerRNA *ptr)
return ID_code_to_RNA_type(GS(id->name));
}
-IDProperty *rna_ID_idprops(PointerRNA *ptr, bool create)
+IDProperty **rna_ID_idprops(PointerRNA *ptr)
{
- return IDP_GetProperties(ptr->data, create);
+ ID *id = (ID *)ptr->data;
+ return &id->properties;
}
void rna_ID_fake_user_set(PointerRNA *ptr, bool value)
@@ -510,9 +602,9 @@ void rna_ID_fake_user_set(PointerRNA *ptr, bool value)
}
}
-IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, bool UNUSED(create))
+IDProperty **rna_PropertyGroup_idprops(PointerRNA *ptr)
{
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
void rna_PropertyGroup_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -538,7 +630,7 @@ StructRNA *rna_PropertyGroup_register(Main *UNUSED(bmain),
return NULL;
}
- /* note: it looks like there is no length limit on the srna id since its
+ /* NOTE: it looks like there is no length limit on the srna id since its
* just a char pointer, but take care here, also be careful that python
* owns the string pointer which it could potentially free while blender
* is running. */
@@ -772,7 +864,7 @@ static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, bool clear_pro
static AnimData *rna_ID_animation_data_create(ID *id, Main *bmain)
{
- AnimData *adt = BKE_animdata_add_id(id);
+ AnimData *adt = BKE_animdata_ensure_id(id);
DEG_relations_tag_update(bmain);
return adt;
}
@@ -1162,12 +1254,12 @@ static PointerRNA rna_IDPreview_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img);
}
-static IDProperty *rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr, bool UNUSED(create))
+static IDProperty **rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr)
{
if (ptr == NULL) {
return NULL;
}
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
static void rna_Library_version_get(PointerRNA *ptr, int *value)
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 840da76403a..0285ef44e17 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -369,15 +369,32 @@ static bool rna_idproperty_ui_set_default(PointerRNA *ptr,
return true;
}
-IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
+IDProperty **RNA_struct_idprops_p(PointerRNA *ptr)
{
StructRNA *type = ptr->type;
+ if (type == NULL) {
+ return NULL;
+ }
+ if (type->idproperties == NULL) {
+ return NULL;
+ }
- if (type && type->idproperties) {
- return type->idproperties(ptr, create);
+ return type->idproperties(ptr);
+}
+
+IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
+{
+ IDProperty **property_ptr = RNA_struct_idprops_p(ptr);
+ if (property_ptr == NULL) {
+ return NULL;
}
- return NULL;
+ if (create && *property_ptr == NULL) {
+ IDPropertyTemplate val = {0};
+ *property_ptr = IDP_New(IDP_GROUP, &val, __func__);
+ }
+
+ return *property_ptr;
}
bool RNA_struct_idprops_check(StructRNA *srna)
@@ -692,7 +709,7 @@ static const char *rna_ensure_property_description(const PropertyRNA *prop)
}
if (description == NULL) {
- description = ((IDProperty *)prop)->name; /* XXX - not correct */
+ description = ((IDProperty *)prop)->name; /* XXX: not correct. */
}
}
@@ -907,7 +924,7 @@ static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
{
- /* note, prop_test could be freed memory, only use for comparison */
+ /* NOTE: prop_test could be freed memory, only use for comparison. */
/* validate the RNA is ok */
PropertyRNA *iterprop;
@@ -1691,7 +1708,7 @@ static void property_enum_translate(PropertyRNA *prop,
if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
int i;
- /* Note: Only do those tests once, and then use BLT_pgettext. */
+ /* NOTE: Only do those tests once, and then use BLT_pgettext. */
bool do_iface = BLT_translate_iface();
bool do_tooltip = BLT_translate_tooltips();
EnumPropertyItem *nitem;
@@ -2026,11 +2043,9 @@ bool RNA_property_enum_item_from_value(
bool RNA_property_enum_item_from_value_gettexted(
bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
{
- bool result;
+ const bool result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
- result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
-
- if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
+ if (result && !(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
if (BLT_translate_iface()) {
r_item->name = BLT_pgettext(prop->translation_context, r_item->name);
}
@@ -2325,7 +2340,7 @@ static void rna_property_update(
}
/* must keep in sync with 'rna_property_update'
- * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
+ * NOTE: its possible this returns a false positive in the case of #PROP_CONTEXT_UPDATE
* but this isn't likely to be a performance problem. */
bool RNA_property_update_check(PropertyRNA *prop)
{
@@ -5812,7 +5827,7 @@ static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr)
BLI_assert(ptr->owner_id != NULL);
- /* TODO, Support Bones/PoseBones. no pointers stored to the bones from here, only the ID.
+ /* TODO: Support Bones/PoseBones. no pointers stored to the bones from here, only the ID.
* See example in T25746.
* Unless this is added only way to find this is to also search
* all bones and pose bones of an armature or object.
@@ -5849,12 +5864,12 @@ ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
*r_path = "collection";
break;
default:
- BLI_assert(!"Missing handling of embedded id type.");
+ BLI_assert_msg(0, "Missing handling of embedded id type.");
}
}
if (id_type->owner_get == NULL) {
- BLI_assert(!"Missing handling of embedded id type.");
+ BLI_assert_msg(0, "Missing handling of embedded id type.");
return id;
}
return id_type->owner_get(bmain, id);
@@ -6244,8 +6259,8 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
data_path = RNA_path_from_ID_to_property(ptr, prop);
if (data_path == NULL) {
- /* this may not be an ID at all, check for simple when pointer owns property.
- * TODO, more complex nested case */
+ /* This may not be an ID at all, check for simple when pointer owns property.
+ * TODO: more complex nested case. */
if (!RNA_struct_is_ID(ptr->type)) {
const char *prop_identifier = RNA_property_identifier(prop);
if (RNA_struct_find_property(ptr, prop_identifier) == prop) {
@@ -6559,7 +6574,7 @@ char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, in
PropertyRNA *prop = RNA_struct_find_property(ptr, name);
if (prop) {
- /* TODO, pass length */
+ /* TODO: pass length. */
return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen, NULL);
}
printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
index c84ef1a6587..3912c873fd0 100644
--- a/source/blender/makesrna/intern/rna_access_compare_override.c
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -132,7 +132,7 @@ bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop)
{
if (prop->magic == RNA_MAGIC) {
/* Special handling for insertions of constraints or modifiers... */
- /* TODO Note We may want to add a more generic system to RNA
+ /* TODO: Note We may want to add a more generic system to RNA
* (like a special property in struct of items)
* if we get more overridable collections,
* for now we can live with those special-cases handling I think. */
@@ -234,7 +234,7 @@ bool RNA_property_copy(
prop_src = rna_ensure_property_realdata(&prop_src, fromptr);
/* IDprops: destination may not exist, if source does and is set, try to create it. */
- /* Note: this is sort of quick hack/bandage to fix the issue,
+ /* NOTE: this is sort of quick hack/bandage to fix the issue,
* we need to rethink how IDProps are handled in 'diff' RNA code completely, imho... */
if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) {
BLI_assert(prop_src->magic != RNA_MAGIC);
@@ -422,7 +422,9 @@ static int rna_property_override_diff(Main *bmain,
bool override_changed = false;
eRNAOverrideMatch diff_flags = flags;
- if (!RNA_property_overridable_get(&prop_a->ptr, prop_a->rawprop)) {
+ if (!RNA_property_overridable_get(&prop_a->ptr, prop_a->rawprop) ||
+ (!ELEM(RNA_property_type(prop_a->rawprop), PROP_POINTER, PROP_COLLECTION) &&
+ !RNA_property_editable_flag(&prop_a->ptr, prop_a->rawprop))) {
diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE;
}
const int diff = override_diff(bmain,
@@ -681,7 +683,7 @@ bool RNA_struct_override_matches(Main *bmain,
* ensure this is valid, but in some situations (like hidden collections etc.) this won't
* be the case, so we need to take care of this ourselves.
*
- * Note: Typically callers of this function (from BKE_lib_override area) will already have
+ * NOTE: Typically callers of this function (from BKE_lib_override area) will already have
* ensured this. However, studio is still reporting sporadic, unreproducible crashes due to
* invalid pose data, so think there are still some cases where some armatures are somehow
* missing updates (possibly due to dependencies?). Since calling this function on same ID
@@ -741,7 +743,7 @@ bool RNA_struct_override_matches(Main *bmain,
char *rna_path = rna_path_buffer;
size_t rna_path_len = 0;
- /* XXX TODO this will have to be refined to handle collections insertions, and array items */
+ /* XXX TODO: this will have to be refined to handle collections insertions, and array items. */
if (root_path) {
BLI_assert(strlen(root_path) == root_path_len);
@@ -865,7 +867,7 @@ bool RNA_struct_override_matches(Main *bmain,
else {
/* Too noisy for now, this triggers on runtime props like transform matrices etc. */
#if 0
- BLI_assert(!"We have differences between reference and "
+ BLI_assert_msg(0, "We have differences between reference and "
"overriding data on non-editable property.");
#endif
matching = false;
@@ -1138,7 +1140,7 @@ static void rna_property_override_apply_ex(Main *bmain,
continue;
}
- /* Note: will have to think about putting that logic into its own function maybe?
+ /* NOTE: will have to think about putting that logic into its own function maybe?
* Would be nice to have it in a single place...
* Note that here, src is the local saved ID, and dst is a copy of the linked ID (since we use
* local ID as storage to apply local changes on top of a clean copy of the linked data). */
@@ -1192,7 +1194,7 @@ void RNA_struct_override_apply(Main *bmain,
#ifdef DEBUG_OVERRIDE_TIMEIT
TIMEIT_START_AVERAGED(RNA_struct_override_apply);
#endif
- /* Note: Applying insert operations in a separate pass is mandatory.
+ /* NOTE: Applying insert operations in a separate pass is mandatory.
* We could optimize this later, but for now, as inefficient as it is,
* don't think this is a critical point.
*/
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index b3b0d7d13f7..49d02524e43 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -260,28 +260,16 @@ static char *rna_Bone_path(PointerRNA *ptr)
return BLI_sprintfN("bones[\"%s\"]", name_esc);
}
-static IDProperty *rna_Bone_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_Bone_idprops(PointerRNA *ptr)
{
Bone *bone = ptr->data;
-
- if (create && !bone->prop) {
- IDPropertyTemplate val = {0};
- bone->prop = IDP_New(IDP_GROUP, &val, "RNA_Bone ID properties");
- }
-
- return bone->prop;
+ return &bone->prop;
}
-static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_EditBone_idprops(PointerRNA *ptr)
{
EditBone *ebone = ptr->data;
-
- if (create && !ebone->prop) {
- IDPropertyTemplate val = {0};
- ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
- }
-
- return ebone->prop;
+ return &ebone->prop;
}
static void rna_bone_layer_set(int *layer, const bool *values)
@@ -1395,7 +1383,7 @@ static void rna_def_armature_bones(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_ui_text(prop, "Active Bone", "Armature's active bone");
RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_bone_set", NULL, NULL);
- /* todo, redraw */
+ /* TODO: redraw. */
/* RNA_def_property_collection_active(prop, prop_act); */
}
@@ -1421,7 +1409,7 @@ static void rna_def_armature_edit_bones(BlenderRNA *brna, PropertyRNA *cprop)
/*RNA_def_property_update(prop, 0, "rna_Armature_act_editbone_update"); */
RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_edit_bone_set", NULL, NULL);
- /* todo, redraw */
+ /* TODO: redraw. */
/* RNA_def_property_collection_active(prop, prop_act); */
/* add target */
diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c
index 1af53e95cc9..0020d90ba1a 100644
--- a/source/blender/makesrna/intern/rna_asset.c
+++ b/source/blender/makesrna/intern/rna_asset.c
@@ -25,6 +25,7 @@
#include "DNA_asset_types.h"
#include "DNA_defs.h"
+#include "DNA_space_types.h"
#include "rna_internal.h"
@@ -35,6 +36,8 @@
# include "BLI_listbase.h"
+# include "ED_asset.h"
+
# include "RNA_access.h"
static AssetTag *rna_AssetMetaData_tag_new(AssetMetaData *asset_data,
@@ -75,16 +78,10 @@ static void rna_AssetMetaData_tag_remove(AssetMetaData *asset_data,
RNA_POINTER_INVALIDATE(tag_ptr);
}
-static IDProperty *rna_AssetMetaData_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_AssetMetaData_idprops(PointerRNA *ptr)
{
AssetMetaData *asset_data = ptr->data;
-
- if (create && !asset_data->properties) {
- IDPropertyTemplate val = {0};
- asset_data->properties = IDP_New(IDP_GROUP, &val, "RNA_AssetMetaData group");
- }
-
- return asset_data->properties;
+ return &asset_data->properties;
}
static void rna_AssetMetaData_description_get(PointerRNA *ptr, char *value)
@@ -129,6 +126,105 @@ static void rna_AssetMetaData_active_tag_range(
*max = *softmax = MAX2(asset_data->tot_tags - 1, 0);
}
+static PointerRNA rna_AssetHandle_file_data_get(PointerRNA *ptr)
+{
+ AssetHandle *asset_handle = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_FileSelectEntry, asset_handle->file_data);
+}
+
+static void rna_AssetHandle_get_full_library_path(
+ // AssetHandle *asset,
+ bContext *C,
+ FileDirEntry *asset_file,
+ AssetLibraryReference *library,
+ char r_result[/*FILE_MAX_LIBEXTRA*/])
+{
+ AssetHandle asset = {.file_data = asset_file};
+ ED_asset_handle_get_full_library_path(C, library, &asset, r_result);
+}
+
+static PointerRNA rna_AssetHandle_local_id_get(PointerRNA *ptr)
+{
+ const AssetHandle *asset = ptr->data;
+ ID *id = ED_assetlist_asset_local_id_get(asset);
+ return rna_pointer_inherit_refine(ptr, &RNA_ID, id);
+}
+
+static void rna_AssetHandle_file_data_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
+{
+ AssetHandle *asset_handle = ptr->data;
+ asset_handle->file_data = value.data;
+}
+
+int rna_asset_library_reference_get(const AssetLibraryReference *library)
+{
+ return ED_asset_library_reference_to_enum_value(library);
+}
+
+void rna_asset_library_reference_set(AssetLibraryReference *library, int value)
+{
+ *library = ED_asset_library_reference_from_enum_value(value);
+}
+
+const EnumPropertyItem *rna_asset_library_reference_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ const EnumPropertyItem predefined_items[] = {
+ /* For the future. */
+ // {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
+ {ASSET_LIBRARY_LOCAL,
+ "LOCAL",
+ ICON_BLENDER,
+ "Current File",
+ "Show the assets currently available in this Blender session"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ /* Add separator if needed. */
+ if (!BLI_listbase_is_empty(&U.asset_libraries)) {
+ const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL};
+ RNA_enum_item_add(&item, &totitem, &sepr);
+ }
+
+ int i = 0;
+ for (bUserAssetLibrary *user_library = U.asset_libraries.first; user_library;
+ user_library = user_library->next, i++) {
+ /* Note that the path itself isn't checked for validity here. If an invalid library path is
+ * used, the Asset Browser can give a nice hint on what's wrong. */
+ const bool is_valid = (user_library->name[0] && user_library->path[0]);
+ if (!is_valid) {
+ continue;
+ }
+
+ /* Use library path as description, it's a nice hint for users. */
+ EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i,
+ user_library->name,
+ ICON_NONE,
+ user_library->name,
+ user_library->path};
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ if (totitem) {
+ const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL};
+ RNA_enum_item_add(&item, &totitem, &sepr);
+ }
+
+ /* Add predefined items. */
+ RNA_enum_items_add(&item, &totitem, predefined_items);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+ return item;
+}
+
#else
static void rna_def_asset_tag(BlenderRNA *brna)
@@ -215,12 +311,87 @@ static void rna_def_asset_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Tag", "Index of the tag set for editing");
}
+static void rna_def_asset_handle_api(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "get_full_library_path", "rna_AssetHandle_get_full_library_path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ /* TODO temporarily static function, for until .py can receive the asset handle from context
+ * properly. `asset_file_handle` should go away too then. */
+ RNA_def_function_flag(func, FUNC_NO_SELF);
+ parm = RNA_def_pointer(func, "asset_file_handle", "FileSelectEntry", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func,
+ "asset_library",
+ "AssetLibraryReference",
+ "",
+ "The asset library containing the given asset, only valid if the asset "
+ "library is external (i.e. not the \"Current File\" one");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string(func, "result", NULL, FILE_MAX_LIBEXTRA, "result", "");
+ RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
+ RNA_def_function_output(func, parm);
+}
+
+static void rna_def_asset_handle(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "AssetHandle", "PropertyGroup");
+ RNA_def_struct_ui_text(srna, "Asset Handle", "Reference to some asset");
+
+ /* TODO why is this editable? There probably shouldn't be a setter. */
+ prop = RNA_def_property(srna, "file_data", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "FileSelectEntry");
+ RNA_def_property_pointer_funcs(
+ prop, "rna_AssetHandle_file_data_get", "rna_AssetHandle_file_data_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "File Entry", "File data used to refer to the asset");
+
+ prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ID");
+ RNA_def_property_pointer_funcs(prop, "rna_AssetHandle_local_id_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop,
+ "",
+ "The local data-block this asset represents; only valid if that is a "
+ "data-block in this file");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ rna_def_asset_handle_api(srna);
+}
+
+static void rna_def_asset_library_reference(BlenderRNA *brna)
+{
+ StructRNA *srna = RNA_def_struct(brna, "AssetLibraryReference", NULL);
+ RNA_def_struct_ui_text(
+ srna, "Asset Library Reference", "Identifier to refere to the asset library");
+}
+
+/**
+ * \note the UI text and updating has to be set by the caller.
+ */
+PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
+ const char *get,
+ const char *set)
+{
+ PropertyRNA *prop = RNA_def_property(srna, "active_asset_library", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, DummyRNA_NULL_items);
+ RNA_def_property_enum_funcs(prop, get, set, "rna_asset_library_reference_itemf");
+
+ return prop;
+}
+
void RNA_def_asset(BlenderRNA *brna)
{
RNA_define_animate_sdna(false);
rna_def_asset_tag(brna);
rna_def_asset_data(brna);
+ rna_def_asset_library_reference(brna);
+ rna_def_asset_handle(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 7e1d513502c..2b09ea51a84 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1486,7 +1486,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
prop = RNA_def_property(srna, "uv_random", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "uv_random");
RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "UV Random", "Random factor for autogenerated UV rotation");
+ RNA_def_property_ui_text(prop, "UV Random", "Random factor for auto-generated UV rotation");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
@@ -3260,7 +3260,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- /* only for projection paint & vertex paint, TODO, other paint modes */
+ /* only for projection paint & vertex paint, TODO: other paint modes. */
prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_LOCK_ALPHA);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 9e57368f8f9..2bc00dd5af5 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -652,7 +652,6 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop, "Vertex Mass", "The mass of each vertex on the cloth material");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "vertex_group_mass", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c
index 577a3273e21..752c9495e50 100644
--- a/source/blender/makesrna/intern/rna_collection.c
+++ b/source/blender/makesrna/intern/rna_collection.c
@@ -189,7 +189,7 @@ static bool rna_Collection_objects_override_apply(Main *bmain,
return false;
}
- /* XXX TODO We most certainly rather want to have a 'swap object pointer in collection'
+ /* XXX TODO: We most certainly rather want to have a 'swap object pointer in collection'
* util in BKE_collection. This is only temp quick dirty test! */
id_us_min(&cob_dst->ob->id);
cob_dst->ob = ob_src;
@@ -292,7 +292,7 @@ static bool rna_Collection_children_override_apply(Main *bmain,
return false;
}
- /* XXX TODO We most certainly rather want to have a 'swap object pointer in collection'
+ /* XXX TODO: We most certainly rather want to have a 'swap object pointer in collection'
* util in BKE_collection. This is only temp quick dirty test! */
id_us_min(&collchild_dst->collection->id);
collchild_dst->collection = subcoll_src;
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 39a44d7568a..9faf2ae7cb7 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -971,7 +971,7 @@ static void rna_def_color_ramp_element_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_path_func(srna, "rna_ColorRampElement_path");
RNA_def_struct_ui_text(srna, "Color Ramp Elements", "Collection of Color Ramp Elements");
- /* TODO, make these functions generic in texture.c */
+ /* TODO: make these functions generic in `texture.c`. */
func = RNA_def_function(srna, "new", "rna_ColorRampElement_new");
RNA_def_function_ui_description(func, "Add element to ColorRamp");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index d79f2c4d13f..3064703b02e 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -206,6 +206,7 @@ static const EnumPropertyItem target_space_pchan_items[] = {
"Custom Space",
"The transformation of the target is evaluated relative to a custom object/bone/vertex "
"group"},
+ {0, "", 0, NULL, NULL},
{CONSTRAINT_SPACE_POSE,
"POSE",
0,
@@ -224,6 +225,14 @@ static const EnumPropertyItem target_space_pchan_items[] = {
"Local Space",
"The transformation of the target is evaluated relative to its local "
"coordinate system"},
+ {CONSTRAINT_SPACE_OWNLOCAL,
+ "LOCAL_OWNER_ORIENT",
+ 0,
+ "Local Space (Owner Orientation)",
+ "The transformation of the target bone is evaluated relative to its local coordinate "
+ "system, followed by a correction for the difference in target and owner rest pose "
+ "orientations. When applied as local transform to the owner produces the same global "
+ "motion as the target if the parents are still in rest pose"},
{0, NULL, 0, NULL, NULL},
};
@@ -238,6 +247,7 @@ static const EnumPropertyItem owner_space_pchan_items[] = {
0,
"Custom Space",
"The constraint is applied in local space of a custom object/bone/vertex group"},
+ {0, "", 0, NULL, NULL},
{CONSTRAINT_SPACE_POSE,
"POSE",
0,
@@ -1624,18 +1634,48 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
0,
"Replace",
"Replace the original transformation with copied"},
+ {0, "", 0, NULL, NULL},
+ {TRANSLIKE_MIX_BEFORE_FULL,
+ "BEFORE_FULL",
+ 0,
+ "Before Original (Full)",
+ "Apply copied transformation before original, using simple matrix multiplication as if "
+ "the constraint target is a parent in Full Inherit Scale mode. "
+ "Will create shear when combining rotation and non-uniform scale"},
{TRANSLIKE_MIX_BEFORE,
"BEFORE",
0,
- "Before Original",
- "Apply copied transformation before original, as if the constraint target is a parent. "
- "Scale is handled specially to avoid creating shear"},
+ "Before Original (Aligned)",
+ "Apply copied transformation before original, as if the constraint target is a parent in "
+ "Aligned Inherit Scale mode. This effectively uses Full for location and Split Channels "
+ "for rotation and scale"},
+ {TRANSLIKE_MIX_BEFORE_SPLIT,
+ "BEFORE_SPLIT",
+ 0,
+ "Before Original (Split Channels)",
+ "Apply copied transformation before original, handling location, rotation and scale "
+ "separately, similar to a sequence of three Copy constraints"},
+ {0, "", 0, NULL, NULL},
+ {TRANSLIKE_MIX_AFTER_FULL,
+ "AFTER_FULL",
+ 0,
+ "After Original (Full)",
+ "Apply copied transformation after original, using simple matrix multiplication as if "
+ "the constraint target is a child in Full Inherit Scale mode. "
+ "Will create shear when combining rotation and non-uniform scale"},
{TRANSLIKE_MIX_AFTER,
"AFTER",
0,
- "After Original",
- "Apply copied transformation after original, as if the constraint target is a child. "
- "Scale is handled specially to avoid creating shear"},
+ "After Original (Aligned)",
+ "Apply copied transformation after original, as if the constraint target is a child in "
+ "Aligned Inherit Scale mode. This effectively uses Full for location and Split Channels "
+ "for rotation and scale"},
+ {TRANSLIKE_MIX_AFTER_SPLIT,
+ "AFTER_SPLIT",
+ 0,
+ "After Original (Split Channels)",
+ "Apply copied transformation after original, handling location, rotation and scale "
+ "separately, similar to a sequence of three Copy constraints"},
{0, NULL, 0, NULL, NULL},
};
@@ -1653,6 +1693,12 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
RNA_define_lib_overridable(true);
+ prop = RNA_def_property(srna, "remove_target_shear", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", TRANSLIKE_REMOVE_TARGET_SHEAR);
+ RNA_def_property_ui_text(
+ prop, "Remove Target Shear", "Remove shear from the target transformation before combining");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
RNA_def_property_enum_items(prop, mix_mode_items);
@@ -2795,7 +2841,7 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
RNA_define_lib_overridable(true);
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO, mesh type */
+ RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO: mesh type. */
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_ui_text(prop, "Target", "Target Mesh object");
RNA_def_property_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 4079406e64b..9da08de2168 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -58,6 +58,8 @@ const EnumPropertyItem rna_enum_context_mode_items[] = {
#ifdef RNA_RUNTIME
+# include "DNA_asset_types.h"
+
# ifdef WITH_PYTHON
# include "BPY_extern.h"
# endif
@@ -134,6 +136,20 @@ static PointerRNA rna_Context_gizmo_group_get(PointerRNA *ptr)
return newptr;
}
+static PointerRNA rna_Context_asset_file_handle_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ bool is_handle_valid;
+ AssetHandle asset_handle = CTX_wm_asset_handle(C, &is_handle_valid);
+ if (!is_handle_valid) {
+ return PointerRNA_NULL;
+ }
+
+ PointerRNA newptr;
+ RNA_pointer_create(NULL, &RNA_FileSelectEntry, asset_handle.file_data, &newptr);
+ return newptr;
+}
+
static PointerRNA rna_Context_main_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
@@ -281,6 +297,17 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "GizmoGroup");
RNA_def_property_pointer_funcs(prop, "rna_Context_gizmo_group_get", NULL, NULL, NULL);
+ /* TODO can't expose AssetHandle, since there is no permanent storage to it (so we can't
+ * return a pointer). Instead provide the FileDirEntry pointer it wraps. */
+ prop = RNA_def_property(srna, "asset_file_handle", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "FileSelectEntry");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_asset_file_handle_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop,
+ "",
+ "The file of an active asset. Avoid using this, it will be replaced by "
+ "a proper AssetHandle design");
+
/* Data */
prop = RNA_def_property(srna, "blend_data", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 299cd2504a8..9c6659a7130 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -591,7 +591,7 @@ static int rna_Curve_body_length(PointerRNA *ptr)
return cu->len;
}
-/* TODO, how to handle editmode? */
+/* TODO: how to handle editmode? */
static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
{
size_t len_bytes;
@@ -1802,7 +1802,7 @@ static void rna_def_curve(BlenderRNA *brna)
prop, "End Mapping Type", "Determine how the geometry end factor is mapped to a spline");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
- /* XXX - would be nice to have a better way to do this, only add for testing. */
+ /* XXX: would be nice to have a better way to do this, only add for testing. */
prop = RNA_def_property(srna, "twist_smooth", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "twist_smooth");
RNA_def_property_ui_range(prop, 0, 100.0, 1, 2);
@@ -2017,7 +2017,7 @@ static void rna_def_curve_nurb(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cyclic V", "Make this surface a closed loop in the V direction");
RNA_def_property_update(prop, 0, "rna_Nurb_update_cyclic_v");
- /* Note, endpoint and bezier flags should never be on at the same time! */
+ /* NOTE: endpoint and bezier flags should never be on at the same time! */
prop = RNA_def_property(srna, "use_endpoint_u", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flagu", CU_NURB_ENDPOINT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 0c6c3fd9b0a..fadce9e3c89 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -52,7 +52,7 @@ static CLG_LogRef LOG = {"rna.define"};
# define ASSERT_SOFT_HARD_LIMITS \
if (softmin < hardmin || softmax > hardmax) { \
CLOG_ERROR(&LOG, "error with soft/hard limits: %s.%s", CONTAINER_RNA_ID(cont), identifier); \
- BLI_assert(!"invalid soft/hard limits"); \
+ BLI_assert_msg(0, "invalid soft/hard limits"); \
} \
(void)0
#else
@@ -781,7 +781,7 @@ void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *rna_ext)
{
#ifdef RNA_RUNTIME
rna_ext->free(rna_ext->data); /* decref's the PyObject that the srna owns */
- RNA_struct_blender_type_set(srna, NULL); /* this gets accessed again - XXX fixme */
+ RNA_struct_blender_type_set(srna, NULL); /* FIXME: this gets accessed again. */
/* NULL the srna's value so RNA_struct_free won't complain of a leak */
RNA_struct_py_type_set(srna, NULL);
@@ -4759,7 +4759,7 @@ static void rna_def_property_free(StructOrFunctionRNA *cont_, PropertyRNA *prop)
}
}
-/* note: only intended for removing dynamic props */
+/* NOTE: only intended for removing dynamic props. */
int RNA_def_property_free_identifier(StructOrFunctionRNA *cont_, const char *identifier)
{
ContainerRNA *cont = cont_;
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 0dfd7d74c25..a9d5ef089bb 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -342,8 +342,8 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- /* Effect type
- * Only used by ui to view per effect settings */
+ /* Effect type
+ * Only used by UI to view per effect settings. */
static const EnumPropertyItem prop_dynamicpaint_effecttype[] = {
{1, "SPREAD", 0, "Spread", ""},
{2, "DRIP", 0, "Drip", ""},
@@ -351,7 +351,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- /* Displacemap file format */
+ /* Displace-map file format. */
static const EnumPropertyItem prop_dynamicpaint_image_fileformat[] = {
{MOD_DPAINT_IMGFORMAT_PNG, "PNG", 0, "PNG", ""},
# ifdef WITH_OPENEXR
@@ -360,7 +360,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- /* Displacemap type */
+ /* Displace-map type. */
static const EnumPropertyItem prop_dynamicpaint_displace_type[] = {
{MOD_DPAINT_DISP_DISPLACE, "DISPLACE", 0, "Displacement", ""},
{MOD_DPAINT_DISP_DEPTH, "DEPTH", 0, "Depth", ""},
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index f81a806b009..1f187382980 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -281,7 +281,7 @@ static void rna_DriverTarget_update_name(Main *bmain, Scene *scene, PointerRNA *
/* ----------- */
-/* note: this function exists only to avoid id refcounting */
+/* NOTE: this function exists only to avoid id refcounting. */
static void rna_DriverTarget_id_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
@@ -1831,7 +1831,7 @@ static void rna_def_drivertarget(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_editable_func(prop, "rna_DriverTarget_id_editable");
- /* note: custom set function is ONLY to avoid rna setting a user for this. */
+ /* NOTE: custom set function is ONLY to avoid rna setting a user for this. */
RNA_def_property_pointer_funcs(
prop, NULL, "rna_DriverTarget_id_set", "rna_DriverTarget_id_typef", NULL);
RNA_def_property_ui_text(prop,
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index decdc728bbe..5e015af8e20 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -2623,7 +2623,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"colors of a ramp or using a predefined color code");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
- /* Coba field items - generated dynamically based on domain type */
+ /* Color ramp field items are generated dynamically based on domain type. */
static const EnumPropertyItem coba_field_items[] = {
{0, "NONE", 0, "", ""},
{0, NULL, 0, NULL, NULL},
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 21e905cfd2a..aad6f1231dd 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -1808,7 +1808,7 @@ static void rna_def_gpencil_frame(BlenderRNA *brna)
/* Frame Number */
prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "framenum");
- /* XXX note: this cannot occur on the same frame as another sketch */
+ /* XXX NOTE: this cannot occur on the same frame as another sketch. */
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears");
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 3e6048e30c4..f1c05079d9c 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -93,6 +93,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
ICON_MOD_SUBSURF,
"Subdivide",
"Subdivide stroke adding more control points"},
+ {eGpencilModifierType_Weight,
+ "GP_WEIGHT",
+ ICON_MOD_VERTEX_WEIGHT,
+ "Vertex Weight",
+ "Generate Vertex Weights"},
{0, "", 0, N_("Deform"), ""},
{eGpencilModifierType_Armature,
"GP_ARMATURE",
@@ -233,6 +238,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr)
return &RNA_TintGpencilModifier;
case eGpencilModifierType_Time:
return &RNA_TimeGpencilModifier;
+ case eGpencilModifierType_Weight:
+ return &RNA_WeightGpencilModifier;
case eGpencilModifierType_Color:
return &RNA_ColorGpencilModifier;
case eGpencilModifierType_Array:
@@ -331,6 +338,8 @@ RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Armature, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Texture, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Tint, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Weight, target_vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Weight, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Lineart, vgname);
# undef RNA_GP_MOD_VGROUP_NAME_SET
@@ -363,8 +372,7 @@ static void greasepencil_modifier_object_set(Object *self,
RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE);
RNA_GP_MOD_OBJECT_SET(Lattice, object, OB_LATTICE);
RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
-RNA_GP_MOD_OBJECT_SET(Opacity, object, OB_EMPTY);
-RNA_GP_MOD_OBJECT_SET(Thick, object, OB_EMPTY);
+RNA_GP_MOD_OBJECT_SET(Weight, object, OB_EMPTY);
# undef RNA_GP_MOD_OBJECT_SET
@@ -538,6 +546,16 @@ static void rna_ThickGpencilModifier_material_set(PointerRNA *ptr,
rna_GpencilModifier_material_set(ptr, value, ma_target, reports);
}
+static void rna_WeightGpencilModifier_material_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *reports)
+{
+ WeightGpencilModifierData *tmd = (WeightGpencilModifierData *)ptr->data;
+ Material **ma_target = &tmd->material;
+
+ rna_GpencilModifier_material_set(ptr, value, ma_target, reports);
+}
+
static void rna_OffsetGpencilModifier_material_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *reports)
@@ -1143,35 +1161,9 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Thickness Factor", "Factor to multiply the thickness with");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_FADING);
- RNA_def_property_ui_text(prop, "Fading", "Fading effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- /* Distance reference object */
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_ThickGpencilModifier_object_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
-
- prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fading_start");
- RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
- RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fading_end");
- RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
- RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fading_end_factor");
- RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor");
+ prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_WEIGHT_FACTOR);
+ RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
@@ -1440,6 +1432,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strength", "Factor for tinting");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_WEIGHT_FACTOR);
+ RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "radius");
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
@@ -1726,35 +1723,9 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hardness", "Factor of stroke hardness");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_FADING);
- RNA_def_property_ui_text(prop, "Fading", "Fading effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- /* Distance reference object */
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_OpacityGpencilModifier_object_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
-
- prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fading_start");
- RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
- RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fading_end");
- RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
- RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
- prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fading_end_factor");
- RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor");
+ prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_WEIGHT_FACTOR);
+ RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
@@ -2733,6 +2704,170 @@ static void rna_def_modifier_gpenciltexture(BlenderRNA *brna)
RNA_define_lib_overridable(false);
}
+static void rna_def_modifier_gpencilweight(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem mode_items[] = {
+ {GP_WEIGHT_MODE_DISTANCE,
+ "DISTANCE",
+ 0,
+ "Distance",
+ "Calculate weights depending on the distance to the target object"},
+ {GP_WEIGHT_MODE_ANGLE,
+ "ANGLE",
+ 0,
+ "Angle",
+ "Calculate weights depending on the stroke orientation"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static const EnumPropertyItem axis_items[] = {
+ {0, "X", 0, "X", ""},
+ {1, "Y", 0, "Y", ""},
+ {2, "Z", 0, "Z", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem space_items[] = {
+ {GP_SPACE_LOCAL, "LOCAL", 0, "Local Space", ""},
+ {GP_SPACE_WORLD, "WORLD", 0, "World Space", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ srna = RNA_def_struct(brna, "WeightGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Weight Modifier", "Calculate Vertex Weight dynamically");
+ RNA_def_struct_sdna(srna, "WeightGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+
+ RNA_define_lib_overridable(true);
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "target_vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "target_vgname");
+ RNA_def_property_ui_text(prop, "Output", "Output Vertex group");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightGpencilModifier_target_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "use_blend", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_BLEND_DATA);
+ RNA_def_property_ui_text(
+ prop, "Blend", "Blend results with existing weights in output weight group");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "use_invert_output", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_OUTPUT);
+ RNA_def_property_ui_text(prop, "Invert", "Invert weight values");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Angle", "Angle");
+ RNA_def_property_range(prop, 0.0f, DEG2RAD(180.0f));
+ RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "axis");
+ RNA_def_property_enum_items(prop, axis_items);
+ RNA_def_property_ui_text(prop, "Axis", "");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "space");
+ RNA_def_property_enum_items(prop, space_items);
+ RNA_def_property_ui_text(prop, "Space", "Coordinates space");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop,
+ NULL,
+ "rna_WeightGpencilModifier_material_set",
+ NULL,
+ "rna_GpencilModifier_material_poll");
+ RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Distance reference object */
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_WeightGpencilModifier_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
+ prop = RNA_def_property(srna, "distance_start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "dist_start");
+ RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
+ RNA_def_property_ui_text(prop, "Distance Start", "Start value for distance calculation");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "minimum_weight", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "min_weight");
+ RNA_def_property_ui_text(prop, "Minimum", "Minimum value for vertex weight");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "distance_end", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "dist_end");
+ RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
+ RNA_def_property_ui_text(prop, "Distance End", "End value for distance calculation");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "layer_pass");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Layer pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_LAYERPASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ RNA_define_lib_overridable(false);
+}
+
static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3187,6 +3322,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna)
rna_def_modifier_gpencilarmature(brna);
rna_def_modifier_gpencilmultiply(brna);
rna_def_modifier_gpenciltexture(brna);
+ rna_def_modifier_gpencilweight(brna);
rna_def_modifier_gpencillineart(brna);
rna_def_modifier_gpencillength(brna);
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 987517320f9..06ff1918040 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -117,7 +117,7 @@ static void rna_Image_save(Image *image, Main *bmain, bContext *C, ReportList *r
BLI_strncpy(filename, image->filepath, sizeof(filename));
BLI_path_abs(filename, ID_BLEND_PATH(bmain, &image->id));
- /* note, we purposefully ignore packed files here,
+ /* NOTE: we purposefully ignore packed files here,
* developers need to explicitly write them via 'packed_files' */
if (IMB_saveiff(ibuf, filename, ibuf->flags)) {
@@ -374,7 +374,7 @@ void RNA_api_image(StructRNA *srna)
func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free");
RNA_def_function_ui_description(func, "Free the image buffers from memory");
- /* TODO, pack/unpack, maybe should be generic functions? */
+ /* TODO: pack/unpack, maybe should be generic functions? */
}
#endif
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index bfe9d4bb77c..9dc08430307 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -30,6 +30,7 @@
#define RNA_MAGIC ((int)~0)
+struct AssetLibraryReference;
struct FreestyleSettings;
struct ID;
struct IDOverrideLibrary;
@@ -266,6 +267,16 @@ void rna_def_mtex_common(struct BlenderRNA *brna,
void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna);
void rna_def_view_layer_common(struct BlenderRNA *brna, struct StructRNA *srna, const bool scene);
+PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
+ const char *get,
+ const char *set);
+int rna_asset_library_reference_get(const struct AssetLibraryReference *library);
+void rna_asset_library_reference_set(struct AssetLibraryReference *library, int value);
+const EnumPropertyItem *rna_asset_library_reference_itemf(struct bContext *C,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ bool *r_free);
+
void rna_def_actionbone_group_common(struct StructRNA *srna,
int update_flag,
const char *update_cb);
@@ -276,10 +287,10 @@ void rna_ID_name_get(struct PointerRNA *ptr, char *value);
int rna_ID_name_length(struct PointerRNA *ptr);
void rna_ID_name_set(struct PointerRNA *ptr, const char *value);
struct StructRNA *rna_ID_refine(struct PointerRNA *ptr);
-struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, bool create);
+struct IDProperty **rna_ID_idprops(struct PointerRNA *ptr);
void rna_ID_fake_user_set(struct PointerRNA *ptr, bool value);
void **rna_ID_instance(PointerRNA *ptr);
-struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, bool create);
+struct IDProperty **rna_PropertyGroup_idprops(struct PointerRNA *ptr);
void rna_PropertyGroup_unregister(struct Main *bmain, struct StructRNA *type);
struct StructRNA *rna_PropertyGroup_register(struct Main *bmain,
struct ReportList *reports,
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 0bb452dfb07..479306e8c06 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -54,7 +54,7 @@ typedef void (*ContextPropUpdateFunc)(struct bContext *C,
typedef void (*ContextUpdateFunc)(struct bContext *C, struct PointerRNA *ptr);
typedef int (*EditableFunc)(struct PointerRNA *ptr, const char **r_info);
typedef int (*ItemEditableFunc)(struct PointerRNA *ptr, int index);
-typedef struct IDProperty *(*IDPropertiesFunc)(struct PointerRNA *ptr, bool create);
+typedef struct IDProperty **(*IDPropertiesFunc)(struct PointerRNA *ptr);
typedef struct StructRNA *(*StructRefineFunc)(struct PointerRNA *ptr);
typedef char *(*StructPathFunc)(struct PointerRNA *ptr);
@@ -280,7 +280,7 @@ struct FunctionRNA {
CallFunc call;
/* parameter for the return value
- * note: this is only the C return value, rna functions can have multiple return values */
+ * NOTE: this is only the C return value, rna functions can have multiple return values. */
PropertyRNA *c_ret;
};
@@ -559,7 +559,7 @@ struct StructRNA {
*/
StructInstanceFunc instance;
- /* callback to get id properties */
+ /** Return the location of the struct's pointer to the root group IDProperty. */
IDPropertiesFunc idproperties;
/* functions of this struct */
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index a48727526c9..9d8ed161738 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -168,7 +168,7 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value)
# undef SHAPEKEY_SLIDER_TOL
/* ***** Normals accessors for shapekeys. ***** */
-/* Note: with this we may recompute several times the same data, should we want to access verts,
+/* NOTE: with this we may recompute several times the same data, should we want to access verts,
* then polys, then loops normals... However,
* such case looks rather unlikely - and not worth adding some kind of caching in KeyBlocks.
*/
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index b4253ab9236..0414afe1514 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -119,16 +119,10 @@ static char *rna_ViewLayer_path(PointerRNA *ptr)
return BLI_sprintfN("view_layers[\"%s\"]", name_esc);
}
-static IDProperty *rna_ViewLayer_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_ViewLayer_idprops(PointerRNA *ptr)
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
-
- if (create && !view_layer->id_properties) {
- IDPropertyTemplate val = {0};
- view_layer->id_properties = IDP_New(IDP_GROUP, &val, "ViewLayer ID properties");
- }
-
- return view_layer->id_properties;
+ return &view_layer->id_properties;
}
static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, bContext *C)
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 24bc5504a58..8c7d9698a67 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -115,7 +115,7 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Mask_update_data(bmain, scene, ptr);
}
-/* note: this function exists only to avoid id refcounting */
+/* NOTE: this function exists only to avoid id refcounting. */
static void rna_MaskParent_id_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
@@ -505,7 +505,7 @@ static void rna_MaskSpline_points_add(ID *id, MaskSpline *spline, int count)
if (!layer) {
/* Shall not happen actually */
- BLI_assert(!"No layer found for the spline");
+ BLI_assert_msg(0, "No layer found for the spline");
return;
}
@@ -631,7 +631,7 @@ static void rna_def_maskParent(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_flag(prop, PROP_EDITABLE);
// RNA_def_property_editable_func(prop, "rna_maskSpline_id_editable");
- /* note: custom set function is ONLY to avoid rna setting a user for this. */
+ /* NOTE: custom set function is ONLY to avoid rna setting a user for this. */
RNA_def_property_pointer_funcs(
prop, NULL, "rna_MaskParent_id_set", "rna_MaskParent_id_typef", NULL);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 81cf1447604..9caff88a3a5 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -14,7 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* note: the original vertex color stuff is now just used for
+/* NOTE: the original vertex color stuff is now just used for
* getting info on the layers themselves, accessing the data is
* done through the (not yet written) mpoly interfaces. */
@@ -1084,7 +1084,7 @@ static void rna_Mesh_face_map_remove(struct Mesh *me,
static int rna_MeshPoly_vertices_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
{
MPoly *mp = (MPoly *)ptr->data;
- /* note, raw access uses dummy item, this _could_ crash,
+ /* NOTE: raw access uses dummy item, this _could_ crash,
* watch out for this, mface uses it but it can't work here. */
return (length[0] = mp->totloop);
}
@@ -3006,7 +3006,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Loop Triangles", "Tessellation of mesh polygons into triangles");
rna_def_mesh_looptris(brna, prop);
- /* TODO, should this be allowed to be its self? */
+ /* TODO: should this be allowed to be its self? */
prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
@@ -3098,7 +3098,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "All vertex colors");
rna_def_vert_colors(brna, prop);
- /* TODO, edge customdata layers (bmesh py api can access already) */
+ /* TODO: edge customdata layers (bmesh py api can access already). */
prop = RNA_def_property(srna, "vertex_layers_float", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
RNA_def_property_collection_funcs(prop,
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 8128bdb83a0..9835d664a55 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -249,7 +249,7 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces");
RNA_def_function_ui_description(func, "Split faces based on the edge angle");
RNA_def_boolean(
- func, "free_loop_normals", 1, "Free Loop Notmals", "Free loop normals custom data layer");
+ func, "free_loop_normals", 1, "Free Loop Normals", "Free loop normals custom data layer");
func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
@@ -288,7 +288,7 @@ void RNA_api_mesh(StructRNA *srna)
"Define custom split normals of this mesh "
"(use zero-vectors to keep auto ones)");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- /* TODO, see how array size of 0 works, this shouldn't be used */
+ /* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
RNA_def_property_multi_array(parm, 2, normals_array_dim);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
@@ -301,7 +301,7 @@ void RNA_api_mesh(StructRNA *srna)
"Define custom split normals of this mesh, from vertices' normals "
"(use zero-vectors to keep auto ones)");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- /* TODO, see how array size of 0 works, this shouldn't be used */
+ /* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f);
RNA_def_property_multi_array(parm, 2, normals_array_dim);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 9a895a0c75a..5fddb0f18a5 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -602,6 +602,7 @@ const EnumPropertyItem rna_enum_axis_flag_xyz_items[] = {
# include "BKE_cachefile.h"
# include "BKE_context.h"
+# include "BKE_deform.h"
# include "BKE_mesh_runtime.h"
# include "BKE_modifier.h"
# include "BKE_object.h"
@@ -690,6 +691,7 @@ static void rna_Modifier_is_active_set(PointerRNA *ptr, bool value)
}
md->flag |= eModifierFlag_Active;
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id);
}
}
@@ -1249,12 +1251,13 @@ static const EnumPropertyItem *rna_DataTransferModifier_layers_select_src_itemf(
# endif
if (ob_src) {
- bDeformGroup *dg;
+ const bDeformGroup *dg;
int i;
RNA_enum_item_add_separator(&item, &totitem);
- for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob_src);
+ for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) {
tmp_item.value = i;
tmp_item.identifier = tmp_item.name = dg->name;
RNA_enum_item_add(&item, &totitem, &tmp_item);
@@ -1348,12 +1351,13 @@ static const EnumPropertyItem *rna_DataTransferModifier_layers_select_dst_itemf(
Object *ob_dst = CTX_data_active_object(C); /* XXX Is this OK? */
if (ob_dst) {
- bDeformGroup *dg;
+ const bDeformGroup *dg;
int i;
RNA_enum_item_add_separator(&item, &totitem);
- for (i = 0, dg = ob_dst->defbase.first; dg; i++, dg = dg->next) {
+ const ListBase *defbase = BKE_object_defgroup_list(ob_dst);
+ for (i = 0, dg = defbase->first; dg; i++, dg = dg->next) {
tmp_item.value = i;
tmp_item.identifier = tmp_item.name = dg->name;
RNA_enum_item_add(&item, &totitem, &tmp_item);
@@ -1617,15 +1621,11 @@ static void rna_NodesModifier_node_group_update(Main *bmain, Scene *scene, Point
MOD_nodes_update_interface(object, nmd);
}
-static IDProperty *rna_NodesModifier_properties(PointerRNA *ptr, bool create)
+static IDProperty **rna_NodesModifier_properties(PointerRNA *ptr)
{
NodesModifierData *nmd = ptr->data;
NodesModifierSettings *settings = &nmd->settings;
- if (create && settings->properties == NULL) {
- IDPropertyTemplate val = {0};
- settings->properties = IDP_New(IDP_GROUP, &val, "Nodes Modifier Settings");
- }
- return settings->properties;
+ return &settings->properties;
}
#else
@@ -2256,7 +2256,7 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- /* Note, keep in sync with operator 'MESH_OT_decimate' */
+ /* NOTE: keep in sync with operator 'MESH_OT_decimate'. */
StructRNA *srna;
PropertyRNA *prop;
@@ -6884,6 +6884,15 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "use_sparse_bind", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SDEF_SPARSE_BIND);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(
+ prop,
+ "Sparse Bind",
+ "Only record binding data for vertices matching the vertex group at the time of bind");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, -100, 100);
RNA_def_property_ui_range(prop, -100, 100, 10, 2);
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 2642ba82bc0..17c7b331c88 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -297,7 +297,7 @@ static int rna_NlaStrip_action_editable(PointerRNA *ptr, const char **UNUSED(r_i
{
NlaStrip *strip = (NlaStrip *)ptr->data;
- /* strip actions shouldn't be editable if NLA tweakmode is on */
+ /* Strip actions shouldn't be editable if NLA tweak-mode is on. */
if (ptr->owner_id) {
AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 6f4f63eaa5e..2ff43296d76 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -350,6 +350,31 @@ const EnumPropertyItem rna_enum_node_float_compare_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_node_float_to_int_items[] = {
+ {FN_NODE_FLOAT_TO_INT_ROUND,
+ "ROUND",
+ 0,
+ "Round",
+ "Round the float up or down to the nearest integer"},
+ {FN_NODE_FLOAT_TO_INT_FLOOR,
+ "FLOOR",
+ 0,
+ "Floor",
+ "Round the float down to the next smallest integer"},
+ {FN_NODE_FLOAT_TO_INT_CEIL,
+ "CEILING",
+ 0,
+ "Ceiling",
+ "Round the float up to the next largest integer"},
+ {FN_NODE_FLOAT_TO_INT_TRUNCATE,
+ "TRUNCATE",
+ 0,
+ "Truncate",
+ "Round the float to the closest integer in the direction of zero (floor if positive; ceiling "
+ "if negative)"},
+ {0, NULL, 0, NULL, NULL},
+};
+
const EnumPropertyItem rna_enum_node_map_range_items[] = {
{NODE_MAP_RANGE_LINEAR,
"LINEAR",
@@ -787,7 +812,7 @@ const EnumPropertyItem *rna_node_socket_type_itemf(void *data,
tmp.value = i;
tmp.identifier = stype->idname;
tmp.icon = RNA_struct_ui_icon(srna);
- tmp.name = RNA_struct_ui_name(srna);
+ tmp.name = nodeSocketTypeLabel(stype);
tmp.description = RNA_struct_ui_description(srna);
RNA_enum_item_add(&item, &totitem, &tmp);
@@ -1013,8 +1038,7 @@ static void rna_NodeTree_get_from_context(
RNA_parameter_list_free(&list);
}
-static bool rna_NodeTree_valid_socket_type(eNodeSocketDatatype socket_type,
- bNodeTreeType *ntreetype)
+static bool rna_NodeTree_valid_socket_type(bNodeTreeType *ntreetype, bNodeSocketType *socket_type)
{
extern FunctionRNA rna_NodeTree_valid_socket_type_func;
@@ -1028,7 +1052,7 @@ static bool rna_NodeTree_valid_socket_type(eNodeSocketDatatype socket_type,
func = &rna_NodeTree_valid_socket_type_func;
RNA_parameter_list_create(&list, &ptr, func);
- RNA_parameter_set_lookup(&list, "type", &socket_type);
+ RNA_parameter_set_lookup(&list, "idname", &socket_type->idname);
ntreetype->rna_ext.call(NULL, &ptr, func, &list);
RNA_parameter_get_lookup(&list, "valid", &ret);
@@ -2370,16 +2394,10 @@ static StructRNA *rna_FunctionNode_register(Main *bmain,
return nt->rna_ext.srna;
}
-static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_Node_idprops(PointerRNA *ptr)
{
bNode *node = ptr->data;
-
- if (create && !node->prop) {
- IDPropertyTemplate val = {0};
- node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties");
- }
-
- return node->prop;
+ return &node->prop;
}
static void rna_Node_parent_set(PointerRNA *ptr,
@@ -2838,16 +2856,10 @@ static char *rna_NodeSocket_path(PointerRNA *ptr)
}
}
-static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_NodeSocket_idprops(PointerRNA *ptr)
{
bNodeSocket *sock = ptr->data;
-
- if (create && !sock->prop) {
- IDPropertyTemplate val = {0};
- sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties");
- }
-
- return sock->prop;
+ return &sock->prop;
}
static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
@@ -2869,7 +2881,7 @@ static void rna_NodeSocket_type_set(PointerRNA *ptr, int value)
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
nodeFindNode(ntree, sock, &node, NULL);
- nodeModifySocketType(ntree, node, sock, value, 0);
+ nodeModifySocketTypeStatic(ntree, node, sock, value, 0);
}
static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -3154,16 +3166,10 @@ static char *rna_NodeSocketInterface_path(PointerRNA *ptr)
return NULL;
}
-static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_NodeSocketInterface_idprops(PointerRNA *ptr)
{
bNodeSocket *sock = ptr->data;
-
- if (create && !sock->prop) {
- IDPropertyTemplate val = {0};
- sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties");
- }
-
- return sock->prop;
+ return &sock->prop;
}
static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -3209,7 +3215,7 @@ static void rna_NodeSocketInterfaceStandard_draw(ID *id,
struct uiLayout *layout)
{
PointerRNA ptr;
- RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ RNA_pointer_create(id, &RNA_NodeSocketInterface, sock, &ptr);
sock->typeinfo->interface_draw(C, layout, &ptr);
}
@@ -3219,7 +3225,7 @@ static void rna_NodeSocketInterfaceStandard_draw_color(ID *id,
float r_color[4])
{
PointerRNA ptr;
- RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ RNA_pointer_create(id, &RNA_NodeSocketInterface, sock, &ptr);
sock->typeinfo->interface_draw_color(C, &ptr, r_color);
}
@@ -4442,7 +4448,7 @@ static int point_density_particle_color_source_from_shader(
case SHD_POINTDENSITY_COLOR_PARTVEL:
return TEX_PD_COLOR_PARTVEL;
default:
- BLI_assert(!"Unknown color source");
+ BLI_assert_msg(0, "Unknown color source");
return TEX_PD_COLOR_CONSTANT;
}
}
@@ -4458,7 +4464,7 @@ static int point_density_vertex_color_source_from_shader(
case SHD_POINTDENSITY_COLOR_VERTNOR:
return TEX_PD_COLOR_VERTNOR;
default:
- BLI_assert(!"Unknown color source");
+ BLI_assert_msg(0, "Unknown color source");
return TEX_PD_COLOR_CONSTANT;
}
}
@@ -4854,6 +4860,18 @@ static void def_float_compare(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_float_to_int(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "rounding_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, rna_enum_node_float_to_int_items);
+ RNA_def_property_ui_text(
+ prop, "Rounding Mode", "Method used to convert the float to an integer");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_vector_math(StructRNA *srna)
{
PropertyRNA *prop;
@@ -5814,7 +5832,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
- /* TODO, See how array size of 0 works, this shouldn't be used. */
+ /* TODO: See how array size of 0 works, this shouldn't be used. */
parm = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, 0);
RNA_def_function_output(func, parm);
@@ -6265,7 +6283,7 @@ static void def_sh_script(StructRNA *srna)
/* API functions */
-# if 0 /* XXX TODO use general node api for this */
+# if 0 /* XXX TODO: use general node api for this. */
func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket");
RNA_def_function_ui_description(func, "Find a socket by name");
parm = RNA_def_string(func, "name", NULL, 0, "Socket name", "");
@@ -9511,6 +9529,32 @@ static void def_geo_curve_primitive_circle(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_curve_primitive_line(StructRNA *srna)
+{
+ static const EnumPropertyItem mode_items[] = {
+ {GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS,
+ "POINTS",
+ ICON_NONE,
+ "Points",
+ "Define the start and end points of the line"},
+ {GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION,
+ "DIRECTION",
+ ICON_NONE,
+ "Direction",
+ "Define a line with a start point, direction and length"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeGeometryCurvePrimitiveLine", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "Method used to determine radius and placement");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_geo_point_rotate(StructRNA *srna)
{
static const EnumPropertyItem type_items[] = {
@@ -9945,6 +9989,45 @@ static void def_geo_switch(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_curve_primitive_quadrilateral(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem mode_items[] = {
+ {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE,
+ "RECTANGLE",
+ 0,
+ "Rectangle",
+ "Create a rectangle"},
+ {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM,
+ "PARALLELOGRAM",
+ 0,
+ "Parallelogram",
+ "Create a parallelogram"},
+ {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID,
+ "TRAPEZOID",
+ 0,
+ "Trapezoid",
+ "Create a trapezoid"},
+ {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE, "KITE", 0, "Kite", "Create a Kite / Dart"},
+ {GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS,
+ "POINTS",
+ 0,
+ "Points",
+ "Create a quadrilateral from four points"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_struct_sdna_from(srna, "NodeGeometryCurvePrimitiveQuad", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_enum_default(prop, GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_geo_curve_resample(StructRNA *srna)
{
PropertyRNA *prop;
@@ -10186,7 +10269,7 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
RNA_def_struct_sdna(srna, "bNodeSocket");
RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
- RNA_def_struct_ui_icon(srna, ICON_PLUGIN);
+ RNA_def_struct_ui_icon(srna, ICON_NONE);
RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
RNA_def_struct_register_funcs(
srna, "rna_NodeSocket_register", "rna_NodeSocket_unregister", NULL);
@@ -10291,6 +10374,11 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "ID Name", "");
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->label");
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Type Label", "Label to display for the socket type in the UI");
+
/* draw socket */
func = RNA_def_function(srna, "draw", NULL);
RNA_def_function_ui_description(func, "Draw socket");
@@ -10379,6 +10467,11 @@ static void rna_def_node_socket_interface(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "ID Name", "");
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->label");
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Type Label", "Label to display for the socket type in the UI");
+
func = RNA_def_function(srna, "draw", NULL);
RNA_def_function_ui_description(func, "Draw template settings");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
@@ -11543,12 +11636,6 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Texture", "Display node in viewport textured shading mode");
RNA_def_property_update(prop, 0, "rna_Node_update");
- prop = RNA_def_property(srna, "active_preview", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_PREVIEW);
- RNA_def_property_ui_text(prop, "Active Preview", "Node is previewed in other editor");
- RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
- RNA_def_property_update(prop, NC_NODE, NULL);
-
/* generic property update function */
func = RNA_def_function(srna, "socket_value_update", "rna_Node_socket_value_update");
RNA_def_function_ui_description(func, "Update after property changes");
@@ -12045,11 +12132,12 @@ static void rna_def_nodetree(BlenderRNA *brna)
func, "result_3", "ID", "From ID", "Original ID data-block selected from the context");
RNA_def_function_output(func, parm);
- /* Check for support of a socket type. */
+ /* Check for support of a socket type with a type identifier. */
func = RNA_def_function(srna, "valid_socket_type", NULL);
RNA_def_function_ui_description(func, "Check if the socket type is valid for the node tree");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
- parm = RNA_def_enum(func, "type", node_socket_type_items, 0, "", "");
+ parm = RNA_def_string(
+ func, "idname", "NodeSocket", MAX_NAME, "Socket Type", "Identifier of the socket type");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
RNA_def_function_return(func, RNA_def_boolean(func, "valid", false, "", ""));
}
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index a208e520d02..ed681291e29 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -790,9 +790,27 @@ static void rna_Object_dup_collection_set(PointerRNA *ptr,
}
}
+static void rna_Object_vertex_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->data;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ iter->valid = 0;
+ return;
+ }
+
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+ iter->valid = defbase != NULL;
+
+ rna_iterator_listbase_begin(iter, defbase, NULL);
+}
+
static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = (Object *)ptr->owner_id;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return;
+ }
+
bDeformGroup *dg = (bDeformGroup *)ptr->data;
BLI_strncpy_utf8(dg->name, value, sizeof(dg->name));
BKE_object_defgroup_unique_name(dg, ob);
@@ -801,15 +819,25 @@ static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
static int rna_VertexGroup_index_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return -1;
+ }
- return BLI_findindex(&ob->defbase, ptr->data);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ return BLI_findindex(defbase, ptr->data);
}
static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return PointerRNA_NULL;
+ }
+
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
return rna_pointer_inherit_refine(
- ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef - 1));
+ ptr, &RNA_VertexGroup, BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1));
}
static void rna_Object_active_vertex_group_set(PointerRNA *ptr,
@@ -817,7 +845,13 @@ static void rna_Object_active_vertex_group_set(PointerRNA *ptr,
struct ReportList *reports)
{
Object *ob = (Object *)ptr->owner_id;
- int index = BLI_findindex(&ob->defbase, value.data);
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return;
+ }
+
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+
+ int index = BLI_findindex(defbase, value.data);
if (index == -1) {
BKE_reportf(reports,
RPT_ERROR,
@@ -827,19 +861,27 @@ static void rna_Object_active_vertex_group_set(PointerRNA *ptr,
return;
}
- ob->actdef = index + 1;
+ BKE_object_defgroup_active_index_set(ob, index + 1);
}
static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
- return ob->actdef - 1;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return -1;
+ }
+
+ return BKE_object_defgroup_active_index_get(ob) - 1;
}
static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value)
{
Object *ob = (Object *)ptr->owner_id;
- ob->actdef = value + 1;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return;
+ }
+
+ BKE_object_defgroup_active_index_set(ob, value + 1);
}
static void rna_Object_active_vertex_group_index_range(
@@ -848,15 +890,24 @@ static void rna_Object_active_vertex_group_index_range(
Object *ob = (Object *)ptr->owner_id;
*min = 0;
- *max = max_ii(0, BLI_listbase_count(&ob->defbase) - 1);
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ *max = 0;
+ return;
+ }
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ *max = max_ii(0, BLI_listbase_count(defbase) - 1);
}
void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index)
{
Object *ob = (Object *)ptr->owner_id;
- bDeformGroup *dg;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ value[0] = '\0';
+ return;
+ }
- dg = BLI_findlink(&ob->defbase, index - 1);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ const bDeformGroup *dg = BLI_findlink(defbase, index - 1);
if (dg) {
BLI_strncpy(value, dg->name, sizeof(dg->name));
@@ -869,21 +920,34 @@ void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index)
int rna_object_vgroup_name_index_length(PointerRNA *ptr, int index)
{
Object *ob = (Object *)ptr->owner_id;
- bDeformGroup *dg;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ return 0;
+ }
- dg = BLI_findlink(&ob->defbase, index - 1);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *dg = BLI_findlink(defbase, index - 1);
return (dg) ? strlen(dg->name) : 0;
}
void rna_object_vgroup_name_index_set(PointerRNA *ptr, const char *value, short *index)
{
Object *ob = (Object *)ptr->owner_id;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ *index = -1;
+ return;
+ }
+
*index = BKE_object_defgroup_name_index(ob, value) + 1;
}
void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
Object *ob = (Object *)ptr->owner_id;
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ result[0] = '\0';
+ return;
+ }
+
bDeformGroup *dg = BKE_object_defgroup_find_name(ob, value);
if (dg) {
/* No need for BLI_strncpy_utf8, since this matches an existing group. */
@@ -1706,6 +1770,8 @@ static void rna_Object_active_modifier_set(PointerRNA *ptr, PointerRNA value, Re
Object *ob = (Object *)ptr->owner_id;
ModifierData *md = value.data;
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
+
if (RNA_pointer_is_null(&value)) {
BKE_object_modifier_set_active(ob, NULL);
return;
@@ -1931,16 +1997,25 @@ static void rna_Object_boundbox_get(PointerRNA *ptr, float *values)
}
}
+static bool check_object_vgroup_support_and_warn(const Object *ob,
+ const char *op_name,
+ ReportList *reports)
+{
+ if (!BKE_object_supports_vertex_groups(ob)) {
+ const char *ob_type_name = "Unknown";
+ RNA_enum_name_from_value(rna_enum_object_type_items, ob->type, &ob_type_name);
+ BKE_reportf(reports, RPT_ERROR, "%s is not supported for '%s' objects", op_name, ob_type_name);
+ return false;
+ }
+ return true;
+}
+
static bDeformGroup *rna_Object_vgroup_new(Object *ob,
Main *bmain,
ReportList *reports,
const char *name)
{
- if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) {
- const char *ob_type_name = "Unknown";
- RNA_enum_name_from_value(rna_enum_object_type_items, ob->type, &ob_type_name);
- BKE_reportf(
- reports, RPT_ERROR, "VertexGroups.new(): is not supported for '%s' objects", ob_type_name);
+ if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.new()", reports)) {
return NULL;
}
@@ -1957,8 +2032,14 @@ static void rna_Object_vgroup_remove(Object *ob,
ReportList *reports,
PointerRNA *defgroup_ptr)
{
+ if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.remove()", reports)) {
+ return;
+ }
+
bDeformGroup *defgroup = defgroup_ptr->data;
- if (BLI_findindex(&ob->defbase, defgroup) == -1) {
+ ListBase *defbase = BKE_object_defgroup_list_mutable(ob);
+
+ if (BLI_findindex(defbase, defgroup) == -1) {
BKE_reportf(reports,
RPT_ERROR,
"DeformGroup '%s' not in object '%s'",
@@ -1974,8 +2055,12 @@ static void rna_Object_vgroup_remove(Object *ob,
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
-static void rna_Object_vgroup_clear(Object *ob, Main *bmain)
+static void rna_Object_vgroup_clear(Object *ob, Main *bmain, ReportList *reports)
{
+ if (!check_object_vgroup_support_and_warn(ob, "VertexGroups.clear()", reports)) {
+ return;
+ }
+
BKE_object_defgroup_remove_all(ob);
DEG_relations_tag_update(bmain);
@@ -2268,7 +2353,7 @@ static void rna_def_vertex_group(BlenderRNA *brna)
func = RNA_def_function(srna, "add", "rna_VertexGroup_vertex_add");
RNA_def_function_ui_description(func, "Add vertices to the group");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
- /* TODO, see how array size of 0 works, this shouldn't be used */
+ /* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
parm = RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight", 0.0f, 1.0f);
@@ -2279,7 +2364,7 @@ static void rna_def_vertex_group(BlenderRNA *brna)
func = RNA_def_function(srna, "remove", "rna_VertexGroup_vertex_remove");
RNA_def_function_ui_description(func, "Remove vertices from the group");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
- /* TODO, see how array size of 0 works, this shouldn't be used */
+ /* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
@@ -2326,14 +2411,14 @@ static void rna_def_face_map(BlenderRNA *brna)
func = RNA_def_function(srna, "add", "rna_FaceMap_face_add");
RNA_def_function_ui_description(func, "Add faces to the face-map");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
- /* TODO, see how array size of 0 works, this shouldn't be used */
+ /* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
func = RNA_def_function(srna, "remove", "rna_FaceMap_face_remove");
RNA_def_function_ui_description(func, "Remove faces from the face-map");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
- /* TODO, see how array size of 0 works, this shouldn't be used */
+ /* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
}
@@ -2488,7 +2573,7 @@ static void rna_def_object_modifiers(BlenderRNA *brna, PropertyRNA *cprop)
/*RNA_def_property_update(prop, 0, "rna_Armature_act_editbone_update"); */
RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_edit_bone_set", NULL, NULL);
- /* todo, redraw */
+ /* TODO: redraw. */
/* RNA_def_property_collection_active(prop, prop_act); */
# endif
@@ -2685,7 +2770,6 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_int_sdna(prop, NULL, "actdef");
RNA_def_property_int_funcs(prop,
"rna_Object_active_vertex_group_index_get",
"rna_Object_active_vertex_group_index_set",
@@ -2710,7 +2794,7 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "clear", "rna_Object_vgroup_clear");
- RNA_def_function_flag(func, FUNC_USE_MAIN);
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Delete all vertex groups from object");
}
@@ -3272,7 +3356,15 @@ static void rna_def_object(BlenderRNA *brna)
/* vertex groups */
prop = RNA_def_property(srna, "vertex_groups", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "defbase", NULL);
+ RNA_def_property_collection_funcs(prop,
+ "rna_Object_vertex_groups_begin",
+ "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end",
+ "rna_iterator_listbase_get",
+ NULL,
+ NULL,
+ NULL,
+ NULL);
RNA_def_property_struct_type(prop, "VertexGroup");
RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Vertex Groups", "Vertex groups of the object");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 4608b0c1bac..10ba2b9acb1 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -303,6 +303,9 @@ static void rna_Object_mat_convert_space(Object *ob,
{
copy_m4_m4((float(*)[4])mat_ret, (float(*)[4])mat);
+ BLI_assert(!ELEM(from, CONSTRAINT_SPACE_OWNLOCAL));
+ BLI_assert(!ELEM(to, CONSTRAINT_SPACE_OWNLOCAL));
+
/* Error in case of invalid from/to values when pchan is NULL */
if (pchan == NULL) {
if (ELEM(from, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL)) {
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 30baf01e952..98d59bf3a1a 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -133,8 +133,9 @@ static bool rna_Cache_get_valid_owner_ID(PointerRNA *ptr, Object **ob, Scene **s
*scene = (Scene *)ptr->owner_id;
break;
default:
- BLI_assert(!"Trying to get PTCacheID from an invalid ID type "
- "(Only scenes and objects are supported).");
+ BLI_assert_msg(0,
+ "Trying to get PTCacheID from an invalid ID type "
+ "(Only scenes and objects are supported).");
break;
}
@@ -1095,7 +1096,7 @@ static void rna_def_pointcache_active(BlenderRNA *brna)
* Those caches items have exact same content as 'active' one, except for that collection,
* to prevent ugly recursive layout pattern.
*
- * Note: This shall probably be redone from scratch in a proper way at some point,
+ * NOTE: This shall probably be redone from scratch in a proper way at some point,
* but for now that will do, and shall not break anything in the API. */
prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop,
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 9ab685fa462..de4cfb2b61a 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -554,7 +554,7 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
}
part = particlesystem->part;
- /* Note: only hair, keyed and baked particles may have cached items... */
+ /* NOTE: only hair, keyed and baked particles may have cached items... */
totpart = particlesystem->totcached != 0 ? particlesystem->totcached : particlesystem->totpart;
totchild = particlesystem->totchildcache != 0 ? particlesystem->totchildcache :
particlesystem->totchild;
@@ -1430,9 +1430,10 @@ static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index)
{
Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
if (psys->vgroup[index] > 0) {
- bDeformGroup *defGroup = BLI_findlink(&ob->defbase, psys->vgroup[index] - 1);
+ bDeformGroup *defGroup = BLI_findlink(defbase, psys->vgroup[index] - 1);
if (defGroup) {
strcpy(value, defGroup->name);
@@ -1448,7 +1449,8 @@ static int psys_vg_name_len__internal(PointerRNA *ptr, int index)
ParticleSystem *psys = (ParticleSystem *)ptr->data;
if (psys->vgroup[index] > 0) {
- bDeformGroup *defGroup = BLI_findlink(&ob->defbase, psys->vgroup[index] - 1);
+ const ListBase *defbase = BKE_object_defgroup_list(ob);
+ bDeformGroup *defGroup = BLI_findlink(defbase, psys->vgroup[index] - 1);
if (defGroup) {
return strlen(defGroup->name);
@@ -3752,7 +3754,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
/* vertex groups */
- /* note, internally store as ints, access as strings */
+ /* NOTE: internally store as ints, access as strings. */
# if 0 /* int access. works ok but isn't useful for the UI */
prop = RNA_def_property(srna, "vertex_group_density", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "vgroup[0]");
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index bb4939a010b..ee509fa92d4 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -224,16 +224,10 @@ static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
sizeof(agrp->name));
}
-static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_PoseBone_idprops(PointerRNA *ptr)
{
bPoseChannel *pchan = ptr->data;
-
- if (create && !pchan->prop) {
- IDPropertyTemplate val = {0};
- pchan->prop = IDP_New(IDP_GROUP, &val, "RNA_PoseBone group");
- }
-
- return pchan->prop;
+ return &pchan->prop;
}
static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value)
diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c
index 0d35365c2d8..1e1667f0ae8 100644
--- a/source/blender/makesrna/intern/rna_pose_api.c
+++ b/source/blender/makesrna/intern/rna_pose_api.c
@@ -117,7 +117,7 @@ static void rna_Pose_apply_pose_from_action(ID *pose_owner,
Object *pose_owner_ob = (Object *)pose_owner;
AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time};
- BKE_pose_apply_action(pose_owner_ob, action, &anim_eval_context);
+ BKE_pose_apply_action_selected_bones(pose_owner_ob, action, &anim_eval_context);
/* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
DEG_id_tag_update(pose_owner, ID_RECALC_GEOMETRY);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 899c3397361..6008ef40b60 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -933,7 +933,7 @@ static const EnumPropertyItem *rna_EnumProperty_default_itemf(bContext *C,
return eprop->item_fn(C, ptr, prop, r_free);
}
-/* XXX - not sure this is needed? */
+/* XXX: not sure this is needed? */
static int rna_EnumProperty_default_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
@@ -1529,7 +1529,7 @@ int rna_property_override_diff_default(Main *bmain,
BLI_assert(len_a == len_b);
- /* Note: at this point, we are sure that when len_a is zero,
+ /* NOTE: at this point, we are sure that when len_a is zero,
* we are not handling an (empty) array. */
const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 &&
@@ -1537,7 +1537,7 @@ int rna_property_override_diff_default(Main *bmain,
const bool no_ownership = (prop_a->rnaprop->flag & PROP_PTR_NO_OWNERSHIP) != 0;
- /* Note: we assume we only insert in ptr_a (i.e. we can only get new items in ptr_a),
+ /* NOTE: we assume we only insert in ptr_a (i.e. we can only get new items in ptr_a),
* and that we never remove anything. */
const bool use_collection_insertion = (prop_a->rnaprop->flag_override &
PROPOVERRIDE_LIBRARY_INSERTION) &&
@@ -1564,7 +1564,7 @@ int rna_property_override_diff_default(Main *bmain,
const int comp = memcmp(array_a, array_b, sizeof(bool) * len_a);
if (do_create && comp != 0) {
- /* XXX TODO this will have to be refined to handle array items */
+ /* XXX TODO: this will have to be refined to handle array items. */
op = BKE_lib_override_library_property_get(override, rna_path, &created);
if (op != NULL && created) {
@@ -1625,7 +1625,7 @@ int rna_property_override_diff_default(Main *bmain,
const int comp = memcmp(array_a, array_b, sizeof(int) * len_a);
if (do_create && comp != 0) {
- /* XXX TODO this will have to be refined to handle array items */
+ /* XXX TODO: this will have to be refined to handle array items. */
op = BKE_lib_override_library_property_get(override, rna_path, &created);
if (op != NULL && created) {
@@ -1686,7 +1686,7 @@ int rna_property_override_diff_default(Main *bmain,
const int comp = memcmp(array_a, array_b, sizeof(float) * len_a);
if (do_create && comp != 0) {
- /* XXX TODO this will have to be refined to handle array items */
+ /* XXX TODO: this will have to be refined to handle array items. */
op = BKE_lib_override_library_property_get(override, rna_path, &created);
if (op != NULL && created) {
@@ -1758,7 +1758,7 @@ int rna_property_override_diff_default(Main *bmain,
ptr_a, rawprop_a, fixed_a, sizeof(fixed_a), &len_str_a);
char *value_b = RNA_property_string_get_alloc(
ptr_b, rawprop_b, fixed_b, sizeof(fixed_b), &len_str_b);
- /* TODO we could do a check on length too,
+ /* TODO: we could do a check on length too,
* but then we would not have a 'real' string comparison...
* Maybe behind a eRNAOverrideMatch flag? */
# if 0
@@ -2079,7 +2079,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain),
return changed;
}
- /* XXX TODO About range limits.
+ /* XXX TODO: About range limits.
* Ideally, it would be great to get rid of RNA range in that specific case.
* However, this won't be that easy and will add yet another layer of complexity in
* generated code, not to mention that we could most likely *not* bypass custom setters anyway.
@@ -2088,7 +2088,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain),
* Time will say whether this is acceptable limitation or not. */
switch (RNA_property_type(prop_local)) {
case PROP_BOOLEAN:
- /* TODO support boolean ops? Really doubt this would ever be useful though... */
+ /* TODO: support boolean ops? Really doubt this would ever be useful though. */
BLI_assert(0 && "Boolean properties support no override diff operation");
break;
case PROP_INT: {
@@ -2306,7 +2306,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain),
return true;
}
case PROP_ENUM:
- /* TODO support add/sub, for bitflags? */
+ /* TODO: support add/sub, for bitflags? */
BLI_assert(0 && "Enum properties support no override diff operation");
break;
case PROP_POINTER:
@@ -2316,7 +2316,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain),
BLI_assert(0 && "String properties support no override diff operation");
break;
case PROP_COLLECTION:
- /* XXX TODO support this of course... */
+ /* XXX TODO: support this of course... */
BLI_assert(0 && "Collection properties support no override diff operation");
break;
default:
@@ -2564,7 +2564,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
case IDOVERRIDE_LIBRARY_OP_REPLACE:
RNA_property_enum_set(ptr_dst, prop_dst, value);
break;
- /* TODO support add/sub, for bitflags? */
+ /* TODO: support add/sub, for bitflags? */
default:
BLI_assert(0 && "Unsupported RNA override operation on enum");
return false;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 503c4a1a1f8..5c9c7b50339 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -190,16 +190,6 @@ const EnumPropertyItem rna_enum_snap_node_element_items[] = {
{0, NULL, 0, NULL, NULL},
};
-const EnumPropertyItem rna_enum_snap_seq_element_items[] = {
- {SEQ_SNAP_TO_CURRENT_FRAME,
- "CURRENT_FRAME",
- ICON_NONE,
- "Current Frame",
- "Snap to current frame"},
- {SEQ_SNAP_TO_STRIP_HOLD, "STRIP_HOLD", ICON_NONE, "Hold Offset", "Snap to strip hold offset"},
- {0, NULL, 0, NULL, NULL},
-};
-
#ifndef RNA_RUNTIME
static const EnumPropertyItem snap_uv_element_items[] = {
{SCE_SNAP_MODE_INCREMENT,
@@ -1282,10 +1272,10 @@ static const EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext
ID *id = ptr->owner_id;
const bool is_render = (id && GS(id->name) == ID_SCE);
- /* note, we need to act differently for render
+ /* NOTE(campbell): we need to act differently for render
* where 'BW' will force grayscale even if the output format writes
* as RGBA, this is age old blender convention and not sure how useful
- * it really is but keep it for now - campbell */
+ * it really is but keep it for now. */
char chan_flag = BKE_imtype_valid_channels(imf->imtype, true) |
(is_render ? IMA_CHAN_FLAG_BW : 0);
@@ -2176,7 +2166,7 @@ static char *rna_MeshStatVis_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("tool_settings.statvis");
}
-/* note: without this, when Multi-Paint is activated/deactivated, the colors
+/* NOTE: without this, when Multi-Paint is activated/deactivated, the colors
* will not change right away when multiple bones are selected, this function
* is not for general use and only for the few cases where changing scene
* settings and NOT for general purpose updates, possibly this should be
@@ -3126,6 +3116,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame");
RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */
prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode");
@@ -3527,25 +3518,29 @@ static void rna_def_sequencer_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Fit Method", "Scale fit method");
/* Transform snapping. */
+ prop = RNA_def_property(srna, "snap_to_current_frame", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_mode", SEQ_SNAP_TO_CURRENT_FRAME);
+ RNA_def_property_ui_text(prop, "Current Frame", "Snap to current frame");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
- /* Sequencer editor uses own set of snap modes */
- prop = RNA_def_property(srna, "snap_seq_element", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode");
- RNA_def_property_enum_items(prop, rna_enum_snap_seq_element_items);
- RNA_def_property_ui_text(prop, "Snap To", "Type of element to snap to");
- RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ prop = RNA_def_property(srna, "snap_to_hold_offset", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_mode", SEQ_SNAP_TO_STRIP_HOLD);
+ RNA_def_property_ui_text(prop, "Hold Offset", "Snap to strip hold offsets");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "snap_ignore_muted", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_MUTED);
- RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Ignore Muted Strips", "Don't snap to hidden strips");
prop = RNA_def_property(srna, "snap_ignore_sound", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_SOUND);
- RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Ignore Sound Strips", "Don't snap to sound strips");
+ prop = RNA_def_property(srna, "use_snap_current_frame_to_strips", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_CURRENT_FRAME_TO_STRIPS);
+ RNA_def_property_ui_text(
+ prop, "Snap Current Frame to Strips", "Snap current frame to strip start or end");
+
prop = RNA_def_property(srna, "snap_distance", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "snap_distance");
RNA_def_property_int_default(prop, 15);
@@ -5397,7 +5392,7 @@ static void rna_def_image_format_stereo3d_format(BlenderRNA *brna)
}
/* use for render output and image save operator,
- * note: there are some cases where the members act differently when this is
+ * NOTE: there are some cases where the members act differently when this is
* used from a scene, video formats can only be selected for render output
* for example, this is checked by seeing if the ptr->owner_id is a Scene id */
@@ -7973,10 +7968,10 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "master_collection");
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_clear_flag(prop, PROP_PTR_NO_OWNERSHIP);
- RNA_def_property_ui_text(
- prop,
- "Collection",
- "Scene master collection that objects and other collections in the scene");
+ RNA_def_property_ui_text(prop,
+ "Collection",
+ "Scene root collection that owns all the objects and other collections "
+ "instantiated in the scene");
/* Scene Display */
prop = RNA_def_property(srna, "display", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index caecd9a07d8..3e292ea89e2 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -207,7 +207,6 @@ static void rna_Scene_alembic_export(Scene *scene,
bool apply_subdiv,
bool flatten_hierarchy,
bool visible_objects_only,
- bool renderable_only,
bool face_sets,
bool use_subdiv_schema,
bool export_hair,
@@ -241,7 +240,6 @@ static void rna_Scene_alembic_export(Scene *scene,
.apply_subdiv = apply_subdiv,
.flatten_hierarchy = flatten_hierarchy,
.visible_objects_only = visible_objects_only,
- .renderable_only = renderable_only,
.face_sets = face_sets,
.use_subdiv_schema = use_subdiv_schema,
.export_hair = export_hair,
@@ -383,11 +381,6 @@ void RNA_api_scene(StructRNA *srna)
0,
"Visible layers only",
"Export only objects in visible layers");
- RNA_def_boolean(func,
- "renderable_only",
- 0,
- "Renderable objects only",
- "Export only objects marked renderable in the outliner");
RNA_def_boolean(func, "face_sets", 0, "Facesets", "Export face sets");
RNA_def_boolean(func,
"subdiv_schema",
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 90029bd14a1..912f47ba9aa 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -495,7 +495,7 @@ static void rna_def_view2d(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "View2D", "Scroll and zoom for a 2D region");
RNA_def_struct_sdna(srna, "View2D");
- /* TODO more View2D properties could be exposed here (read-only) */
+ /* TODO: more View2D properties could be exposed here (read-only). */
rna_def_view2d_api(srna);
}
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 29100cd7658..b1f0b0d760f 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -28,6 +28,7 @@
#include "DNA_sequence_types.h"
#include "DNA_vfont_types.h"
+#include "BLI_iterator.h"
#include "BLI_math.h"
#include "BLT_translation.h"
@@ -102,17 +103,6 @@ typedef struct SequenceSearchData {
SequenceModifierData *smd;
} SequenceSearchData;
-/* build a temp reference to the parent */
-static void meta_tmp_ref(Sequence *seq_par, Sequence *seq)
-{
- for (; seq; seq = seq->next) {
- seq->tmp = seq_par;
- if (seq->type == SEQ_TYPE_META) {
- meta_tmp_ref(seq, seq->seqbase.first);
- }
- }
-}
-
static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
@@ -203,46 +193,41 @@ static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *i
{
Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = SEQ_editing_get(scene, false);
+ SeqCollection *all_strips = SEQ_query_all_strips_recursive(&ed->seqbase);
- meta_tmp_ref(NULL, ed->seqbase.first);
+ BLI_Iterator *bli_iter = MEM_callocN(sizeof(BLI_Iterator), __func__);
+ bli_iter->data = MEM_callocN(sizeof(SeqIterator), __func__);
+ iter->internal.custom = bli_iter;
- rna_iterator_listbase_begin(iter, &ed->seqbase, NULL);
-}
-
-static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain),
- Scene *scene,
- PointerRNA *UNUSED(ptr))
-{
- Editing *ed = scene->ed;
+ if (!SEQ_iterator_ensure(all_strips, bli_iter->data, (Sequence **)&bli_iter->current)) {
+ SEQ_collection_free(all_strips);
+ }
- SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
- SEQ_cache_cleanup(scene);
+ iter->valid = bli_iter->current != NULL;
}
static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter)
{
- ListBaseIterator *internal = &iter->internal.listbase;
- Sequence *seq = (Sequence *)internal->link;
+ BLI_Iterator *bli_iter = iter->internal.custom;
+ bli_iter->current = SEQ_iterator_yield(bli_iter->data);
+ iter->valid = bli_iter->current != NULL;
+}
- if (seq->seqbase.first) {
- internal->link = (Link *)seq->seqbase.first;
- }
- else if (seq->next) {
- internal->link = (Link *)seq->next;
- }
- else {
- internal->link = NULL;
+static PointerRNA rna_SequenceEditor_sequences_all_get(CollectionPropertyIterator *iter)
+{
+ Sequence *seq = ((BLI_Iterator *)iter->internal.custom)->current;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Sequence, seq);
+}
- do {
- seq = seq->tmp; /* XXX - seq's don't reference their parents! */
- if (seq && seq->next) {
- internal->link = (Link *)seq->next;
- break;
- }
- } while (seq);
+static void rna_SequenceEditor_sequences_all_end(CollectionPropertyIterator *iter)
+{
+ BLI_Iterator *bli_iter = iter->internal.custom;
+ SeqIterator *seq_iter = bli_iter->data;
+ if (seq_iter->collection != NULL) {
+ SEQ_collection_free(seq_iter->collection);
}
-
- iter->valid = (internal->link != NULL);
+ MEM_freeN(seq_iter);
+ MEM_freeN(bli_iter);
}
static int rna_SequenceEditor_sequences_all_lookup_string(PointerRNA *ptr,
@@ -260,6 +245,16 @@ static int rna_SequenceEditor_sequences_all_lookup_string(PointerRNA *ptr,
return false;
}
+static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain),
+ Scene *scene,
+ PointerRNA *UNUSED(ptr))
+{
+ Editing *ed = scene->ed;
+
+ SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
+ SEQ_cache_cleanup(scene);
+}
+
/* internal use */
static int rna_SequenceEditor_elements_length(PointerRNA *ptr)
{
@@ -308,7 +303,7 @@ static void do_sequence_frame_change_update(Scene *scene, Sequence *seq)
}
if (SEQ_transform_test_overlap(seqbase, seq)) {
- SEQ_transform_seqbase_shuffle(seqbase, seq, scene); /* XXX - BROKEN!, uses context seqbasep */
+ SEQ_transform_seqbase_shuffle(seqbase, seq, scene); /* XXX: BROKEN!, uses context seqbasep. */
}
SEQ_sort(seqbase);
}
@@ -488,7 +483,7 @@ static void rna_Sequence_channel_set(PointerRNA *ptr, int value)
seq->machine = value;
if (SEQ_transform_test_overlap(seqbase, seq)) {
- /* XXX - BROKEN!, uses context seqbasep */
+ /* XXX: BROKEN!, uses context seqbasep. */
SEQ_transform_seqbase_shuffle_ex(seqbase, seq, scene, channel_delta);
}
SEQ_sort(seqbase);
@@ -739,16 +734,10 @@ static char *rna_Sequence_path(PointerRNA *ptr)
}
}
-static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_Sequence_idprops(PointerRNA *ptr)
{
Sequence *seq = ptr->data;
-
- if (create && !seq->prop) {
- IDPropertyTemplate val = {0};
- seq->prop = IDP_New(IDP_GROUP, &val, "Sequence ID properties");
- }
-
- return seq->prop;
+ return &seq->prop;
}
static bool rna_MovieSequence_reload_if_needed(ID *scene_id, Sequence *seq, Main *bmain)
@@ -799,7 +788,7 @@ static PointerRNA rna_SequenceEditor_meta_stack_get(CollectionPropertyIterator *
return rna_pointer_inherit_refine(&iter->parent, &RNA_Sequence, ms->parseq);
}
-/* TODO, expose seq path setting as a higher level sequencer BKE function */
+/* TODO: expose seq path setting as a higher level sequencer BKE function. */
static void rna_Sequence_filepath_set(PointerRNA *ptr, const char *value)
{
Sequence *seq = (Sequence *)(ptr->data);
@@ -2009,8 +1998,8 @@ static void rna_def_editor(BlenderRNA *brna)
RNA_def_property_collection_funcs(prop,
"rna_SequenceEditor_sequences_all_begin",
"rna_SequenceEditor_sequences_all_next",
- NULL,
- NULL,
+ "rna_SequenceEditor_sequences_all_end",
+ "rna_SequenceEditor_sequences_all_get",
NULL,
NULL,
"rna_SequenceEditor_sequences_all_lookup_string",
@@ -2513,7 +2502,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
srna, "MovieClip Sequence", "Sequence strip to load a video from the clip editor");
RNA_def_struct_sdna(srna, "Sequence");
- /* TODO - add clip property? */
+ /* TODO: add clip property? */
prop = RNA_def_property(srna, "undistort", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_UNDISTORTED);
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 8aab0c079a3..057f49c0319 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -30,6 +30,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "SEQ_edit.h"
+
#include "rna_internal.h"
#ifdef RNA_RUNTIME
@@ -99,6 +101,24 @@ static void rna_Sequences_move_strip_to_meta(
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
}
+static Sequence *rna_Sequence_split(
+ ID *id, Sequence *seq, Main *bmain, int frame, int split_method)
+{
+ Scene *scene = (Scene *)id;
+ Editing *ed = SEQ_editing_get(scene, false);
+ ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq);
+
+ Sequence *r_seq = SEQ_edit_strip_split(bmain, scene, seqbase, seq, frame, split_method);
+
+ /* Update depsgraph. */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
+
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
+
+ return r_seq;
+}
+
static Sequence *rna_Sequences_new_clip(ID *id,
ListBase *seqbase,
Main *bmain,
@@ -635,6 +655,12 @@ void RNA_api_sequence_strip(StructRNA *srna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem seq_split_method_items[] = {
+ {SEQ_SPLIT_SOFT, "SOFT", 0, "Soft", ""},
+ {SEQ_SPLIT_HARD, "HARD", 0, "Hard", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
func = RNA_def_function(srna, "update", "rna_Sequence_update_rnafunc");
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
RNA_def_function_ui_description(func, "Update the strip dimensions");
@@ -676,6 +702,18 @@ void RNA_api_sequence_strip(StructRNA *srna)
"Invalidate cached images for strip and all dependent strips");
parm = RNA_def_enum(func, "type", seq_cahce_type_items, 0, "Type", "Cache Type");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "split", "rna_Sequence_split");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ RNA_def_function_ui_description(func, "Split Sequence");
+ parm = RNA_def_int(
+ func, "frame", 0, INT_MIN, INT_MAX, "", "Frame where to split the strip", INT_MIN, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_enum(func, "split_method", seq_split_method_items, 0, "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ /* Retirn type. */
+ parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Right side Sequence");
+ RNA_def_function_return(func, parm);
}
void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
index 4a6cb0d740a..7c5212073ab 100644
--- a/source/blender/makesrna/intern/rna_shader_fx.c
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -649,12 +649,12 @@ static void rna_def_shader_fx_flip(BlenderRNA *brna)
RNA_define_lib_overridable(true);
- prop = RNA_def_property(srna, "flip_horizontal", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_FLIP_HORIZONTAL);
RNA_def_property_ui_text(prop, "Horizontal", "Flip image horizontally");
RNA_def_property_update(prop, NC_OBJECT | ND_SHADERFX, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "flip_vertical", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FX_FLIP_VERTICAL);
RNA_def_property_ui_text(prop, "Vertical", "Flip image vertically");
RNA_def_property_update(prop, NC_OBJECT | ND_SHADERFX, "rna_ShaderFx_update");
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index d0a7e4aeea3..f2d2b190d87 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -509,6 +509,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
#ifdef RNA_RUNTIME
# include "DNA_anim_types.h"
+# include "DNA_asset_types.h"
# include "DNA_scene_types.h"
# include "DNA_screen_types.h"
# include "DNA_userdef_types.h"
@@ -1041,16 +1042,10 @@ static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr)
return RV3D_VIEW_IS_AXIS(rv3d->view);
}
-static IDProperty *rna_View3DShading_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_View3DShading_idprops(PointerRNA *ptr)
{
View3DShading *shading = ptr->data;
-
- if (create && !shading->prop) {
- IDPropertyTemplate val = {0};
- shading->prop = IDP_New(IDP_GROUP, &val, "View3DShading ID properties");
- }
-
- return shading->prop;
+ return &shading->prop;
}
static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -1839,7 +1834,7 @@ static void rna_SpaceTextEditor_updateEdited(Main *UNUSED(bmain),
/* Space Properties */
-/* note: this function exists only to avoid id refcounting */
+/* NOTE: this function exists only to avoid id refcounting. */
static void rna_SpaceProperties_pin_id_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
@@ -2106,7 +2101,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
switch (saction->mode) {
case SACTCONT_ACTION:
/* TODO: context selector could help decide this with more control? */
- adt = BKE_animdata_add_id(&obact->id);
+ adt = BKE_animdata_ensure_id(&obact->id);
id = &obact->id;
break;
case SACTCONT_SHAPEKEY: {
@@ -2114,7 +2109,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
if (key == NULL) {
return;
}
- adt = BKE_animdata_add_id(&key->id);
+ adt = BKE_animdata_ensure_id(&key->id);
id = &key->id;
break;
}
@@ -2136,7 +2131,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
return;
}
- /* Exit editmode first - we cannot change actions while in tweakmode. */
+ /* Exit editmode first - we cannot change actions while in tweak-mode. */
BKE_nla_tweakmode_exit(adt);
/* To prevent data loss (i.e. if users flip between actions using the Browse menu),
@@ -2567,6 +2562,8 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data);
}
+/* TODO use rna_def_asset_library_reference_common() */
+
static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
{
FileAssetSelectParams *params = ptr->data;
@@ -2574,7 +2571,7 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
BLI_assert(ptr->type == &RNA_FileAssetSelectParams);
/* Simple case: Predefined repo, just set the value. */
- if (params->asset_library.type < FILE_ASSET_LIBRARY_CUSTOM) {
+ if (params->asset_library.type < ASSET_LIBRARY_CUSTOM) {
return params->asset_library.type;
}
@@ -2583,11 +2580,11 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
&U, params->asset_library.custom_library_index);
if (user_library) {
- return FILE_ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index;
+ return ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index;
}
BLI_assert(0);
- return FILE_ASSET_LIBRARY_LOCAL;
+ return ASSET_LIBRARY_LOCAL;
}
static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int value)
@@ -2595,26 +2592,26 @@ static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int val
FileAssetSelectParams *params = ptr->data;
/* Simple case: Predefined repo, just set the value. */
- if (value < FILE_ASSET_LIBRARY_CUSTOM) {
+ if (value < ASSET_LIBRARY_CUSTOM) {
params->asset_library.type = value;
params->asset_library.custom_library_index = -1;
- BLI_assert(ELEM(value, FILE_ASSET_LIBRARY_LOCAL));
+ BLI_assert(ELEM(value, ASSET_LIBRARY_LOCAL));
return;
}
const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
- &U, value - FILE_ASSET_LIBRARY_CUSTOM);
+ &U, value - ASSET_LIBRARY_CUSTOM);
/* Note that the path isn't checked for validity here. If an invalid library path is used, the
* Asset Browser can give a nice hint on what's wrong. */
const bool is_valid = (user_library->name[0] && user_library->path[0]);
if (!user_library) {
- params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL;
+ params->asset_library.type = ASSET_LIBRARY_LOCAL;
params->asset_library.custom_library_index = -1;
}
else if (user_library && is_valid) {
- params->asset_library.custom_library_index = value - FILE_ASSET_LIBRARY_CUSTOM;
- params->asset_library.type = FILE_ASSET_LIBRARY_CUSTOM;
+ params->asset_library.custom_library_index = value - ASSET_LIBRARY_CUSTOM;
+ params->asset_library.type = ASSET_LIBRARY_CUSTOM;
}
}
@@ -2623,8 +2620,8 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf(
{
const EnumPropertyItem predefined_items[] = {
/* For the future. */
- // {FILE_ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
- {FILE_ASSET_LIBRARY_LOCAL,
+ // {ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"},
+ {ASSET_LIBRARY_LOCAL,
"LOCAL",
ICON_BLENDER,
"Current File",
@@ -2652,7 +2649,7 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf(
}
/* Use library path as description, it's a nice hint for users. */
- EnumPropertyItem tmp = {FILE_ASSET_LIBRARY_CUSTOM + i,
+ EnumPropertyItem tmp = {ASSET_LIBRARY_CUSTOM + i,
user_library->name,
ICON_NONE,
user_library->name,
@@ -2697,6 +2694,32 @@ static int rna_FileBrowser_FileSelectEntry_name_length(PointerRNA *ptr)
return (int)strlen(entry->name);
}
+static const EnumPropertyItem *rna_FileBrowser_FileSelectEntry_id_type_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ const FileDirEntry *entry = ptr->data;
+ if (entry->blentype == 0) {
+ static const EnumPropertyItem none_items[] = {
+ {0, "NONE", 0, "None", ""},
+ };
+ return none_items;
+ }
+
+ return rna_enum_id_type_items;
+}
+
+static int rna_FileBrowser_FileSelectEntry_id_type_get(PointerRNA *ptr)
+{
+ const FileDirEntry *entry = ptr->data;
+ return entry->blentype;
+}
+
+static PointerRNA rna_FileBrowser_FileSelectEntry_local_id_get(PointerRNA *ptr)
+{
+ const FileDirEntry *entry = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_ID, entry->id);
+}
+
static int rna_FileBrowser_FileSelectEntry_preview_icon_id_get(PointerRNA *ptr)
{
const FileDirEntry *entry = ptr->data;
@@ -2721,7 +2744,7 @@ static StructRNA *rna_FileBrowser_params_typef(PointerRNA *ptr)
return &RNA_FileAssetSelectParams;
}
- BLI_assert(!"Could not identify file select parameters");
+ BLI_assert_msg(0, "Could not identify file select parameters");
return NULL;
}
@@ -2756,7 +2779,7 @@ static void rna_FileBrowser_FSMenuEntry_path_set(PointerRNA *ptr, const char *va
{
FSMenuEntry *fsm = ptr->data;
- /* Note: this will write to file immediately.
+ /* NOTE: this will write to file immediately.
* Not nice (and to be fixed ultimately), but acceptable in this case for now. */
ED_fsmenu_entry_set_path(fsm, value);
}
@@ -2775,7 +2798,7 @@ static void rna_FileBrowser_FSMenuEntry_name_set(PointerRNA *ptr, const char *va
{
FSMenuEntry *fsm = ptr->data;
- /* Note: this will write to file immediately.
+ /* NOTE: this will write to file immediately.
* Not nice (and to be fixed ultimately), but acceptable in this case for now. */
ED_fsmenu_entry_set_name(fsm, value);
}
@@ -2980,7 +3003,7 @@ static void rna_FileBrowser_FSMenu_active_range(PointerRNA *UNUSED(ptr),
static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *ptr)
{
ScrArea *area = rna_area_from_space(ptr);
- ED_file_change_dir_ex(C, (bScreen *)ptr->owner_id, area);
+ ED_file_change_dir_ex(C, area);
}
static int rna_FileBrowser_FSMenuSystem_active_get(PointerRNA *ptr)
@@ -3177,11 +3200,9 @@ static void rna_spreadsheet_context_update(Main *UNUSED(bmain),
}
}
-static void rna_spreadsheet_set_geometry_node_context(SpaceSpreadsheet *sspreadsheet,
- SpaceNode *snode,
- bNode *node)
+static void rna_SpaceSpreadsheet_context_path_guess(SpaceSpreadsheet *sspreadsheet, bContext *C)
{
- ED_spreadsheet_set_geometry_node_context(sspreadsheet, snode, node);
+ ED_spreadsheet_context_path_guess(C, sspreadsheet);
ED_spreadsheet_context_path_update_tag(sspreadsheet);
WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
}
@@ -3196,6 +3217,45 @@ static const EnumPropertyItem dt_uv_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static struct IDFilterEnumPropertyItem rna_enum_space_file_id_filter_categories[] = {
+ /* Categories */
+ {FILTER_ID_SCE, "category_scene", ICON_SCENE_DATA, "Scenes", "Show scenes"},
+ {FILTER_ID_AC, "category_animation", ICON_ANIM_DATA, "Animations", "Show animation data"},
+ {FILTER_ID_OB | FILTER_ID_GR,
+ "category_object",
+ ICON_OUTLINER_COLLECTION,
+ "Objects & Collections",
+ "Show objects and collections"},
+ {FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA |
+ FILTER_ID_PT | FILTER_ID_VO,
+ "category_geometry",
+ ICON_NODETREE,
+ "Geometry",
+ "Show meshes, curves, lattice, armatures and metaballs data"},
+ {FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE,
+ "category_shading",
+ ICON_MATERIAL_DATA,
+ "Shading",
+ "Show materials, nodetrees, textures and Freestyle's linestyles"},
+ {FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO,
+ "category_image",
+ ICON_IMAGE_DATA,
+ "Images & Sounds",
+ "Show images, movie clips, sounds and masks"},
+ {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO,
+ "category_environment",
+ ICON_WORLD_DATA,
+ "Environment",
+ "Show worlds, lights, cameras and speakers"},
+ {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT |
+ FILTER_ID_VF | FILTER_ID_CF | FILTER_ID_WS,
+ "category_misc",
+ ICON_GREASEPENCIL,
+ "Miscellaneous",
+ "Show other data types"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int region_type_mask)
{
PropertyRNA *prop;
@@ -3438,7 +3498,7 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Opacity", "Opacity of UV overlays");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
- /* todo: move edge and face drawing options here from G.f */
+ /* TODO: move edge and face drawing options here from `G.f`. */
prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, pixel_snap_mode_items);
@@ -5073,7 +5133,7 @@ static void rna_def_space_properties(BlenderRNA *brna)
prop = RNA_def_property(srna, "pin_id", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "pinid");
RNA_def_property_struct_type(prop, "ID");
- /* note: custom set function is ONLY to avoid rna setting a user for this. */
+ /* NOTE: custom set function is ONLY to avoid rna setting a user for this. */
RNA_def_property_pointer_funcs(
prop, NULL, "rna_SpaceProperties_pin_id_set", "rna_SpaceProperties_pin_id_typef", NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
@@ -6143,142 +6203,6 @@ static void rna_def_space_console(BlenderRNA *brna)
/* Filter for datablock types in link/append. */
static void rna_def_fileselect_idfilter(BlenderRNA *brna)
{
- struct IDFilterBoolean {
- /* 64 bit, so we can't use bitflag enum. */
- const uint64_t flag;
- const char *identifier;
- const int icon;
- const char *name;
- const char *description;
- };
-
- static const struct IDFilterBoolean booleans[] = {
- /* Datablocks */
- {FILTER_ID_AC, "filter_action", ICON_ANIM_DATA, "Actions", "Show Action data-blocks"},
- {FILTER_ID_AR,
- "filter_armature",
- ICON_ARMATURE_DATA,
- "Armatures",
- "Show Armature data-blocks"},
- {FILTER_ID_BR, "filter_brush", ICON_BRUSH_DATA, "Brushes", "Show Brushes data-blocks"},
- {FILTER_ID_CA, "filter_camera", ICON_CAMERA_DATA, "Cameras", "Show Camera data-blocks"},
- {FILTER_ID_CF, "filter_cachefile", ICON_FILE, "Cache Files", "Show Cache File data-blocks"},
- {FILTER_ID_CU, "filter_curve", ICON_CURVE_DATA, "Curves", "Show Curve data-blocks"},
- {FILTER_ID_GD,
- "filter_grease_pencil",
- ICON_GREASEPENCIL,
- "Grease Pencil",
- "Show Grease pencil data-blocks"},
- {FILTER_ID_GR,
- "filter_group",
- ICON_OUTLINER_COLLECTION,
- "Collections",
- "Show Collection data-blocks"},
- {FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"},
- {FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"},
- {FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"},
- {FILTER_ID_LP,
- "filter_light_probe",
- ICON_OUTLINER_DATA_LIGHTPROBE,
- "Light Probes",
- "Show Light Probe data-blocks"},
- {FILTER_ID_LS,
- "filter_linestyle",
- ICON_LINE_DATA,
- "Freestyle Linestyles",
- "Show Freestyle's Line Style data-blocks"},
- {FILTER_ID_LT, "filter_lattice", ICON_LATTICE_DATA, "Lattices", "Show Lattice data-blocks"},
- {FILTER_ID_MA,
- "filter_material",
- ICON_MATERIAL_DATA,
- "Materials",
- "Show Material data-blocks"},
- {FILTER_ID_MB, "filter_metaball", ICON_META_DATA, "Metaballs", "Show Metaball data-blocks"},
- {FILTER_ID_MC,
- "filter_movie_clip",
- ICON_TRACKER_DATA,
- "Movie Clips",
- "Show Movie Clip data-blocks"},
- {FILTER_ID_ME, "filter_mesh", ICON_MESH_DATA, "Meshes", "Show Mesh data-blocks"},
- {FILTER_ID_MSK, "filter_mask", ICON_MOD_MASK, "Masks", "Show Mask data-blocks"},
- {FILTER_ID_NT,
- "filter_node_tree",
- ICON_NODETREE,
- "Node Trees",
- "Show Node Tree data-blocks"},
- {FILTER_ID_OB, "filter_object", ICON_OBJECT_DATA, "Objects", "Show Object data-blocks"},
- {FILTER_ID_PA,
- "filter_particle_settings",
- ICON_PARTICLE_DATA,
- "Particles Settings",
- "Show Particle Settings data-blocks"},
- {FILTER_ID_PAL, "filter_palette", ICON_COLOR, "Palettes", "Show Palette data-blocks"},
- {FILTER_ID_PC,
- "filter_paint_curve",
- ICON_CURVE_BEZCURVE,
- "Paint Curves",
- "Show Paint Curve data-blocks"},
- {FILTER_ID_PT,
- "filter_pointcloud",
- ICON_POINTCLOUD_DATA,
- "Point Clouds",
- "Show/hide Point Cloud data-blocks"},
- {FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"},
- {FILTER_ID_SIM,
- "filter_simulation",
- ICON_PHYSICS,
- "Simulations",
- "Show Simulation data-blocks"}, /* TODO: Use correct icon. */
- {FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"},
- {FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"},
- {FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"},
- {FILTER_ID_TXT, "filter_text", ICON_TEXT, "Texts", "Show Text data-blocks"},
- {FILTER_ID_VF, "filter_font", ICON_FONT_DATA, "Fonts", "Show Font data-blocks"},
- {FILTER_ID_VO, "filter_volume", ICON_VOLUME_DATA, "Volumes", "Show/hide Volume data-blocks"},
- {FILTER_ID_WO, "filter_world", ICON_WORLD_DATA, "Worlds", "Show World data-blocks"},
- {FILTER_ID_WS,
- "filter_work_space",
- ICON_WORKSPACE,
- "Workspaces",
- "Show workspace data-blocks"},
-
- /* Categories */
- {FILTER_ID_SCE, "category_scene", ICON_SCENE_DATA, "Scenes", "Show scenes"},
- {FILTER_ID_AC, "category_animation", ICON_ANIM_DATA, "Animations", "Show animation data"},
- {FILTER_ID_OB | FILTER_ID_GR,
- "category_object",
- ICON_OUTLINER_COLLECTION,
- "Objects & Collections",
- "Show objects and collections"},
- {FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA |
- FILTER_ID_PT | FILTER_ID_VO,
- "category_geometry",
- ICON_NODETREE,
- "Geometry",
- "Show meshes, curves, lattice, armatures and metaballs data"},
- {FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE,
- "category_shading",
- ICON_MATERIAL_DATA,
- "Shading",
- "Show materials, nodetrees, textures and Freestyle's linestyles"},
- {FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO,
- "category_image",
- ICON_IMAGE_DATA,
- "Images & Sounds",
- "Show images, movie clips, sounds and masks"},
- {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO,
- "category_environment",
- ICON_WORLD_DATA,
- "Environment",
- "Show worlds, lights, cameras and speakers"},
- {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT |
- FILTER_ID_VF | FILTER_ID_CF | FILTER_ID_WS,
- "category_misc",
- ICON_GREASEPENCIL,
- "Miscellaneous",
- "Show other data types"},
-
- {0, NULL, 0, NULL, NULL}};
StructRNA *srna = RNA_def_struct(brna, "FileSelectIDFilter", NULL);
RNA_def_struct_sdna(srna, "FileSelectParams");
@@ -6286,12 +6210,23 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "File Select ID Filter", "Which ID types to show/hide, when browsing a library");
- for (int i = 0; booleans[i].identifier; i++) {
- PropertyRNA *prop = RNA_def_property(srna, booleans[i].identifier, PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "filter_id", booleans[i].flag);
- RNA_def_property_ui_text(prop, booleans[i].name, booleans[i].description);
- RNA_def_property_ui_icon(prop, booleans[i].icon, 0);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ const struct IDFilterEnumPropertyItem *individual_ids_and_categories[] = {
+ rna_enum_id_type_filter_items,
+ rna_enum_space_file_id_filter_categories,
+ NULL,
+ };
+ for (uint i = 0; individual_ids_and_categories[i]; i++) {
+ for (int j = 0; individual_ids_and_categories[i][j].identifier; j++) {
+ PropertyRNA *prop = RNA_def_property(
+ srna, individual_ids_and_categories[i][j].identifier, PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "filter_id", individual_ids_and_categories[i][j].flag);
+ RNA_def_property_ui_text(prop,
+ individual_ids_and_categories[i][j].name,
+ individual_ids_and_categories[i][j].description);
+ RNA_def_property_ui_icon(prop, individual_ids_and_categories[i][j].icon, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
}
}
@@ -6311,6 +6246,28 @@ static void rna_def_fileselect_entry(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
+ prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_id_type_items);
+ RNA_def_property_enum_funcs(prop,
+ "rna_FileBrowser_FileSelectEntry_id_type_get",
+ NULL,
+ "rna_FileBrowser_FileSelectEntry_id_type_itemf");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop,
+ "Data-block Type",
+ "The type of the data-block, if the file represents one ('NONE' otherwise)");
+
+ prop = RNA_def_property(srna, "local_id", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ID");
+ RNA_def_property_pointer_funcs(
+ prop, "rna_FileBrowser_FileSelectEntry_local_id_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop,
+ "",
+ "The local data-block this file represents; only valid if that is a "
+ "data-block in this file");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
prop = RNA_def_int(
srna,
"preview_icon_id",
@@ -6547,7 +6504,7 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- /* XXX copied from rna_def_fileselect_idfilter. */
+ /* XXX copied from rna_enum_id_type_filter_items. */
static const EnumPropertyItem asset_category_items[] = {
{FILTER_ID_SCE, "SCENES", ICON_SCENE_DATA, "Scenes", "Show scenes"},
{FILTER_ID_AC, "ANIMATIONS", ICON_ANIM_DATA, "Animations", "Show animation data"},
@@ -7646,13 +7603,16 @@ static void rna_def_space_spreadsheet_context_path(BlenderRNA *brna, PropertyRNA
func = RNA_def_function(srna, "clear", "rna_SpaceSpreadsheet_context_path_clear");
RNA_def_function_ui_description(func, "Clear entire context path");
+
+ func = RNA_def_function(srna, "guess", "rna_SpaceSpreadsheet_context_path_guess");
+ RNA_def_function_ui_description(func, "Guess the context path from the current context");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
}
static void rna_def_space_spreadsheet(BlenderRNA *brna)
{
- PropertyRNA *prop, *parm;
+ PropertyRNA *prop;
StructRNA *srna;
- FunctionRNA *func;
static const EnumPropertyItem geometry_component_type_items[] = {
{GEO_COMPONENT_TYPE_MESH,
@@ -7689,6 +7649,11 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
ICON_NONE,
"Original",
"Use data from original object without any modifiers applied"},
+ {SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE,
+ "VIEWER_NODE",
+ ICON_NONE,
+ "Viewer Node",
+ "Use intermediate data from viewer node"},
{0, NULL, 0, NULL, NULL},
};
@@ -7764,16 +7729,6 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SpreadsheetRowFilter");
RNA_def_property_ui_text(prop, "Row Filters", "Filters to remove rows from the displayed data");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
-
- func = RNA_def_function(
- srna, "set_geometry_node_context", "rna_spreadsheet_set_geometry_node_context");
- RNA_def_function_ui_description(
- func, "Update context_path to point to a specific node in a node editor");
- parm = RNA_def_pointer(
- func, "node_editor", "SpaceNodeEditor", "", "Editor to take the context from");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "node", "Node", "", "");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
void RNA_def_space(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c
index c0bd9fd92a2..223e6389942 100644
--- a/source/blender/makesrna/intern/rna_timeline.c
+++ b/source/blender/makesrna/intern/rna_timeline.c
@@ -33,16 +33,10 @@
# include "BKE_idprop.h"
# include "WM_api.h"
-static IDProperty *rna_TimelineMarker_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_TimelineMarker_idprops(PointerRNA *ptr)
{
TimeMarker *marker = ptr->data;
-
- if (create && marker->prop == NULL) {
- IDPropertyTemplate val = {0};
- marker->prop = IDP_New(IDP_GROUP, &val, "Marker ID properties");
- }
-
- return marker->prop;
+ return &marker->prop;
}
static void rna_TimelineMarker_update(Main *UNUSED(bmain),
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index acf580e3ddf..a88b100435a 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -452,15 +452,31 @@ static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *UNUSED(p
return UILST_FLT_ITEM;
}
-static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_UIList_idprops(PointerRNA *ptr)
{
uiList *ui_list = (uiList *)ptr->data;
- if (create && !ui_list->properties) {
- IDPropertyTemplate val = {0};
- ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group");
+ return &ui_list->properties;
+}
+
+static void rna_UIList_list_id_get(PointerRNA *ptr, char *value)
+{
+ uiList *ui_list = (uiList *)ptr->data;
+ if (!ui_list->type) {
+ value[0] = '\0';
+ return;
+ }
+
+ strcpy(value, WM_uilisttype_list_id_get(ui_list->type, ui_list));
+}
+
+static int rna_UIList_list_id_length(PointerRNA *ptr)
+{
+ uiList *ui_list = (uiList *)ptr->data;
+ if (!ui_list->type) {
+ return 0;
}
- return ui_list->properties;
+ return strlen(WM_uilisttype_list_id_get(ui_list->type, ui_list));
}
static void uilist_draw_item(uiList *ui_list,
@@ -553,7 +569,7 @@ static void uilist_filter_items(uiList *ui_list,
RNA_parameter_dynamic_length_get(&list, parm),
"filter_flags",
len);
- /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
+ /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
filter_flags = NULL;
}
else {
@@ -569,7 +585,7 @@ static void uilist_filter_items(uiList *ui_list,
RNA_parameter_dynamic_length_get(&list, parm),
"filter_neworder",
len);
- /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
+ /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
filter_neworder = NULL;
}
else {
@@ -638,7 +654,7 @@ static void uilist_filter_items(uiList *ui_list,
RNA_parameter_list_free(&list);
}
-static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
+static void rna_UIList_unregister(Main *bmain, StructRNA *type)
{
uiListType *ult = RNA_struct_blender_type_get(type);
@@ -649,7 +665,7 @@ static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
RNA_struct_free_extension(type, &ult->rna_ext);
RNA_struct_free(&BLENDER_RNA, type);
- WM_uilisttype_freelink(ult);
+ WM_uilisttype_remove_ptr(bmain, ult);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -1019,7 +1035,7 @@ static void rna_Panel_bl_description_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_description on a non-builtin panel");
+ BLI_assert_msg(0, "setting the bl_description on a non-builtin panel");
}
}
@@ -1031,7 +1047,7 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_description on a non-builtin menu");
+ BLI_assert_msg(0, "setting the bl_description on a non-builtin menu");
}
}
@@ -1540,6 +1556,16 @@ static void rna_def_uilist(BlenderRNA *brna)
"script, then bl_idname = \"OBJECT_UL_vgroups\")");
/* Data */
+ /* Note that this is the "non-full" list-ID as obtained through #WM_uilisttype_list_id_get(),
+ * which differs from the (internal) `uiList.list_id`. */
+ prop = RNA_def_property(srna, "list_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_string_funcs(prop, "rna_UIList_list_id_get", "rna_UIList_list_id_length", NULL);
+ RNA_def_property_ui_text(prop,
+ "List Name",
+ "Identifier of the list, if any was passed to the \"list_id\" "
+ "parameter of \"template_list()\"");
+
prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_uilist_layout_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index aa235b599b7..e06cc39a88b 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -50,6 +50,8 @@ const EnumPropertyItem rna_enum_icon_items[] = {
#ifdef RNA_RUNTIME
+# include "DNA_asset_types.h"
+
const char *rna_translate_ui_text(
const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, bool translate)
{
@@ -525,6 +527,46 @@ static void rna_uiTemplateAnyID(uiLayout *layout,
uiTemplateAnyID(layout, ptr, propname, proptypename, name);
}
+void rna_uiTemplateList(uiLayout *layout,
+ struct bContext *C,
+ const char *listtype_name,
+ const char *list_id,
+ struct PointerRNA *dataptr,
+ const char *propname,
+ struct PointerRNA *active_dataptr,
+ const char *active_propname,
+ const char *item_dyntip_propname,
+ const int rows,
+ const int maxrows,
+ const int layout_type,
+ const int columns,
+ const bool sort_reverse,
+ const bool sort_lock)
+{
+ int flags = UI_TEMPLATE_LIST_FLAG_NONE;
+ if (sort_reverse) {
+ flags |= UI_TEMPLATE_LIST_SORT_REVERSE;
+ }
+ if (sort_lock) {
+ flags |= UI_TEMPLATE_LIST_SORT_LOCK;
+ }
+
+ uiTemplateList(layout,
+ C,
+ listtype_name,
+ list_id,
+ dataptr,
+ propname,
+ active_dataptr,
+ active_propname,
+ item_dyntip_propname,
+ rows,
+ maxrows,
+ layout_type,
+ columns,
+ flags);
+}
+
static void rna_uiTemplateCacheFile(uiLayout *layout,
bContext *C,
PointerRNA *ptr,
@@ -570,6 +612,69 @@ static void rna_uiTemplateEventFromKeymapItem(
uiTemplateEventFromKeymapItem(layout, name, kmi, true);
}
+static void rna_uiTemplateAssetView(uiLayout *layout,
+ bContext *C,
+ const char *list_id,
+ PointerRNA *asset_library_dataptr,
+ const char *asset_library_propname,
+ PointerRNA *assets_dataptr,
+ const char *assets_propname,
+ PointerRNA *active_dataptr,
+ const char *active_propname,
+ int filter_id_types,
+ const char *activate_opname,
+ PointerRNA *r_activate_op_properties,
+ const char *drag_opname,
+ PointerRNA *r_drag_op_properties)
+{
+ AssetFilterSettings filter_settings = {
+ .id_types = filter_id_types ? filter_id_types : FILTER_ID_ALL,
+ };
+ uiTemplateAssetView(layout,
+ C,
+ list_id,
+ asset_library_dataptr,
+ asset_library_propname,
+ assets_dataptr,
+ assets_propname,
+ active_dataptr,
+ active_propname,
+ &filter_settings,
+ activate_opname,
+ r_activate_op_properties,
+ drag_opname,
+ r_drag_op_properties);
+}
+
+/**
+ * XXX Remove filter items that require more than 32 bits for storage. RNA enums don't support
+ * that currently.
+ */
+static const EnumPropertyItem *rna_uiTemplateAssetView_filter_id_types_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem *items = NULL;
+ int totitem = 0;
+
+ for (int i = 0; rna_enum_id_type_filter_items[i].identifier; i++) {
+ if (rna_enum_id_type_filter_items[i].flag > (1ULL << 31)) {
+ continue;
+ }
+
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ tmp.value = rna_enum_id_type_filter_items[i].flag;
+ tmp.identifier = rna_enum_id_type_filter_items[i].identifier;
+ tmp.icon = rna_enum_id_type_filter_items[i].icon;
+ tmp.name = rna_enum_id_type_filter_items[i].name;
+ tmp.description = rna_enum_id_type_filter_items[i].description;
+ RNA_enum_item_add(&items, &totitem, &tmp);
+ }
+ RNA_enum_item_end(&items, &totitem);
+
+ *r_free = true;
+ return items;
+}
+
static uiLayout *rna_uiLayoutRowWithHeading(
uiLayout *layout, bool align, const char *heading, const char *heading_ctxt, bool translate)
{
@@ -1508,7 +1613,7 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "clip_user", "MovieClipUser", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- func = RNA_def_function(srna, "template_list", "uiTemplateList");
+ func = RNA_def_function(srna, "template_list", "rna_uiTemplateList");
RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups.");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_string(func, "listtype_name", NULL, 0, "", "Identifier of the list type to use");
@@ -1689,6 +1794,81 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_property_ui_text(parm, "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
api_ui_item_common_text(func);
+
+ func = RNA_def_function(srna, "template_asset_view", "rna_uiTemplateAssetView");
+ RNA_def_function_ui_description(func, "Item. A scrollable list of assets in a grid view");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm = RNA_def_string(func,
+ "list_id",
+ NULL,
+ 0,
+ "",
+ "Identifier of this asset view. Necessary to tell apart different asset "
+ "views and to idenify an asset view read from a .blend");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func,
+ "asset_library_dataptr",
+ "AnyType",
+ "",
+ "Data from which to take the active asset library property");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(
+ func, "asset_library_propname", NULL, 0, "", "Identifier of the asset library property");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(
+ func, "assets_dataptr", "AnyType", "", "Data from which to take the asset list property");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(
+ func, "assets_propname", NULL, 0, "", "Identifier of the asset list property");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func,
+ "active_dataptr",
+ "AnyType",
+ "",
+ "Data from which to take the integer property, index of the active item");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(
+ func,
+ "active_propname",
+ NULL,
+ 0,
+ "",
+ "Identifier of the integer property in active_data, index of the active item");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_property(func, "filter_id_types", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(parm, DummyRNA_NULL_items);
+ RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_uiTemplateAssetView_filter_id_types_itemf");
+ RNA_def_property_flag(parm, PROP_ENUM_FLAG);
+ RNA_def_string(func,
+ "activate_operator",
+ NULL,
+ 0,
+ "",
+ "Name of a custom operator to invoke when activating an item");
+ parm = RNA_def_pointer(
+ func,
+ "activate_operator_properties",
+ "OperatorProperties",
+ "",
+ "Operator properties to fill in for the custom activate operator passed to the template");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_output(func, parm);
+ RNA_def_string(func,
+ "drag_operator",
+ NULL,
+ 0,
+ "",
+ "Name of a custom operator to invoke when starting to drag an item. Never "
+ "invoked together with the `active_operator` (if set), it's either the drag or "
+ "the activate one");
+ parm = RNA_def_pointer(
+ func,
+ "drag_operator_properties",
+ "OperatorProperties",
+ "",
+ "Operator properties to fill in for the custom drag operator passed to the template");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_output(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 3b7af07479c..d29a90a1886 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -809,14 +809,9 @@ static const EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C
}
# endif
-static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_AddonPref_idprops(PointerRNA *ptr)
{
- if (create && !ptr->data) {
- IDPropertyTemplate val = {0};
- ptr->data = IDP_New(IDP_GROUP, &val, "RNA_AddonPreferences group");
- }
-
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr)
@@ -1105,7 +1100,7 @@ int rna_show_statusbar_vram_editable(struct PointerRNA *UNUSED(ptr), const char
static size_t max_memory_in_megabytes(void)
{
/* Maximum addressable bytes on this platform. */
- const size_t limit_bytes = (((size_t)1) << ((sizeof(size_t[8])) - 1));
+ const size_t limit_bytes = (((size_t)1) << (sizeof(size_t[8]) - 1));
/* Convert it to megabytes and return. */
return (limit_bytes >> 20);
}
@@ -3460,7 +3455,7 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna)
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(
prop, "Keyframe Scale Factor", "Scale factor for adjusting the height of keyframes");
- /* Note: These limits prevent buttons overlapping (min), and excessive size... (max) */
+ /* NOTE: These limits prevent buttons overlapping (min), and excessive size... (max). */
RNA_def_property_range(prop, 0.8f, 5.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, "rna_userdef_theme_update");
@@ -6161,7 +6156,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
"Python Scripts Directory",
"Alternate script path, matching the default layout with subdirectories: "
"startup, addons, modules, and presets (requires restart)");
- /* TODO, editing should reset sys.path! */
+ /* TODO: editing should reset sys.path! */
prop = RNA_def_property(srna, "i18n_branches_directory", PROP_STRING, PROP_DIRPATH);
RNA_def_property_string_sdna(prop, NULL, "i18ndir");
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index a563541b968..2a4abac04f8 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -568,14 +568,9 @@ static StructRNA *rna_OperatorProperties_refine(PointerRNA *ptr)
}
}
-static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_OperatorProperties_idprops(PointerRNA *ptr)
{
- if (create && !ptr->data) {
- IDPropertyTemplate val = {0};
- ptr->data = IDP_New(IDP_GROUP, &val, "RNA_OperatorProperties group");
- }
-
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
static void rna_Operator_name_get(PointerRNA *ptr, char *value)
@@ -1120,13 +1115,9 @@ static PointerRNA rna_wmKeyConfig_preferences_get(PointerRNA *ptr)
}
}
-static IDProperty *rna_wmKeyConfigPref_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_wmKeyConfigPref_idprops(PointerRNA *ptr)
{
- if (create && !ptr->data) {
- IDPropertyTemplate val = {0};
- ptr->data = IDP_New(IDP_GROUP, &val, "RNA_KeyConfigPreferences group");
- }
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
static void rna_wmKeyConfigPref_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -1774,7 +1765,7 @@ static void rna_Operator_bl_idname_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_idname on a non-builtin operator");
+ BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator");
}
}
@@ -1786,7 +1777,7 @@ static void rna_Operator_bl_label_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_label on a non-builtin operator");
+ BLI_assert_msg(0, "setting the bl_label on a non-builtin operator");
}
}
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index e7ca41bb5be..bde15daa682 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -641,7 +641,7 @@ static wmEvent *rna_Window_event_add_simulate(wmWindow *win,
e.is_repeat = false;
e.x = x;
e.y = y;
- /* Note: KM_MOD_FIRST, KM_MOD_SECOND aren't used anywhere, set as bools */
+ /* NOTE: KM_MOD_FIRST, KM_MOD_SECOND aren't used anywhere, set as bools. */
e.shift = shift;
e.ctrl = ctrl;
e.alt = alt;
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index e91df38c96e..6a1574f3dbe 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -244,7 +244,7 @@ static void rna_Gizmo_bl_idname_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_idname on a non-builtin operator");
+ BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator");
}
}
@@ -293,14 +293,9 @@ static StructRNA *rna_GizmoProperties_refine(PointerRNA *ptr)
}
}
-static IDProperty *rna_GizmoProperties_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_GizmoProperties_idprops(PointerRNA *ptr)
{
- if (create && !ptr->data) {
- IDPropertyTemplate val = {0};
- ptr->data = IDP_New(IDP_GROUP, &val, "RNA_GizmoProperties group");
- }
-
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
static PointerRNA rna_Gizmo_properties_get(PointerRNA *ptr)
@@ -585,14 +580,9 @@ static StructRNA *rna_GizmoGroupProperties_refine(PointerRNA *ptr)
}
}
-static IDProperty *rna_GizmoGroupProperties_idprops(PointerRNA *ptr, bool create)
+static IDProperty **rna_GizmoGroupProperties_idprops(PointerRNA *ptr)
{
- if (create && !ptr->data) {
- IDPropertyTemplate val = {0};
- ptr->data = IDP_New(IDP_GROUP, &val, "RNA_GizmoGroupProperties group");
- }
-
- return ptr->data;
+ return (IDProperty **)&ptr->data;
}
static wmGizmo *rna_GizmoGroup_gizmo_new(wmGizmoGroup *gzgroup,
@@ -653,7 +643,7 @@ static void rna_GizmoGroup_bl_idname_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_idname on a non-builtin operator");
+ BLI_assert_msg(0, "setting the bl_idname on a non-builtin operator");
}
}
@@ -665,7 +655,7 @@ static void rna_GizmoGroup_bl_label_set(PointerRNA *ptr, const char *value)
BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */
}
else {
- BLI_assert(!"setting the bl_label on a non-builtin operator");
+ BLI_assert_msg(0, "setting the bl_label on a non-builtin operator");
}
}
@@ -1097,7 +1087,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_pointer(func, "event", "Event", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- /* TODO, should be a enum-flag */
+ /* TODO: should be a enum-flag. */
parm = RNA_def_enum_flag(func, "tweak", tweak_actions, 0, "Tweak", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_enum_flag(
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo_api.c b/source/blender/makesrna/intern/rna_wm_gizmo_api.c
index b4b7e02a95b..d6f2ffca65f 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo_api.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo_api.c
@@ -263,7 +263,7 @@ void RNA_api_gizmo(StructRNA *srna)
/* Property API */
/* Define Properties */
- /* note, 'target_set_handler' is defined in 'bpy_rna_gizmo.c' */
+ /* NOTE: 'target_set_handler' is defined in `bpy_rna_gizmo.c`. */
func = RNA_def_function(srna, "target_set_prop", "rna_gizmo_target_set_prop");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "");
@@ -292,7 +292,7 @@ void RNA_api_gizmo(StructRNA *srna)
RNA_def_function_return(func, parm);
/* Access Properties */
- /* note, 'target_get', 'target_set' is defined in 'bpy_rna_gizmo.c' */
+ /* NOTE: 'target_get', 'target_set' is defined in `bpy_rna_gizmo.c`. */
func = RNA_def_function(srna, "target_is_valid", "rna_gizmo_target_is_valid");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_string(func, "property", NULL, 0, "", "Property identifier");
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 6b52a38c2da..b053bb0ff62 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -107,6 +107,18 @@ static void rna_WorkSpace_owner_ids_clear(WorkSpace *workspace)
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, workspace);
}
+static int rna_WorkSpace_active_asset_library_get(PointerRNA *ptr)
+{
+ const WorkSpace *workspace = ptr->data;
+ return rna_asset_library_reference_get(&workspace->active_asset_library);
+}
+
+static void rna_WorkSpace_active_asset_library_set(PointerRNA *ptr, int value)
+{
+ WorkSpace *workspace = ptr->data;
+ rna_asset_library_reference_set(&workspace->active_asset_library, value);
+}
+
static bToolRef *rna_WorkSpace_tools_from_tkey(WorkSpace *workspace,
const bToolKey *tkey,
bool create)
@@ -407,6 +419,14 @@ static void rna_def_workspace(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use UI Tags", "Filter the UI by tags");
RNA_def_property_update(prop, 0, "rna_window_update_all");
+ prop = rna_def_asset_library_reference_common(
+ srna, "rna_WorkSpace_active_asset_library_get", "rna_WorkSpace_active_asset_library_set");
+ RNA_def_property_ui_text(prop,
+ "Asset Library",
+ "Active asset library to show in the UI, not used by the Asset Browser "
+ "(which has its own active asset library)");
+ RNA_def_property_update(prop, NC_ASSET | ND_ASSET_LIST_READING, NULL);
+
RNA_api_workspace(srna);
}
diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py
index 61622f281a6..f5e5e32ee76 100755
--- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py
+++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py
@@ -229,7 +229,7 @@ def sort(props_list, sort_priority):
def file_basename(input_filename):
- # if needed will use os.path
+ # If needed will use `os.path`.
if input_filename.endswith(".txt"):
if input_filename.endswith("_work.txt"):
base_filename = input_filename.replace("_work.txt", "")
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 649d36e3d57..828b8b79664 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -37,6 +37,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
@@ -122,7 +123,8 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
/* If neither vertex groups nor envelopes are used, the modifier has no bone dependencies. */
if ((amd->deformflag & ARM_DEF_VGROUP) != 0) {
/* Enumerate groups that match existing bones. */
- LISTBASE_FOREACH (bDeformGroup *, dg, &ctx->object->defbase) {
+ const ListBase *defbase = BKE_object_defgroup_list(ctx->object);
+ LISTBASE_FOREACH (bDeformGroup *, dg, defbase) {
if (BKE_pose_channel_find_name(amd->object->pose, dg->name) != NULL) {
/* Can't check BONE_NO_DEFORM because it can be animated. */
DEG_add_bone_relation(
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index c5e3833aa4a..722614c4831 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -427,7 +427,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
}
}
- /* Build up offset array, cumulating all settings options */
+ /* Build up offset array, accumulating all settings options. */
unit_m4(offset);
src_mvert = mesh->mvert;
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc
index 4b9b24e4e47..bdb791dc8e7 100644
--- a/source/blender/modifiers/intern/MOD_boolean.cc
+++ b/source/blender/modifiers/intern/MOD_boolean.cc
@@ -109,7 +109,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
- walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_USER);
walk(userData, ob, (ID **)&bmd->object, IDWALK_CB_NOP);
}
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index c38e5126f6b..52f21e3d3d0 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -101,7 +101,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
range_vn_i(faceMap, numPoly_src, 0);
struct Scene *scene = DEG_get_input_scene(ctx->depsgraph);
- frac = (BKE_scene_frame_get(scene) - bmd->start) / bmd->length;
+ frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length;
CLAMP(frac, 0.0f, 1.0f);
if (bmd->flag & MOD_BUILD_FLAG_REVERSE) {
frac = 1.0f - frac;
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 40d027f3044..4487adcfdda 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -206,6 +206,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
tclmd->point_cache->step = clmd->point_cache->step;
tclmd->point_cache->startframe = clmd->point_cache->startframe;
tclmd->point_cache->endframe = clmd->point_cache->endframe;
+ tclmd->point_cache->flag |= (clmd->point_cache->flag & PTCACHE_FLAGS_COPY);
}
}
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index fef235b456b..9e8f5bee396 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -267,7 +267,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
{
const float eps = FLT_EPSILON * 10.0f;
const uint numEdges = (uint)mesh->totedge;
- /* note: the way this smoothing method works, its approx half as strong as the simple-smooth,
+ /* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth,
* and 2.0 rarely spikes, double the value for consistent behavior. */
const float lambda = csmd->lambda * 2.0f;
const MEdge *edges = mesh->medge;
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 20dbb299767..aae6d257766 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -167,7 +167,7 @@ static void deformVertsEM(ModifierData *md,
int defgrp_index = -1;
if (ctx->object->type == OB_MESH && cmd->name[0] != '\0') {
- defgrp_index = BKE_object_defgroup_name_index(ctx->object, cmd->name);
+ defgrp_index = BKE_id_defgroup_name_index(&mesh->id, cmd->name);
if (defgrp_index != -1) {
use_dverts = true;
}
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index dbdc76f0edc..e2b2cc58d48 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -203,7 +203,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
BKE_reports_init(&reports, RPT_STORE);
- /* Note: no islands precision for now here. */
+ /* NOTE: no islands precision for now here. */
if (BKE_object_data_transfer_ex(ctx->depsgraph,
scene,
ob_source,
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 4e53243d820..bf197dca7e5 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -756,9 +756,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
/* override original facepa (original pointer is saved in caller function) */
- /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are
+ /* TODO(campbell): `(totfsplit * 2)` over allocation is used since the quads are
* later interpreted as tri's, for this to work right I think we probably
- * have to stop using tessface - campbell */
+ * have to stop using tessface. */
facepa = MEM_calloc_arrayN((totface + (totfsplit * 2)), sizeof(int), "explode_facepa");
// memcpy(facepa, emd->facepa, totface*sizeof(int));
@@ -919,7 +919,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
EdgeHashIterator *ehi;
float *vertco = NULL, imat[4][4];
float rot[4];
- float cfra;
+ float ctime;
/* float timestep; */
const int *facepa = emd->facepa;
int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
@@ -940,7 +940,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
/* timestep = psys_get_timestep(&sim); */
- cfra = BKE_scene_frame_get(scene);
+ ctime = BKE_scene_ctime_get(scene);
/* hash table for vertice <-> particle relations */
vertpahash = BLI_edgehash_new(__func__);
@@ -962,7 +962,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
/* do mindex + totvert to ensure the vertex index to be the first
* with BLI_edgehashIterator_getKey */
- if (pa == NULL || cfra < pa->time) {
+ if (pa == NULL || ctime < pa->time) {
mindex = totvert + totpart;
}
else {
@@ -1022,7 +1022,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
psys_get_birth_coords(&sim, pa, &birth, 0, 0);
- state.time = cfra;
+ state.time = ctime;
psys_get_particle_state(&sim, ed_v2, &state, 1);
vertco = explode->mvert[v].co;
@@ -1076,7 +1076,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
orig_v4 = source.v4;
/* Same as above in the first loop over mesh's faces. */
- if (pa == NULL || cfra < pa->time) {
+ if (pa == NULL || ctime < pa->time) {
mindex = totvert + totpart;
}
else {
@@ -1096,7 +1096,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
/* override uv channel for particle age */
if (mtface) {
- float age = (pa != NULL) ? (cfra - pa->time) / pa->lifetime : 0.0f;
+ float age = (pa != NULL) ? (ctime - pa->time) / pa->lifetime : 0.0f;
/* Clamp to this range to avoid flipping to the other side of the coordinates. */
CLAMP(age, 0.001f, 0.999f);
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index ff581e92cdd..18ce37c5d85 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -94,7 +94,7 @@ static void requiredDataMask(Object *UNUSED(ob),
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
}
if (hmd->indexar != NULL) {
- /* TODO check which origindex are actually needed? */
+ /* TODO: check which origindex are actually needed? */
r_cddata_masks->vmask |= CD_MASK_ORIGINDEX;
r_cddata_masks->emask |= CD_MASK_ORIGINDEX;
r_cddata_masks->pmask |= CD_MASK_ORIGINDEX;
diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc
index a77f6cfe8ba..9aa8e3dd7c8 100644
--- a/source/blender/modifiers/intern/MOD_mask.cc
+++ b/source/blender/modifiers/intern/MOD_mask.cc
@@ -119,7 +119,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
/* A vertex will be in the mask if a selected bone influences it more than a certain threshold. */
static void compute_vertex_mask__armature_mode(MDeformVert *dvert,
- Object *ob,
+ Mesh *mesh,
Object *armature_ob,
float threshold,
MutableSpan<bool> r_vertex_mask)
@@ -127,7 +127,7 @@ static void compute_vertex_mask__armature_mode(MDeformVert *dvert,
/* Element i is true if there is a selected bone that uses vertex group i. */
Vector<bool> selected_bone_uses_group;
- for (bDeformGroup *def : ListBaseWrapper<bDeformGroup>(ob->defbase)) {
+ LISTBASE_FOREACH (bDeformGroup *, def, &mesh->vertex_group_names) {
bPoseChannel *pchan = BKE_pose_channel_find_name(armature_ob->pose, def->name);
bool bone_for_group_exists = pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED);
selected_bone_uses_group.append(bone_for_group_exists);
@@ -325,10 +325,9 @@ void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
* 2. Find edges and polygons only using those vertices.
* 3. Create a new mesh that only uses the found vertices, edges and polygons.
*/
-static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
+static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh)
{
MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md);
- Object *ob = ctx->object;
const bool invert_mask = mmd->flag & MOD_MASK_INV;
/* Return empty or input mesh when there are no vertex groups. */
@@ -339,7 +338,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Quick test to see if we can return early. */
if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (mesh->totvert == 0) ||
- BLI_listbase_is_empty(&ob->defbase)) {
+ BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
@@ -348,15 +347,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
Object *armature_ob = mmd->ob_arm;
/* Return input mesh if there is no armature with bones. */
- if (ELEM(NULL, armature_ob, armature_ob->pose, ob->defbase.first)) {
+ if (ELEM(NULL, armature_ob, armature_ob->pose)) {
return mesh;
}
vertex_mask = Array<bool>(mesh->totvert);
- compute_vertex_mask__armature_mode(dvert, ob, armature_ob, mmd->threshold, vertex_mask);
+ compute_vertex_mask__armature_mode(dvert, mesh, armature_ob, mmd->threshold, vertex_mask);
}
else {
- int defgrp_index = BKE_object_defgroup_name_index(ob, mmd->vgroup);
+ int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, mmd->vgroup);
/* Return input mesh if the vertex group does not exist. */
if (defgrp_index == -1) {
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index 6ec3277ee7a..e0507320628 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -104,20 +104,20 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
/* -------------------------------------------------------------------- */
/* Interpret Time (the reading functions also do some of this ) */
if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) {
- const float cfra = BKE_scene_frame_get(scene);
+ const float ctime = BKE_scene_ctime_get(scene);
switch (mcmd->time_mode) {
case MOD_MESHCACHE_TIME_FRAME: {
- time = cfra;
+ time = ctime;
break;
}
case MOD_MESHCACHE_TIME_SECONDS: {
- time = cfra / fps;
+ time = ctime / fps;
break;
}
case MOD_MESHCACHE_TIME_FACTOR:
default: {
- time = cfra / fps;
+ time = ctime / fps;
break;
}
}
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index f7f7c7b0276..87fce26c45e 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -48,6 +48,7 @@
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
+#include "BKE_attribute_math.hh"
#include "BKE_customdata.h"
#include "BKE_geometry_set_instances.hh"
#include "BKE_global.h"
@@ -56,7 +57,6 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
-#include "BKE_node_ui_storage.hh"
#include "BKE_object.h"
#include "BKE_pointcloud.h"
#include "BKE_screen.h"
@@ -83,8 +83,10 @@
#include "NOD_derived_node_tree.hh"
#include "NOD_geometry.h"
+#include "NOD_geometry_nodes_eval_log.hh"
#include "NOD_node_tree_multi_function.hh"
+using blender::destruct_ptr;
using blender::float3;
using blender::FunctionRef;
using blender::IndexRange;
@@ -97,6 +99,7 @@ using blender::Vector;
using blender::fn::GMutablePointer;
using blender::fn::GPointer;
using blender::nodes::GeoNodeExecParams;
+using blender::threading::EnumerableThreadSpecific;
using namespace blender::fn::multi_function_types;
using namespace blender::nodes::derived_node_tree_types;
@@ -734,19 +737,6 @@ static void initialize_group_input(NodesModifierData &nmd,
property_type->init_cpp_value(*property, r_value);
}
-static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> trees,
- const Object &object,
- const ModifierData &modifier)
-{
- const NodeTreeEvaluationContext context = {object, modifier};
-
- for (const blender::nodes::NodeTreeRef *tree : trees) {
- bNodeTree *btree_cow = tree->btree();
- bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow);
- BKE_nodetree_ui_storage_free_for_context(*btree_original, context);
- }
-}
-
static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain)
{
wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
@@ -766,24 +756,6 @@ static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain)
return spreadsheets;
}
-using PreviewSocketMap = blender::MultiValueMap<DSocket, uint64_t>;
-
-static DSocket try_find_preview_socket_in_node(const DNode node)
-{
- for (const SocketRef *socket : node->outputs()) {
- if (socket->bsocket()->type == SOCK_GEOMETRY) {
- return {node.context(), socket};
- }
- }
- for (const SocketRef *socket : node->inputs()) {
- if (socket->bsocket()->type == SOCK_GEOMETRY &&
- (socket->bsocket()->flag & SOCK_MULTI_INPUT) == 0) {
- return {node.context(), socket};
- }
- }
- return {};
-}
-
static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet,
NodesModifierData *nmd,
const ModifierEvalContext *ctx,
@@ -837,9 +809,10 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre
}
const NodeTreeRef &tree_ref = context->tree();
- for (const NodeRef *node_ref : tree_ref.nodes()) {
+ for (const NodeRef *node_ref : tree_ref.nodes_by_type("GeometryNodeViewer")) {
if (node_ref->name() == last_context->node_name) {
- return try_find_preview_socket_in_node({context, node_ref});
+ const DNode viewer_node{context, node_ref};
+ return viewer_node.input(0);
}
}
return {};
@@ -848,7 +821,7 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre
static void find_sockets_to_preview(NodesModifierData *nmd,
const ModifierEvalContext *ctx,
const DerivedNodeTree &tree,
- PreviewSocketMap &r_sockets_to_preview)
+ Set<DSocket> &r_sockets_to_preview)
{
Main *bmain = DEG_get_bmain(ctx->depsgraph);
@@ -858,51 +831,16 @@ static void find_sockets_to_preview(NodesModifierData *nmd,
for (SpaceSpreadsheet *sspreadsheet : spreadsheets) {
const DSocket socket = try_get_socket_to_preview_for_spreadsheet(sspreadsheet, nmd, ctx, tree);
if (socket) {
- const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet);
- r_sockets_to_preview.add_non_duplicates(socket, key);
+ r_sockets_to_preview.add(socket);
}
}
}
-static void log_preview_socket_value(const Span<GPointer> values,
- Object *object,
- Span<uint64_t> keys)
+static void clear_runtime_data(NodesModifierData *nmd)
{
- GeometrySet geometry_set = *(const GeometrySet *)values[0].get();
- geometry_set.ensure_owns_direct_data();
- for (uint64_t key : keys) {
- BKE_object_preview_geometry_set_add(object, key, new GeometrySet(geometry_set));
- }
-}
-
-static void log_ui_hints(const DSocket socket,
- const Span<GPointer> values,
- Object *self_object,
- NodesModifierData *nmd)
-{
- const DNode node = socket.node();
- if (node->is_reroute_node() || socket->typeinfo()->type != SOCK_GEOMETRY) {
- return;
- }
- bNodeTree *btree_cow = node->btree();
- bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow);
- const NodeTreeEvaluationContext context{*self_object, nmd->modifier};
- for (const GPointer &data : values) {
- if (data.type() == &CPPType::get<GeometrySet>()) {
- const GeometrySet &geometry_set = *(const GeometrySet *)data.get();
- blender::bke::geometry_set_instances_attribute_foreach(
- geometry_set,
- [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) {
- BKE_nodetree_attribute_hint_add(*btree_original,
- context,
- *node->bnode(),
- attribute_name,
- meta_data.domain,
- meta_data.data_type);
- return true;
- },
- 8);
- }
+ if (nmd->runtime_eval_log != nullptr) {
+ delete (geo_log::ModifierLog *)nmd->runtime_eval_log;
+ nmd->runtime_eval_log = nullptr;
}
}
@@ -958,30 +896,32 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
Vector<DInputSocket> group_outputs;
group_outputs.append({root_context, &socket_to_compute});
- PreviewSocketMap preview_sockets;
- find_sockets_to_preview(nmd, ctx, tree, preview_sockets);
-
- auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) {
- if (!logging_enabled(ctx)) {
- return;
- }
- Span<uint64_t> keys = preview_sockets.lookup(socket);
- if (!keys.is_empty()) {
- log_preview_socket_value(values, ctx->object, keys);
- }
- log_ui_hints(socket, values, ctx->object, nmd);
- };
+ std::optional<geo_log::GeoLogger> geo_logger;
blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params;
+
+ if (logging_enabled(ctx)) {
+ Set<DSocket> preview_sockets;
+ find_sockets_to_preview(nmd, ctx, tree, preview_sockets);
+ eval_params.force_compute_sockets.extend(preview_sockets.begin(), preview_sockets.end());
+ geo_logger.emplace(std::move(preview_sockets));
+ }
+
eval_params.input_values = group_inputs;
eval_params.output_sockets = group_outputs;
eval_params.mf_by_node = &mf_by_node;
eval_params.modifier_ = nmd;
eval_params.depsgraph = ctx->depsgraph;
eval_params.self_object = ctx->object;
- eval_params.log_socket_value_fn = log_socket_value;
+ eval_params.geo_logger = geo_logger.has_value() ? &*geo_logger : nullptr;
blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params);
+ if (geo_logger.has_value()) {
+ NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(&nmd->modifier);
+ clear_runtime_data(nmd_orig);
+ nmd_orig->runtime_eval_log = new geo_log::ModifierLog(*geo_logger);
+ }
+
BLI_assert(eval_params.r_output_values.size() == 1);
GMutablePointer result = eval_params.r_output_values[0];
return result.relocate_out<GeometrySet>();
@@ -1071,10 +1011,6 @@ static void modifyGeometry(ModifierData *md,
return;
}
- if (logging_enabled(ctx)) {
- reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md);
- }
-
geometry_set = compute_geometry(
tree, input_nodes, *group_outputs[0], std::move(geometry_set), nmd, ctx);
}
@@ -1082,13 +1018,14 @@ static void modifyGeometry(ModifierData *md,
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
{
GeometrySet geometry_set = GeometrySet::create_with_mesh(mesh, GeometryOwnershipType::Editable);
- geometry_set.get_component_for_write<MeshComponent>().copy_vertex_group_names_from_object(
- *ctx->object);
+
modifyGeometry(md, ctx, geometry_set);
- /* This function is only called when applying modifiers. In this case it makes sense to realize
- * instances, otherwise in some cases there might be no results when applying the modifier. */
- geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set);
+ if (ctx->flag & MOD_APPLY_TO_BASE_MESH) {
+ /* In this case it makes sense to realize instances, otherwise in some cases there might be no
+ * results when applying the modifier. */
+ geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set);
+ }
Mesh *new_mesh = geometry_set.get_component_for_write<MeshComponent>().release();
if (new_mesh == nullptr) {
@@ -1219,6 +1156,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md)
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
BLO_read_data_address(reader, &nmd->settings.properties);
IDP_BlendDataRead(reader, &nmd->settings.properties);
+ nmd->runtime_eval_log = nullptr;
}
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
@@ -1228,6 +1166,8 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
BKE_modifier_copydata_generic(md, target, flag);
+ tnmd->runtime_eval_log = nullptr;
+
if (nmd->settings.properties != nullptr) {
tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag);
}
@@ -1240,6 +1180,8 @@ static void freeData(ModifierData *md)
IDP_FreeProperty_ex(nmd->settings.properties, false);
nmd->settings.properties = nullptr;
}
+
+ clear_runtime_data(nmd);
}
static void requiredDataMask(Object *UNUSED(ob),
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index c2f2f358b9e..cf18f60ec22 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -411,6 +411,9 @@ class GeometryNodesEvaluator {
for (const DInputSocket &socket : params_.output_sockets) {
nodes_to_check.push(socket.node());
}
+ for (const DSocket &socket : params_.force_compute_sockets) {
+ nodes_to_check.push(socket.node());
+ }
/* Use the local allocator because the states do not need to outlive the evaluator. */
LinearAllocator<> &allocator = local_allocators_.local();
while (!nodes_to_check.is_empty()) {
@@ -544,7 +547,8 @@ class GeometryNodesEvaluator {
},
{});
if (output_state.potential_users == 0) {
- /* If it does not have any potential users, it is unused. */
+ /* If it does not have any potential users, it is unused. It might become required again in
+ * `schedule_initial_nodes`. */
output_state.output_usage = ValueUsage::Unused;
}
}
@@ -622,11 +626,11 @@ class GeometryNodesEvaluator {
for (auto &&item : params_.input_values.items()) {
const DOutputSocket socket = item.key;
GMutablePointer value = item.value;
- this->log_socket_value(socket, value);
const DNode node = socket.node();
if (!node_states_.contains_as(node)) {
/* The socket is not connected to any output. */
+ this->log_socket_value({socket}, value);
value.destruct();
continue;
}
@@ -644,6 +648,20 @@ class GeometryNodesEvaluator {
this->set_input_required(locked_node, socket);
});
}
+ for (const DSocket socket : params_.force_compute_sockets) {
+ const DNode node = socket.node();
+ NodeState &node_state = this->get_node_state(node);
+ this->with_locked_node(node, node_state, [&](LockedNode &locked_node) {
+ if (socket->is_input()) {
+ this->set_input_required(locked_node, DInputSocket(socket));
+ }
+ else {
+ OutputState &output_state = node_state.outputs[socket->index()];
+ output_state.output_usage = ValueUsage::Required;
+ this->schedule_node(locked_node);
+ }
+ });
+ }
}
void schedule_node(LockedNode &locked_node)
@@ -830,7 +848,6 @@ class GeometryNodesEvaluator {
/* Checks if all the linked sockets have been provided already. */
if (multi_value.items.size() == multi_value.expected_size) {
input_state.was_ready_for_execution = true;
- this->log_socket_value(socket, input_state, multi_value.items);
}
else if (is_required) {
/* The input is required but is not fully provided yet. Therefore the node cannot be
@@ -842,7 +859,6 @@ class GeometryNodesEvaluator {
SingleInputValue &single_value = *input_state.value.single;
if (single_value.value != nullptr) {
input_state.was_ready_for_execution = true;
- this->log_socket_value(socket, GPointer{input_state.type, single_value.value});
}
else if (is_required) {
/* The input is required but has not been provided yet. Therefore the node cannot be
@@ -1192,10 +1208,14 @@ class GeometryNodesEvaluator {
this->with_locked_node(node, node_state, [&](LockedNode &locked_node) {
output_state.potential_users -= 1;
if (output_state.potential_users == 0) {
- /* The output socket has no users anymore. */
- output_state.output_usage = ValueUsage::Unused;
- /* Schedule the origin node in case it wants to set its inputs as unused as well. */
- this->schedule_node(locked_node);
+ /* The socket might be required even though the output is not used by other sockets. That
+ * can happen when the socket is forced to be computed. */
+ if (output_state.output_usage != ValueUsage::Required) {
+ /* The output socket has no users anymore. */
+ output_state.output_usage = ValueUsage::Unused;
+ /* Schedule the origin node in case it wants to set its inputs as unused as well. */
+ this->schedule_node(locked_node);
+ }
}
});
}
@@ -1216,16 +1236,17 @@ class GeometryNodesEvaluator {
{
BLI_assert(value_to_forward.get() != nullptr);
+ Vector<DSocket> sockets_to_log_to;
+ sockets_to_log_to.append(from_socket);
+
Vector<DInputSocket> to_sockets;
auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) {
if (this->should_forward_to_socket(to_socket)) {
to_sockets.append(to_socket);
}
};
- auto handle_skipped_socket_fn = [&, this](const DSocket socket) {
- /* Log socket value on intermediate sockets to support e.g. attribute search or spreadsheet
- * breadcrumbs on group nodes. */
- this->log_socket_value(socket, value_to_forward);
+ auto handle_skipped_socket_fn = [&](const DSocket socket) {
+ sockets_to_log_to.append(socket);
};
from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn);
@@ -1238,11 +1259,18 @@ class GeometryNodesEvaluator {
if (from_type == to_type) {
/* All target sockets that do not need a conversion will be handled afterwards. */
to_sockets_same_type.append(to_socket);
+ /* Multi input socket values are logged once all values are available. */
+ if (!to_socket->is_multi_input_socket()) {
+ sockets_to_log_to.append(to_socket);
+ }
continue;
}
this->forward_to_socket_with_different_type(
allocator, value_to_forward, from_socket, to_socket, to_type);
}
+
+ this->log_socket_value(sockets_to_log_to, value_to_forward);
+
this->forward_to_sockets_with_same_type(
allocator, to_sockets_same_type, value_to_forward, from_socket);
}
@@ -1273,6 +1301,7 @@ class GeometryNodesEvaluator {
/* Allocate a buffer for the converted value. */
void *buffer = allocator.allocate(to_type.size(), to_type.alignment());
+ GMutablePointer value{to_type, buffer};
if (conversions_.is_convertible(from_type, to_type)) {
/* Do the conversion if possible. */
@@ -1282,7 +1311,11 @@ class GeometryNodesEvaluator {
/* Cannot convert, use default value instead. */
to_type.copy_construct(to_type.default_value(), buffer);
}
- this->add_value_to_input_socket(to_socket, from_socket, {to_type, buffer});
+ /* Multi input socket values are logged once all values are available. */
+ if (!to_socket->is_multi_input_socket()) {
+ this->log_socket_value({to_socket}, value);
+ }
+ this->add_value_to_input_socket(to_socket, from_socket, value);
}
void forward_to_sockets_with_same_type(LinearAllocator<> &allocator,
@@ -1330,6 +1363,10 @@ class GeometryNodesEvaluator {
/* Add a new value to the multi-input. */
MultiInputValue &multi_value = *input_state.value.multi;
multi_value.items.append({origin, value.get()});
+
+ if (multi_value.expected_size == multi_value.items.size()) {
+ this->log_socket_value({socket}, input_state, multi_value.items);
+ }
}
else {
/* Assign the value to the input. */
@@ -1360,10 +1397,14 @@ class GeometryNodesEvaluator {
if (input_socket->is_multi_input_socket()) {
MultiInputValue &multi_value = *input_state.value.multi;
multi_value.items.append({origin_socket, value.get()});
+ if (multi_value.expected_size == multi_value.items.size()) {
+ this->log_socket_value({input_socket}, input_state, multi_value.items);
+ }
}
else {
SingleInputValue &single_value = *input_state.value.single;
single_value.value = value.get();
+ this->log_socket_value({input_socket}, value);
}
}
@@ -1416,29 +1457,27 @@ class GeometryNodesEvaluator {
return *node_states_.lookup_key_as(node).state;
}
- void log_socket_value(const DSocket socket, Span<GPointer> values)
+ void log_socket_value(DSocket socket, InputState &input_state, Span<MultiInputValueItem> values)
{
- if (params_.log_socket_value_fn) {
- params_.log_socket_value_fn(socket, values);
+ if (params_.geo_logger == nullptr) {
+ return;
}
- }
- void log_socket_value(const DSocket socket,
- InputState &input_state,
- Span<MultiInputValueItem> values)
- {
Vector<GPointer, 16> value_pointers;
value_pointers.reserve(values.size());
const CPPType &type = *input_state.type;
for (const MultiInputValueItem &item : values) {
value_pointers.append({type, item.value});
}
- this->log_socket_value(socket, value_pointers);
+ params_.geo_logger->local().log_multi_value_socket(socket, value_pointers);
}
- void log_socket_value(const DSocket socket, GPointer value)
+ void log_socket_value(Span<DSocket> sockets, GPointer value)
{
- this->log_socket_value(socket, Span<GPointer>(&value, 1));
+ if (params_.geo_logger == nullptr) {
+ return;
+ }
+ params_.geo_logger->local().log_value_for_sockets(sockets, value);
}
/* In most cases when `NodeState` is accessed, the node has to be locked first to avoid race
@@ -1477,6 +1516,7 @@ NodeParamsProvider::NodeParamsProvider(GeometryNodesEvaluator &evaluator,
this->self_object = evaluator.params_.self_object;
this->modifier = &evaluator.params_.modifier_->modifier;
this->depsgraph = evaluator.params_.depsgraph;
+ this->logger = evaluator.params_.geo_logger;
}
bool NodeParamsProvider::can_get_input(StringRef identifier) const
@@ -1576,8 +1616,6 @@ void NodeParamsProvider::set_output(StringRef identifier, GMutablePointer value)
const DOutputSocket socket = this->dnode.output_by_identifier(identifier);
BLI_assert(socket);
- evaluator_.log_socket_value(socket, value);
-
OutputState &output_state = node_state_.outputs[socket->index()];
BLI_assert(!output_state.has_been_computed);
evaluator_.forward_output(socket, value);
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh
index 84249e4244e..f4ee6242dcb 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh
@@ -19,30 +19,37 @@
#include "BLI_map.hh"
#include "NOD_derived_node_tree.hh"
+#include "NOD_geometry_nodes_eval_log.hh"
#include "NOD_node_tree_multi_function.hh"
#include "FN_generic_pointer.hh"
#include "DNA_modifier_types.h"
+namespace geo_log = blender::nodes::geometry_nodes_eval_log;
+
namespace blender::modifiers::geometry_nodes {
using namespace nodes::derived_node_tree_types;
using fn::GMutablePointer;
using fn::GPointer;
-using LogSocketValueFn = std::function<void(DSocket, Span<GPointer>)>;
-
struct GeometryNodesEvaluationParams {
blender::LinearAllocator<> allocator;
Map<DOutputSocket, GMutablePointer> input_values;
Vector<DInputSocket> output_sockets;
+ /* These sockets will be computed but are not part of the output. Their value can be retrieved in
+ * `log_socket_value_fn`. These sockets are not part of `output_sockets` because then the
+ * evaluator would have to keep the socket values in memory until the end, which might not be
+ * necessary in all cases. Sometimes `log_socket_value_fn` might just want to look at the value
+ * and then it can be freed. */
+ Vector<DSocket> force_compute_sockets;
nodes::MultiFunctionByNode *mf_by_node;
const NodesModifierData *modifier_;
Depsgraph *depsgraph;
Object *self_object;
- LogSocketValueFn log_socket_value_fn;
+ geo_log::GeoLogger *geo_logger;
Vector<GMutablePointer> r_output_values;
};
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 4bfd6aba4b2..54bb68dc21a 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -335,7 +335,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
if (do_polynors_fix &&
polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) {
- /* XXX TODO is this still needed? */
+ /* XXX TODO: is this still needed? */
// mesh->dirty |= DM_DIRTY_TESS_CDLAYERS;
/* We need to recompute vertex normals! */
BKE_mesh_calc_normals(mesh);
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 3de6bb62c8a..8f3206da5be 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -455,7 +455,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
/* displace the geometry */
- /* Note: tried to parallelized that one and previous foam loop,
+ /* NOTE: tried to parallelized that one and previous foam loop,
* but gives 20% slower results... odd. */
{
const int num_verts = result->totvert;
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 62ac9d4452d..49b5dabe72d 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -182,7 +182,7 @@ static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *ps
totpart = psys->totpart + psys->totchild;
- /* TODO make randomization optional? */
+ /* TODO: make randomization optional? */
randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart;
minp = (int)(totpart * pimd->particle_offset) % (totpart + 1);
@@ -442,7 +442,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
mul_qt_qtqt(frame, frame, rot);
}
- /* note: direction is same as normal vector currently,
+ /* NOTE: direction is same as normal vector currently,
* but best to keep this separate so the frame can be
* rotated later if necessary
*/
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 38cce5e6a50..ef70f3fe6f4 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -120,7 +120,6 @@ static void deformVerts(ModifierData *md,
Mesh *mesh_src = mesh;
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
ParticleSystem *psys = NULL;
- /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */
if (ctx->object->particlesystem.first) {
psys = psmd->psys;
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index b90bf91dcb8..0819b314e32 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -357,7 +357,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
/* Will the screw be closed?
- * Note! smaller than `FLT_EPSILON * 100`
+ * NOTE: smaller than `FLT_EPSILON * 100`
* gives problems with float precision so its never closed. */
if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) &&
fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3) {
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 58d70ef3a4a..543cee18868 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -296,7 +296,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "convex_hull input=%hv", BM_ELEM_TAG);
BMO_op_exec(bm, &op);
- if (BMO_error_occurred(bm)) {
+ if (BMO_error_occurred_at_level(bm, BMO_ERROR_CANCEL)) {
BMO_op_finish(bm, &op);
return false;
}
@@ -1202,7 +1202,7 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMVert **orig_
slot_targetmap = BMO_slot_get(op.slots_in, "targetmap");
- /* Note: could probably calculate merges in one go to be
+ /* NOTE: could probably calculate merges in one go to be
* faster */
v_safe = shortest_edge->v1;
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c
index 95fb87bb54c..e97190b1878 100644
--- a/source/blender/modifiers/intern/MOD_solidify_extrude.c
+++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c
@@ -242,9 +242,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
MDeformVert *dvert;
const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
int defgrp_index;
- const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object,
- smd->shell_defgrp_name);
- const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name);
+ const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name);
+ const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name);
/* array size is doubled in case of using a shell */
const uint stride = do_shell ? 2 : 1;
@@ -505,7 +504,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
}
- /* note, copied vertex layers don't have flipped normals yet. do this after applying offset */
+ /* NOTE: copied vertex layers don't have flipped normals yet. do this after applying offset. */
if ((smd->flag & MOD_SOLIDIFY_EVEN) == 0) {
/* no even thickness, very simple */
float scalar_short;
@@ -1028,14 +1027,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (do_rim) {
uint i;
- /* bugger, need to re-calculate the normals for the new edge faces.
+ /* NOTE(campbell): Unfortunately re-calculate the normals for the new edge faces is necessary.
* This could be done in many ways, but probably the quickest way
* is to calculate the average normals for side faces only.
* Then blend them with the normals of the edge verts.
*
- * at the moment its easiest to allocate an entire array for every vertex,
- * even though we only need edge verts - campbell
- */
+ * At the moment its easiest to allocate an entire array for every vertex,
+ * even though we only need edge verts. */
#define SOLIDIFY_SIDE_NORMALS
@@ -1200,7 +1198,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
short *nor_short;
int k;
- /* note, only the first vertex (lower half of the index) is calculated */
+ /* NOTE: only the first vertex (lower half of the index) is calculated. */
BLI_assert(ed->v1 < numVerts);
normalize_v3_v3(nor_cpy, edge_vert_nos[ed_orig->v1]);
diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
index 0f8503eddde..b872f04b60f 100644
--- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
+++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
@@ -181,9 +181,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MDeformVert *dvert;
const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
int defgrp_index;
- const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object,
- smd->shell_defgrp_name);
- const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name);
+ const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name);
+ const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name);
MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index);
@@ -913,7 +912,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
uint unassigned_edges_len = 0;
for (uint j = 0; j < tot_adj_edges; j++) {
NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
- /* TODO check where the null pointer come from,
+ /* TODO: check where the null pointer come from,
* because there should not be any... */
if (new_edges) {
/* count the number of new edges around the original vert */
@@ -1107,7 +1106,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEM_freeN(unassigned_edges);
- /* TODO reshape the edge_groups array to its actual size
+ /* TODO: reshape the edge_groups array to its actual size
* after writing is finished to save on memory. */
}
@@ -1374,7 +1373,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEM_freeN(vert_adj_edges);
}
- /* TODO create_regions if fix_intersections. */
+ /* TODO: create_regions if fix_intersections. */
/* General use pointer for #EdgeGroup iteration. */
EdgeGroup **gs_ptr;
@@ -1854,7 +1853,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEM_freeN(null_faces);
}
- /* TODO create vertdata for intersection fixes (intersection fixing per topology region). */
+ /* TODO: create vertdata for intersection fixes (intersection fixing per topology region). */
/* Correction for adjacent one sided groups around a vert to
* prevent edge duplicates and null polys. */
@@ -2018,7 +2017,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
* - new_edge value should have no duplicates
* - every old_edge value should appear twice
* - every group should have at least two members (edges)
- * Note: that there can be vertices that only have one group. They are called singularities.
+ * NOTE: that there can be vertices that only have one group. They are called singularities.
* These vertices will only have one side (there is no way of telling apart front
* from back like on a mobius strip)
*/
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index dd011a293ee..ec6de8f8387 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -94,6 +94,11 @@ typedef struct SDefBindCalcData {
float imat[4][4];
const float falloff;
int success;
+ /** Vertex group lookup data. */
+ const MDeformVert *const dvert;
+ int const defgrp_index;
+ bool const invert_vgroup;
+ bool const sparse_bind;
} SDefBindCalcData;
/**
@@ -218,7 +223,7 @@ static void freeData(ModifierData *md)
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
if (smd->verts) {
- for (int i = 0; i < smd->numverts; i++) {
+ for (int i = 0; i < smd->num_bind_verts; i++) {
if (smd->verts[i].binds) {
for (int j = 0; j < smd->verts[i].numbinds; j++) {
MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
@@ -243,7 +248,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
if (smd->verts) {
tsmd->verts = MEM_dupallocN(smd->verts);
- for (int i = 0; i < smd->numverts; i++) {
+ for (int i = 0; i < smd->num_bind_verts; i++) {
if (smd->verts[i].binds) {
tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
@@ -963,12 +968,32 @@ static void bindVert(void *__restrict userdata,
SDefBindPoly *bpoly;
SDefBind *sdbind;
+ sdvert->vertex_idx = index;
+
if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
sdvert->binds = NULL;
sdvert->numbinds = 0;
return;
}
+ if (data->sparse_bind) {
+ float weight = 0.0f;
+
+ if (data->dvert && data->defgrp_index != -1) {
+ weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index);
+ }
+
+ if (data->invert_vgroup) {
+ weight = 1.0f - weight;
+ }
+
+ if (weight <= 0) {
+ sdvert->binds = NULL;
+ sdvert->numbinds = 0;
+ return;
+ }
+ }
+
copy_v3_v3(point_co, data->vertexCos[index]);
bwdata = computeBindWeights(data, point_co);
@@ -1135,6 +1160,21 @@ static void bindVert(void *__restrict userdata,
freeBindData(bwdata);
}
+/* Remove vertices without bind data from the bind array. */
+static void compactSparseBinds(SurfaceDeformModifierData *smd)
+{
+ smd->num_bind_verts = 0;
+
+ for (uint i = 0; i < smd->num_mesh_verts; i++) {
+ if (smd->verts[i].numbinds > 0) {
+ smd->verts[smd->num_bind_verts++] = smd->verts[i];
+ }
+ }
+
+ smd->verts = MEM_reallocN_id(
+ smd->verts, sizeof(*smd->verts) * smd->num_bind_verts, "SDefBindVerts (sparse)");
+}
+
static bool surfacedeformBind(Object *ob,
SurfaceDeformModifierData *smd_orig,
SurfaceDeformModifierData *smd_eval,
@@ -1142,7 +1182,8 @@ static bool surfacedeformBind(Object *ob,
uint numverts,
uint tnumpoly,
uint tnumverts,
- Mesh *target)
+ Mesh *target,
+ Mesh *mesh)
{
BVHTreeFromMesh treeData = {NULL};
const MVert *mvert = target->mvert;
@@ -1205,9 +1246,15 @@ static bool surfacedeformBind(Object *ob,
return false;
}
- smd_orig->numverts = numverts;
+ smd_orig->num_mesh_verts = numverts;
smd_orig->numpoly = tnumpoly;
+ int defgrp_index;
+ MDeformVert *dvert;
+ MOD_get_vgroup(ob, mesh, smd_orig->defgrp_name, &dvert, &defgrp_index);
+ const bool invert_vgroup = (smd_orig->flags & MOD_SDEF_INVERT_VGROUP) != 0;
+ const bool sparse_bind = (smd_orig->flags & MOD_SDEF_SPARSE_BIND) != 0;
+
SDefBindCalcData data = {
.treeData = &treeData,
.vert_edges = vert_edges,
@@ -1221,6 +1268,10 @@ static bool surfacedeformBind(Object *ob,
.vertexCos = vertexCos,
.falloff = smd_orig->falloff,
.success = MOD_SDEF_BIND_RESULT_SUCCESS,
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .invert_vgroup = invert_vgroup,
+ .sparse_bind = sparse_bind,
};
if (data.targetCos == NULL) {
@@ -1242,6 +1293,13 @@ static bool surfacedeformBind(Object *ob,
MEM_freeN(data.targetCos);
+ if (sparse_bind) {
+ compactSparseBinds(smd_orig);
+ }
+ else {
+ smd_orig->num_bind_verts = numverts;
+ }
+
if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
freeData((ModifierData *)smd_orig);
@@ -1267,6 +1325,11 @@ static bool surfacedeformBind(Object *ob,
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons");
freeData((ModifierData *)smd_orig);
}
+ else if (smd_orig->num_bind_verts == 0 || !smd_orig->verts) {
+ data.success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
+ BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound");
+ freeData((ModifierData *)smd_orig);
+ }
freeAdjacencyMap(vert_edges, adj_array, edge_polys);
free_bvhtree_from_mesh(&treeData);
@@ -1281,14 +1344,15 @@ static void deformVert(void *__restrict userdata,
const SDefDeformData *const data = (SDefDeformData *)userdata;
const SDefBind *sdbind = data->bind_verts[index].binds;
const int num_binds = data->bind_verts[index].numbinds;
- float *const vertexCos = data->vertexCos[index];
+ const unsigned int vertex_idx = data->bind_verts[index].vertex_idx;
+ float *const vertexCos = data->vertexCos[vertex_idx];
float norm[3], temp[3], offset[3];
/* Retrieve the value of the weight vertex group if specified. */
float weight = 1.0f;
if (data->dvert && data->defgrp_index != -1) {
- weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index);
+ weight = BKE_defvert_find_weight(&data->dvert[vertex_idx], data->defgrp_index);
if (data->invert_vgroup) {
weight = 1.0f - weight;
@@ -1423,7 +1487,8 @@ static void surfacedeformModifier_do(ModifierData *md,
/* Avoid converting edit-mesh data, binding is an exception. */
BKE_mesh_wrapper_ensure_mdata(target);
- if (!surfacedeformBind(ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) {
+ if (!surfacedeformBind(
+ ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target, mesh)) {
smd->flags &= ~MOD_SDEF_BIND;
}
/* Early abort, this is binding 'call', no need to perform whole evaluation. */
@@ -1431,8 +1496,9 @@ static void surfacedeformModifier_do(ModifierData *md,
}
/* Poly count checks */
- if (smd->numverts != numverts) {
- BKE_modifier_set_error(ob, md, "Vertices changed from %u to %u", smd->numverts, numverts);
+ if (smd->num_mesh_verts != numverts) {
+ BKE_modifier_set_error(
+ ob, md, "Vertices changed from %u to %u", smd->num_mesh_verts, numverts);
return;
}
if (smd->numpoly != tnumpoly) {
@@ -1468,8 +1534,8 @@ static void surfacedeformModifier_do(ModifierData *md,
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numverts > 10000);
- BLI_task_parallel_range(0, numverts, &data, deformVert, &settings);
+ settings.use_threading = (smd->num_bind_verts > 10000);
+ BLI_task_parallel_range(0, smd->num_bind_verts, &data, deformVert, &settings);
MEM_freeN(data.targetCos);
}
@@ -1554,6 +1620,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetEnabled(col, !is_bound);
+ uiLayoutSetActive(col, !is_bound && RNA_string_length(ptr, "vertex_group") != 0);
+ uiItemR(col, ptr, "use_sparse_bind", 0, NULL, ICON_NONE);
+
uiItemS(layout);
col = uiLayoutColumn(layout, false);
@@ -1576,10 +1647,10 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md)
{
const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
- BLO_write_struct_array(writer, SDefVert, smd->numverts, smd->verts);
+ BLO_write_struct_array(writer, SDefVert, smd->num_bind_verts, smd->verts);
if (smd->verts) {
- for (int i = 0; i < smd->numverts; i++) {
+ for (int i = 0; i < smd->num_bind_verts; i++) {
BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
if (smd->verts[i].binds) {
@@ -1607,7 +1678,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md)
BLO_read_data_address(reader, &smd->verts);
if (smd->verts) {
- for (int i = 0; i < smd->numverts; i++) {
+ for (int i = 0; i < smd->num_bind_verts; i++) {
BLO_read_data_address(reader, &smd->verts[i].binds);
if (smd->verts[i].binds) {
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 55409cba114..5b97d0eb259 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -71,7 +71,7 @@ void MOD_init_texture(MappingInfoModifierData *dmd, const ModifierEvalContext *c
}
}
-/* TODO to be renamed to get_texture_coords once we are done with moving modifiers to Mesh. */
+/* TODO: to be renamed to get_texture_coords once we are done with moving modifiers to Mesh. */
/** \param cos: may be NULL, in which case we use directly mesh vertices' coordinates. */
void MOD_get_texture_coords(MappingInfoModifierData *dmd,
const ModifierEvalContext *UNUSED(ctx),
@@ -254,15 +254,22 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
void MOD_get_vgroup(
Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
{
- *defgrp_index = BKE_object_defgroup_name_index(ob, name);
- *dvert = NULL;
-
- if (*defgrp_index != -1) {
- if (ob->type == OB_LATTICE) {
+ if (mesh) {
+ *defgrp_index = BKE_id_defgroup_name_index(&mesh->id, name);
+ if (*defgrp_index != -1) {
+ *dvert = mesh->dvert;
+ }
+ else {
+ *dvert = NULL;
+ }
+ }
+ else {
+ *defgrp_index = BKE_object_defgroup_name_index(ob, name);
+ if (*defgrp_index != -1 && ob->type == OB_LATTICE) {
*dvert = BKE_lattice_deform_verts_get(ob);
}
- else if (mesh) {
- *dvert = mesh->dvert;
+ else {
+ *dvert = NULL;
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 5742144b6dd..3f161d339c2 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -233,7 +233,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
settings.use_threading = (numPolys > 1000);
BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings);
- /* XXX TODO is this still needed? */
+ /* XXX TODO: is this still needed? */
// me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS;
mesh->runtime.is_original = false;
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 2f2da7d6554..bbdd7d0e647 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -378,7 +378,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
* But this is not exactly trivial change, better to keep this optimization for later...
*/
if (!has_vgroup) {
- /* Note: in theory, we could avoid this extra allocation & copying...
+ /* NOTE: in theory, we could avoid this extra allocation & copying...
* But think we can live with it for now,
* and it makes code simpler & cleaner. */
float(*vert_normals)[3] = MEM_calloc_arrayN(
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index c5e2ecb9660..696c4c855c7 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -230,7 +230,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx,
MEM_freeN(tex_co);
}
- else if ((ref_didx = BKE_object_defgroup_name_index(ob, defgrp_name)) != -1) {
+ else if ((ref_didx = BKE_id_defgroup_name_index(&mesh->id, defgrp_name)) != -1) {
MDeformVert *dvert = NULL;
/* Check whether we want to set vgroup weights from a constant weight factor or a vertex
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index b5f72c88800..093fa118ee0 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -194,12 +194,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Check if we can just return the original mesh.
* Must have verts and therefore verts assigned to vgroups to do anything useful!
*/
- if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) {
+ if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
/* Get vgroup idx from its name. */
- const int defgrp_index = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name);
+ const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
if (defgrp_index == -1) {
return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index a71a2f3b480..7aae089fa18 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -245,19 +245,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Check if we can just return the original mesh.
* Must have verts and therefore verts assigned to vgroups to do anything useful!
*/
- if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) {
+ if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
/* Get vgroup idx from its name. */
- const int defgrp_index = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name_a);
+ const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_a);
if (defgrp_index == -1) {
return mesh;
}
/* Get second vgroup idx from its name, if given. */
int defgrp_index_other = -1;
if (wmd->defgrp_name_b[0] != '\0') {
- defgrp_index_other = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name_b);
+ defgrp_index_other = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_b);
if (defgrp_index_other == -1) {
return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index cd03175f16c..6e78774269a 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -174,7 +174,7 @@ static void get_vert2geom_distance(int numVerts,
BVHTreeFromMesh treeData_f = {NULL};
if (dist_v) {
- /* Create a bvh-tree of the given target's verts. */
+ /* Create a BVH-tree of the given target's verts. */
BKE_bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2);
if (treeData_v.tree == NULL) {
OUT_OF_MEMORY();
@@ -182,7 +182,7 @@ static void get_vert2geom_distance(int numVerts,
}
}
if (dist_e) {
- /* Create a bvh-tree of the given target's edges. */
+ /* Create a BVH-tree of the given target's edges. */
BKE_bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2);
if (treeData_e.tree == NULL) {
OUT_OF_MEMORY();
@@ -190,7 +190,7 @@ static void get_vert2geom_distance(int numVerts,
}
}
if (dist_f) {
- /* Create a bvh-tree of the given target's faces. */
+ /* Create a BVH-tree of the given target's faces. */
BKE_bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_LOOPTRI, 2);
if (treeData_f.tree == NULL) {
OUT_OF_MEMORY();
@@ -468,7 +468,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Check if we can just return the original mesh.
* Must have verts and therefore verts assigned to vgroups to do anything useful!
*/
- if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) {
+ if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
@@ -479,11 +479,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
/* Get vgroup idx from its name. */
- defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name);
+ defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
if (defgrp_index == -1) {
return mesh;
}
-
const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT);
/* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
/* As this modifier never add vertices to vgroup, just return. */
diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c
index 1590f342666..fe2d699aea8 100644
--- a/source/blender/modifiers/intern/MOD_weld.c
+++ b/source/blender/modifiers/intern/MOD_weld.c
@@ -1573,11 +1573,12 @@ struct WeldVertexCluster {
uint merged_verts;
};
-static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh)
+static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
+ const ModifierEvalContext *UNUSED(ctx),
+ Mesh *mesh)
{
Mesh *result = mesh;
- Object *ob = ctx->object;
BLI_bitmap *v_mask = NULL;
int v_mask_act = 0;
@@ -1590,7 +1591,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
totvert = mesh->totvert;
/* Vertex Group. */
- const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name);
+ const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
if (defgrp_index != -1) {
MDeformVert *dvert, *dv;
dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index 16bf1f7d763..e188a61e975 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -76,7 +76,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh *
Mesh *result;
BMesh *bm;
- const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name);
+ const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
bm = BKE_mesh_to_bmesh_ex(mesh,
&(struct BMeshCreateParams){0},
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index d27f45c4d98..929b1c3e6b2 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -134,6 +134,7 @@ set(SRC
function/nodes/node_fn_boolean_math.cc
function/nodes/node_fn_float_compare.cc
+ function/nodes/node_fn_float_to_int.cc
function/nodes/node_fn_input_string.cc
function/nodes/node_fn_input_vector.cc
function/nodes/node_fn_random_float.cc
@@ -165,17 +166,20 @@ set(SRC
geometry/nodes/node_geo_collection_info.cc
geometry/nodes/node_geo_common.cc
geometry/nodes/node_geo_convex_hull.cc
- geometry/nodes/node_geo_curve_length.cc
+ geometry/nodes/node_geo_curve_endpoints.cc
+ geometry/nodes/node_geo_curve_length.cc
geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
geometry/nodes/node_geo_curve_primitive_circle.cc
+ geometry/nodes/node_geo_curve_primitive_line.cc
geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
+ geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
geometry/nodes/node_geo_curve_primitive_spiral.cc
geometry/nodes/node_geo_curve_primitive_star.cc
- geometry/nodes/node_geo_curve_to_mesh.cc
- geometry/nodes/node_geo_curve_to_points.cc
geometry/nodes/node_geo_curve_resample.cc
geometry/nodes/node_geo_curve_reverse.cc
geometry/nodes/node_geo_curve_subdivide.cc
+ geometry/nodes/node_geo_curve_to_mesh.cc
+ geometry/nodes/node_geo_curve_to_points.cc
geometry/nodes/node_geo_delete_geometry.cc
geometry/nodes/node_geo_edge_split.cc
geometry/nodes/node_geo_input_material.cc
@@ -191,6 +195,7 @@ set(SRC
geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
geometry/nodes/node_geo_mesh_primitive_line.cc
geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
+ geometry/nodes/node_geo_mesh_subdivide.cc
geometry/nodes/node_geo_mesh_to_curve.cc
geometry/nodes/node_geo_object_info.cc
geometry/nodes/node_geo_point_distribute.cc
@@ -203,11 +208,11 @@ set(SRC
geometry/nodes/node_geo_raycast.cc
geometry/nodes/node_geo_select_by_material.cc
geometry/nodes/node_geo_separate_components.cc
- geometry/nodes/node_geo_subdivide.cc
geometry/nodes/node_geo_subdivision_surface.cc
geometry/nodes/node_geo_switch.cc
geometry/nodes/node_geo_transform.cc
geometry/nodes/node_geo_triangulate.cc
+ geometry/nodes/node_geo_viewer.cc
geometry/nodes/node_geo_volume_to_mesh.cc
geometry/node_geometry_exec.cc
geometry/node_geometry_tree.cc
@@ -333,6 +338,7 @@ set(SRC
texture/node_texture_util.c
intern/derived_node_tree.cc
+ intern/geometry_nodes_eval_log.cc
intern/math_functions.cc
intern/attribute_ref.cc
intern/node_common.c
@@ -358,6 +364,7 @@ set(SRC
NOD_function.h
NOD_geometry.h
NOD_geometry_exec.hh
+ NOD_geometry_nodes_eval_log.hh
NOD_math_functions.hh
NOD_node_tree_multi_function.hh
NOD_node_tree_ref.hh
@@ -418,6 +425,11 @@ if(WITH_TBB)
${TBB_INCLUDE_DIRS}
)
add_definitions(-DWITH_TBB)
+ if(WIN32)
+ # TBB includes Windows.h which will define min/max macros
+ # that will collide with the stl versions.
+ add_definitions(-DNOMINMAX)
+ endif()
endif()
if(WITH_IMAGE_OPENEXR)
diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h
index b31b5326d66..29f1a465491 100644
--- a/source/blender/nodes/NOD_function.h
+++ b/source/blender/nodes/NOD_function.h
@@ -22,6 +22,7 @@ extern "C" {
void register_node_type_fn_boolean_math(void);
void register_node_type_fn_float_compare(void);
+void register_node_type_fn_float_to_int(void);
void register_node_type_fn_input_string(void);
void register_node_type_fn_input_vector(void);
void register_node_type_fn_random_float(void);
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 788978c4246..3b546d208e4 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -43,27 +43,30 @@ void register_node_type_geo_attribute_math(void);
void register_node_type_geo_attribute_mix(void);
void register_node_type_geo_attribute_proximity(void);
void register_node_type_geo_attribute_randomize(void);
+void register_node_type_geo_attribute_remove(void);
void register_node_type_geo_attribute_separate_xyz(void);
void register_node_type_geo_attribute_transfer(void);
void register_node_type_geo_attribute_vector_math(void);
void register_node_type_geo_attribute_vector_rotate(void);
-void register_node_type_geo_attribute_remove(void);
void register_node_type_geo_attribute_set(void);
void register_node_type_geo_boolean(void);
void register_node_type_geo_bounding_box(void);
void register_node_type_geo_collection_info(void);
void register_node_type_geo_convex_hull(void);
+void register_node_type_geo_curve_endpoints(void);
void register_node_type_geo_curve_length(void);
void register_node_type_geo_curve_primitive_bezier_segment(void);
void register_node_type_geo_curve_primitive_circle(void);
+void register_node_type_geo_curve_primitive_line(void);
void register_node_type_geo_curve_primitive_quadratic_bezier(void);
+void register_node_type_geo_curve_primitive_quadrilateral(void);
void register_node_type_geo_curve_primitive_spiral(void);
void register_node_type_geo_curve_primitive_star(void);
-void register_node_type_geo_curve_to_mesh(void);
-void register_node_type_geo_curve_to_points(void);
void register_node_type_geo_curve_resample(void);
void register_node_type_geo_curve_reverse(void);
void register_node_type_geo_curve_subdivide(void);
+void register_node_type_geo_curve_to_mesh(void);
+void register_node_type_geo_curve_to_points(void);
void register_node_type_geo_delete_geometry(void);
void register_node_type_geo_edge_split(void);
void register_node_type_geo_input_material(void);
@@ -79,6 +82,7 @@ void register_node_type_geo_mesh_primitive_grid(void);
void register_node_type_geo_mesh_primitive_ico_sphere(void);
void register_node_type_geo_mesh_primitive_line(void);
void register_node_type_geo_mesh_primitive_uv_sphere(void);
+void register_node_type_geo_mesh_subdivide(void);
void register_node_type_geo_mesh_to_curve(void);
void register_node_type_geo_object_info(void);
void register_node_type_geo_point_distribute(void);
@@ -92,11 +96,11 @@ void register_node_type_geo_raycast(void);
void register_node_type_geo_sample_texture(void);
void register_node_type_geo_select_by_material(void);
void register_node_type_geo_separate_components(void);
-void register_node_type_geo_subdivide(void);
void register_node_type_geo_subdivision_surface(void);
void register_node_type_geo_switch(void);
void register_node_type_geo_transform(void);
void register_node_type_geo_triangulate(void);
+void register_node_type_geo_viewer(void);
void register_node_type_geo_volume_to_mesh(void);
#ifdef __cplusplus
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index caefccfdba0..cc01465f4e5 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -21,12 +21,12 @@
#include "BKE_attribute_access.hh"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
-#include "BKE_node_ui_storage.hh"
#include "DNA_node_types.h"
#include "NOD_attribute_ref.hh"
#include "NOD_derived_node_tree.hh"
+#include "NOD_geometry_nodes_eval_log.hh"
struct Depsgraph;
struct ModifierData;
@@ -53,10 +53,11 @@ using fn::GVMutableArray;
using fn::GVMutableArray_GSpan;
using fn::GVMutableArray_Typed;
using fn::GVMutableArrayPtr;
+using geometry_nodes_eval_log::NodeWarningType;
/**
- * This class exists to separate the memory management details of the geometry nodes evaluator from
- * the node execution functions and related utilities.
+ * This class exists to separate the memory management details of the geometry nodes evaluator
+ * from the node execution functions and related utilities.
*/
class GeoNodeExecParamsProvider {
public:
@@ -64,6 +65,7 @@ class GeoNodeExecParamsProvider {
const Object *self_object = nullptr;
const ModifierData *modifier = nullptr;
Depsgraph *depsgraph = nullptr;
+ geometry_nodes_eval_log::GeoLogger *logger = nullptr;
/**
* Returns true when the node is allowed to get/extract the input value. The identifier is
diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
new file mode 100644
index 00000000000..b85862a0176
--- /dev/null
+++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
@@ -0,0 +1,309 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+/**
+ * Many geometry nodes related UI features need access to data produced during evaluation. Not only
+ * is the final output required but also the intermediate results. Those features include
+ * attribute search, node warnings, socket inspection and the viewer node.
+ *
+ * This file provides the framework for logging data during evaluation and accessing the data after
+ * evaluation.
+ *
+ * During logging every thread gets its own local logger to avoid too much locking (logging
+ * generally happens for every socket). After geometry nodes evaluation is done, the thread-local
+ * logging information is combined and post-processed to make it easier for the UI to lookup.
+ * necessary information.
+ */
+
+#include "BLI_enumerable_thread_specific.hh"
+#include "BLI_linear_allocator.hh"
+#include "BLI_map.hh"
+
+#include "BKE_geometry_set.hh"
+
+#include "FN_generic_pointer.hh"
+
+#include "NOD_derived_node_tree.hh"
+
+struct SpaceNode;
+struct SpaceSpreadsheet;
+
+namespace blender::nodes::geometry_nodes_eval_log {
+
+using fn::GMutablePointer;
+using fn::GPointer;
+
+/** Contains information about a value that has been computed during geometry nodes evaluation. */
+class ValueLog {
+ public:
+ virtual ~ValueLog() = default;
+};
+
+/** Contains an owned copy of a value of a generic type. */
+class GenericValueLog : public ValueLog {
+ private:
+ GMutablePointer data_;
+
+ public:
+ GenericValueLog(GMutablePointer data) : data_(data)
+ {
+ }
+
+ ~GenericValueLog()
+ {
+ data_.destruct();
+ }
+
+ GPointer value() const
+ {
+ return data_;
+ }
+};
+
+struct GeometryAttributeInfo {
+ std::string name;
+ AttributeDomain domain;
+ CustomDataType data_type;
+};
+
+/** Contains information about a geometry set. In most cases this does not store the entire
+ * geometry set as this would require too much memory. */
+class GeometryValueLog : public ValueLog {
+ private:
+ Vector<GeometryAttributeInfo> attributes_;
+ Vector<GeometryComponentType> component_types_;
+ std::unique_ptr<GeometrySet> full_geometry_;
+
+ public:
+ struct MeshInfo {
+ int tot_verts, tot_edges, tot_faces;
+ };
+ struct CurveInfo {
+ int tot_splines;
+ };
+ struct PointCloudInfo {
+ int tot_points;
+ };
+ struct InstancesInfo {
+ int tot_instances;
+ };
+
+ std::optional<MeshInfo> mesh_info;
+ std::optional<CurveInfo> curve_info;
+ std::optional<PointCloudInfo> pointcloud_info;
+ std::optional<InstancesInfo> instances_info;
+
+ GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry);
+
+ Span<GeometryAttributeInfo> attributes() const
+ {
+ return attributes_;
+ }
+
+ Span<GeometryComponentType> component_types() const
+ {
+ return component_types_;
+ }
+
+ const GeometrySet *full_geometry() const
+ {
+ return full_geometry_.get();
+ }
+};
+
+enum class NodeWarningType {
+ Error,
+ Warning,
+ Info,
+};
+
+struct NodeWarning {
+ NodeWarningType type;
+ std::string message;
+};
+
+struct NodeWithWarning {
+ DNode node;
+ NodeWarning warning;
+};
+
+/** The same value can be referenced by multiple sockets when they are linked. */
+struct ValueOfSockets {
+ Span<DSocket> sockets;
+ destruct_ptr<ValueLog> value;
+};
+
+class GeoLogger;
+class ModifierLog;
+
+/** Every thread has its own local logger to avoid having to communicate between threads during
+ * evaluation. After evaluation the individual logs are combined. */
+class LocalGeoLogger {
+ private:
+ /* Back pointer to the owner of this local logger. */
+ GeoLogger *main_logger_;
+ /* Allocator for the many small allocations during logging. This is in a `unique_ptr` so that
+ * ownership can be transferred later on. */
+ std::unique_ptr<LinearAllocator<>> allocator_;
+ Vector<ValueOfSockets> values_;
+ Vector<NodeWithWarning> node_warnings_;
+
+ friend ModifierLog;
+
+ public:
+ LocalGeoLogger(GeoLogger &main_logger) : main_logger_(&main_logger)
+ {
+ this->allocator_ = std::make_unique<LinearAllocator<>>();
+ }
+
+ void log_value_for_sockets(Span<DSocket> sockets, GPointer value);
+ void log_multi_value_socket(DSocket socket, Span<GPointer> values);
+ void log_node_warning(DNode node, NodeWarningType type, std::string message);
+};
+
+/** The root logger class. */
+class GeoLogger {
+ private:
+ /** The entire geometry of sockets in this set should be cached, because e.g. the spreadsheet
+ * displays the data. We don't log the entire geometry at all places, because that would require
+ * way too much memory. */
+ Set<DSocket> log_full_geometry_sockets_;
+ threading::EnumerableThreadSpecific<LocalGeoLogger> threadlocals_;
+
+ friend LocalGeoLogger;
+
+ public:
+ GeoLogger(Set<DSocket> log_full_geometry_sockets)
+ : log_full_geometry_sockets_(std::move(log_full_geometry_sockets)),
+ threadlocals_([this]() { return LocalGeoLogger(*this); })
+ {
+ }
+
+ LocalGeoLogger &local()
+ {
+ return threadlocals_.local();
+ }
+
+ auto begin()
+ {
+ return threadlocals_.begin();
+ }
+
+ auto end()
+ {
+ return threadlocals_.end();
+ }
+};
+
+/** Contains information that has been logged for one specific socket. */
+class SocketLog {
+ private:
+ ValueLog *value_ = nullptr;
+
+ friend ModifierLog;
+
+ public:
+ const ValueLog *value() const
+ {
+ return value_;
+ }
+};
+
+/** Contains information that has been logged for one specific node. */
+class NodeLog {
+ private:
+ Vector<SocketLog> input_logs_;
+ Vector<SocketLog> output_logs_;
+ Vector<NodeWarning, 0> warnings_;
+
+ friend ModifierLog;
+
+ public:
+ const SocketLog *lookup_socket_log(eNodeSocketInOut in_out, int index) const;
+ const SocketLog *lookup_socket_log(const bNode &node, const bNodeSocket &socket) const;
+
+ Span<SocketLog> input_logs() const
+ {
+ return input_logs_;
+ }
+
+ Span<SocketLog> output_logs() const
+ {
+ return output_logs_;
+ }
+
+ Span<NodeWarning> warnings() const
+ {
+ return warnings_;
+ }
+
+ Vector<const GeometryAttributeInfo *> lookup_available_attributes() const;
+};
+
+/** Contains information that has been logged for one specific tree. */
+class TreeLog {
+ private:
+ Map<std::string, destruct_ptr<NodeLog>> node_logs_;
+ Map<std::string, destruct_ptr<TreeLog>> child_logs_;
+
+ friend ModifierLog;
+
+ public:
+ const NodeLog *lookup_node_log(StringRef node_name) const;
+ const NodeLog *lookup_node_log(const bNode &node) const;
+ const TreeLog *lookup_child_log(StringRef node_name) const;
+};
+
+/** Contains information about an entire geometry nodes evaluation. */
+class ModifierLog {
+ private:
+ LinearAllocator<> allocator_;
+ /* Allocators of the individual loggers. */
+ Vector<std::unique_ptr<LinearAllocator<>>> logger_allocators_;
+ destruct_ptr<TreeLog> root_tree_logs_;
+ Vector<destruct_ptr<ValueLog>> logged_values_;
+
+ public:
+ ModifierLog(GeoLogger &logger);
+
+ const TreeLog &root_tree() const
+ {
+ return *root_tree_logs_;
+ }
+
+ /* Utilities to find logged information for a specific context. */
+ static const ModifierLog *find_root_by_node_editor_context(const SpaceNode &snode);
+ static const TreeLog *find_tree_by_node_editor_context(const SpaceNode &snode);
+ static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode,
+ const bNode &node);
+ static const SocketLog *find_socket_by_node_editor_context(const SpaceNode &snode,
+ const bNode &node,
+ const bNodeSocket &socket);
+ static const NodeLog *find_node_by_spreadsheet_editor_context(
+ const SpaceSpreadsheet &sspreadsheet);
+
+ private:
+ using LogByTreeContext = Map<const DTreeContext *, TreeLog *>;
+
+ TreeLog &lookup_or_add_tree_log(LogByTreeContext &log_by_tree_context,
+ const DTreeContext &tree_context);
+ NodeLog &lookup_or_add_node_log(LogByTreeContext &log_by_tree_context, DNode node);
+ SocketLog &lookup_or_add_socket_log(LogByTreeContext &log_by_tree_context, DSocket socket);
+};
+
+} // namespace blender::nodes::geometry_nodes_eval_log
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index f5f8f77f2a1..60a10d2c508 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -210,7 +210,7 @@ DefNode(CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIPS
DefNode(CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE", BokehImage, "Bokeh Image", "" )
DefNode(CompositorNode, CMP_NODE_BOKEHBLUR, def_cmp_bokehblur, "BOKEHBLUR", BokehBlur, "Bokeh Blur", "" )
DefNode(CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH", Switch, "Switch", "" )
-DefNode(CompositorNode, CMP_NODE_SWITCH_VIEW, def_cmp_switch_view, "VIEWSWITCH", SwitchView, "View Switch", "" )
+DefNode(CompositorNode, CMP_NODE_SWITCH_VIEW, def_cmp_switch_view, "VIEWSWITCH", SwitchView, "Switch View", "" )
DefNode(CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "Color Correction", "" )
DefNode(CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" )
DefNode(CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYINGSCREEN", KeyingScreen, "Keying Screen", "" )
@@ -263,6 +263,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "")
+DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "")
DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "")
DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "")
@@ -294,7 +295,9 @@ DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLEC
DefNode(GeometryNode, GEO_NODE_CONVEX_HULL, 0, "CONVEX_HULL", ConvexHull, "Convex Hull", "")
DefNode(GeometryNode, GEO_NODE_CURVE_LENGTH, 0, "CURVE_LENGTH", CurveLength, "Curve Length", "")
DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT, def_geo_curve_primitive_bezier_segment, "CURVE_PRIMITIVE_BEZIER_SEGMENT", CurvePrimitiveBezierSegment, "Bezier Segment", "")
-DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, def_geo_curve_primitive_circle, "CURVE_PRIMITIVE_CIRCLE", CurvePrimitiveCircle, "Circle", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, def_geo_curve_primitive_circle, "CURVE_PRIMITIVE_CIRCLE", CurvePrimitiveCircle, "Curve Circle", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_LINE, def_geo_curve_primitive_line, "CURVE_PRIMITIVE_LINE", CurvePrimitiveLine, "Curve Line", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL, def_geo_curve_primitive_quadrilateral, "CURVE_PRIMITIVE_QUADRILATERAL", CurvePrimitiveQuadrilateral, "Quadrilateral", "")
DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER, 0, "CURVE_PRIMITIVE_QUADRATIC_BEZIER", CurveQuadraticBezier, "Quadratic Bezier", "")
DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR", CurveStar, "Star", "")
DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_SPIRAL, 0, "CURVE_PRIMITIVE_SPIRAL", CurveSpiral, "Curve Spiral", "")
@@ -303,6 +306,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_
DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "")
DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "")
DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_ENDPOINTS, 0, "CURVE_ENDPOINTS", CurveEndpoints, "Curve Endpoints", "")
DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, 0, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "")
DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "")
DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "")
@@ -310,13 +314,13 @@ DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Vi
DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "")
DefNode(GeometryNode, GEO_NODE_MATERIAL_ASSIGN, 0, "MATERIAL_ASSIGN", MaterialAssign, "Material Assign", "")
DefNode(GeometryNode, GEO_NODE_MATERIAL_REPLACE, 0, "MATERIAL_REPLACE", MaterialReplace, "Material Replace", "")
-DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Circle", "")
+DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CUBE, 0, "MESH_PRIMITIVE_CUBE", MeshCube, "Cube", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CYLINDER, def_geo_mesh_cylinder, "MESH_PRIMITIVE_CYLINDER", MeshCylinder, "Cylinder", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_GRID, 0, "MESH_PRIMITIVE_GRID", MeshGrid, "Grid", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO_SPHERE", MeshIcoSphere, "Ico Sphere", "")
-DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Line", "")
+DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Mesh Line", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "")
DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "")
DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "")
@@ -330,11 +334,12 @@ DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POIN
DefNode(GeometryNode, GEO_NODE_RAYCAST, def_geo_raycast, "RAYCAST", Raycast, "Raycast", "")
DefNode(GeometryNode, GEO_NODE_SELECT_BY_MATERIAL, 0, "SELECT_BY_MATERIAL", SelectByMaterial, "Select by Material", "")
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "")
-DefNode(GeometryNode, GEO_NODE_SUBDIVIDE, 0, "SUBDIVIDE", Subdivide, "Subdivide", "")
+DefNode(GeometryNode, GEO_NODE_MESH_SUBDIVIDE, 0, "MESH_SUBDIVIDE", MeshSubdivide, "Mesh Subdivide", "")
DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "")
DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "")
DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "")
DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "")
+DefNode(GeometryNode, GEO_NODE_VIEWER, 0, "VIEWER", Viewer, "Viewer", "")
DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "")
/* undefine macros */
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 19815d01278..013d196e1c8 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -205,10 +205,11 @@ static void composite_node_add_init(bNodeTree *UNUSED(bnodetree), bNode *bnode)
}
}
-static bool composite_node_tree_socket_type_valid(eNodeSocketDatatype socket_type,
- bNodeTreeType *UNUSED(ntreetype))
+static bool composite_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype),
+ bNodeSocketType *socket_type)
{
- return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
+ return nodeIsStaticSocketType(socket_type) &&
+ ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
}
bNodeTreeType *ntreeType_Composite;
diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
index 7437496d878..fa276e9a794 100644
--- a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
+++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
@@ -42,9 +42,9 @@ static void node_composit_init_antialiasing(bNodeTree *UNUSED(ntree), bNode *nod
{
NodeAntiAliasingData *data = MEM_callocN(sizeof(NodeAntiAliasingData), "node antialiasing data");
- data->threshold = 1.0f;
- data->contrast_limit = 0.2f;
- data->corner_rounding = 0.25f;
+ data->threshold = CMP_DEFAULT_SMAA_THRESHOLD;
+ data->contrast_limit = CMP_DEFAULT_SMAA_CONTRAST_LIMIT;
+ data->corner_rounding = CMP_DEFAULT_SMAA_CORNER_ROUNDING;
node->storage = data;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c
index be1359f795f..5041b16c303 100644
--- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c
+++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c
@@ -24,7 +24,7 @@
#include "node_composite_util.h"
/* **************** Z COMBINE ******************** */
-/* lazy coder note: node->custom2 is abused to send signal */
+/* lazy coder NOTE: node->custom2 is abused to send signal. */
static bNodeSocketTemplate cmp_node_zcombine_in[] = {
{SOCK_RGBA, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
{SOCK_FLOAT, N_("Z"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_NONE},
diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
new file mode 100644
index 00000000000..26cde576400
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
@@ -0,0 +1,95 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <cmath>
+
+#include "BLI_string.h"
+
+#include "RNA_enum_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_function_util.hh"
+
+static bNodeSocketTemplate fn_node_float_to_int_in[] = {
+ {SOCK_FLOAT, N_("Float"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate fn_node_float_to_int_out[] = {
+ {SOCK_INT, N_("Integer")},
+ {-1, ""},
+};
+
+static void fn_node_float_to_int_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "rounding_mode", 0, "", ICON_NONE);
+}
+
+static void node_float_to_int_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
+{
+ const char *name;
+ bool enum_label = RNA_enum_name(rna_enum_node_float_to_int_items, node->custom1, &name);
+ if (!enum_label) {
+ name = "Unknown";
+ }
+ BLI_strncpy(label, IFACE_(name), maxlen);
+}
+
+static const blender::fn::MultiFunction &get_multi_function(bNode &bnode)
+{
+ static blender::fn::CustomMF_SI_SO<float, int> round_fn{"Round",
+ [](float a) { return (int)round(a); }};
+ static blender::fn::CustomMF_SI_SO<float, int> floor_fn{"Floor",
+ [](float a) { return (int)floor(a); }};
+ static blender::fn::CustomMF_SI_SO<float, int> ceil_fn{"Ceiling",
+ [](float a) { return (int)ceil(a); }};
+ static blender::fn::CustomMF_SI_SO<float, int> trunc_fn{"Truncate",
+ [](float a) { return (int)trunc(a); }};
+
+ switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) {
+ case FN_NODE_FLOAT_TO_INT_ROUND:
+ return round_fn;
+ case FN_NODE_FLOAT_TO_INT_FLOOR:
+ return floor_fn;
+ case FN_NODE_FLOAT_TO_INT_CEIL:
+ return ceil_fn;
+ case FN_NODE_FLOAT_TO_INT_TRUNCATE:
+ return trunc_fn;
+ }
+
+ BLI_assert_unreachable();
+ return blender::fn::dummy_multi_function;
+}
+
+static void node_float_to_int_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
+{
+ const blender::fn::MultiFunction &fn = get_multi_function(builder.bnode());
+ builder.set_matching_fn(fn);
+}
+
+void register_node_type_fn_float_to_int()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_FLOAT_TO_INT, "Float to Integer", NODE_CLASS_CONVERTOR, 0);
+ node_type_socket_templates(&ntype, fn_node_float_to_int_in, fn_node_float_to_int_out);
+ node_type_label(&ntype, node_float_to_int_label);
+ ntype.expand_in_mf_network = node_float_to_int_expand_in_mf_network;
+ ntype.draw_buttons = fn_node_float_to_int_layout;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc
index f36d5b3c9ca..5f10cd87049 100644
--- a/source/blender/nodes/geometry/node_geometry_tree.cc
+++ b/source/blender/nodes/geometry/node_geometry_tree.cc
@@ -108,22 +108,22 @@ static bool geometry_node_tree_validate_link(bNodeTree *UNUSED(ntree), bNodeLink
return (link->tosock->type == link->fromsock->type);
}
-static bool geometry_node_tree_socket_type_valid(eNodeSocketDatatype socket_type,
- bNodeTreeType *UNUSED(ntreetype))
+static bool geometry_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype),
+ bNodeSocketType *socket_type)
{
- return ELEM(socket_type,
- SOCK_FLOAT,
- SOCK_VECTOR,
- SOCK_RGBA,
- SOCK_BOOLEAN,
- SOCK_INT,
- SOCK_STRING,
- SOCK_OBJECT,
- SOCK_GEOMETRY,
- SOCK_COLLECTION,
- SOCK_TEXTURE,
- SOCK_MATERIAL,
- SOCK_ATTRIBUTE);
+ return nodeIsStaticSocketType(socket_type) && ELEM(socket_type->type,
+ SOCK_FLOAT,
+ SOCK_VECTOR,
+ SOCK_RGBA,
+ SOCK_BOOLEAN,
+ SOCK_INT,
+ SOCK_STRING,
+ SOCK_OBJECT,
+ SOCK_GEOMETRY,
+ SOCK_COLLECTION,
+ SOCK_TEXTURE,
+ SOCK_MATERIAL,
+ SOCK_ATTRIBUTE);
}
void register_node_tree_type_geo(void)
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index 67d32d540a8..98c92eac98f 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -79,4 +79,26 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
Span<bool> masks,
const bool invert);
+struct CurveToPointsResults {
+ int result_size;
+ MutableSpan<float3> positions;
+ MutableSpan<float> radii;
+ MutableSpan<float> tilts;
+
+ Map<std::string, GMutableSpan> point_attributes;
+
+ MutableSpan<float3> tangents;
+ MutableSpan<float3> normals;
+ MutableSpan<float3> rotations;
+};
+/**
+ * Create references for all result point cloud attributes to simplify accessing them later on.
+ */
+CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points,
+ const CurveEval &curve);
+
+void curve_create_default_rotation_attribute(Span<float3> tangents,
+ Span<float3> normals,
+ MutableSpan<float3> rotations);
+
} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc
index 06a4327a6c5..3b951bda95e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc
@@ -108,15 +108,14 @@ static AttributeDomain get_result_domain(const GeometryComponent &component,
StringRef result_name)
{
/* Use the domain of the result attribute if it already exists. */
- ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name);
- if (result_attribute) {
- return result_attribute.domain;
+ std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name);
+ if (result_info) {
+ return result_info->domain;
}
-
/* Otherwise use the input attribute's domain if it exists. */
- ReadAttributeLookup input_attribute = component.attribute_try_get_for_read(input_name);
- if (input_attribute) {
- return input_attribute.domain;
+ std::optional<AttributeMetaData> input_info = component.attribute_get_meta_data(input_name);
+ if (input_info) {
+ return input_info->domain;
}
return ATTR_DOMAIN_POINT;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
index b7863d38fc2..d71cb09f1bd 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
@@ -143,8 +143,7 @@ static bool bvh_from_mesh(const Mesh *target_mesh,
break;
}
- /* This only updates a cache and can be considered to be logically const. */
- BKE_bvhtree_from_mesh_get(&r_tree_data_mesh, const_cast<Mesh *>(target_mesh), bvh_type, 2);
+ BKE_bvhtree_from_mesh_get(&r_tree_data_mesh, target_mesh, bvh_type, 2);
if (r_tree_data_mesh.tree == nullptr) {
return false;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc
index d1114713672..756f93f154f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc
@@ -162,7 +162,7 @@ static void get_closest_mesh_points(const Mesh &mesh,
{
BLI_assert(mesh.totvert > 0);
BVHTreeFromMesh tree_data;
- BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(&mesh), BVHTREE_FROM_VERTS, 2);
+ BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_VERTS, 2);
get_closest_in_bvhtree(tree_data, positions, r_point_indices, r_distances_sq, r_positions);
free_bvhtree_from_mesh(&tree_data);
}
@@ -175,7 +175,7 @@ static void get_closest_mesh_edges(const Mesh &mesh,
{
BLI_assert(mesh.totedge > 0);
BVHTreeFromMesh tree_data;
- BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(&mesh), BVHTREE_FROM_EDGES, 2);
+ BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_EDGES, 2);
get_closest_in_bvhtree(tree_data, positions, r_edge_indices, r_distances_sq, r_positions);
free_bvhtree_from_mesh(&tree_data);
}
@@ -188,7 +188,7 @@ static void get_closest_mesh_looptris(const Mesh &mesh,
{
BLI_assert(mesh.totpoly > 0);
BVHTreeFromMesh tree_data;
- BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(&mesh), BVHTREE_FROM_LOOPTRI, 2);
+ BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 2);
get_closest_in_bvhtree(tree_data, positions, r_looptri_indices, r_distances_sq, r_positions);
free_bvhtree_from_mesh(&tree_data);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
index b1b17a321b8..4286db52115 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -82,7 +82,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords)
copy_v3_v3(result->mvert[i].co, co);
}
else {
- BLI_assert(!"Unexpected new vertex in hull output");
+ BLI_assert_msg(0, "Unexpected new vertex in hull output");
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc
new file mode 100644
index 00000000000..1f878259f30
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc
@@ -0,0 +1,223 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_task.hh"
+#include "BLI_timeit.hh"
+
+#include "BKE_pointcloud.h"
+#include "BKE_spline.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_curve_endpoints_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_curve_endpoints_out[] = {
+ {SOCK_GEOMETRY, N_("Start Points")},
+ {SOCK_GEOMETRY, N_("End Points")},
+ {-1, ""},
+};
+
+namespace blender::nodes {
+
+/**
+ * Evaluate splines in parallel to speed up the rest of the node's execution.
+ */
+static void evaluate_splines(Span<SplinePtr> splines)
+{
+ threading::parallel_for_each(splines, [](const SplinePtr &spline) {
+ /* These functions fill the corresponding caches on each spline. */
+ spline->evaluated_positions();
+ spline->evaluated_tangents();
+ spline->evaluated_normals();
+ spline->evaluated_lengths();
+ });
+}
+
+/**
+ * \note Use attributes from the curve component rather than the attribute data directly on the
+ * attribute storage to allow reading the virtual spline attributes like "cyclic" and "resolution".
+ */
+static void copy_spline_domain_attributes(const CurveComponent &curve_component,
+ Span<int> offsets,
+ PointCloudComponent &points)
+{
+ curve_component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) {
+ if (meta_data.domain != ATTR_DOMAIN_CURVE) {
+ return true;
+ }
+ GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
+ name, ATTR_DOMAIN_CURVE, meta_data.data_type);
+
+ OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
+ name, ATTR_DOMAIN_POINT, meta_data.data_type);
+ GMutableSpan result = result_attribute.as_span();
+
+ /* Only copy the attributes of splines in the offsets. */
+ for (const int i : offsets.index_range()) {
+ spline_attribute->get(offsets[i], result[i]);
+ }
+
+ result_attribute.save();
+ return true;
+ });
+}
+
+/**
+ * Get the offsets for the splines whose endpoints we want to output.
+ * Filter those which are cyclic, or that evaluate to empty.
+ * Could be easily adapted to include a selection argument to support attribute selection.
+ */
+static blender::Vector<int> get_endpoint_spline_offsets(Span<SplinePtr> splines)
+{
+ blender::Vector<int> spline_offsets;
+ spline_offsets.reserve(splines.size());
+
+ for (const int i : splines.index_range()) {
+ if (!(splines[i]->is_cyclic() || splines[i]->evaluated_points_size() == 0)) {
+ spline_offsets.append(i);
+ }
+ }
+
+ return spline_offsets;
+}
+
+/**
+ * Copy the endpoint attributes from the correct positions at the splines at the offsets to
+ * the start and end attributes.
+ */
+static void copy_endpoint_attributes(Span<SplinePtr> splines,
+ Span<int> offsets,
+ CurveToPointsResults &start_data,
+ CurveToPointsResults &end_data)
+{
+ threading::parallel_for(offsets.index_range(), 64, [&](IndexRange range) {
+ for (const int i : range) {
+ const Spline &spline = *splines[offsets[i]];
+
+ /* Copy the start and end point data over. */
+ start_data.positions[i] = spline.evaluated_positions().first();
+ start_data.tangents[i] = spline.evaluated_tangents().first();
+ start_data.normals[i] = spline.evaluated_normals().first();
+ start_data.radii[i] = spline.radii().first();
+ start_data.tilts[i] = spline.tilts().first();
+
+ end_data.positions[i] = spline.evaluated_positions().last();
+ end_data.tangents[i] = spline.evaluated_tangents().last();
+ end_data.normals[i] = spline.evaluated_normals().last();
+ end_data.radii[i] = spline.radii().last();
+ end_data.tilts[i] = spline.tilts().last();
+
+ /* Copy the point attribute data over. */
+ for (const auto &item : start_data.point_attributes.items()) {
+ const StringRef name = item.key;
+ GMutableSpan point_span = item.value;
+
+ BLI_assert(spline.attributes.get_for_read(name));
+ GSpan spline_span = *spline.attributes.get_for_read(name);
+ blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]);
+ }
+
+ for (const auto &item : end_data.point_attributes.items()) {
+ const StringRef name = item.key;
+ GMutableSpan point_span = item.value;
+
+ BLI_assert(spline.attributes.get_for_read(name));
+ GSpan spline_span = *spline.attributes.get_for_read(name);
+ blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]);
+ }
+ }
+ });
+}
+
+static void geo_node_curve_endpoints_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ geometry_set = bke::geometry_set_realize_instances(geometry_set);
+
+ if (!geometry_set.has_curve()) {
+ params.set_output("Start Points", GeometrySet());
+ params.set_output("End Points", GeometrySet());
+ return;
+ }
+
+ const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>();
+ const CurveEval &curve = *curve_component.get_for_read();
+ const Span<SplinePtr> splines = curve.splines();
+ curve.assert_valid_point_attributes();
+
+ evaluate_splines(splines);
+
+ const Vector<int> offsets = get_endpoint_spline_offsets(splines);
+ const int total_size = offsets.size();
+
+ if (total_size == 0) {
+ params.set_output("Start Points", GeometrySet());
+ params.set_output("End Points", GeometrySet());
+ return;
+ }
+
+ GeometrySet start_result = GeometrySet::create_with_pointcloud(
+ BKE_pointcloud_new_nomain(total_size));
+ GeometrySet end_result = GeometrySet::create_with_pointcloud(
+ BKE_pointcloud_new_nomain(total_size));
+ PointCloudComponent &start_point_component =
+ start_result.get_component_for_write<PointCloudComponent>();
+ PointCloudComponent &end_point_component =
+ end_result.get_component_for_write<PointCloudComponent>();
+
+ CurveToPointsResults start_attributes = curve_to_points_create_result_attributes(
+ start_point_component, curve);
+ CurveToPointsResults end_attributes = curve_to_points_create_result_attributes(
+ end_point_component, curve);
+
+ copy_endpoint_attributes(splines, offsets.as_span(), start_attributes, end_attributes);
+ copy_spline_domain_attributes(curve_component, offsets.as_span(), start_point_component);
+ curve_create_default_rotation_attribute(
+ start_attributes.tangents, start_attributes.normals, start_attributes.rotations);
+ curve_create_default_rotation_attribute(
+ end_attributes.tangents, end_attributes.normals, end_attributes.rotations);
+
+ /* The default radius is way too large for points, divide by 10. */
+ for (float &radius : start_attributes.radii) {
+ radius *= 0.1f;
+ }
+ for (float &radius : end_attributes.radii) {
+ radius *= 0.1f;
+ }
+
+ params.set_output("Start Points", std::move(start_result));
+ params.set_output("End Points", std::move(end_result));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_curve_endpoints()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_CURVE_ENDPOINTS, "Curve Endpoints", NODE_CLASS_GEOMETRY, 0);
+ node_type_socket_templates(&ntype, geo_node_curve_endpoints_in, geo_node_curve_endpoints_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_curve_endpoints_exec;
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
index 963c48b7536..ae947b7aeed 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
@@ -83,9 +83,10 @@ static bool colinear_f3_f3_f3(const float3 p1, const float3 p2, const float3 p3)
}
static std::unique_ptr<CurveEval> create_point_circle_curve(
- const float3 p1, const float3 p2, const float3 p3, const int resolution, float center_out[3])
+ const float3 p1, const float3 p2, const float3 p3, const int resolution, float3 &r_center)
{
if (colinear_f3_f3_f3(p1, p2, p3)) {
+ r_center = float3(0);
return nullptr;
}
@@ -118,6 +119,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve(
/* If the 3 planes do not intersect at one point, just return empty geometry. */
if (!isect_plane_plane_plane_v3(plane_1, plane_2, plane_3, center)) {
+ r_center = float3(0);
return nullptr;
}
@@ -126,7 +128,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve(
const float theta_step = ((2 * M_PI) / (float)resolution);
for (const int i : IndexRange(resolution)) {
- /* Formula for a circle around a point and 2 unit vectors perpendicular.
+ /* Formula for a circle around a point and 2 unit vectors perpendicular
* to each other and the axis of the circle from:
* https://math.stackexchange.com/questions/73237/parametric-equation-of-a-circle-in-3d-space
*/
@@ -141,7 +143,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve(
curve->add_spline(std::move(spline));
curve->attributes.reallocate(curve->splines().size());
- copy_v3_v3(center_out, center);
+ r_center = center;
return curve;
}
@@ -179,18 +181,13 @@ static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params)
std::unique_ptr<CurveEval> curve;
if (mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS) {
- float center_point[3];
+ float3 center_point;
curve = create_point_circle_curve(params.extract_input<float3>("Point 1"),
params.extract_input<float3>("Point 2"),
params.extract_input<float3>("Point 3"),
std::max(params.extract_input<int>("Resolution"), 3),
center_point);
- if (curve) {
- params.set_output("Center", float3(center_point));
- }
- else {
- params.set_output("Center", float3(0, 0, 0));
- }
+ params.set_output("Center", center_point);
}
else if (mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_RADIUS) {
curve = create_radius_circle_curve(std::max(params.extract_input<int>("Resolution"), 3),
@@ -210,7 +207,8 @@ static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params)
void register_node_type_geo_curve_primitive_circle()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Circle", NODE_CLASS_GEOMETRY, 0);
+ geo_node_type_base(
+ &ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Curve Circle", NODE_CLASS_GEOMETRY, 0);
node_type_socket_templates(
&ntype, geo_node_curve_primitive_circle_in, geo_node_curve_primitive_circle_out);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
new file mode 100644
index 00000000000..eed3a998ef6
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
@@ -0,0 +1,146 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BKE_spline.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_curve_primitive_line_in[] = {
+ {SOCK_VECTOR, N_("Start"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION},
+ {SOCK_VECTOR, N_("End"), 0.0f, 0.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION},
+ {SOCK_VECTOR, N_("Direction"), 0.0f, 0.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Length"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_curve_primitive_line_out[] = {
+ {SOCK_GEOMETRY, N_("Curve")},
+ {-1, ""},
+};
+
+static void geo_node_curve_primitive_line_layout(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
+}
+
+namespace blender::nodes {
+
+static void geo_node_curve_primitive_line_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometryCurvePrimitiveLine *data = (NodeGeometryCurvePrimitiveLine *)MEM_callocN(
+ sizeof(NodeGeometryCurvePrimitiveLine), __func__);
+
+ data->mode = GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS;
+ node->storage = data;
+}
+
+static void geo_node_curve_primitive_line_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ const NodeGeometryCurvePrimitiveLine *node_storage = (NodeGeometryCurvePrimitiveLine *)
+ node->storage;
+ const GeometryNodeCurvePrimitiveLineMode mode = (const GeometryNodeCurvePrimitiveLineMode)
+ node_storage->mode;
+
+ bNodeSocket *p2_socket = ((bNodeSocket *)node->inputs.first)->next;
+ bNodeSocket *direction_socket = p2_socket->next;
+ bNodeSocket *length_socket = direction_socket->next;
+
+ nodeSetSocketAvailability(p2_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS);
+ nodeSetSocketAvailability(direction_socket,
+ mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION);
+ nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION);
+}
+
+static std::unique_ptr<CurveEval> create_point_line_curve(const float3 start, const float3 end)
+{
+ std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
+ std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
+
+ spline->resize(2);
+ MutableSpan<float3> positions = spline->positions();
+ positions[0] = start;
+ positions[1] = end;
+ spline->radii().fill(1.0f);
+ spline->tilts().fill(0.0f);
+ curve->add_spline(std::move(spline));
+ curve->attributes.reallocate(curve->splines().size());
+ return curve;
+}
+
+static std::unique_ptr<CurveEval> create_direction_line_curve(const float3 start,
+ const float3 direction,
+ const float length)
+{
+ std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
+ std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
+
+ spline->resize(2);
+ MutableSpan<float3> positions = spline->positions();
+ positions[0] = start;
+ positions[1] = direction.normalized() * length + start;
+
+ spline->radii().fill(1.0f);
+ spline->tilts().fill(0.0f);
+ curve->add_spline(std::move(spline));
+ curve->attributes.reallocate(curve->splines().size());
+ return curve;
+}
+
+static void geo_node_curve_primitive_line_exec(GeoNodeExecParams params)
+{
+
+ const NodeGeometryCurvePrimitiveLine *node_storage =
+ (NodeGeometryCurvePrimitiveLine *)params.node().storage;
+
+ GeometryNodeCurvePrimitiveLineMode mode = (GeometryNodeCurvePrimitiveLineMode)node_storage->mode;
+
+ std::unique_ptr<CurveEval> curve;
+ if (mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS) {
+ curve = create_point_line_curve(params.extract_input<float3>("Start"),
+ params.extract_input<float3>("End"));
+ }
+ else if (mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION) {
+ curve = create_direction_line_curve(params.extract_input<float3>("Start"),
+ params.extract_input<float3>("Direction"),
+ params.extract_input<float>("Length"));
+ }
+
+ params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_curve_primitive_line()
+{
+ static bNodeType ntype;
+ geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_LINE, "Curve Line", NODE_CLASS_GEOMETRY, 0);
+ node_type_socket_templates(
+ &ntype, geo_node_curve_primitive_line_in, geo_node_curve_primitive_line_out);
+ node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_line_init);
+ node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_line_update);
+ node_type_storage(&ntype,
+ "NodeGeometryCurvePrimitiveLine",
+ node_free_standard_storage,
+ node_copy_standard_storage);
+ ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_line_exec;
+ ntype.draw_buttons = geo_node_curve_primitive_line_layout;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
new file mode 100644
index 00000000000..5f3f159c305
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
@@ -0,0 +1,241 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BKE_spline.hh"
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_curve_primitive_quadrilateral_in[] = {
+ {SOCK_FLOAT, N_("Width"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
+ {SOCK_FLOAT, N_("Height"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
+ {SOCK_FLOAT, N_("Bottom Width"), 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
+ {SOCK_FLOAT, N_("Top Width"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
+ {SOCK_FLOAT, N_("Offset"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {SOCK_FLOAT, N_("Bottom Height"), 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
+ {SOCK_FLOAT, N_("Top Height"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {SOCK_VECTOR, N_("Point 1"), -1.0f, 1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {SOCK_VECTOR, N_("Point 2"), 1.0f, 1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {SOCK_VECTOR, N_("Point 3"), 1.0f, -1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {SOCK_VECTOR, N_("Point 4"), -1.0f, -1.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_curve_primitive_quadrilateral_out[] = {
+ {SOCK_GEOMETRY, N_("Curve")},
+ {-1, ""},
+};
+
+static void geo_node_curve_primitive_quadrilateral_layout(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+}
+
+static void geo_node_curve_primitive_quadrilateral_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometryCurvePrimitiveQuad *data = (NodeGeometryCurvePrimitiveQuad *)MEM_callocN(
+ sizeof(NodeGeometryCurvePrimitiveQuad), __func__);
+ data->mode = GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE;
+ node->storage = data;
+}
+
+namespace blender::nodes {
+
+static void geo_node_curve_primitive_quadrilateral_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeGeometryCurvePrimitiveQuad &node_storage = *(NodeGeometryCurvePrimitiveQuad *)node->storage;
+ GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>(
+ node_storage.mode);
+
+ bNodeSocket *width = ((bNodeSocket *)node->inputs.first);
+ bNodeSocket *height = width->next;
+ bNodeSocket *bottom = height->next;
+ bNodeSocket *top = bottom->next;
+ bNodeSocket *offset = top->next;
+ bNodeSocket *bottom_height = offset->next;
+ bNodeSocket *top_height = bottom_height->next;
+ bNodeSocket *p1 = top_height->next;
+ bNodeSocket *p2 = p1->next;
+ bNodeSocket *p3 = p2->next;
+ bNodeSocket *p4 = p3->next;
+
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+ nodeSetSocketAvailability(sock, false);
+ }
+
+ if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE) {
+ nodeSetSocketAvailability(width, true);
+ nodeSetSocketAvailability(height, true);
+ }
+ else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM) {
+ nodeSetSocketAvailability(width, true);
+ nodeSetSocketAvailability(height, true);
+ nodeSetSocketAvailability(offset, true);
+ }
+ else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID) {
+ nodeSetSocketAvailability(bottom, true);
+ nodeSetSocketAvailability(top, true);
+ nodeSetSocketAvailability(offset, true);
+ nodeSetSocketAvailability(height, true);
+ }
+ else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE) {
+ nodeSetSocketAvailability(width, true);
+ nodeSetSocketAvailability(bottom_height, true);
+ nodeSetSocketAvailability(top_height, true);
+ }
+ else if (mode == GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS) {
+ nodeSetSocketAvailability(p1, true);
+ nodeSetSocketAvailability(p2, true);
+ nodeSetSocketAvailability(p3, true);
+ nodeSetSocketAvailability(p4, true);
+ }
+}
+
+static void create_rectangle_curve(MutableSpan<float3> positions,
+ const float height,
+ const float width)
+{
+ positions[0] = float3(width / 2.0f, -height / 2.0f, 0.0f);
+ positions[1] = float3(-width / 2.0f, -height / 2.0f, 0.0f);
+ positions[2] = float3(-width / 2.0f, height / 2.0f, 0.0f);
+ positions[3] = float3(width / 2.0f, height / 2.0f, 0.0f);
+}
+
+static void create_points_curve(MutableSpan<float3> positions,
+ const float3 &p1,
+ const float3 &p2,
+ const float3 &p3,
+ const float3 &p4)
+{
+ positions[0] = p1;
+ positions[1] = p2;
+ positions[2] = p3;
+ positions[3] = p4;
+}
+
+static void create_parallelogram_curve(MutableSpan<float3> positions,
+ const float height,
+ const float width,
+ const float offset)
+{
+ positions[0] = float3(width / 2.0f - offset / 2.0f, -height / 2.0f, 0.0f);
+ positions[1] = float3(-width / 2.0f - offset / 2.0f, -height / 2.0f, 0.0f);
+ positions[2] = float3(-width / 2.0f + offset / 2.0f, height / 2.0f, 0.0f);
+ positions[3] = float3(width / 2.0f + offset / 2.0f, height / 2.0f, 0.0f);
+}
+static void create_trapezoid_curve(MutableSpan<float3> positions,
+ const float bottom,
+ const float top,
+ const float offset,
+ const float height)
+{
+ positions[0] = float3(bottom / 2.0f, -height / 2.0f, 0.0f);
+ positions[1] = float3(-bottom / 2.0f, -height / 2.0f, 0.0f);
+ positions[2] = float3(-top / 2.0f + offset, height / 2.0f, 0.0f);
+ positions[3] = float3(top / 2.0f + offset, height / 2.0f, 0.0f);
+}
+
+static void create_kite_curve(MutableSpan<float3> positions,
+ const float width,
+ const float bottom_height,
+ const float top_height)
+{
+ positions[0] = float3(-width / 2.0f, 0, 0);
+ positions[1] = float3(0, top_height, 0);
+ positions[2] = float3(width / 2, 0, 0);
+ positions[3] = float3(0, -bottom_height, 0);
+}
+
+static void geo_node_curve_primitive_quadrilateral_exec(GeoNodeExecParams params)
+{
+ const NodeGeometryCurvePrimitiveQuad &node_storage =
+ *(NodeGeometryCurvePrimitiveQuad *)(params.node()).storage;
+ const GeometryNodeCurvePrimitiveQuadMode mode = static_cast<GeometryNodeCurvePrimitiveQuadMode>(
+ node_storage.mode);
+
+ std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
+ std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
+ spline->resize(4);
+ spline->radii().fill(1.0f);
+ spline->tilts().fill(0.0f);
+ spline->set_cyclic(true);
+ MutableSpan<float3> positions = spline->positions();
+
+ switch (mode) {
+ case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE:
+ create_rectangle_curve(positions,
+ std::max(params.extract_input<float>("Height"), 0.0f),
+ std::max(params.extract_input<float>("Width"), 0.0f));
+ break;
+
+ case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_PARALLELOGRAM:
+ create_parallelogram_curve(positions,
+ std::max(params.extract_input<float>("Height"), 0.0f),
+ std::max(params.extract_input<float>("Width"), 0.0f),
+ params.extract_input<float>("Offset"));
+ break;
+ case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_TRAPEZOID:
+ create_trapezoid_curve(positions,
+ std::max(params.extract_input<float>("Bottom Width"), 0.0f),
+ std::max(params.extract_input<float>("Top Width"), 0.0f),
+ params.extract_input<float>("Offset"),
+ std::max(params.extract_input<float>("Height"), 0.0f));
+ break;
+ case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_KITE:
+ create_kite_curve(positions,
+ std::max(params.extract_input<float>("Width"), 0.0f),
+ std::max(params.extract_input<float>("Bottom Height"), 0.0f),
+ params.extract_input<float>("Top Height"));
+ break;
+ case GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_POINTS:
+ create_points_curve(positions,
+ params.extract_input<float3>("Point 1"),
+ params.extract_input<float3>("Point 2"),
+ params.extract_input<float3>("Point 3"),
+ params.extract_input<float3>("Point 4"));
+ break;
+ default:
+ params.set_output("Curve", GeometrySet());
+ return;
+ }
+
+ curve->add_spline(std::move(spline));
+ curve->attributes.reallocate(curve->splines().size());
+ params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_curve_primitive_quadrilateral()
+{
+ static bNodeType ntype;
+ geo_node_type_base(
+ &ntype, GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL, "Quadrilateral", NODE_CLASS_GEOMETRY, 0);
+ node_type_socket_templates(&ntype,
+ geo_node_curve_primitive_quadrilateral_in,
+ geo_node_curve_primitive_quadrilateral_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_quadrilateral_exec;
+ ntype.draw_buttons = geo_node_curve_primitive_quadrilateral_layout;
+ node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_quadrilateral_update);
+ node_type_init(&ntype, geo_node_curve_primitive_quadrilateral_init);
+ node_type_storage(&ntype,
+ "NodeGeometryCurvePrimitiveQuad",
+ node_free_standard_storage,
+ node_copy_standard_storage);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
index 367da3bc3c2..2e2bb247e2b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
@@ -19,7 +19,7 @@
#include "node_geometry_util.hh"
static bNodeSocketTemplate geo_node_curve_primitive_star_in[] = {
- {SOCK_INT, N_("Points"), 8.0f, 0.0f, 0.0f, 0.0f, 4, 256, PROP_UNSIGNED},
+ {SOCK_INT, N_("Points"), 8.0f, 0.0f, 0.0f, 0.0f, 3, 256, PROP_UNSIGNED},
{SOCK_FLOAT, N_("Inner Radius"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
{SOCK_FLOAT, N_("Outer Radius"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
{SOCK_FLOAT, N_("Twist"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_ANGLE},
@@ -64,7 +64,7 @@ static void geo_node_curve_primitive_star_exec(GeoNodeExecParams params)
std::max(params.extract_input<float>("Inner Radius"), 0.0f),
std::max(params.extract_input<float>("Outer Radius"), 0.0f),
params.extract_input<float>("Twist"),
- std::max(params.extract_input<int>("Points"), 4));
+ std::max(params.extract_input<int>("Points"), 3));
params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index fc65d1754e9..ad0c453c2af 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -87,6 +87,23 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count)
input_spline.tilts().first(),
input_spline.radii().first());
output_spline->attributes.reallocate(1);
+ input_spline.attributes.foreach_attribute(
+ [&](StringRefNull name, const AttributeMetaData &meta_data) {
+ std::optional<GSpan> src = input_spline.attributes.get_for_read(name);
+ BLI_assert(src);
+ if (!output_spline->attributes.create(name, meta_data.data_type)) {
+ BLI_assert_unreachable();
+ return false;
+ }
+ std::optional<GMutableSpan> dst = output_spline->attributes.get_for_write(name);
+ if (!dst) {
+ BLI_assert_unreachable();
+ return false;
+ }
+ src->type().copy_assign(src->data(), dst->data());
+ return true;
+ },
+ ATTR_DOMAIN_POINT);
return output_spline;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
index 3de2604cd0a..7908c26e2dc 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
@@ -116,38 +116,6 @@ static void subdivide_attribute(Span<T> src,
}
/**
- * De Casteljau Bezier subdivision.
- *
- * <pre>
- * handle_prev handle_next
- * O----------------O
- * / \
- * / x---O---x \
- * / new_* \
- * / \
- * O O
- * point_prev point_next
- * </pre>
- */
-static void calculate_new_bezier_point(const float3 &point_prev,
- float3 &handle_prev,
- float3 &new_left_handle,
- float3 &new_position,
- float3 &new_right_handle,
- float3 &handle_next,
- const float3 &point_next,
- const float parameter)
-{
- const float3 center_point = float3::interpolate(handle_prev, handle_next, parameter);
-
- handle_prev = float3::interpolate(point_prev, handle_prev, parameter);
- handle_next = float3::interpolate(handle_next, point_next, parameter);
- new_left_handle = float3::interpolate(handle_prev, center_point, parameter);
- new_right_handle = float3::interpolate(center_point, handle_next, parameter);
- new_position = float3::interpolate(new_left_handle, new_right_handle, parameter);
-}
-
-/**
* In order to generate a Bezier spline with the same shape as the input spline, apply the
* De Casteljau algorithm iteratively for the provided number of cuts, constantly updating the
* previous result point's right handle and the left handle at the end of the segment.
@@ -171,6 +139,10 @@ static void subdivide_bezier_segment(const BezierSpline &src,
{
const bool is_last_cyclic_segment = index == (src.size() - 1);
const int next_index = is_last_cyclic_segment ? 0 : index + 1;
+
+ /* The first point in the segment is always copied. */
+ dst_positions[offset] = src_positions[index];
+
if (src.segment_is_vector(index)) {
if (is_last_cyclic_segment) {
dst_type_left.first() = BezierSpline::HandleType::Vector;
@@ -178,7 +150,6 @@ static void subdivide_bezier_segment(const BezierSpline &src,
dst_type_left.slice(offset + 1, result_size).fill(BezierSpline::HandleType::Vector);
dst_type_right.slice(offset, result_size).fill(BezierSpline::HandleType::Vector);
- dst_positions[offset] = src_positions[index];
const float factor_delta = 1.0f / result_size;
for (const int cut : IndexRange(result_size)) {
const float factor = cut * factor_delta;
@@ -194,21 +165,38 @@ static void subdivide_bezier_segment(const BezierSpline &src,
dst_type_right.slice(offset, result_size).fill(BezierSpline::HandleType::Free);
const int i_segment_last = is_last_cyclic_segment ? 0 : offset + result_size;
- dst_positions[offset] = src_positions[index];
- dst_handles_right[offset] = src_handles_right[index];
- dst_handles_left[i_segment_last] = src_handles_left[next_index];
+
+ /* Create a Bezier segment to update iteratively for every subdivision
+ * and references to the meaningful values for ease of use. */
+ BezierSpline temp;
+ temp.resize(2);
+ float3 &segment_start = temp.positions().first();
+ float3 &segment_end = temp.positions().last();
+ float3 &handle_prev = temp.handle_positions_right().first();
+ float3 &handle_next = temp.handle_positions_left().last();
+ segment_start = src_positions[index];
+ segment_end = src_positions[next_index];
+ handle_prev = src_handles_right[index];
+ handle_next = src_handles_left[next_index];
for (const int cut : IndexRange(result_size - 1)) {
const float parameter = 1.0f / (result_size - cut);
- calculate_new_bezier_point(dst_positions[offset + cut],
- dst_handles_right[offset + cut],
- dst_handles_left[offset + cut + 1],
- dst_positions[offset + cut + 1],
- dst_handles_right[offset + cut + 1],
- dst_handles_left[i_segment_last],
- src_positions[next_index],
- parameter);
+ const BezierSpline::InsertResult insert = temp.calculate_segment_insertion(0, 1, parameter);
+
+ /* Copy relevant temporary data to the result. */
+ dst_handles_right[offset + cut] = insert.handle_prev;
+ dst_handles_left[offset + cut + 1] = insert.left_handle;
+ dst_positions[offset + cut + 1] = insert.position;
+
+ /* Update the segment to prepare it for the next subdivision. */
+ segment_start = insert.position;
+ handle_prev = insert.right_handle;
+ handle_next = insert.handle_next;
}
+
+ /* Copy the handles for the last segment from the temporary spline. */
+ dst_handles_right[offset + result_size - 1] = handle_prev;
+ dst_handles_left[i_segment_last] = handle_next;
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index c0d817385e2..f1bcb4ed47f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -337,7 +337,17 @@ static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params)
curve_set = bke::geometry_set_realize_instances(curve_set);
profile_set = bke::geometry_set_realize_instances(profile_set);
+ /* NOTE: Theoretically an "is empty" check would be more correct for errors. */
+ if (profile_set.has_mesh() && !profile_set.has_curve()) {
+ params.error_message_add(NodeWarningType::Warning,
+ TIP_("No curve data available in profile input"));
+ }
+
if (!curve_set.has_curve()) {
+ if (curve_set.has_mesh()) {
+ params.error_message_add(NodeWarningType::Warning,
+ TIP_("No curve data available in curve input"));
+ }
params.set_output("Mesh", GeometrySet());
return;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
index e37822bd262..bb8f560f92d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
@@ -118,22 +118,6 @@ static Array<int> calculate_spline_point_offsets(GeoNodeExecParams &params,
return {0};
}
-/**
- * \note This doesn't store a map for spline domain attributes.
- */
-struct ResultAttributes {
- int result_size;
- MutableSpan<float3> positions;
- MutableSpan<float> radii;
- MutableSpan<float> tilts;
-
- Map<std::string, GMutableSpan> point_attributes;
-
- MutableSpan<float3> tangents;
- MutableSpan<float3> normals;
- MutableSpan<float3> rotations;
-};
-
static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points,
const StringRef name,
const CustomDataType data_type)
@@ -153,13 +137,10 @@ static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &po
return attribute.typed<T>();
}
-/**
- * Create references for all result point cloud attributes to simplify accessing them later on.
- */
-static ResultAttributes create_point_attributes(PointCloudComponent &points,
- const CurveEval &curve)
+CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points,
+ const CurveEval &curve)
{
- ResultAttributes attributes;
+ CurveToPointsResults attributes;
attributes.result_size = points.attribute_domain_size(ATTR_DOMAIN_POINT);
@@ -190,7 +171,7 @@ static ResultAttributes create_point_attributes(PointCloudComponent &points,
*/
static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
Span<int> offsets,
- ResultAttributes &data)
+ CurveToPointsResults &data)
{
threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) {
for (const int i : range) {
@@ -221,7 +202,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines,
Span<int> offsets,
- ResultAttributes &data)
+ CurveToPointsResults &data)
{
threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) {
for (const int i : range) {
@@ -307,13 +288,14 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
});
}
-static void create_default_rotation_attribute(ResultAttributes &data)
+void curve_create_default_rotation_attribute(Span<float3> tangents,
+ Span<float3> normals,
+ MutableSpan<float3> rotations)
{
- threading::parallel_for(IndexRange(data.result_size), 512, [&](IndexRange range) {
+ threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) {
for (const int i : range) {
- data.rotations[i] = float4x4::from_normalized_axis_data(
- {0, 0, 0}, data.normals[i], data.tangents[i])
- .to_euler();
+ rotations[i] =
+ float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler();
}
});
}
@@ -348,8 +330,8 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params)
GeometrySet result = GeometrySet::create_with_pointcloud(BKE_pointcloud_new_nomain(total_size));
PointCloudComponent &point_component = result.get_component_for_write<PointCloudComponent>();
- ResultAttributes new_attributes = create_point_attributes(point_component, curve);
-
+ CurveToPointsResults new_attributes = curve_to_points_create_result_attributes(point_component,
+ curve);
switch (mode) {
case GEO_NODE_CURVE_SAMPLE_COUNT:
case GEO_NODE_CURVE_SAMPLE_LENGTH:
@@ -361,7 +343,8 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params)
}
copy_spline_domain_attributes(curve_component, offsets, point_component);
- create_default_rotation_attribute(new_attributes);
+ curve_create_default_rotation_attribute(
+ new_attributes.tangents, new_attributes.normals, new_attributes.rotations);
/* The default radius is way too large for points, divide by 10. */
for (float &radius : new_attributes.radii) {
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 b1da2dcd3c4..8c697275f88 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -627,7 +627,7 @@ static void delete_mesh_selection(MeshComponent &component,
mesh_out = nullptr;
break;
}
- component.replace_mesh_but_keep_vertex_group_names(mesh_out);
+ component.replace(mesh_out);
}
static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc
index 2915a17d2c8..667e1c931bd 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc
@@ -228,7 +228,8 @@ void register_node_type_geo_mesh_primitive_circle()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Circle", NODE_CLASS_GEOMETRY, 0);
+ geo_node_type_base(
+ &ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Mesh Circle", NODE_CLASS_GEOMETRY, 0);
node_type_socket_templates(
&ntype, geo_node_mesh_primitive_circle_in, geo_node_mesh_primitive_circle_out);
node_type_init(&ntype, geo_node_mesh_primitive_circle_init);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
index e841455e58c..a193c05daa1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc
@@ -177,7 +177,7 @@ void register_node_type_geo_mesh_primitive_line()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Line", NODE_CLASS_GEOMETRY, 0);
+ geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Mesh Line", NODE_CLASS_GEOMETRY, 0);
node_type_socket_templates(
&ntype, geo_node_mesh_primitive_line_in, geo_node_mesh_primitive_line_out);
node_type_init(&ntype, geo_node_mesh_primitive_line_init);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
index a4c6522c57a..245d7800621 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc
@@ -14,8 +14,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// #include "MEM_guardedalloc.h"
-
#include "BKE_mesh.h"
#include "BKE_subdiv.h"
#include "BKE_subdiv_mesh.h"
@@ -25,20 +23,20 @@
#include "node_geometry_util.hh"
-static bNodeSocketTemplate geo_node_subdivide_in[] = {
+static bNodeSocketTemplate geo_node_mesh_subdivide_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{SOCK_INT, N_("Level"), 1, 0, 0, 0, 0, 6},
{-1, ""},
};
-static bNodeSocketTemplate geo_node_subdivide_out[] = {
+static bNodeSocketTemplate geo_node_mesh_subdivide_out[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{-1, ""},
};
namespace blender::nodes {
-static void geo_node_subdivide_exec(GeoNodeExecParams params)
+static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
geometry_set = geometry_set_realize_instances(geometry_set);
@@ -93,7 +91,7 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
BKE_mesh_calc_normals(mesh_out);
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace_mesh_but_keep_vertex_group_names(mesh_out);
+ mesh_component.replace(mesh_out);
BKE_subdiv_free(subdiv);
@@ -102,12 +100,12 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
} // namespace blender::nodes
-void register_node_type_geo_subdivide()
+void register_node_type_geo_mesh_subdivide()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_SUBDIVIDE, "Subdivide", NODE_CLASS_GEOMETRY, 0);
- node_type_socket_templates(&ntype, geo_node_subdivide_in, geo_node_subdivide_out);
- ntype.geometry_node_execute = blender::nodes::geo_node_subdivide_exec;
+ geo_node_type_base(&ntype, GEO_NODE_MESH_SUBDIVIDE, "Mesh Subdivide", NODE_CLASS_GEOMETRY, 0);
+ node_type_socket_templates(&ntype, geo_node_mesh_subdivide_in, geo_node_mesh_subdivide_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_mesh_subdivide_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index 772bd8a1080..d456c72744f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -83,8 +83,7 @@ static float3 normal_to_euler_rotation(const float3 normal)
static Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
{
- /* This only updates a cache and can be considered to be logically const. */
- const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(const_cast<Mesh *>(&mesh));
+ const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(&mesh);
const int looptris_len = BKE_mesh_runtime_looptri_len(&mesh);
return {looptris, looptris_len};
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index bfd6027e0fc..0c1d8645411 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -95,7 +95,7 @@ static void raycast_to_mesh(const Mesh *mesh,
BLI_assert(ray_origins.size() == r_hit_distances.size() || r_hit_distances.is_empty());
BVHTreeFromMesh tree_data;
- BKE_bvhtree_from_mesh_get(&tree_data, const_cast<Mesh *>(mesh), BVHTREE_FROM_LOOPTRI, 4);
+ BKE_bvhtree_from_mesh_get(&tree_data, mesh, BVHTREE_FROM_LOOPTRI, 4);
if (tree_data.tree != nullptr) {
for (const int i : ray_origins.index_range()) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
index 20ffcdb516d..f0f032ed8f4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
@@ -96,7 +96,7 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params)
BKE_mesh_calc_normals(mesh_out);
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace_mesh_but_keep_vertex_group_names(mesh_out);
+ mesh_component.replace(mesh_out);
// BKE_subdiv_stats_print(&subdiv->stats);
BKE_subdiv_free(subdiv);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
new file mode 100644
index 00000000000..f0b91f49f52
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc
@@ -0,0 +1,31 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_viewer_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+void register_node_type_geo_viewer()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, 0);
+ node_type_socket_templates(&ntype, geo_node_viewer_in, nullptr);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
new file mode 100644
index 00000000000..3024cc51cad
--- /dev/null
+++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
@@ -0,0 +1,361 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "NOD_geometry_nodes_eval_log.hh"
+
+#include "BKE_geometry_set_instances.hh"
+
+#include "DNA_modifier_types.h"
+#include "DNA_space_types.h"
+
+namespace blender::nodes::geometry_nodes_eval_log {
+
+using fn::CPPType;
+
+ModifierLog::ModifierLog(GeoLogger &logger)
+{
+ root_tree_logs_ = allocator_.construct<TreeLog>();
+
+ LogByTreeContext log_by_tree_context;
+
+ /* Combine all the local loggers that have been used by separate threads. */
+ for (LocalGeoLogger &local_logger : logger) {
+ /* Take ownership of the allocator. */
+ logger_allocators_.append(std::move(local_logger.allocator_));
+
+ for (ValueOfSockets &value_of_sockets : local_logger.values_) {
+ ValueLog *value_log = value_of_sockets.value.get();
+
+ /* Take centralized ownership of the logged value. It might be referenced by multiple
+ * sockets. */
+ logged_values_.append(std::move(value_of_sockets.value));
+
+ for (const DSocket &socket : value_of_sockets.sockets) {
+ SocketLog &socket_log = this->lookup_or_add_socket_log(log_by_tree_context, socket);
+ socket_log.value_ = value_log;
+ }
+ }
+
+ for (NodeWithWarning &node_with_warning : local_logger.node_warnings_) {
+ NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context,
+ node_with_warning.node);
+ node_log.warnings_.append(node_with_warning.warning);
+ }
+ }
+}
+
+TreeLog &ModifierLog::lookup_or_add_tree_log(LogByTreeContext &log_by_tree_context,
+ const DTreeContext &tree_context)
+{
+ TreeLog *tree_log = log_by_tree_context.lookup_default(&tree_context, nullptr);
+ if (tree_log != nullptr) {
+ return *tree_log;
+ }
+
+ const DTreeContext *parent_context = tree_context.parent_context();
+ if (parent_context == nullptr) {
+ return *root_tree_logs_.get();
+ }
+ TreeLog &parent_log = this->lookup_or_add_tree_log(log_by_tree_context, *parent_context);
+ destruct_ptr<TreeLog> owned_tree_log = allocator_.construct<TreeLog>();
+ tree_log = owned_tree_log.get();
+ log_by_tree_context.add_new(&tree_context, tree_log);
+ parent_log.child_logs_.add_new(tree_context.parent_node()->name(), std::move(owned_tree_log));
+ return *tree_log;
+}
+
+NodeLog &ModifierLog::lookup_or_add_node_log(LogByTreeContext &log_by_tree_context, DNode node)
+{
+ TreeLog &tree_log = this->lookup_or_add_tree_log(log_by_tree_context, *node.context());
+ NodeLog &node_log = *tree_log.node_logs_.lookup_or_add_cb(node->name(), [&]() {
+ destruct_ptr<NodeLog> node_log = allocator_.construct<NodeLog>();
+ node_log->input_logs_.resize(node->inputs().size());
+ node_log->output_logs_.resize(node->outputs().size());
+ return node_log;
+ });
+ return node_log;
+}
+
+SocketLog &ModifierLog::lookup_or_add_socket_log(LogByTreeContext &log_by_tree_context,
+ DSocket socket)
+{
+ NodeLog &node_log = this->lookup_or_add_node_log(log_by_tree_context, socket.node());
+ MutableSpan<SocketLog> socket_logs = socket->is_input() ? node_log.input_logs_ :
+ node_log.output_logs_;
+ SocketLog &socket_log = socket_logs[socket->index()];
+ return socket_log;
+}
+
+const NodeLog *TreeLog::lookup_node_log(StringRef node_name) const
+{
+ const destruct_ptr<NodeLog> *node_log = node_logs_.lookup_ptr_as(node_name);
+ if (node_log == nullptr) {
+ return nullptr;
+ }
+ return node_log->get();
+}
+
+const NodeLog *TreeLog::lookup_node_log(const bNode &node) const
+{
+ return this->lookup_node_log(node.name);
+}
+
+const TreeLog *TreeLog::lookup_child_log(StringRef node_name) const
+{
+ const destruct_ptr<TreeLog> *tree_log = child_logs_.lookup_ptr_as(node_name);
+ if (tree_log == nullptr) {
+ return nullptr;
+ }
+ return tree_log->get();
+}
+
+const SocketLog *NodeLog::lookup_socket_log(eNodeSocketInOut in_out, int index) const
+{
+ BLI_assert(index >= 0);
+ Span<SocketLog> socket_logs = (in_out == SOCK_IN) ? input_logs_ : output_logs_;
+ if (index >= socket_logs.size()) {
+ return nullptr;
+ }
+ return &socket_logs[index];
+}
+
+const SocketLog *NodeLog::lookup_socket_log(const bNode &node, const bNodeSocket &socket) const
+{
+ ListBase sockets = socket.in_out == SOCK_IN ? node.inputs : node.outputs;
+ int index = BLI_findindex(&sockets, &socket);
+ return this->lookup_socket_log((eNodeSocketInOut)socket.in_out, index);
+}
+
+GeometryValueLog::GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry)
+{
+ bke::geometry_set_instances_attribute_foreach(
+ geometry_set,
+ [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) {
+ this->attributes_.append({attribute_name, meta_data.domain, meta_data.data_type});
+ return true;
+ },
+ 8);
+ for (const GeometryComponent *component : geometry_set.get_components_for_read()) {
+ component_types_.append(component->type());
+ switch (component->type()) {
+ case GEO_COMPONENT_TYPE_MESH: {
+ const MeshComponent &mesh_component = *(const MeshComponent *)component;
+ MeshInfo &info = this->mesh_info.emplace();
+ info.tot_verts = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ info.tot_edges = mesh_component.attribute_domain_size(ATTR_DOMAIN_EDGE);
+ info.tot_faces = mesh_component.attribute_domain_size(ATTR_DOMAIN_FACE);
+ break;
+ }
+ case GEO_COMPONENT_TYPE_CURVE: {
+ const CurveComponent &curve_component = *(const CurveComponent *)component;
+ CurveInfo &info = this->curve_info.emplace();
+ info.tot_splines = curve_component.attribute_domain_size(ATTR_DOMAIN_CURVE);
+ break;
+ }
+ case GEO_COMPONENT_TYPE_POINT_CLOUD: {
+ const PointCloudComponent &pointcloud_component = *(const PointCloudComponent *)component;
+ PointCloudInfo &info = this->pointcloud_info.emplace();
+ info.tot_points = pointcloud_component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ break;
+ }
+ case GEO_COMPONENT_TYPE_INSTANCES: {
+ const InstancesComponent &instances_component = *(const InstancesComponent *)component;
+ InstancesInfo &info = this->instances_info.emplace();
+ info.tot_instances = instances_component.instances_amount();
+ break;
+ }
+ case GEO_COMPONENT_TYPE_VOLUME: {
+ break;
+ }
+ }
+ }
+ if (log_full_geometry) {
+ full_geometry_ = std::make_unique<GeometrySet>(geometry_set);
+ full_geometry_->ensure_owns_direct_data();
+ }
+}
+
+Vector<const GeometryAttributeInfo *> NodeLog::lookup_available_attributes() const
+{
+ Vector<const GeometryAttributeInfo *> attributes;
+ Set<StringRef> names;
+ for (const SocketLog &socket_log : input_logs_) {
+ const ValueLog *value_log = socket_log.value();
+ if (const GeometryValueLog *geo_value_log = dynamic_cast<const GeometryValueLog *>(
+ value_log)) {
+ for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) {
+ if (names.add(attribute.name)) {
+ attributes.append(&attribute);
+ }
+ }
+ }
+ }
+ return attributes;
+}
+
+const ModifierLog *ModifierLog::find_root_by_node_editor_context(const SpaceNode &snode)
+{
+ if (snode.id == nullptr) {
+ return nullptr;
+ }
+ if (GS(snode.id->name) != ID_OB) {
+ return nullptr;
+ }
+ Object *object = (Object *)snode.id;
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ if (md->type == eModifierType_Nodes) {
+ NodesModifierData *nmd = (NodesModifierData *)md;
+ if (nmd->node_group == snode.nodetree) {
+ return (ModifierLog *)nmd->runtime_eval_log;
+ }
+ }
+ }
+ return nullptr;
+}
+
+const TreeLog *ModifierLog::find_tree_by_node_editor_context(const SpaceNode &snode)
+{
+ const ModifierLog *eval_log = ModifierLog::find_root_by_node_editor_context(snode);
+ if (eval_log == nullptr) {
+ return nullptr;
+ }
+ Vector<bNodeTreePath *> tree_path_vec = snode.treepath;
+ if (tree_path_vec.is_empty()) {
+ return nullptr;
+ }
+ TreeLog *current = eval_log->root_tree_logs_.get();
+ for (bNodeTreePath *path : tree_path_vec.as_span().drop_front(1)) {
+ destruct_ptr<TreeLog> *tree_log = current->child_logs_.lookup_ptr_as(path->node_name);
+ if (tree_log == nullptr) {
+ return nullptr;
+ }
+ current = tree_log->get();
+ }
+ return current;
+}
+
+const NodeLog *ModifierLog::find_node_by_node_editor_context(const SpaceNode &snode,
+ const bNode &node)
+{
+ const TreeLog *tree_log = ModifierLog::find_tree_by_node_editor_context(snode);
+ if (tree_log == nullptr) {
+ return nullptr;
+ }
+ return tree_log->lookup_node_log(node);
+}
+
+const SocketLog *ModifierLog::find_socket_by_node_editor_context(const SpaceNode &snode,
+ const bNode &node,
+ const bNodeSocket &socket)
+{
+ const NodeLog *node_log = ModifierLog::find_node_by_node_editor_context(snode, node);
+ if (node_log == nullptr) {
+ return nullptr;
+ }
+ return node_log->lookup_socket_log(node, socket);
+}
+
+const NodeLog *ModifierLog::find_node_by_spreadsheet_editor_context(
+ const SpaceSpreadsheet &sspreadsheet)
+{
+ Vector<SpreadsheetContext *> context_path = sspreadsheet.context_path;
+ if (context_path.size() <= 2) {
+ return nullptr;
+ }
+ if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
+ return nullptr;
+ }
+ if (context_path[1]->type != SPREADSHEET_CONTEXT_MODIFIER) {
+ return nullptr;
+ }
+ for (SpreadsheetContext *context : context_path.as_span().drop_front(2)) {
+ if (context->type != SPREADSHEET_CONTEXT_NODE) {
+ return nullptr;
+ }
+ }
+ Span<SpreadsheetContextNode *> node_contexts =
+ context_path.as_span().drop_front(2).cast<SpreadsheetContextNode *>();
+
+ Object *object = ((SpreadsheetContextObject *)context_path[0])->object;
+ StringRefNull modifier_name = ((SpreadsheetContextModifier *)context_path[1])->modifier_name;
+ if (object == nullptr) {
+ return nullptr;
+ }
+
+ const ModifierLog *eval_log = nullptr;
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ if (md->type == eModifierType_Nodes) {
+ if (md->name == modifier_name) {
+ NodesModifierData *nmd = (NodesModifierData *)md;
+ eval_log = (const ModifierLog *)nmd->runtime_eval_log;
+ break;
+ }
+ }
+ }
+ if (eval_log == nullptr) {
+ return nullptr;
+ }
+
+ const TreeLog *tree_log = &eval_log->root_tree();
+ for (SpreadsheetContextNode *context : node_contexts.drop_back(1)) {
+ tree_log = tree_log->lookup_child_log(context->node_name);
+ if (tree_log == nullptr) {
+ return nullptr;
+ }
+ }
+ const NodeLog *node_log = tree_log->lookup_node_log(node_contexts.last()->node_name);
+ return node_log;
+}
+
+void LocalGeoLogger::log_value_for_sockets(Span<DSocket> sockets, GPointer value)
+{
+ const CPPType &type = *value.type();
+ Span<DSocket> copied_sockets = allocator_->construct_array_copy(sockets);
+ if (type.is<GeometrySet>()) {
+ bool log_full_geometry = false;
+ for (const DSocket &socket : sockets) {
+ if (main_logger_->log_full_geometry_sockets_.contains(socket)) {
+ log_full_geometry = true;
+ break;
+ }
+ }
+
+ const GeometrySet &geometry_set = *value.get<GeometrySet>();
+ destruct_ptr<GeometryValueLog> value_log = allocator_->construct<GeometryValueLog>(
+ geometry_set, log_full_geometry);
+ values_.append({copied_sockets, std::move(value_log)});
+ }
+ else {
+ void *buffer = allocator_->allocate(type.size(), type.alignment());
+ type.copy_construct(value.get(), buffer);
+ destruct_ptr<GenericValueLog> value_log = allocator_->construct<GenericValueLog>(
+ GMutablePointer{type, buffer});
+ values_.append({copied_sockets, std::move(value_log)});
+ }
+}
+
+void LocalGeoLogger::log_multi_value_socket(DSocket socket, Span<GPointer> values)
+{
+ /* Doesn't have to be logged currently. */
+ UNUSED_VARS(socket, values);
+}
+
+void LocalGeoLogger::log_node_warning(DNode node, NodeWarningType type, std::string message)
+{
+ node_warnings_.append({node, {type, std::move(message)}});
+}
+
+} // namespace blender::nodes::geometry_nodes_eval_log
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index 7fc9f664df0..b8c89d1db37 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -127,7 +127,7 @@ static bNodeSocket *group_verify_socket(
bNodeSocket *sock;
for (sock = verify_lb->first; sock; sock = sock->next) {
- if (sock->typeinfo == iosock->typeinfo && STREQ(sock->identifier, iosock->identifier)) {
+ if (STREQ(sock->identifier, iosock->identifier)) {
break;
}
}
@@ -137,6 +137,13 @@ static bNodeSocket *group_verify_socket(
const int mask = SOCK_HIDE_VALUE;
sock->flag = (sock->flag & ~mask) | (iosock->flag & mask);
+ /* Update socket type if necessary */
+ if (sock->typeinfo != iosock->typeinfo) {
+ nodeModifySocketType(ntree, gnode, sock, iosock->idname);
+ /* Flag the tree to make sure link validity is updated after type changes. */
+ ntree->update |= NTREE_UPDATE_LINKS;
+ }
+
if (iosock->typeinfo->interface_verify_socket) {
iosock->typeinfo->interface_verify_socket(ntree, iosock, gnode, sock, "interface");
}
@@ -259,7 +266,7 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node)
static void node_reroute_init(bNodeTree *ntree, bNode *node)
{
- /* Note: Cannot use socket templates for this, since it would reset the socket type
+ /* NOTE: Cannot use socket templates for this, since it would reset the socket type
* on each file read via the template verification procedure.
*/
nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input");
diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc
index 8b61758a673..1e39aa5214d 100644
--- a/source/blender/nodes/intern/node_geometry_exec.cc
+++ b/source/blender/nodes/intern/node_geometry_exec.cc
@@ -16,8 +16,6 @@
#include "DNA_modifier_types.h"
-#include "BKE_node_ui_storage.hh"
-
#include "DEG_depsgraph_query.h"
#include "NOD_geometry_exec.hh"
@@ -26,21 +24,17 @@
#include "node_geometry_util.hh"
+using blender::nodes::geometry_nodes_eval_log::LocalGeoLogger;
+
namespace blender::nodes {
void GeoNodeExecParams::error_message_add(const NodeWarningType type, std::string message) const
{
- bNodeTree *btree_cow = provider_->dnode->btree();
- BLI_assert(btree_cow != nullptr);
- if (btree_cow == nullptr) {
+ if (provider_->logger == nullptr) {
return;
}
- bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow);
-
- const NodeTreeEvaluationContext context(*provider_->self_object, *provider_->modifier);
-
- BKE_nodetree_error_message_add(
- *btree_original, context, *provider_->dnode->bnode(), type, std::move(message));
+ LocalGeoLogger &local_logger = provider_->logger->local();
+ local_logger.log_node_warning(provider_->dnode, type, std::move(message));
}
const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name) const
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index c0a8382a661..e2568fd8f85 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -131,7 +131,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree,
}
if (sock) {
if (sock->type != stemp->type) {
- nodeModifySocketType(ntree, node, sock, stemp->type, stemp->subtype);
+ nodeModifySocketTypeStatic(ntree, node, sock, stemp->type, stemp->subtype);
}
sock->flag |= stemp->flag;
}
@@ -563,12 +563,14 @@ static bNodeSocketType *make_standard_socket_type(int type, int subtype)
{
const char *socket_idname = nodeStaticSocketType(type, subtype);
const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype);
+ const char *socket_label = nodeStaticSocketLabel(type, subtype);
bNodeSocketType *stype;
StructRNA *srna;
stype = (bNodeSocketType *)MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
stype->free_self = (void (*)(bNodeSocketType * stype)) MEM_freeN;
BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+ BLI_strncpy(stype->label, socket_label, sizeof(stype->label));
/* set the RNA type
* uses the exact same identifier as the socket type idname */
diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc
index bed4d60382d..9ce9d6fc273 100644
--- a/source/blender/nodes/intern/node_tree_ref.cc
+++ b/source/blender/nodes/intern/node_tree_ref.cc
@@ -461,7 +461,7 @@ bool NodeTreeRef::has_undefined_nodes_or_sockets() const
return true;
}
}
- return true;
+ return false;
}
std::string NodeTreeRef::to_dot() const
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index e23e2ac3b9d..7367f73d171 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -184,10 +184,11 @@ static bool shader_validate_link(bNodeTree *UNUSED(ntree), bNodeLink *link)
return true;
}
-static bool shader_node_tree_socket_type_valid(eNodeSocketDatatype socket_type,
- bNodeTreeType *UNUSED(ntreetype))
+static bool shader_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype),
+ bNodeSocketType *socket_type)
{
- return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
+ return nodeIsStaticSocketType(socket_type) &&
+ ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
}
bNodeTreeType *ntreeType_Shader;
@@ -790,7 +791,7 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
*/
nodeAddLink(ntree, displacement_node, displacement_socket, bump_node, bump_input_socket);
- /* Tag as part of the new displacmeent tree. */
+ /* Tag as part of the new displacement tree. */
dot_node->tmp_flag = -2;
geo_node->tmp_flag = -2;
bump_node->tmp_flag = -2;
diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
index 7a05fc95eec..50eb5bf32c9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
@@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_hue_sat_out[] = {
{-1, ""},
};
-/* note: it would be possible to use CMP version for both nodes */
+/* NOTE: it would be possible to use CMP version for both nodes. */
static void do_hue_sat_fac(
bNode *UNUSED(node), float *out, float hue, float sat, float val, const float in[4], float fac)
{
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 2ae722e3cd8..f771b4934b2 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -152,10 +152,11 @@ static void update(bNodeTree *ntree)
}
}
-static bool texture_node_tree_socket_type_valid(eNodeSocketDatatype socket_type,
- bNodeTreeType *UNUSED(ntreetype))
+static bool texture_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype),
+ bNodeSocketType *socket_type)
{
- return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
+ return nodeIsStaticSocketType(socket_type) &&
+ ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
}
bNodeTreeType *ntreeType_Texture;
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 90f54c50a6d..84d804f8bdf 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -20,8 +20,8 @@
#pragma once
-struct AnimationEvalContext;
struct ARegionType;
+struct AnimationEvalContext;
struct ChannelDriver; /* DNA_anim_types.h */
struct ID; /* DNA_ID.h */
struct ListBase; /* DNA_listBase.h */
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index d198c6ca559..24887b24eb6 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -44,10 +44,10 @@ BLI_STATIC_ASSERT(sizeof(PyC_FlagSet) == sizeof(BMO_FlagSet), "size mismatch");
static int bpy_bm_op_as_py_error(BMesh *bm)
{
- if (BMO_error_occurred(bm)) {
- /* note: we could have multiple errors */
+ if (BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL)) {
+ /* NOTE: we could have multiple errors. */
const char *errmsg;
- if (BMO_error_get(bm, &errmsg, NULL)) {
+ if (BMO_error_get(bm, &errmsg, NULL, NULL)) {
PyErr_Format(PyExc_RuntimeError, "bmesh operator: %.200s", errmsg);
BMO_error_clear(bm);
return -1;
@@ -243,7 +243,7 @@ static int bpy_slot_from_py(BMesh *bm,
break;
}
case BMO_OP_SLOT_MAT: {
- /* XXX - BMesh operator design is crappy here, operator slot should define matrix size,
+ /* XXX: BMesh operator design is crappy here, operator slot should define matrix size,
* not the caller! */
MatrixObject *pymat;
if (!Matrix_ParseAny(value, &pymat)) {
@@ -583,7 +583,7 @@ static int bpy_slot_from_py(BMesh *bm,
break;
}
default:
- /* TODO --- many others */
+ /* TODO: many others. */
PyErr_Format(PyExc_NotImplementedError,
"%.200s: keyword \"%.200s\" type %d not working yet!",
opname,
@@ -608,7 +608,7 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
/* keep switch in same order as above */
switch (slot->slot_type) {
case BMO_OP_SLOT_BOOL:
- item = PyBool_FromLong((BMO_SLOT_AS_BOOL(slot)));
+ item = PyBool_FromLong(BMO_SLOT_AS_BOOL(slot));
break;
case BMO_OP_SLOT_INT:
item = PyLong_FromLong(BMO_SLOT_AS_INT(slot));
@@ -776,8 +776,8 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
return NULL;
}
- /* TODO - error check this!, though we do the error check on attribute access */
- /* TODO - make flags optional */
+ /* TODO: error check this!, though we do the error check on attribute access. */
+ /* TODO: make flags optional. */
BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, self->opname);
if (kw && PyDict_Size(kw) > 0) {
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 9334e9893b0..612446e6d19 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -553,7 +553,7 @@ static PyObject *bpy_bmloop_is_convex_get(BPy_BMLoop *self)
/* ElemSeq
* ^^^^^^^ */
-/* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */
+/* NOTE: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly. */
PyDoc_STRVAR(bpy_bmelemseq_layers_vert_doc,
"custom-data layers (read-only).\n\n:type: :class:`BMLayerAccessVert`");
PyDoc_STRVAR(bpy_bmelemseq_layers_edge_doc,
@@ -2588,7 +2588,7 @@ PyDoc_STRVAR(
* If a portable alternative to qsort_r becomes available, remove this static
* var hack!
*
- * Note: the functions below assumes the keys array has been allocated and it
+ * NOTE: the functions below assumes the keys array has been allocated and it
* has enough elements to complete the task.
*/
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index ed307ce59a0..043c5322735 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -114,7 +114,7 @@ typedef struct BPy_BMElemSeq {
/* we hold a reference to this.
* check in case the owner becomes invalid on access */
- /* TODO - make this a GC'd object!, will function OK without this though */
+ /* TODO: make this a GC'd object!, will function OK without this though. */
BPy_BMElem *py_ele;
/* iterator type */
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index d9a82f52be0..8f4e07c30d3 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -500,7 +500,7 @@ static PySequenceMethods bpy_bmdeformvert_as_sequence = {
NULL, /* sq_concat */
NULL, /* sq_repeat */
- /* Note: if this is set #PySequence_Check() returns True,
+ /* NOTE: if this is set #PySequence_Check() returns True,
* but in this case we don't want to be treated as a seq. */
NULL, /* sq_item */
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index c1e28182c53..1c3334f1adc 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -189,7 +189,7 @@ static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *ar
bm = py_vert->bm;
- return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v)));
+ return PyBool_FromLong(BM_vert_dissolve(bm, py_vert->v));
}
PyDoc_STRVAR(bpy_bm_utils_vert_splice_doc,
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index c6afb694413..bfdc763e4df 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -1547,7 +1547,7 @@ static PySequenceMethods BPy_IDGroup_Seq = {
NULL, /* binaryfunc sq_concat */
NULL, /* ssizeargfunc sq_repeat */
NULL,
- /* ssizeargfunc sq_item */ /* TODO - setting this will allow PySequence_Check to return True */
+ /* ssizeargfunc sq_item */ /* TODO: setting this will allow PySequence_Check to return True. */
NULL, /* intintargfunc ***was_sq_slice*** */
NULL, /* intobjargproc sq_ass_item */
NULL, /* ssizeobjargproc ***was_sq_ass_slice*** */
diff --git a/source/blender/python/generic/imbuf_py_api.c b/source/blender/python/generic/imbuf_py_api.c
index 57e148b56c8..08ddef992a3 100644
--- a/source/blender/python/generic/imbuf_py_api.c
+++ b/source/blender/python/generic/imbuf_py_api.c
@@ -443,7 +443,7 @@ static PyObject *M_imbuf_new(PyObject *UNUSED(self), PyObject *args, PyObject *k
return NULL;
}
- /* TODO, make options */
+ /* TODO: make options. */
const uchar planes = 4;
const uint flags = IB_rect;
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 127380feec1..a27ef30c849 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -367,7 +367,7 @@ void PyC_LineSpit(void)
const char *filename;
int lineno;
- /* Note, allow calling from outside python (RNA) */
+ /* NOTE: allow calling from outside python (RNA). */
if (!PyC_IsInterpreterActive()) {
fprintf(stderr, "python line lookup failed, interpreter inactive\n");
return;
@@ -381,7 +381,7 @@ void PyC_LineSpit(void)
void PyC_StackSpit(void)
{
- /* Note, allow calling from outside python (RNA) */
+ /* NOTE: allow calling from outside python (RNA). */
if (!PyC_IsInterpreterActive()) {
fprintf(stderr, "python line lookup failed, interpreter inactive\n");
return;
@@ -826,13 +826,13 @@ PyObject *PyC_UnicodeFromByte(const char *str)
/*****************************************************************************
* Description: This function creates a new Python dictionary object.
- * note: dict is owned by sys.modules["__main__"] module, reference is borrowed
- * note: important we use the dict from __main__, this is what python expects
+ * NOTE: dict is owned by sys.modules["__main__"] module, reference is borrowed
+ * NOTE: important we use the dict from __main__, this is what python expects
* for 'pickle' to work as well as strings like this...
* >> foo = 10
* >> print(__import__("__main__").foo)
*
- * note: this overwrites __main__ which gives problems with nested calls.
+ * NOTE: this overwrites __main__ which gives problems with nested calls.
* be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is
* any chance that python is in the call stack.
****************************************************************************/
@@ -846,7 +846,7 @@ PyObject *PyC_DefaultNameSpace(const char *filename)
PyModule_AddStringConstant(mod_main, "__name__", "__main__");
if (filename) {
/* __file__ mainly for nice UI'ness
- * note: this won't map to a real file when executing text-blocks and buttons. */
+ * NOTE: this won't map to a real file when executing text-blocks and buttons. */
PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename));
}
PyModule_AddObject(mod_main, "__builtins__", builtins);
diff --git a/source/blender/python/gpu/gpu_py_uniformbuffer.c b/source/blender/python/gpu/gpu_py_uniformbuffer.c
index edcec486398..cfef20e2e4d 100644
--- a/source/blender/python/gpu/gpu_py_uniformbuffer.c
+++ b/source/blender/python/gpu/gpu_py_uniformbuffer.c
@@ -104,7 +104,7 @@ static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject *UNUSED(self),
}
PyDoc_STRVAR(pygpu_uniformbuffer_update_doc,
- ".. method::update(data)\n"
+ ".. method:: update(data)\n"
"\n"
" Update the data of the uniform buffer object.\n");
static PyObject *pygpu_uniformbuffer_update(BPyGPUUniformBuf *self, PyObject *obj)
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index bc05c51414f..d66643c5d61 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -225,7 +225,7 @@ PyObject *BPY_app_handlers_struct(void)
#endif
if (PyType_Ready(&BPyPersistent_Type) < 0) {
- BLI_assert(!"error initializing 'bpy.app.handlers.persistent'");
+ BLI_assert_msg(0, "error initializing 'bpy.app.handlers.persistent'");
}
PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc);
@@ -283,7 +283,7 @@ void BPY_app_handlers_reset(const short do_all)
for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) {
- if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) &&
+ if (PyFunction_Check((item = PyList_GET_ITEM(ls, i))) &&
(dict_ptr = _PyObject_GetDictPtr(item)) && (*dict_ptr) &&
(PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) {
/* keep */
@@ -347,7 +347,7 @@ void bpy_app_generic_callback(struct Main *UNUSED(main),
}
/* Iterate the list and run the callbacks
- * note: don't store the list size since the scripts may remove themselves */
+ * NOTE: don't store the list size since the scripts may remove themselves. */
for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) {
func = PyList_GET_ITEM(cb_list, pos);
PyObject *args = choose_arguments(func, args_all, args_single);
diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c
index 478ae61aecd..7437598582f 100644
--- a/source/blender/python/intern/bpy_app_translations.c
+++ b/source/blender/python/intern/bpy_app_translations.c
@@ -101,7 +101,7 @@ static bool _ghashutil_keycmp(const void *a, const void *b)
const GHashKey *A = a;
const GHashKey *B = b;
- /* Note: comparing msgid first, most of the time it will be enough! */
+ /* NOTE: comparing msgid first, most of the time it will be enough! */
if (BLI_ghashutil_strcmp(A->msgid, B->msgid) == false) {
return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt);
}
@@ -497,7 +497,7 @@ static PyObject *app_translations_locale_get(PyObject *UNUSED(self), void *UNUSE
return PyUnicode_FromString(BLT_lang_get());
}
-/* Note: defining as getter, as (even if quite unlikely), this *may* change during runtime... */
+/* NOTE: defining as getter, as (even if quite unlikely), this *may* change during runtime... */
PyDoc_STRVAR(app_translations_locales_doc,
"All locales currently known by Blender (i.e. available as translations).");
static PyObject *app_translations_locales_get(PyObject *UNUSED(self), void *UNUSED(userdata))
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index a7b99f211c2..7effa25e6e8 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -175,7 +175,7 @@ int bpy_pydriver_create_dict(void)
return 0;
}
-/* note, this function should do nothing most runs, only when changing frame */
+/* NOTE: this function should do nothing most runs, only when changing frame. */
/* not thread safe but neither is python */
static struct {
float evaltime;
@@ -266,7 +266,7 @@ static void pydriver_error(ChannelDriver *driver)
"\nError in Driver: The following Python expression failed:\n\t'%s'\n\n",
driver->expression);
- // BPy_errors_to_report(NULL); /* TODO - reports */
+ // BPy_errors_to_report(NULL); /* TODO: reports. */
PyErr_Print();
PyErr_Clear();
}
@@ -433,12 +433,12 @@ static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars,
* This evaluates Python driver expressions, `driver_orig->expression`
* is a Python expression that should evaluate to a float number, which is returned.
*
- * (old)note: PyGILState_Ensure() isn't always called because python can call
+ * (old) NOTE: PyGILState_Ensure() isn't always called because python can call
* the bake operator which intern starts a thread which calls scene update
* which does a driver update. to avoid a deadlock check #PyC_IsInterpreterActive()
* if #PyGILState_Ensure() is needed, see T27683.
*
- * (new)note: checking if python is running is not thread-safe T28114
+ * (new) NOTE: checking if python is running is not thread-safe T28114
* now release the GIL on python operator execution instead, using
* #PyEval_SaveThread() / #PyEval_RestoreThread() so we don't lock up blender.
*
@@ -613,7 +613,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
fprintf(
stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name);
- // BPy_errors_to_report(NULL); /* TODO - reports */
+ // BPy_errors_to_report(NULL); /* TODO: reports. */
PyErr_Print();
PyErr_Clear();
}
diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c
index 686a4d88266..34d2ba16e69 100644
--- a/source/blender/python/intern/bpy_gizmo_wrap.c
+++ b/source/blender/python/intern/bpy_gizmo_wrap.c
@@ -49,7 +49,7 @@
static bool bpy_gizmotype_target_property_def(wmGizmoType *gzt, PyObject *item)
{
- /* Note: names based on 'rna_rna.c' */
+ /* NOTE: names based on `rna_rna.c`. */
PyObject *empty_tuple = PyTuple_New(0);
struct {
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 832af9e8460..f91ba4d362c 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -154,7 +154,7 @@ void bpy_context_clear(bContext *UNUSED(C), const PyGILState_STATE *gilstate)
fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n");
}
else if (py_call_level == 0) {
- /* XXX - Calling classes currently won't store the context :\,
+ /* XXX: Calling classes currently won't store the context :\,
* can't set NULL because of this. but this is very flakey still. */
#if 0
BPY_context_set(NULL);
@@ -763,7 +763,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
}
#ifdef WITH_PYTHON_MODULE
-/* TODO, reloading the module isn't functional at the moment. */
+/* TODO: reloading the module isn't functional at the moment. */
static void bpy_module_free(void *mod);
@@ -825,7 +825,7 @@ static void dealloc_obj_dealloc(PyObject *self)
{
bpy_module_delay_init(((dealloc_obj *)self)->mod);
- /* Note, for subclassed PyObjects we can't just call PyObject_DEL() directly or it will crash */
+ /* NOTE: for subclassed PyObjects we can't just call PyObject_DEL() directly or it will crash. */
dealloc_obj_Type.tp_free(self);
}
diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c
index 03d51b2fd59..f92a48eb597 100644
--- a/source/blender/python/intern/bpy_interface_atexit.c
+++ b/source/blender/python/intern/bpy_interface_atexit.c
@@ -46,9 +46,8 @@ static PyObject *func_bpy_atregister = NULL; /* borrowed reference, `atexit` hol
static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg)
{
- /* note - no error checking, if any of these fail we'll get a crash
- * this is intended, but if its problematic it could be changed
- * - campbell */
+ /* NOTE(campbell): no error checking, if any of these fail we'll get a crash
+ * this is intended, but if its problematic it could be changed. */
PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0);
PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name);
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 28a97c3fa3b..d9a357c5e2e 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -66,6 +66,8 @@ typedef struct {
char relpath[FILE_MAX];
char abspath[FILE_MAX]; /* absolute path */
BlendHandle *blo_handle;
+ /* Referenced by `blo_handle`, so stored here to keep alive for long enough. */
+ BlendFileReadReport bf_reports;
int flag;
PyObject *dict;
/* Borrowed reference to the `bmain`, taken from the RNA instance of #RNA_BlendDataLibraries.
@@ -259,7 +261,8 @@ static PyObject *bpy_lib_enter(BPy_Library *self)
BKE_reports_init(&reports, RPT_STORE);
BlendFileReadReport bf_reports = {.reports = &reports};
- self->blo_handle = BLO_blendhandle_from_file(self->abspath, &bf_reports);
+ self->bf_reports = bf_reports;
+ self->blo_handle = BLO_blendhandle_from_file(self->abspath, &self->bf_reports);
if (self->blo_handle == NULL) {
if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) {
diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c
index 4e6d2aacb49..04220cf3105 100644
--- a/source/blender/python/intern/bpy_msgbus.c
+++ b/source/blender/python/intern/bpy_msgbus.c
@@ -90,12 +90,12 @@ static int py_msgbus_rna_key_from_py(PyObject *py_sub,
msg_key_params->prop = data_prop->prop;
}
else if (BPy_StructRNA_Check(py_sub)) {
- /* note, this isn't typically used since we don't edit structs directly. */
+ /* NOTE: this isn't typically used since we don't edit structs directly. */
BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub;
PYRNA_STRUCT_CHECK_INT(data_srna);
msg_key_params->ptr = data_srna->ptr;
}
- /* TODO - property / type, not instance. */
+ /* TODO: property / type, not instance. */
else if (PyType_Check(py_sub)) {
StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix);
if (data_type == NULL) {
@@ -264,7 +264,7 @@ static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args
return NULL;
}
- /* Note: we may want to have a way to pass this in. */
+ /* NOTE: we may want to have a way to pass this in. */
bContext *C = BPY_context_get();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
wmMsgParams_RNA msg_key_params = {{0}};
@@ -339,7 +339,7 @@ static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args,
return NULL;
}
- /* Note: we may want to have a way to pass this in. */
+ /* NOTE: we may want to have a way to pass this in. */
bContext *C = BPY_context_get();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
wmMsgParams_RNA msg_key_params = {{0}};
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 055dd624ea8..9ee9f2e477f 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -82,8 +82,8 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
int context = WM_OP_EXEC_DEFAULT;
- /* XXX Todo, work out a better solution for passing on context,
- * could make a tuple from self and pack the name and Context into it... */
+ /* XXX TODO: work out a better solution for passing on context,
+ * could make a tuple from self and pack the name and Context into it. */
bContext *C = BPY_context_get();
if (C == NULL) {
@@ -169,8 +169,8 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
int context = WM_OP_EXEC_DEFAULT;
int is_undo = false;
- /* XXX Todo, work out a better solution for passing on context,
- * could make a tuple from self and pack the name and Context into it... */
+ /* XXX TODO: work out a better solution for passing on context,
+ * could make a tuple from self and pack the name and Context into it. */
bContext *C = BPY_context_get();
if (C == NULL) {
@@ -276,7 +276,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
#ifdef BPY_RELEASE_GIL
/* release GIL, since a thread could be started from an operator
* that updates a driver */
- /* note: I have not seen any examples of code that does this
+ /* NOTE: I have not seen any examples of code that does this
* so it may not be officially supported but seems to work ok. */
{
PyThreadState *ts = PyEval_SaveThread();
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 0d451a8dd7f..f332d547965 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -1779,12 +1779,12 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
item = seq_fast_items[i];
- if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) &&
+ if (PyTuple_CheckExact(item) && (item_size = PyTuple_GET_SIZE(item)) &&
(item_size >= 3 && item_size <= 5) &&
(tmp.identifier = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) &&
(tmp.name = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) &&
(tmp.description = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) &&
- /* TODO, number isn't ensured to be unique from the script author */
+ /* TODO: number isn't ensured to be unique from the script author. */
(item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value)) &&
(item_size != 5 || ((py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.icon) ||
(tmp_icon = PyUnicode_AsUTF8(PyTuple_GET_ITEM(item, 3)))) &&
@@ -3509,7 +3509,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
if (def) {
/* Only support getting integer default values here. */
if (!py_long_as_int(def, &defvalue)) {
- /* note, using type error here is odd but python does this for invalid arguments */
+ /* NOTE: using type error here is odd but python does this for invalid arguments. */
PyErr_SetString(
PyExc_TypeError,
"EnumProperty(...): 'default' can only be an integer when 'items' is a function");
@@ -3557,7 +3557,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
RNA_def_property_duplicate_pointers(srna, prop);
if (is_itemf == false) {
- /* note: this must be postponed until after #RNA_def_property_duplicate_pointers
+ /* NOTE: this must be postponed until after #RNA_def_property_duplicate_pointers
* otherwise if this is a generator it may free the strings before we copy them */
Py_DECREF(items_fast);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index a3c5d4e9d66..e6f3e509469 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -734,12 +734,12 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
const short order = pyrna_rotation_euler_order_get(
ptr, EULER_ORDER_XYZ, &prop_eul_order);
- ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA. */
+ ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO: get order from RNA. */
RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul);
}
else {
/* Order will be updated from callback on use. */
- /* TODO, get order from RNA. */
+ /* TODO: get order from RNA. */
PyObject *eul_cb = Euler_CreatePyObject_cb(
ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL);
Py_DECREF(ret); /* The euler owns 'ret' now. */
@@ -817,7 +817,7 @@ int pyrna_enum_value_from_id(const EnumPropertyItem *item,
return 0;
}
-/* note on __cmp__:
+/* NOTE(campbell): Regarding comparison `__cmp__`:
* checking the 'ptr->data' matches works in almost all cases,
* however there are a few RNA properties that are fake sub-structs and
* share the pointer with the parent, in those cases this happens 'a.b == a'
@@ -825,8 +825,7 @@ int pyrna_enum_value_from_id(const EnumPropertyItem *item,
*
* So compare the 'ptr->type' as well to avoid this problem.
* It's highly unlikely this would happen that 'ptr->data' and 'ptr->prop' would match,
- * but _not_ 'ptr->type' but include this check for completeness.
- * - campbell */
+ * but _not_ 'ptr->type' but include this check for completeness. */
static int pyrna_struct_compare(BPy_StructRNA *a, BPy_StructRNA *b)
{
@@ -1196,7 +1195,7 @@ static void pyrna_struct_dealloc(BPy_StructRNA *self)
}
#endif /* !USE_PYRNA_STRUCT_REFERENCE */
- /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */
+ /* NOTE: for subclassed PyObjects calling PyObject_DEL() directly crashes. */
Py_TYPE(self)->tp_free(self);
}
@@ -1225,7 +1224,7 @@ static void pyrna_prop_dealloc(BPy_PropertyRNA *self)
PyObject_ClearWeakRefs((PyObject *)self);
}
#endif
- /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */
+ /* NOTE: for subclassed PyObjects calling PyObject_DEL() directly crashes. */
Py_TYPE(self)->tp_free(self);
}
@@ -1236,7 +1235,7 @@ static void pyrna_prop_array_dealloc(BPy_PropertyRNA *self)
PyObject_ClearWeakRefs((PyObject *)self);
}
#endif
- /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */
+ /* NOTE: for subclassed PyObjects calling PyObject_DEL() directly crashes. */
Py_TYPE(self)->tp_free(self);
}
@@ -1879,7 +1878,7 @@ static int pyrna_py_to_prop(
#ifdef USE_STRING_COERCE
PyObject *value_coerce = NULL;
if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
- /* TODO, get size. */
+ /* TODO: get size. */
param = PyC_UnicodeAsByte(value, &value_coerce);
}
else {
@@ -2640,7 +2639,7 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self,
}
/**
- * TODO - dimensions
+ * TODO: dimensions
* \note Could also use pyrna_prop_array_to_py_index(self, count) in a loop, but it's much slower
* since at the moment it reads (and even allocates) the entire array for each index.
*/
@@ -2729,7 +2728,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self,
break;
}
default:
- BLI_assert(!"Invalid array type");
+ BLI_assert_msg(0, "Invalid array type");
PyErr_SetString(PyExc_TypeError, "not an array type");
Py_DECREF(tuple);
@@ -2853,7 +2852,7 @@ static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *val
return -1;
}
-/* note: currently this is a copy of 'pyrna_prop_collection_subscript' with
+/* NOTE: currently this is a copy of 'pyrna_prop_collection_subscript' with
* large blocks commented, we may support slice/key indices later */
static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self,
PyObject *key,
@@ -2884,7 +2883,7 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self,
return pyrna_prop_collection_ass_subscript_int(self, i, value);
}
-#if 0 /* TODO, fake slice assignment. */
+#if 0 /* TODO: fake slice assignment. */
else if (PySlice_Check(key)) {
PySliceObject *key_slice = (PySliceObject *)key;
Py_ssize_t step = 1;
@@ -2967,7 +2966,7 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject
return NULL;
}
if (key_slice->start == Py_None && key_slice->stop == Py_None) {
- /* Note: no significant advantage with optimizing [:] slice as with collections,
+ /* NOTE: no significant advantage with optimizing [:] slice as with collections,
* but include here for consistency with collection slice func */
const Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self);
return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len);
@@ -4113,7 +4112,7 @@ static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
}
}
else {
- /* TODO, panels, menus etc. */
+ /* TODO: panels, menus etc. */
PyErr_Format(
PyExc_ValueError, "Class type \"%.200s\" not supported", RNA_struct_identifier(srna_base));
return NULL;
@@ -4254,6 +4253,56 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
return ret;
}
+PyDoc_STRVAR(pyrna_struct_id_properties_ensure_doc,
+ ".. method:: id_properties_ensure()\n"
+ " :return: the parent group for an RNA struct's custom IDProperties.\n"
+ " :rtype: :class:`bpy.types.IDPropertyGroup`\n");
+static PyObject *pyrna_struct_id_properties_ensure(BPy_StructRNA *self)
+{
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (RNA_struct_idprops_check(self->ptr.type) == 0) {
+ PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
+ return NULL;
+ }
+
+ IDProperty *idprops = RNA_struct_idprops(&self->ptr, true);
+
+ /* This is a paranoid check that theoretically might not be necessary.
+ * It allows the possibility that some structs can't ensure IDProperties. */
+ if (idprops == NULL) {
+ return Py_None;
+ }
+
+ BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type);
+ group->owner_id = self->ptr.owner_id;
+ group->prop = idprops;
+ group->parent = NULL;
+ return (PyObject *)group;
+}
+
+PyDoc_STRVAR(pyrna_struct_id_properties_clear_doc,
+ ".. method:: id_properties_clear()\n"
+ " :return: Remove the parent group for an RNA struct's custom IDProperties.\n");
+static PyObject *pyrna_struct_id_properties_clear(BPy_StructRNA *self)
+{
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (RNA_struct_idprops_check(self->ptr.type) == 0) {
+ PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
+ return NULL;
+ }
+
+ IDProperty **idprops = RNA_struct_idprops_p(&self->ptr);
+
+ if (*idprops) {
+ IDP_FreeProperty(*idprops);
+ *idprops = NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
/* ---------------getattr-------------------------------------------- */
static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
{
@@ -4326,7 +4375,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
}
default:
/* Should never happen. */
- BLI_assert(!"Invalid context type");
+ BLI_assert_msg(0, "Invalid context type");
PyErr_Format(PyExc_AttributeError,
"bpy_struct: Context type invalid %d, can't get \"%.200s\" from context",
@@ -5183,7 +5232,7 @@ static int foreach_parse_args(BPy_PropertyRNA *self,
return -1;
}
- /* TODO - buffer may not be a sequence! array.array() is though. */
+ /* TODO: buffer may not be a sequence! array.array() is though. */
*r_tot = PySequence_Size(*r_seq);
if (*r_tot > 0) {
@@ -5340,7 +5389,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
break;
case PROP_RAW_UNSET:
/* Should never happen. */
- BLI_assert(!"Invalid array type - set");
+ BLI_assert_msg(0, "Invalid array type - set");
break;
}
@@ -5357,7 +5406,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
Py_buffer buf;
PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT);
- /* Check if the buffer matches, TODO - signed/unsigned types. */
+ /* Check if the buffer matches, TODO: signed/unsigned types. */
buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format);
@@ -5404,7 +5453,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
break;
default: /* PROP_RAW_UNSET */
/* Should never happen. */
- BLI_assert(!"Invalid array type - get");
+ BLI_assert_msg(0, "Invalid array type - get");
item = Py_None;
Py_INCREF(item);
break;
@@ -5744,6 +5793,14 @@ static struct PyMethodDef pyrna_struct_methods[] = {
METH_VARARGS | METH_CLASS,
pyrna_struct_bl_rna_get_subclass_doc},
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
+ {"id_properties_ensure",
+ (PyCFunction)pyrna_struct_id_properties_ensure,
+ METH_NOARGS,
+ pyrna_struct_id_properties_ensure_doc},
+ {"id_properties_clear",
+ (PyCFunction)pyrna_struct_id_properties_clear,
+ METH_NOARGS,
+ pyrna_struct_id_properties_clear_doc},
/* experimental */
/* unused for now */
@@ -5817,8 +5874,10 @@ static struct PyMethodDef pyrna_prop_collection_idprop_methods[] = {
{NULL, NULL, 0, NULL},
};
-/* only needed for subtyping, so a new class gets a valid BPy_StructRNA
- * todo - also accept useful args */
+/**
+ * only needed for sub-typing, so a new class gets a valid #BPy_StructRNA
+ * TODO: also accept useful args.
+ */
static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds))
{
if (PyTuple_GET_SIZE(args) == 1) {
@@ -5865,8 +5924,10 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *
return NULL;
}
-/* only needed for subtyping, so a new class gets a valid BPy_StructRNA
- * todo - also accept useful args */
+/**
+ * Only needed for sub-typing, so a new class gets a valid #BPy_StructRNA
+ * TODO: also accept useful args.
+ */
static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds))
{
BPy_PropertyRNA *base;
@@ -6025,7 +6086,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
RNA_id_pointer_create(*(void **)data, &newptr);
}
else {
- /* note: this is taken from the function's ID pointer
+ /* NOTE: this is taken from the function's ID pointer
* and will break if a function returns a pointer from
* another ID block, watch this! - it should at least be
* easy to debug since they are all ID's */
@@ -6088,7 +6149,7 @@ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_look
static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject *kw)
{
- /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here. */
+ /* NOTE: both BPy_StructRNA and BPy_PropertyRNA can be used here. */
PointerRNA *self_ptr = &self->ptr;
FunctionRNA *self_func = self->func;
@@ -6436,11 +6497,11 @@ static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *UNUSED(closure)
}
/* Subclasses of pyrna_struct_Type which support idprop definitions use this as a metaclass. */
-/* note: tp_base member is set to &PyType_Type on init */
+/* NOTE: tp_base member is set to &PyType_Type on init. */
PyTypeObject pyrna_struct_meta_idprop_Type = {
PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct_meta_idprop", /* tp_name */
- /* NOTE! would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's */
+ /* NOTE: would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's. */
sizeof(PyHeapTypeObject), /* tp_basicsize */
0, /* tp_itemsize */
@@ -7216,7 +7277,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr);
item = pyrna_struct_CreatePyObject(&ptr);
- /* Note, must set the class not the __dict__ else the internal slots are not updated correctly.
+ /* NOTE: must set the class not the __dict__ else the internal slots are not updated correctly.
*/
PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
Py_DECREF(item);
@@ -7433,7 +7494,9 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna)
return newclass;
}
-/* Use for subtyping so we know which srna is used for a PointerRNA. */
+/**
+ * Use for sub-typing so we know which SRNA is used for a #PointerRNA.
+ */
static StructRNA *srna_from_ptr(PointerRNA *ptr)
{
if (ptr->type == &RNA_Struct) {
@@ -7454,7 +7517,7 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
{
BPy_StructRNA *pyrna = NULL;
- /* Note: don't rely on this to return None since NULL data with a valid type can often crash. */
+ /* NOTE: don't rely on this to return None since NULL data with a valid type can often crash. */
if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data. */
Py_RETURN_NONE;
}
@@ -8367,7 +8430,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
return bpy_class_validate_recursive(dummyptr, dummyptr->type, py_data, have_function);
}
-/* TODO - multiple return values like with RNA functions. */
+/* TODO: multiple return values like with RNA functions. */
static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
{
PyObject *args;
@@ -8772,7 +8835,7 @@ void pyrna_free_types(void)
void *py_ptr = RNA_struct_py_type_get(srna);
if (py_ptr) {
-#if 0 /* XXX - should be able to do this, but makes Python crash on exit. */
+#if 0 /* XXX: should be able to do this, but makes Python crash on exit. */
bpy_class_free(py_ptr);
#endif
RNA_struct_py_type_set(srna, NULL);
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index b359e93315e..9745f39b6b8 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -240,7 +240,7 @@ static int pyrna_struct_keyframe_parse(PointerRNA *ptr,
PyObject *pyoptions = NULL;
const char *path;
- /* note, parse_str MUST start with 's|ifsO!' */
+ /* NOTE: `parse_str` MUST start with `s|ifsO!`. */
if (!PyArg_ParseTupleAndKeywords(args,
kw,
parse_str,
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index aafc787b6fc..abbc332d89d 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -548,7 +548,7 @@ static int py_to_array(PyObject *seq,
}
if (totitem) {
- /* note: this code is confusing */
+ /* NOTE: this code is confusing. */
if (param_data && RNA_property_flag(prop) & PROP_DYNAMIC) {
/* not freeing allocated mem, RNA_parameter_list_free() will do this */
ParameterDynAlloc *param_alloc = (ParameterDynAlloc *)param_data;
@@ -990,7 +990,7 @@ PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop)
return pyrna_prop_CreatePyObject(ptr, prop);
}
-/* TODO, multi-dimensional arrays */
+/* TODO: multi-dimensional arrays. */
int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
{
const int len = RNA_property_array_length(ptr, prop);
diff --git a/source/blender/python/intern/bpy_rna_gizmo.c b/source/blender/python/intern/bpy_rna_gizmo.c
index 1f27e4bcca8..869019692df 100644
--- a/source/blender/python/intern/bpy_rna_gizmo.c
+++ b/source/blender/python/intern/bpy_rna_gizmo.c
@@ -246,7 +246,7 @@ static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject *
.py_fn_slots = {NULL},
};
- /* Note: this is a counter-part to functions:
+ /* NOTE: this is a counter-part to functions:
* 'Gizmo.target_set_prop & target_set_operator'
* (see: rna_wm_gizmo_api.c). conventions should match. */
static const char *const _keywords[] = {"self", "target", "get", "set", "range", NULL};
@@ -537,7 +537,7 @@ bool BPY_rna_gizmo_module(PyObject *mod_par)
PyObject *func_inst = PyInstanceMethod_New(func);
char name_prefix[128];
PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name);
- /* TODO, return a type that binds nearly to a method. */
+ /* TODO: return a type that binds nearly to a method. */
PyModule_AddObject(mod_par, name_prefix, func_inst);
}
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index ac061c3dd60..66044311321 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -130,7 +130,7 @@ static int foreach_libblock_id_user_map_callback(LibraryIDLinkCallbackData *cb_d
}
PyDoc_STRVAR(bpy_user_map_doc,
- ".. method:: user_map([subset=(id1, id2, ...)], key_types={..}, value_types={..})\n"
+ ".. method:: user_map(subset, key_types, value_types)\n"
"\n"
" Returns a mapping of all ID data-blocks in current ``bpy.data`` to a set of all "
"datablocks using them.\n"
@@ -277,7 +277,7 @@ error:
}
PyDoc_STRVAR(bpy_batch_remove_doc,
- ".. method:: batch_remove(ids=(id1, id2, ...))\n"
+ ".. method:: batch_remove(ids)\n"
"\n"
" Remove (delete) several IDs at once.\n"
"\n"
diff --git a/source/blender/python/intern/bpy_utils_previews.c b/source/blender/python/intern/bpy_utils_previews.c
index 7a826d99a3d..6a46d2a1a96 100644
--- a/source/blender/python/intern/bpy_utils_previews.c
+++ b/source/blender/python/intern/bpy_utils_previews.c
@@ -59,7 +59,6 @@ PyDoc_STRVAR(
" :type name: string\n"
" :return: The Preview matching given name, or a new empty one.\n"
" :rtype: :class:`bpy.types.ImagePreview`\n"
- " :rtype: :class:`bpy.types.ImagePreview`\n"
/* This is only true when accessed via 'bpy.utils.previews.ImagePreviewCollection.load',
* however this is the public API, allow this minor difference to the internal version here. */
" :raises KeyError: if ``name`` already exists.");
diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c
index 8a7f782de3c..7546f2ef730 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -68,7 +68,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* -----------------------------METHODS---------------------------- */
-/* note: BaseMath_ReadCallback must be called beforehand */
+/* NOTE: BaseMath_ReadCallback must be called beforehand. */
static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits)
{
PyObject *ret;
@@ -570,7 +570,7 @@ static PyObject *Color_mul(PyObject *v1, PyObject *v2)
}
}
else {
- BLI_assert(!"internal error");
+ BLI_assert_msg(0, "internal error");
}
PyErr_Format(PyExc_TypeError,
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 4e1b31b6371..595d03b533b 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -110,7 +110,7 @@ short euler_order_from_string(const char *str, const char *error_prefix)
return -1;
}
-/* note: BaseMath_ReadCallback must be called beforehand */
+/* NOTE: BaseMath_ReadCallback must be called beforehand. */
static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
{
PyObject *ret;
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 3dde0177648..8b8130f3cc2 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -263,7 +263,7 @@ Mathutils_Callback mathutils_matrix_col_cb = {
/* ----------------------------------------------------------------------------
* matrix row callbacks
* this is so you can do matrix.translation = val
- * note, this is _exactly like matrix.col except the 4th component is always omitted */
+ * NOTE: this is _exactly like matrix.col except the 4th component is always omitted. */
uchar mathutils_matrix_translation_cb_index = -1;
@@ -1938,7 +1938,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
return NULL;
}
- /* TODO, different sized matrix */
+ /* TODO: different sized matrix. */
if (self->num_col == 4 && self->num_row == 4) {
#ifdef MATH_STANDALONE
blend_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac);
@@ -2998,7 +2998,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU
return -1;
}
- if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1) {
+ if (mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation") == -1) {
return -1;
}
@@ -3614,7 +3614,7 @@ static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item,
}
return Matrix_ass_item_col(matrix_user, i, value);
}
- /* TODO, slice */
+ /* TODO: slice. */
PyErr_Format(
PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 88aa1f146e2..77a30dcd447 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -42,7 +42,7 @@ static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args);
/* -----------------------------METHODS------------------------------ */
-/* note: BaseMath_ReadCallback must be called beforehand */
+/* NOTE: BaseMath_ReadCallback must be called beforehand. */
static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits)
{
PyObject *ret;
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index a9cb125f715..c2223b023ad 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -149,7 +149,7 @@ static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
}
PyDoc_STRVAR(C_Vector_Range_doc,
- ".. classmethod:: Range(start=0, stop, step=1)\n"
+ ".. classmethod:: Range(start, stop, step=1)\n"
"\n"
" Create a filled with a range of values.\n"
"\n"
@@ -628,7 +628,7 @@ PyDoc_STRVAR(Vector_to_tuple_doc,
" :type precision: int\n"
" :return: the values of the vector rounded by *precision*\n"
" :rtype: tuple\n");
-/* note: BaseMath_ReadCallback must be called beforehand */
+/* NOTE: BaseMath_ReadCallback must be called beforehand. */
static PyObject *Vector_to_tuple_ex(VectorObject *self, int ndigits)
{
PyObject *ret;
@@ -2553,7 +2553,7 @@ static PyGetSetDef Vector_getseters[] = {
NULL},
{"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
- /* autogenerated swizzle attrs, see Python script above */
+ /* Auto-generated swizzle attributes, see Python script above. */
{"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)},
{"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)},
{"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)},
@@ -3019,8 +3019,7 @@ static struct PyMethodDef Vector_methods[] = {
};
/**
- * Note:
- * #Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
+ * NOTE: #Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
* but this means for eg that (vec * mat) and (mat * vec)
* both get sent to Vector_mul and it needs to sort out the order
*/
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 80919e014d5..588d3753eab 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -1109,7 +1109,7 @@ PyDoc_STRVAR(C_BVHTree_FromObject_doc,
" :type cage: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC);
static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs)
{
- /* note, options here match 'bpy_bmesh_from_object' */
+ /* NOTE: options here match #bpy_bmesh_from_object. */
const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", NULL};
PyObject *py_ob, *py_depsgraph;
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 3b1a6524ed9..88b3bddddf6 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -1102,7 +1102,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
return NULL;
}
- /* note, this could be refactored into plain C easy - py bits are noted */
+ /* NOTE: this could be refactored into plain C easy - py bits are noted. */
struct PointsInPlanes_UserData user_data = {
.py_verts = PyList_New(0),
diff --git a/source/blender/render/RE_texture.h b/source/blender/render/RE_texture.h
index b394cfeee75..39d773777ab 100644
--- a/source/blender/render/RE_texture.h
+++ b/source/blender/render/RE_texture.h
@@ -79,7 +79,7 @@ void RE_point_density_fix_linking(void);
/* texture_procedural.c */
/* Texture evaluation result.
- * Note; tr tg tb ta has to remain in this order for array access. */
+ * NOTE: tr tg tb ta has to remain in this order for array access. */
typedef struct TexResult {
float tin, tr, tg, tb, ta;
int talpha;
diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c
index 340a35eac15..d5653f87c2b 100644
--- a/source/blender/render/intern/bake.c
+++ b/source/blender/render/intern/bake.c
@@ -340,10 +340,10 @@ static bool cast_ray_highpoly(BVHTreeFromMesh *treeData,
float co_high[3], dir_high[3];
hits[i].index = -1;
- /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
+ /* TODO: we should use FLT_MAX here, but sweep-sphere code isn't prepared for that. */
hits[i].dist = BVH_RAYCAST_DIST_MAX;
- /* transform the ray from the world space to the highpoly space */
+ /* Transform the ray from the world space to the `highpoly` space. */
mul_v3_m4v3(co_high, highpoly[i].imat, co);
/* rotates */
@@ -550,15 +550,15 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
Mesh **me_highpoly;
BVHTreeFromMesh *treeData;
- /* Note: all coordinates are in local space */
+ /* NOTE: all coordinates are in local space. */
TriTessFace *tris_low = NULL;
TriTessFace *tris_cage = NULL;
TriTessFace **tris_high;
- /* assume all lowpoly tessfaces can be quads */
+ /* Assume all low-poly tessfaces can be quads. */
tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array");
- /* assume all highpoly tessfaces are triangles */
+ /* Assume all high-poly tessfaces are triangles. */
me_highpoly = MEM_mallocN(sizeof(Mesh *) * tot_highpoly, "Highpoly Derived Meshes");
treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees");
@@ -583,7 +583,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
BKE_mesh_runtime_looptri_ensure(me_highpoly[i]);
if (me_highpoly[i]->runtime.looptris.len != 0) {
- /* Create a bvh-tree for each highpoly object */
+ /* Create a BVH-tree for each `highpoly` object. */
BKE_bvhtree_from_mesh_get(&treeData[i], me_highpoly[i], BVHTREE_FROM_LOOPTRI, 2);
if (treeData[i].tree == NULL) {
@@ -752,10 +752,10 @@ void RE_bake_pixels_populate(Mesh *me,
for (int a = 0; a < 3; a++) {
const float *uv = mloopuv[lt->tri[a]].uv;
- /* Note, workaround for pixel aligned UVs which are common and can screw up our
+ /* NOTE(campbell): workaround for pixel aligned UVs which are common and can screw up our
* intersection tests where a pixel gets in between 2 faces or the middle of a quad,
* camera aligned quads also have this problem but they are less common.
- * Add a small offset to the UVs, fixes bug T18685 - Campbell */
+ * Add a small offset to the UVs, fixes bug T18685. */
vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
}
diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c
index db2458a636b..657cd1f606b 100644
--- a/source/blender/render/intern/engine.c
+++ b/source/blender/render/intern/engine.c
@@ -124,7 +124,7 @@ bool RE_engine_is_external(const Render *re)
bool RE_engine_is_opengl(RenderEngineType *render_type)
{
- /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
+ /* TODO: refine? Can we have ogl render engine without ogl render pipeline? */
return (render_type->draw_engine != NULL) && DRW_engine_render_support(render_type->draw_engine);
}
@@ -310,7 +310,7 @@ RenderResult *RE_engine_begin_result(
result = render_result_new(re, &disprect, RR_USE_MEM, layername, viewname);
- /* todo: make this thread safe */
+ /* TODO: make this thread safe. */
/* can be NULL if we CLAMP the width or height to 0 */
if (result) {
@@ -679,7 +679,7 @@ static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
DRW_render_context_enable(engine->re);
}
- DEG_evaluate_on_framechange(depsgraph, CFRA);
+ DEG_evaluate_on_framechange(depsgraph, BKE_scene_frame_get(scene));
if (use_gpu_context) {
DRW_render_context_disable(engine->re);
diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c
index d3ea27c6bb0..6329901b4ce 100644
--- a/source/blender/render/intern/pipeline.c
+++ b/source/blender/render/intern/pipeline.c
@@ -1464,7 +1464,7 @@ static void do_render_full_pipeline(Render *re)
/* in this case external render overrides all */
}
else if (RE_seq_render_active(re->scene, &re->r)) {
- /* note: do_render_sequencer() frees rect32 when sequencer returns float images */
+ /* NOTE: do_render_sequencer() frees rect32 when sequencer returns float images. */
if (!re->test_break(re->tbh)) {
do_render_sequencer(re);
render_seq = true;
@@ -1828,7 +1828,7 @@ void RE_SetReports(Render *re, ReportList *reports)
static void render_update_depsgraph(Render *re)
{
Scene *scene = re->scene;
- DEG_evaluate_on_framechange(re->pipeline_depsgraph, CFRA);
+ DEG_evaluate_on_framechange(re->pipeline_depsgraph, BKE_scene_frame_get(scene));
BKE_scene_update_sound(re->pipeline_depsgraph, re->main);
}
@@ -2410,7 +2410,7 @@ void RE_RenderAnim(Render *re,
* -sergey-
*/
{
- float ctime = BKE_scene_frame_get(scene);
+ float ctime = BKE_scene_ctime_get(scene);
AnimData *adt = BKE_animdata_from_id(&scene->id);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
re->pipeline_depsgraph, ctime);
@@ -2419,7 +2419,7 @@ void RE_RenderAnim(Render *re,
render_update_depsgraph(re);
- /* only border now, todo: camera lens. (ton) */
+ /* Only border now, TODO(ton): camera lens. */
render_init_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0);
if (nfra != scene->r.cfra) {
@@ -2612,7 +2612,7 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
}
}
-/* note; repeated win/disprect calc... solve that nicer, also in compo */
+/* NOTE: repeated win/disprect calc... solve that nicer, also in compo. */
/* only the temp file! */
bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c
index 70bd4f92512..53252cdb42f 100644
--- a/source/blender/render/intern/render_result.c
+++ b/source/blender/render/intern/render_result.c
@@ -473,15 +473,15 @@ RenderResult *render_result_new(
render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA");
}
- /* note, this has to be in sync with scene.c */
+ /* NOTE: this has to be in sync with `scene.c`. */
rl->layflag = 0x7FFF; /* solid ztra halo strand */
rl->passflag = SCE_PASS_COMBINED;
re->active_view_layer = 0;
}
- /* border render; calculate offset for use in compositor. compo is centralized coords */
- /* XXX obsolete? I now use it for drawing border render offset (ton) */
+ /* Border render; calculate offset for use in compositor. compo is centralized coords. */
+ /* XXX(ton): obsolete? I now use it for drawing border render offset. */
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);
@@ -1016,7 +1016,7 @@ bool RE_WriteRenderResult(ReportList *reports,
IMB_exr_write_channels(exrhandle);
}
else {
- /* TODO, get the error from openexr's exception */
+ /* TODO: get the error from openexr's exception. */
BKE_reportf(
reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
}
diff --git a/source/blender/render/intern/render_types.h b/source/blender/render/intern/render_types.h
index 9f399971049..50b684beba9 100644
--- a/source/blender/render/intern/render_types.h
+++ b/source/blender/render/intern/render_types.h
@@ -153,7 +153,7 @@ struct Render {
void **movie_ctx_arr;
char viewname[MAX_NAME];
- /* TODO replace by a whole draw manager. */
+ /* TODO: replace by a whole draw manager. */
void *gl_context;
void *gpu_context;
};
diff --git a/source/blender/render/intern/texture_image.c b/source/blender/render/intern/texture_image.c
index 9f6980a5b0a..c4ee16a0ecc 100644
--- a/source/blender/render/intern/texture_image.c
+++ b/source/blender/render/intern/texture_image.c
@@ -634,11 +634,11 @@ static void boxsample(ImBuf *ibuf,
* If variable 'imaprepeat' has been set, the
* clipped-away parts are sampled as well.
*/
- /* note: actually minx etc isn't in the proper range...
- * this due to filter size and offset vectors for bump */
- /* note: talpha must be initialized */
- /* note: even when 'imaprepeat' is set, this can only repeat once in any direction.
- * the point which min/max is derived from is assumed to be wrapped */
+ /* NOTE: actually minx etc isn't in the proper range...
+ * this due to filter size and offset vectors for bump. */
+ /* NOTE: talpha must be initialized. */
+ /* NOTE: even when 'imaprepeat' is set, this can only repeat once in any direction.
+ * the point which min/max is derived from is assumed to be wrapped. */
TexResult texr;
rctf *rf, stack[8];
float opp, tot, alphaclip = 1.0;
diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c
index c0ff00d4f59..31d5bf67f28 100644
--- a/source/blender/render/intern/texture_pointdensity.c
+++ b/source/blender/render/intern/texture_pointdensity.c
@@ -169,7 +169,7 @@ static void pointdensity_cache_psys(
ParticleCacheKey *cache;
ParticleSimulationData sim = {NULL};
ParticleData *pa = NULL;
- float cfra = BKE_scene_frame_get(scene);
+ float cfra = BKE_scene_ctime_get(scene);
int i /*, Childexists*/ /* UNUSED */;
int total_particles;
int data_used;
@@ -347,9 +347,9 @@ static void pointdensity_cache_vertex_weight(PointDensity *pd,
if (!mdef) {
return;
}
- mdef_index = BKE_object_defgroup_name_index(ob, pd->vertex_attribute_name);
+ mdef_index = BKE_id_defgroup_name_index(&mesh->id, pd->vertex_attribute_name);
if (mdef_index < 0) {
- mdef_index = ob->actdef - 1;
+ mdef_index = BKE_object_defgroup_active_index_get(ob) - 1;
}
if (mdef_index < 0) {
return;
@@ -782,7 +782,7 @@ static void particle_system_minmax(Depsgraph *depsgraph,
float max[3])
{
const float size[3] = {radius, radius, radius};
- const float cfra = BKE_scene_frame_get(scene);
+ const float cfra = BKE_scene_ctime_get(scene);
ParticleSettings *part = psys->part;
ParticleSimulationData sim = {NULL};
ParticleData *pa = NULL;
diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt
index 9340cfbf03d..e324bc8b407 100644
--- a/source/blender/sequencer/CMakeLists.txt
+++ b/source/blender/sequencer/CMakeLists.txt
@@ -77,9 +77,9 @@ set(SRC
intern/proxy_job.c
intern/render.c
intern/render.h
+ intern/sequence_lookup.c
intern/sequencer.c
intern/sequencer.h
- intern/sequence_lookup.c
intern/sound.c
intern/strip_add.c
intern/strip_edit.c
diff --git a/source/blender/sequencer/SEQ_clipboard.h b/source/blender/sequencer/SEQ_clipboard.h
index 4b2bf69a8ac..ea7f01e6ae3 100644
--- a/source/blender/sequencer/SEQ_clipboard.h
+++ b/source/blender/sequencer/SEQ_clipboard.h
@@ -29,12 +29,16 @@ extern "C" {
struct ListBase;
struct Main;
+struct Scene;
+struct Sequence;
extern struct ListBase seqbase_clipboard;
extern int seqbase_clipboard_frame;
void SEQ_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase);
void SEQ_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain);
void SEQ_clipboard_free(void);
+void SEQ_clipboard_active_seq_name_store(struct Scene *scene);
+bool SEQ_clipboard_pasted_seq_was_active(struct Sequence *pasted_seq);
#ifdef __cplusplus
}
diff --git a/source/blender/sequencer/SEQ_iterator.h b/source/blender/sequencer/SEQ_iterator.h
index eab2277bbe3..e4c9f20f736 100644
--- a/source/blender/sequencer/SEQ_iterator.h
+++ b/source/blender/sequencer/SEQ_iterator.h
@@ -30,9 +30,9 @@ extern "C" {
#include "BLI_ghash.h"
struct Editing;
-struct Sequence;
struct GSet;
struct GSetIterator;
+struct Sequence;
#define SEQ_ITERATOR_FOREACH(var, collection) \
for (SeqIterator iter = {{{NULL}}}; \
@@ -70,7 +70,7 @@ bool SEQ_iterator_ensure(SeqCollection *collection,
struct Sequence **r_seq);
struct Sequence *SEQ_iterator_yield(SeqIterator *iterator);
-SeqCollection *SEQ_collection_create(void);
+SeqCollection *SEQ_collection_create(const char *name);
uint SEQ_collection_len(const SeqCollection *collection);
bool SEQ_collection_append_strip(struct Sequence *seq, SeqCollection *data);
bool SEQ_collection_remove_strip(struct Sequence *seq, SeqCollection *data);
diff --git a/source/blender/sequencer/SEQ_proxy.h b/source/blender/sequencer/SEQ_proxy.h
index b06adef2802..7bfe932ff1c 100644
--- a/source/blender/sequencer/SEQ_proxy.h
+++ b/source/blender/sequencer/SEQ_proxy.h
@@ -34,8 +34,8 @@ struct ListBase;
struct Main;
struct Scene;
struct SeqIndexBuildContext;
-struct Sequence;
struct SeqRenderData;
+struct Sequence;
bool SEQ_proxy_rebuild_context(struct Main *bmain,
struct Depsgraph *depsgraph,
diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h
index 706f4064bf3..f4338d13c8f 100644
--- a/source/blender/sequencer/SEQ_sequencer.h
+++ b/source/blender/sequencer/SEQ_sequencer.h
@@ -32,8 +32,8 @@ extern "C" {
struct Editing;
struct Scene;
struct Sequence;
-struct SequencerToolSettings;
struct SequenceLookup;
+struct SequencerToolSettings;
/* RNA enums, just to be more readable */
enum {
diff --git a/source/blender/sequencer/SEQ_time.h b/source/blender/sequencer/SEQ_time.h
index 593a8fe7bf2..732e9bb985a 100644
--- a/source/blender/sequencer/SEQ_time.h
+++ b/source/blender/sequencer/SEQ_time.h
@@ -44,7 +44,6 @@ int SEQ_time_find_next_prev_edit(struct Scene *scene,
const bool do_unselected);
void SEQ_time_update_sequence(struct Scene *scene, struct Sequence *seq);
void SEQ_time_update_sequence_bounds(struct Scene *scene, struct Sequence *seq);
-int SEQ_time_cmp_time_startdisp(const void *a, const void *b);
bool SEQ_time_strip_intersects_frame(const struct Sequence *seq, const int timeline_frame);
void SEQ_time_update_meta_strip_range(struct Scene *scene, struct Sequence *seq_meta);
diff --git a/source/blender/sequencer/SEQ_transform.h b/source/blender/sequencer/SEQ_transform.h
index 837a2de5742..9ff827333be 100644
--- a/source/blender/sequencer/SEQ_transform.h
+++ b/source/blender/sequencer/SEQ_transform.h
@@ -29,8 +29,8 @@ extern "C" {
struct ListBase;
struct Scene;
-struct Sequence;
struct SeqCollection;
+struct Sequence;
int SEQ_transform_get_left_handle_frame(struct Sequence *seq);
int SEQ_transform_get_right_handle_frame(struct Sequence *seq);
diff --git a/source/blender/sequencer/intern/clipboard.c b/source/blender/sequencer/intern/clipboard.c
index e3f82dd4bb0..9e702a4e60b 100644
--- a/source/blender/sequencer/intern/clipboard.c
+++ b/source/blender/sequencer/intern/clipboard.c
@@ -24,6 +24,8 @@
* \ingroup bke
*/
+#include <string.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
@@ -31,6 +33,7 @@
#include "DNA_sound_types.h"
#include "BLI_listbase.h"
+#include "BLI_string.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
@@ -38,6 +41,7 @@
#include "BKE_sound.h"
#include "SEQ_clipboard.h"
+#include "SEQ_select.h"
#include "sequencer.h"
@@ -55,6 +59,7 @@
ListBase seqbase_clipboard;
int seqbase_clipboard_frame;
+static char seq_clipboard_active_seq_name[SEQ_NAME_MAXSTR];
void seq_clipboard_pointers_free(struct ListBase *seqbase);
@@ -177,3 +182,26 @@ void SEQ_clipboard_pointers_restore(ListBase *seqbase, Main *bmain)
SEQ_clipboard_pointers_restore(&seq->seqbase, bmain);
}
}
+
+void SEQ_clipboard_active_seq_name_store(Scene *scene)
+{
+ Sequence *active_seq = SEQ_select_active_get(scene);
+ if (active_seq != NULL) {
+ STRNCPY(seq_clipboard_active_seq_name, active_seq->name);
+ }
+ else {
+ seq_clipboard_active_seq_name[0] = '\0';
+ }
+}
+
+/**
+ * Check if strip was active when it was copied. User should restrict this check to pasted strips
+ * before ensuring original name, because strip name comparison is used to check.
+ *
+ * \param pasted_seq: Strip that is pasted(duplicated) from clipboard
+ * \return true if strip was active, false otherwise
+ */
+bool SEQ_clipboard_pasted_seq_was_active(Sequence *pasted_seq)
+{
+ return STREQ(pasted_seq->name, seq_clipboard_active_seq_name);
+}
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index 1f518a69395..0a8be3b33ae 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -3187,8 +3187,8 @@ void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force)
return;
}
- /* XXX - new in 2.5x. should we use the animation system this way?
- * The fcurve is needed because many frames need evaluating at once - campbell */
+ /* XXX(campbell): new in 2.5x. should we use the animation system this way?
+ * The fcurve is needed because many frames need evaluating at once. */
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
if (!v->frameMap || v->length != seq->len) {
if (v->frameMap) {
diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c
index a6e4b6ea7ed..604c9900355 100644
--- a/source/blender/sequencer/intern/image_cache.c
+++ b/source/blender/sequencer/intern/image_cache.c
@@ -521,7 +521,7 @@ static bool seq_disk_cache_read_header(FILE *file, DiskCacheHeader *header)
BLI_fseek(file, 0LL, SEEK_SET);
const size_t num_items_read = fread(header, sizeof(*header), 1, file);
if (num_items_read < 1) {
- BLI_assert(!"unable to read disk cache header");
+ BLI_assert_msg(0, "unable to read disk cache header");
perror("unable to read disk cache header");
return false;
}
diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c
index 0754d9b38ed..20a2ee3b183 100644
--- a/source/blender/sequencer/intern/iterator.c
+++ b/source/blender/sequencer/intern/iterator.c
@@ -106,9 +106,9 @@ void SEQ_collection_free(SeqCollection *collection)
*
* \return empty strip collection.
*/
-SeqCollection *SEQ_collection_create(void)
+SeqCollection *SEQ_collection_create(const char *name)
{
- SeqCollection *collection = MEM_callocN(sizeof(SeqCollection), "SeqCollection");
+ SeqCollection *collection = MEM_callocN(sizeof(SeqCollection), name);
collection->set = BLI_gset_new(
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "SeqCollection GSet");
return collection;
@@ -136,7 +136,7 @@ SeqCollection *SEQ_query_by_reference(Sequence *seq_reference,
ListBase *seqbase,
SeqCollection *collection))
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
seq_query_func(seq_reference, seqbase, collection);
return collection;
}
@@ -223,7 +223,7 @@ void SEQ_collection_expand(ListBase *seqbase,
*/
SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase)
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (seq->type == SEQ_TYPE_META) {
SEQ_collection_merge(collection, SEQ_query_all_strips_recursive(&seq->seqbase));
@@ -241,7 +241,7 @@ SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase)
*/
SeqCollection *SEQ_query_all_strips(ListBase *seqbase)
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
SEQ_collection_append_strip(seq, collection);
}
@@ -256,7 +256,7 @@ SeqCollection *SEQ_query_all_strips(ListBase *seqbase)
*/
SeqCollection *SEQ_query_selected_strips(ListBase *seqbase)
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT) == 0) {
continue;
diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c
index 75c7d599be5..07d09f4ae17 100644
--- a/source/blender/sequencer/intern/modifier.c
+++ b/source/blender/sequencer/intern/modifier.c
@@ -262,7 +262,7 @@ static StripColorBalance calc_cb(StripColorBalance *cb_)
return cb;
}
-/* note: lift is actually 2-lift */
+/* NOTE: lift is actually 2-lift. */
MINLINE float color_balance_fl(
float in, const float lift, const float gain, const float gamma, const float mul)
{
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index 7360d525ce3..aba84743621 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -308,7 +308,7 @@ static bool must_render_strip(const Sequence *seq, SeqCollection *strips_at_time
static SeqCollection *query_strips_at_frame(ListBase *seqbase, const int timeline_frame)
{
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (SEQ_time_strip_intersects_frame(seq, timeline_frame)) {
@@ -370,7 +370,7 @@ int seq_get_shown_sequences(ListBase *seqbase,
const int strip_count = BLI_gset_len(collection->set);
if (strip_count > MAXSEQ) {
- BLI_assert(!"Too many strips, this shouldn't happen");
+ BLI_assert_msg(0, "Too many strips, this shouldn't happen");
return 0;
}
@@ -1260,7 +1260,7 @@ ImBuf *seq_render_mask(const SeqRenderData *context,
float frame_index,
bool make_float)
{
- /* TODO - add option to rasterize to alpha imbuf? */
+ /* TODO: add option to rasterize to alpha imbuf? */
ImBuf *ibuf = NULL;
float *maskbuf;
int i;
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c
index 7907b11989c..7dc19cf39a6 100644
--- a/source/blender/sequencer/intern/sequencer.c
+++ b/source/blender/sequencer/intern/sequencer.c
@@ -625,7 +625,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char
str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
}
-/* XXX - hackish function needed for transforming strips! TODO - have some better solution */
+/* XXX: hackish function needed for transforming strips! TODO: have some better solution. */
void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
{
char str[SEQ_RNAPATH_MAXSTR];
@@ -693,7 +693,7 @@ void SEQ_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst)
BLI_movelisttolist(&scene->adt->action->curves, &lb);
}
-/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */
+/* XXX: hackish function needed to remove all fcurves belonging to a sequencer strip. */
static void seq_free_animdata(Scene *scene, Sequence *seq)
{
char str[SEQ_RNAPATH_MAXSTR];
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index 142991eeacf..dab5593be37 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -597,12 +597,12 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
return seq;
}
-/* note: caller should run SEQ_time_update_sequence(scene, seq) after */
+/* NOTE: caller should run SEQ_time_update_sequence(scene, seq) after. */
void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range)
{
char path[FILE_MAX];
int prev_startdisp = 0, prev_enddisp = 0;
- /* note: don't rename the strip, will break animation curves */
+ /* NOTE: don't rename the strip, will break animation curves. */
if (ELEM(seq->type,
SEQ_TYPE_MOVIE,
diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c
index 3e6eb74fcb3..0dc8dfa10d7 100644
--- a/source/blender/sequencer/intern/strip_edit.c
+++ b/source/blender/sequencer/intern/strip_edit.c
@@ -255,7 +255,7 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene,
return false;
}
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
SEQ_collection_append_strip(src_seq, collection);
SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain);
@@ -396,7 +396,7 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
return NULL;
}
- SeqCollection *collection = SEQ_collection_create();
+ SeqCollection *collection = SEQ_collection_create(__func__);
SEQ_collection_append_strip(seq, collection);
SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain);
@@ -407,6 +407,8 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
BLI_addtail(&left_strips, seq);
}
+ SEQ_collection_free(collection);
+
/* Sort list, so that no strip can depend on next strip in list.
* This is important for SEQ_time_update_sequence functionality. */
SEQ_sort(&left_strips);
diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c
index e5eb0b3f00f..20e2421ea88 100644
--- a/source/blender/sequencer/intern/strip_time.c
+++ b/source/blender/sequencer/intern/strip_time.c
@@ -257,15 +257,6 @@ void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
}
}
-/** Comparison function suitable to be used with BLI_listbase_sort()... */
-int SEQ_time_cmp_time_startdisp(const void *a, const void *b)
-{
- const Sequence *seq_a = a;
- const Sequence *seq_b = b;
-
- return (seq_a->startdisp > seq_b->startdisp);
-}
-
int SEQ_time_find_next_prev_edit(Scene *scene,
int timeline_frame,
const short side,
@@ -471,7 +462,7 @@ void seq_time_gap_info_get(const Scene *scene,
/**
* Test if strip intersects with timeline frame.
- * Note: This checks if strip would be rendered at this frame. For rendering it is assumed, that
+ * NOTE: This checks if strip would be rendered at this frame. For rendering it is assumed, that
* timeline frame has width of 1 frame and therefore ends at timeline_frame + 1
*
* \param seq: Sequence to be checked
diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c
index 20cbe933b2f..b7989349ebe 100644
--- a/source/blender/sequencer/intern/strip_transform.c
+++ b/source/blender/sequencer/intern/strip_transform.c
@@ -149,7 +149,7 @@ void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
SEQ_transform_set_left_handle_frame(seq, seq_tx_get_end(seq) - 1);
}
- /* doesn't work now - TODO */
+ /* TODO: This doesn't work at the moment. */
#if 0
if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) {
int ofs;
@@ -271,7 +271,7 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
test->machine += channel_delta;
SEQ_time_update_sequence(
evil_scene,
- test); // XXX - I don't think this is needed since were only moving vertically, Campbell.
+ test); // XXX: I don't think this is needed since were only moving vertically, Campbell.
}
if ((test->machine < 1) || (test->machine > MAXSEQ)) {
diff --git a/source/blender/shader_fx/intern/FX_shader_flip.c b/source/blender/shader_fx/intern/FX_shader_flip.c
index b6a36378f7e..048ff3deba1 100644
--- a/source/blender/shader_fx/intern/FX_shader_flip.c
+++ b/source/blender/shader_fx/intern/FX_shader_flip.c
@@ -65,8 +65,8 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
row = uiLayoutRowWithHeading(layout, true, IFACE_("Axis"));
- uiItemR(row, ptr, "flip_horizontal", toggles_flag, NULL, ICON_NONE);
- uiItemR(row, ptr, "flip_vertical", toggles_flag, NULL, ICON_NONE);
+ uiItemR(row, ptr, "use_flip_x", toggles_flag, NULL, ICON_NONE);
+ uiItemR(row, ptr, "use_flip_y", toggles_flag, NULL, ICON_NONE);
shaderfx_panel_end(layout, ptr);
}
diff --git a/source/blender/simulation/SIM_mass_spring.h b/source/blender/simulation/SIM_mass_spring.h
index 43de8b155cf..b3299258209 100644
--- a/source/blender/simulation/SIM_mass_spring.h
+++ b/source/blender/simulation/SIM_mass_spring.h
@@ -45,6 +45,8 @@ void SIM_mass_spring_solver_free(struct Implicit_Data *id);
int SIM_mass_spring_solver_numvert(struct Implicit_Data *id);
int SIM_cloth_solver_init(struct Object *ob, struct ClothModifierData *clmd);
+void SIM_mass_spring_set_implicit_vertex_mass(struct Implicit_Data *data, int index, float mass);
+
void SIM_cloth_solver_free(struct ClothModifierData *clmd);
int SIM_cloth_solve(struct Depsgraph *depsgraph,
struct Object *ob,
diff --git a/source/blender/simulation/intern/ConstrainedConjugateGradient.h b/source/blender/simulation/intern/ConstrainedConjugateGradient.h
index 11dc3ebe91b..c5a2827a09f 100644
--- a/source/blender/simulation/intern/ConstrainedConjugateGradient.h
+++ b/source/blender/simulation/intern/ConstrainedConjugateGradient.h
@@ -68,7 +68,7 @@ EIGEN_DONT_INLINE void constrained_conjugate_gradient(const MatrixType &mat,
RealScalar rhsNorm2 = (filter * rhs).squaredNorm();
if (rhsNorm2 == 0) {
- /* XXX TODO set constrained result here */
+ /* XXX TODO: set constrained result here. */
x.setZero();
iters = 0;
tol_error = 0;
diff --git a/source/blender/simulation/intern/SIM_mass_spring.cpp b/source/blender/simulation/intern/SIM_mass_spring.cpp
index cf654ebff07..ca01120eecb 100644
--- a/source/blender/simulation/intern/SIM_mass_spring.cpp
+++ b/source/blender/simulation/intern/SIM_mass_spring.cpp
@@ -203,7 +203,7 @@ int SIM_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
cloth->implicit = id = SIM_mass_spring_solver_create(cloth->mvert_num, nondiag);
for (i = 0; i < cloth->mvert_num; i++) {
- SIM_mass_spring_set_vertex_mass(id, i, verts[i].mass);
+ SIM_mass_spring_set_implicit_vertex_mass(id, i, verts[i].mass);
}
for (i = 0; i < cloth->mvert_num; i++) {
@@ -213,6 +213,10 @@ int SIM_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
return 1;
}
+void SIM_mass_spring_set_implicit_vertex_mass(Implicit_Data *data, int index, float mass){
+ SIM_mass_spring_set_vertex_mass(data, index, mass);
+}
+
void SIM_cloth_solver_free(ClothModifierData *clmd)
{
Cloth *cloth = clmd->clothObject;
diff --git a/source/blender/simulation/intern/hair_volume.cpp b/source/blender/simulation/intern/hair_volume.cpp
index d954d9b5fff..4966fa2510d 100644
--- a/source/blender/simulation/intern/hair_volume.cpp
+++ b/source/blender/simulation/intern/hair_volume.cpp
@@ -200,7 +200,7 @@ BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid,
}
if (velocity_gradient) {
- /* XXX TODO */
+ /* XXX TODO: */
zero_m3(velocity_gradient);
}
}
@@ -530,7 +530,7 @@ void SIM_hair_volume_add_segment(HairGrid *grid,
const int stride2 = strides[axis2];
/* increment of secondary directions per step in the primary direction
- * note: we always go in the positive direction along axis0, so the sign can be inverted
+ * NOTE: we always go in the positive direction along axis0, so the sign can be inverted
*/
const float inc1 = dir2[axis1] / dir2[axis0];
const float inc2 = dir2[axis2] / dir2[axis0];
@@ -800,7 +800,7 @@ bool SIM_hair_volume_solve_divergence(HairGrid *grid,
vert->density, target_density, target_strength);
/* B vector contains the finite difference approximation of the velocity divergence.
- * Note: according to the discretized Navier-Stokes equation the rhs vector
+ * NOTE: according to the discretized Navier-Stokes equation the rhs vector
* and resulting pressure gradient should be multiplied by the (inverse) density;
* however, this is already included in the weighting of hair velocities on the grid!
*/
diff --git a/source/blender/simulation/intern/implicit_blender.c b/source/blender/simulation/intern/implicit_blender.c
index 4c01fd3aee0..8aa3774a3f2 100644
--- a/source/blender/simulation/intern/implicit_blender.c
+++ b/source/blender/simulation/intern/implicit_blender.c
@@ -583,7 +583,7 @@ DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix)
/* copy big matrix */
DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from)
{
- /* TODO bounds checking */
+ /* TODO: bounds checking. */
memcpy(to, from, sizeof(fmatrix3x3) * (from[0].vcount + from[0].scount));
}
@@ -697,7 +697,7 @@ Implicit_Data *SIM_mass_spring_solver_create(int numverts, int numsprings)
id->S = create_bfmatrix(numverts, 0);
id->Pinv = create_bfmatrix(numverts, numsprings);
id->P = create_bfmatrix(numverts, numsprings);
- id->bigI = create_bfmatrix(numverts, numsprings); /* TODO 0 springs */
+ id->bigI = create_bfmatrix(numverts, numsprings); /* TODO: 0 springs. */
id->M = create_bfmatrix(numverts, numsprings);
id->X = create_lfvector(numverts);
id->Xnew = create_lfvector(numverts);
@@ -2112,7 +2112,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdx(Implicit_Data *data,
int q,
float dfdx[3][3])
{
- const float delta = 0.00001f; /* TODO find a good heuristic for this */
+ const float delta = 0.00001f; /* TODO: find a good heuristic for this. */
float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
float f[3];
int a, b;
@@ -2123,7 +2123,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdx(Implicit_Data *data,
copy_m3_m3(dvec_neg, dvec_pos);
negate_m3(dvec_neg);
- /* XXX TODO offset targets to account for position dependency */
+ /* XXX TODO: offset targets to account for position dependency. */
for (a = 0; a < 3; a++) {
spring_hairbend_forces(
@@ -2151,7 +2151,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdv(Implicit_Data *data,
int q,
float dfdv[3][3])
{
- const float delta = 0.00001f; /* TODO find a good heuristic for this */
+ const float delta = 0.00001f; /* TODO: find a good heuristic for this. */
float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
float f[3];
int a, b;
@@ -2162,7 +2162,7 @@ BLI_INLINE void spring_hairbend_estimate_dfdv(Implicit_Data *data,
copy_m3_m3(dvec_neg, dvec_pos);
negate_m3(dvec_neg);
- /* XXX TODO offset targets to account for position dependency */
+ /* XXX TODO: offset targets to account for position dependency. */
for (a = 0; a < 3; a++) {
spring_hairbend_forces(
diff --git a/source/blender/simulation/intern/implicit_eigen.cpp b/source/blender/simulation/intern/implicit_eigen.cpp
index 8eb227d38ab..aa9d5d1d34d 100644
--- a/source/blender/simulation/intern/implicit_eigen.cpp
+++ b/source/blender/simulation/intern/implicit_eigen.cpp
@@ -1223,7 +1223,7 @@ BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data,
int q,
float dfdx[3][3])
{
- const float delta = 0.00001f; /* TODO find a good heuristic for this */
+ const float delta = 0.00001f; /* TODO: find a good heuristic for this. */
float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
float f[3];
int a, b;
@@ -1234,7 +1234,7 @@ BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data,
copy_m3_m3(dvec_neg, dvec_pos);
negate_m3(dvec_neg);
- /* XXX TODO offset targets to account for position dependency */
+ /* XXX TODO: offset targets to account for position dependency. */
for (a = 0; a < 3; a++) {
spring_angbend_forces(
@@ -1262,7 +1262,7 @@ BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data,
int q,
float dfdv[3][3])
{
- const float delta = 0.00001f; /* TODO find a good heuristic for this */
+ const float delta = 0.00001f; /* TODO: find a good heuristic for this. */
float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
float f[3];
int a, b;
@@ -1273,7 +1273,7 @@ BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data,
copy_m3_m3(dvec_neg, dvec_pos);
negate_m3(dvec_neg);
- /* XXX TODO offset targets to account for position dependency */
+ /* XXX TODO: offset targets to account for position dependency. */
for (a = 0; a < 3; a++) {
spring_angbend_forces(
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 183b22c9791..e513c49c11b 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -181,7 +181,7 @@ if(WITH_INPUT_NDOF)
add_definitions(-DWITH_INPUT_NDOF)
endif()
-if(WIN32)
+if(WIN32 OR APPLE)
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 319683c8d8e..1c994707ca9 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -31,6 +31,7 @@
/* dna-savable wmStructs here */
#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
#include "DNA_windowmanager_types.h"
#include "WM_keymap.h"
@@ -617,9 +618,14 @@ void WM_operator_type_modal_from_exec_for_object_edit_coords(struct wmOperatorTy
void WM_uilisttype_init(void);
struct uiListType *WM_uilisttype_find(const char *idname, bool quiet);
bool WM_uilisttype_add(struct uiListType *ult);
-void WM_uilisttype_freelink(struct uiListType *ult);
+void WM_uilisttype_remove_ptr(struct Main *bmain, struct uiListType *ult);
void WM_uilisttype_free(void);
+void WM_uilisttype_to_full_list_id(const struct uiListType *ult,
+ const char *list_id,
+ char r_full_list_id[]);
+const char *WM_uilisttype_list_id_get(const struct uiListType *ult, struct uiList *list);
+
/* wm_menu_type.c */
void WM_menutype_init(void);
struct MenuType *WM_menutype_find(const char *idname, bool quiet);
@@ -961,7 +967,7 @@ bool WM_xr_session_state_controller_pose_rotation_get(const wmXrData *xr,
/* wm_xr_actions.c */
/* XR action functions to be called pre-XR session start.
- * Note: The "destroy" functions can also be called post-session start. */
+ * NOTE: The "destroy" functions can also be called post-session start. */
bool WM_xr_action_set_create(wmXrData *xr, const char *action_set_name);
void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name);
bool WM_xr_action_create(wmXrData *xr,
@@ -1015,7 +1021,7 @@ bool WM_xr_action_state_get(const wmXrData *xr,
bool WM_xr_haptic_action_apply(wmXrData *xr,
const char *action_set_name,
const char *action_name,
- const long long *duration,
+ const int64_t *duration,
const float *frequency,
const float *amplitude);
void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index e83e36d7a9b..2b48a5f6648 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -339,7 +339,7 @@ typedef struct wmNotifier {
#define ND_RENDER_OPTIONS (4 << 16)
#define ND_NODES (5 << 16)
#define ND_SEQUENCER (6 << 16)
-/* Note: If an object was added, removed, merged/joined, ..., it is not enough to notify with
+/* NOTE: If an object was added, removed, merged/joined, ..., it is not enough to notify with
* this. This affects the layer so also send a layer change notifier (e.g. ND_LAYER_CONTENT)! */
#define ND_OB_ACTIVE (7 << 16)
/* See comment on ND_OB_ACTIVE. */
@@ -439,6 +439,13 @@ typedef struct wmNotifier {
#define ND_SPACE_FILE_PREVIEW (21 << 16)
#define ND_SPACE_SPREADSHEET (22 << 16)
+/* NC_ASSET */
+/* Denotes that the AssetList is done reading some previews. NOT that the preview generation of
+ * assets is done. */
+#define ND_ASSET_LIST (1 << 16)
+#define ND_ASSET_LIST_PREVIEW (2 << 16)
+#define ND_ASSET_LIST_READING (3 << 16)
+
/* subtype, 256 entries too */
#define NOTE_SUBTYPE 0x0000FF00
@@ -908,7 +915,7 @@ typedef enum wmDragFlags {
WM_DRAG_FREE_DATA = 1,
} wmDragFlags;
-/* note: structs need not exported? */
+/* NOTE: structs need not exported? */
typedef struct wmDragID {
struct wmDragID *next, *prev;
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index 9a993e1f8d7..1fbbec7f949 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -107,7 +107,7 @@ typedef enum eWM_GizmoFlagGroupTypeFlag {
/** Mark gizmo-group as being 3D */
WM_GIZMOGROUPTYPE_3D = (1 << 0),
/** Scale gizmos as 3D object that respects zoom (otherwise zoom independent draw size).
- * note: currently only for 3D views, 2D support needs adding. */
+ * NOTE: currently only for 3D views, 2D support needs adding. */
WM_GIZMOGROUPTYPE_SCALE = (1 << 1),
/** Gizmos can be depth culled with scene objects (covered by other geometry - TODO) */
WM_GIZMOGROUPTYPE_DEPTH_3D = (1 << 2),
@@ -445,7 +445,7 @@ typedef struct wmGizmoGroupType {
/** Only for convenient removal. */
struct wmKeyConfig *keyconf;
- /* Note: currently gizmo-group instances don't store properties,
+ /* NOTE: currently gizmo-group instances don't store properties,
* they're kept in the tool properties. */
/** RNA for properties. */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index 062731dfb3d..213a3c2e342 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -981,10 +981,10 @@ void WM_gizmomaptype_group_unlink(bContext *C,
WM_gizmomaptype_group_free(gzgt_ref);
}
- /* TODO(campbell): Gizmos may share keymaps, for now don't
+ /* TODO(campbell): Gizmos may share key-maps, for now don't
* remove however we could flag them as temporary/owned by the gizmo. */
#if 0
- /* Note, we may want to keep this keymap for editing */
+ /* NOTE: we may want to keep this key-map for editing. */
WM_keymap_remove(gzgt->keyconf, gzgt->keymap);
#endif
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
index 6ebeb5a76b6..6a793d52f74 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
@@ -162,7 +162,7 @@ void WM_gizmo_group_type_free_ptr(wmGizmoGroupType *gzgt)
gizmogrouptype_free(gzgt);
- /* XXX, TODO, update the world! */
+ /* XXX, TODO: update the world! */
}
bool WM_gizmo_group_type_free(const char *idname)
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index 2ffa04bd8ae..6a328679c2e 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -264,7 +264,7 @@ bool WM_gizmomap_minmax(const wmGizmoMap *gzmap,
}
bool ok = false;
- BLI_assert(!"TODO");
+ BLI_assert_msg(0, "TODO");
return ok;
}
@@ -918,7 +918,7 @@ static bool wm_gizmomap_select_all_intern(bContext *C, wmGizmoMap *gzmap)
* Select/Deselect all selectable gizmos in \a gzmap.
* \return if selection has changed.
*
- * TODO select all by type
+ * TODO: select all by type.
*/
bool WM_gizmomap_select_all(bContext *C, wmGizmoMap *gzmap, const int action)
{
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 6dd3e4186c4..9657f8aa03c 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -168,7 +168,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
win->eventstate = NULL;
win->cursor_keymap_status = NULL;
win->tweak = NULL;
-#ifdef WIN32
+#if defined(WIN32) || defined(__APPLE__)
win->ime_data = NULL;
#endif
@@ -516,7 +516,7 @@ void WM_check(bContext *C)
}
/* Case: fileread. */
- /* Note: this runs in background mode to set the screen context cb. */
+ /* NOTE: this runs in background mode to set the screen context cb. */
if ((wm->initialized & WM_WINDOW_IS_INIT) == 0) {
ED_screens_init(bmain, wm);
wm->initialized |= WM_WINDOW_IS_INIT;
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 11783ae3517..50d3a856cbe 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -124,14 +124,14 @@ static void window_set_custom_cursor(
wmWindow *win, const uchar mask[16][2], const uchar bitmap[16][2], int hotx, int hoty)
{
GHOST_SetCustomCursorShape(
- win->ghostwin, (GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask, 16, 16, hotx, hoty, true);
+ win->ghostwin, (uint8_t *)bitmap, (uint8_t *)mask, 16, 16, hotx, hoty, true);
}
static void window_set_custom_cursor_ex(wmWindow *win, BCursor *cursor)
{
GHOST_SetCustomCursorShape(win->ghostwin,
- (GHOST_TUns8 *)cursor->bitmap,
- (GHOST_TUns8 *)cursor->mask,
+ (uint8_t *)cursor->bitmap,
+ (uint8_t *)cursor->mask,
16,
16,
cursor->hotx,
@@ -163,7 +163,7 @@ void WM_cursor_set(wmWindow *win, int curs)
win->cursor = curs;
if (curs < 0 || curs >= WM_CURSOR_NUM) {
- BLI_assert(!"Invalid cursor number");
+ BLI_assert_msg(0, "Invalid cursor number");
return;
}
@@ -301,7 +301,7 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
static void wm_cursor_warp_relative(wmWindow *win, int x, int y)
{
- /* note: don't use wmEvent coords because of continuous grab T36409. */
+ /* NOTE: don't use wmEvent coords because of continuous grab T36409. */
int cx, cy;
wm_cursor_position_get(win, &cx, &cy);
WM_cursor_warp(win, cx + x, cy + y);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index e899cbb22b9..da40040ce56 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -144,7 +144,7 @@ wmDrag *WM_event_start_drag(
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag");
- /* keep track of future multitouch drag too, add a mousepointer id or so */
+ /* Keep track of future multi-touch drag too, add a mouse-pointer id or so. */
/* if multiple drags are added, they're drawn as list */
BLI_addtail(&wm->drags, drag);
@@ -321,7 +321,7 @@ void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent)
return;
}
if (GS(drag_id->id->name) != GS(id->name)) {
- BLI_assert(!"All dragged IDs must have the same type");
+ BLI_assert_msg(0, "All dragged IDs must have the same type");
return;
}
}
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 0922aaaee53..f01e28f8822 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -457,6 +457,7 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_
GPUOffScreen *offscreen = GPU_offscreen_create(
region->winx, region->winy, false, false, NULL);
if (!offscreen) {
+ WM_report(RPT_ERROR, "Region could not be drawn!");
return;
}
diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c
index 905b0f7b128..e7603a02cff 100644
--- a/source/blender/windowmanager/intern/wm_event_query.c
+++ b/source/blender/windowmanager/intern/wm_event_query.c
@@ -484,7 +484,10 @@ int WM_event_absolute_delta_y(const struct wmEvent *event)
* \{ */
#ifdef WITH_INPUT_IME
-/* most os using ctrl/oskey + space to switch ime, avoid added space */
+/**
+ * Most OS's use `Ctrl+Space` / `OsKey+Space` to switch IME,
+ * so don't type in the space character.
+ */
bool WM_event_is_ime_switch(const struct wmEvent *event)
{
return event->val == KM_PRESS && event->type == EVT_SPACEKEY &&
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index b82b3c1ff5d..5e29a22304c 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -61,6 +61,7 @@
#include "BLT_translation.h"
+#include "ED_asset.h"
#include "ED_fileselect.h"
#include "ED_info.h"
#include "ED_screen.h"
@@ -129,7 +130,7 @@ wmEvent *wm_event_add_ex(wmWindow *win,
BLI_addtail(&win->event_queue, event);
}
else {
- /* Note: strictly speaking this breaks const-correctness,
+ /* NOTE: strictly speaking this breaks const-correctness,
* however we're only changing 'next' member. */
BLI_insertlinkafter(&win->event_queue, (void *)event_to_add_after, event);
}
@@ -189,7 +190,7 @@ void wm_event_free(wmEvent *event)
if (event->customdata) {
if (event->customdatafree) {
- /* Note: pointer to listbase struct elsewhere. */
+ /* NOTE: pointer to listbase struct elsewhere. */
if (event->custom == EVT_DATA_DRAGDROP) {
ListBase *lb = event->customdata;
WM_drag_free_list(lb);
@@ -326,6 +327,7 @@ void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id)
}
}
}
+ ED_assetlist_storage_id_remap(old_id, new_id);
wmWindowManager *wm = bmain->wm.first;
if (wm && wm->message_bus) {
@@ -627,7 +629,7 @@ void wm_event_do_notifiers(bContext *C)
CTX_wm_window_set(C, NULL);
}
- /* Autorun warning */
+ /* Auto-run warning. */
wm_test_autorun_warning(C);
}
@@ -915,7 +917,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
{
if (G.background == 0 && caller_owns_reports == false) { /* popup */
if (op->reports->list.first) {
- /* FIXME, temp setting window, see other call to UI_popup_menu_reports for why. */
+ /* FIXME: temp setting window, see other call to #UI_popup_menu_reports for why. */
wmWindow *win_prev = CTX_wm_window(C);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *region_prev = CTX_wm_region(C);
@@ -1370,7 +1372,7 @@ static int wm_operator_invoke(bContext *C,
CLOG_ERROR(WM_LOG_OPERATORS, "invalid operator call '%s'", op->idname);
}
- /* Note, if the report is given as an argument then assume the caller will deal with displaying
+ /* NOTE: if the report is given as an argument then assume the caller will deal with displaying
* them currently Python only uses this. */
if (!(retval & OPERATOR_HANDLED) && (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED))) {
/* Only show the report if the report list was not given in the function. */
@@ -2379,9 +2381,9 @@ static int wm_handler_fileselect_do(bContext *C,
if (handler->op->reports->list.first) {
- /* FIXME, temp setting window, this is really bad!
+ /* FIXME(campbell): temp setting window, this is really bad!
* only have because lib linking errors need to be seen by users :(
- * it can be removed without breaking anything but then no linking errors - campbell */
+ * it can be removed without breaking anything but then no linking errors. */
wmWindow *win_prev = CTX_wm_window(C);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *region_prev = CTX_wm_region(C);
@@ -2393,7 +2395,7 @@ static int wm_handler_fileselect_do(bContext *C,
BKE_report_print_level_set(handler->op->reports, RPT_WARNING);
UI_popup_menu_reports(C, handler->op->reports);
- /* XXX - copied from 'wm_operator_finished()' */
+ /* XXX: copied from 'wm_operator_finished()'. */
/* add reports to the global list, otherwise they are not seen */
BLI_movelisttolist(&CTX_wm_reports(C)->list, &handler->op->reports->list);
@@ -2796,7 +2798,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
/* Modal handlers can get removed in this loop, we keep the loop this way.
*
- * Note: check 'handlers->first' because in rare cases the handlers can be cleared
+ * NOTE: check 'handlers->first' because in rare cases the handlers can be cleared
* by the event that's called, for eg:
*
* Calling a python script which changes the area.type, see T32232. */
@@ -3398,7 +3400,7 @@ void wm_event_do_handlers(bContext *C)
wm_tweakevent_test(C, event, action);
if ((action & WM_HANDLER_BREAK) == 0) {
- /* Note: setting subwin active should be done here, after modal handlers have been done */
+ /* NOTE: setting subwin active should be done here, after modal handlers have been done. */
if (event->type == MOUSEMOVE) {
/* State variables in screen, cursors.
* Also used in wm_draw.c, fails for modal handlers though. */
@@ -4011,7 +4013,7 @@ wmEventHandler_Dropbox *WM_event_add_dropbox_handler(ListBase *handlers, ListBas
return handler;
}
-/* XXX solution works, still better check the real cause (ton) */
+/* XXX(ton): solution works, still better check the real cause. */
void WM_event_remove_area_handler(ListBase *handlers, void *area)
{
LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, handlers) {
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 6230b240d11..3633d3c07d3 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -844,7 +844,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* first try to append data from exotic file formats... */
/* it throws error box when file doesn't exist and returns -1 */
- /* note; it should set some error message somewhere... (ton) */
+ /* NOTE(ton): it should set some error message somewhere. */
const int retval = wm_read_exotic(filepath);
/* we didn't succeed, now try to read Blender file */
@@ -929,7 +929,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
else {
BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath);
- BLI_assert(!"invalid 'retval'");
+ BLI_assert_msg(0, "invalid 'retval'");
}
if (success == false) {
@@ -1606,7 +1606,7 @@ static bool wm_file_write(bContext *C,
return ok;
}
- /* note: used to replace the file extension (to ensure '.blend'),
+ /* NOTE: used to replace the file extension (to ensure '.blend'),
* no need to now because the operator ensures,
* its handy for scripts to save to a predefined name without blender editing it */
@@ -1645,13 +1645,13 @@ static bool wm_file_write(bContext *C,
ED_editors_flush_edits(bmain);
- /* first time saving */
- /* XXX temp solution to solve bug, real fix coming (ton) */
+ /* First time saving. */
+ /* XXX(ton): temp solution to solve bug, real fix coming. */
if ((BKE_main_blendfile_path(bmain)[0] == '\0') && (use_save_as_copy == false)) {
BLI_strncpy(bmain->name, filepath, sizeof(bmain->name));
}
- /* XXX temp solution to solve bug, real fix coming (ton) */
+ /* XXX(ton): temp solution to solve bug, real fix coming. */
bmain->recovered = 0;
if (BLO_write_file(CTX_data_main(C),
diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c
index 94535427dac..9da901d6c4e 100644
--- a/source/blender/windowmanager/intern/wm_gesture_ops.c
+++ b/source/blender/windowmanager/intern/wm_gesture_ops.c
@@ -447,7 +447,7 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
#if 0
/* Allow view navigation??? */
- /* note, this gives issues:
+ /* NOTE: this gives issues:
* 1) other modal ops run on top (box select),
* 2) middle-mouse is used now 3) tablet/trackpad? */
else {
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 48ab76317b5..d7ea47fc625 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -109,6 +109,7 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
+#include "ED_asset.h"
#include "ED_gpencil.h"
#include "ED_keyframes_edit.h"
#include "ED_keyframing.h"
@@ -226,7 +227,7 @@ void WM_init(bContext *C, int argc, const char **argv)
{
if (!G.background) {
- wm_ghost_init(C); /* note: it assigns C to ghost! */
+ wm_ghost_init(C); /* NOTE: it assigns C to ghost! */
wm_init_cursor_data();
BKE_sound_jack_sync_callback_set(sound_jack_sync_callback);
}
@@ -327,13 +328,13 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_spacemacros_init();
- /* note: there is a bug where python needs initializing before loading the
+ /* NOTE(campbell): there is a bug where python needs initializing before loading the
* startup.blend because it may contain PyDrivers. It also needs to be after
* initializing space types and other internal data.
*
* However can't redo this at the moment. Solution is to load python
* before wm_homefile_read() or make py-drivers check if python is running.
- * Will try fix when the crash can be repeated. - campbell. */
+ * Will try fix when the crash can be repeated. */
#ifdef WITH_PYTHON
BPY_python_start(C, argc, argv);
@@ -376,7 +377,7 @@ void WM_init(bContext *C, int argc, const char **argv)
{
Main *bmain = CTX_data_main(C);
- /* note, logic here is from wm_file_read_post,
+ /* NOTE: logic here is from wm_file_read_post,
* call functions that depend on Python being initialized. */
/* normally 'wm_homefile_read' will do this,
@@ -481,7 +482,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
/* first wrap up running stuff, we assume only the active WM is running */
/* modal handlers are on window level freed, others too? */
- /* note; same code copied in wm_files.c */
+ /* NOTE: same code copied in `wm_files.c`. */
if (C && wm) {
if (!G.background) {
struct MemFile *undo_memfile = wm->undo_stack ?
@@ -552,7 +553,6 @@ void WM_exit_ex(bContext *C, const bool do_python)
wm_surfaces_free();
wm_dropbox_free();
WM_menutype_free();
- WM_uilisttype_free();
/* all non-screen and non-space stuff editors did, like editmode */
if (C) {
@@ -571,6 +571,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
RE_engines_exit();
ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */
+ ED_assetlist_storage_exit();
if (wm) {
/* Before BKE_blender_free! - since the ListBases get freed there. */
@@ -607,6 +608,8 @@ void WM_exit_ex(bContext *C, const bool do_python)
wm_gizmomaptypes_free();
wm_gizmogrouptype_free();
wm_gizmotype_free();
+ /* Same for UI-list types. */
+ WM_uilisttype_free();
BLF_exit();
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 69b3660038d..25bcf1967ea 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -135,7 +135,7 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
/* matches wm_keymap_item_properties_set but doesn't alloc new ptr */
WM_operator_properties_create_ptr(kmi->ptr, ot);
/* 'kmi->ptr->data' NULL'd above, keep using existing properties.
- * Note: the operators property types may have changed,
+ * NOTE: the operators property types may have changed,
* we will need a more comprehensive sanitize function to support this properly.
*/
if (kmi->properties) {
@@ -971,7 +971,7 @@ static const wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(const wmKeyMap *km
}
}
else {
- BLI_assert(!"called with non modal keymap");
+ BLI_assert_msg(0, "called with non modal keymap");
}
return NULL;
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index ba236988c1d..898671706d1 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -133,7 +133,7 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
}
if (action == FILE_SAVE) {
- /* note, this is only used to check if we should highlight the filename area red when the
+ /* NOTE: this is only used to check if we should highlight the filename area red when the
* filepath is an existing file. */
prop = RNA_def_boolean(ot->srna,
"check_existing",
@@ -198,7 +198,7 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- /* TODO asset only filter? */
+ /* TODO: asset only filter? */
prop = RNA_def_int(
ot->srna,
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index a2d783afc32..576f15731a0 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -126,8 +126,8 @@ void WM_operator_py_idname(char *to, const char *from)
if (sep) {
int ofs = (sep - from);
- /* note, we use ascii tolower instead of system tolower, because the
- * latter depends on the locale, and can lead to idname mismatch */
+ /* NOTE: we use ascii `tolower` instead of system `tolower`, because the
+ * latter depends on the locale, and can lead to `idname` mismatch. */
memcpy(to, from, sizeof(char) * ofs);
BLI_str_tolower_ascii(to, ofs);
@@ -604,6 +604,12 @@ void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
* used for keymaps and macros */
void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
{
+ IDProperty *tmp_properties = NULL;
+ /* Allow passing NULL for properties, just create the properties here then. */
+ if (properties == NULL) {
+ properties = &tmp_properties;
+ }
+
if (*properties == NULL) {
IDPropertyTemplate val = {0};
*properties = IDP_New(IDP_GROUP, &val, "wmOpItemProp");
@@ -745,7 +751,7 @@ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_
if (idp_src) {
IDProperty *idp_dst = IDP_CopyProperty(idp_src);
- /* note - in the future this may need to be done recursively,
+ /* NOTE: in the future this may need to be done recursively,
* but for now RNA doesn't access nested operators */
idp_dst->flag |= IDP_FLAG_GHOST;
@@ -1156,7 +1162,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor
RNA_property_string_get(op->ptr, prop, filepath);
if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) {
RNA_property_string_set(op->ptr, prop, filepath);
- /* note, we could check for and update 'filename' here,
+ /* NOTE: we could check for and update 'filename' here,
* but so far nothing needs this. */
return true;
}
@@ -2361,7 +2367,7 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void
strdrawlen = BLI_strlen_utf8(str);
break;
default:
- tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* note, this is a dummy value */
+ tex_radius = WM_RADIAL_CONTROL_DISPLAY_SIZE; /* NOTE: this is a dummy value. */
alpha = 0.75;
break;
}
@@ -3202,7 +3208,7 @@ static void redraw_timer_step(bContext *C,
int tot = (scene->r.efra - scene->r.sfra) + 1;
while (tot--) {
- /* todo, ability to escape! */
+ /* TODO: ability to escape! */
scene->r.cfra++;
if (scene->r.cfra > scene->r.efra) {
scene->r.cfra = scene->r.sfra;
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 5300649a0cd..fa21dbcb4bb 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -220,7 +220,7 @@ static void playanim_window_get_size(int *r_width, int *r_height)
static void playanim_gl_matrix(void)
{
/* unified matrix, note it affects offset for drawing */
- /* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */
+ /* NOTE: cannot use GPU_matrix_ortho_2d_set here because shader ignores. */
GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f);
}
@@ -1114,7 +1114,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
#ifdef WITH_AUDASPACE
{
PlayAnimPict *picture = picsbase.first;
- /* TODO - store in ps direct? */
+ /* TODO: store in ps direct? */
int i = 0;
while (picture && picture != ps->picture) {
@@ -1151,7 +1151,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
#ifdef WITH_AUDASPACE
{
PlayAnimPict *picture = picsbase.first;
- /* TODO - store in ps direct? */
+ /* TODO: store in ps direct? */
int i = 0;
while (picture && picture != ps->picture) {
i++;
@@ -1357,7 +1357,7 @@ static int 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};
- GHOST_TUns32 scr_w, scr_h;
+ uint32_t scr_w, scr_h;
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
@@ -1405,7 +1405,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
{
struct ImBuf *ibuf = NULL;
static char filepath[FILE_MAX]; /* abused to return dropped file path */
- GHOST_TUns32 maxwinx, maxwiny;
+ uint32_t maxwinx, maxwiny;
int i;
/* This was done to disambiguate the name for use under c++. */
int start_x = 0, start_y = 0;
diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c
index ae726e73fe7..f5881a00998 100644
--- a/source/blender/windowmanager/intern/wm_splash_screen.c
+++ b/source/blender/windowmanager/intern/wm_splash_screen.c
@@ -112,7 +112,7 @@ static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf)
const float distance = sqrt(u * u + v * v);
/* Pointer offset to the alpha value of pixel. */
- /* Note, the left corner is flipped in the X-axis. */
+ /* NOTE: the left corner is flipped in the X-axis. */
const int offset_l = 4 * (size - x - x - 1) + 3;
const int offset_r = 4 * (ibuf->x - size) + 3;
diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c
index 45c14c0bbe9..82ba4aa6e6f 100644
--- a/source/blender/windowmanager/intern/wm_uilist_type.c
+++ b/source/blender/windowmanager/intern/wm_uilist_type.c
@@ -21,16 +21,24 @@
*/
#include <stdio.h>
+#include <string.h>
+#include "BLI_listbase.h"
#include "BLI_sys_types.h"
+#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h"
+#include "UI_interface.h"
+
#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_main.h"
#include "BKE_screen.h"
#include "WM_api.h"
@@ -60,8 +68,62 @@ bool WM_uilisttype_add(uiListType *ult)
return 1;
}
-void WM_uilisttype_freelink(uiListType *ult)
+static void wm_uilisttype_unlink_from_region(const uiListType *ult, ARegion *region)
{
+ LISTBASE_FOREACH (uiList *, list, &region->ui_lists) {
+ if (list->type == ult) {
+ /* Don't delete the list, it's not just runtime data but stored in files. Freeing would make
+ * that data get lost. */
+ list->type = NULL;
+ }
+ }
+}
+
+static void wm_uilisttype_unlink_from_area(const uiListType *ult, ScrArea *area)
+{
+ LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) {
+ ListBase *regionbase = (space_link == area->spacedata.first) ? &area->regionbase :
+ &space_link->regionbase;
+ LISTBASE_FOREACH (ARegion *, region, regionbase) {
+ wm_uilisttype_unlink_from_region(ult, region);
+ }
+ }
+}
+
+/**
+ * For all lists representing \a ult, clear their `uiListType` pointer. Use when a list-type is
+ * deleted, so that the UI doesn't keep references to it.
+ *
+ * This is a common pattern for unregistering (usually .py defined) types at runtime, e.g. see
+ * #WM_gizmomaptype_group_unlink().
+ * Note that unlike in some other cases using this pattern, we don't actually free the lists with
+ * type \a ult, we just clear the reference to the type. That's because UI-Lists are written to
+ * files and we don't want them to get lost together with their (user visible) settings.
+ */
+static void wm_uilisttype_unlink(Main *bmain, const uiListType *ult)
+{
+ for (wmWindowManager *wm = bmain->wm.first; wm != NULL; wm = wm->id.next) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
+ LISTBASE_FOREACH (ScrArea *, global_area, &win->global_areas.areabase) {
+ wm_uilisttype_unlink_from_area(ult, global_area);
+ }
+ }
+ }
+
+ for (bScreen *screen = bmain->screens.first; screen != NULL; screen = screen->id.next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ wm_uilisttype_unlink_from_area(ult, area);
+ }
+
+ LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
+ wm_uilisttype_unlink_from_region(ult, region);
+ }
+ }
+}
+
+void WM_uilisttype_remove_ptr(Main *bmain, uiListType *ult)
+{
+ wm_uilisttype_unlink(bmain, ult);
bool ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN);
@@ -88,3 +150,34 @@ void WM_uilisttype_free(void)
BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN);
uilisttypes_hash = NULL;
}
+
+/**
+ * The "full" list-ID is an internal name used for storing and identifying a list. It is built like
+ * this:
+ * "{uiListType.idname}_{list_id}", whereby "list_id" is an optional parameter passed to
+ * `UILayout.template_list()`. If it is not set, the full list-ID is just "{uiListType.idname}_".
+ *
+ * Note that whenever the Python API refers to the list-ID, it's the short, "non-full" one it
+ * passed to `UILayout.template_list()`. C code can query that through
+ * #WM_uilisttype_list_id_get().
+ */
+void WM_uilisttype_to_full_list_id(const uiListType *ult,
+ const char *list_id,
+ char r_full_list_id[/*UI_MAX_NAME_STR*/])
+{
+ /* We tag the list id with the list type... */
+ BLI_snprintf(r_full_list_id, UI_MAX_NAME_STR, "%s_%s", ult->idname, list_id ? list_id : "");
+}
+
+/**
+ * Get the "non-full" list-ID, see #WM_uilisttype_to_full_list_id() for details.
+ *
+ * \note Assumes `uiList.list_id` was set using #WM_uilisttype_to_full_list_id()!
+ */
+const char *WM_uilisttype_list_id_get(const uiListType *ult, uiList *list)
+{
+ /* Some sanity check for the assumed behavior of #WM_uilisttype_to_full_list_id(). */
+ BLI_assert((list->list_id + strlen(ult->idname))[0] == '_');
+ /* +1 to skip the '_' */
+ return list->list_id + strlen(ult->idname) + 1;
+}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 8f8577e2616..1b08b8dad92 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -462,7 +462,7 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
/* Informs GHOST of unsaved changes, to set window modified visual indicator (macOS)
* and to give hint of unsaved changes for a user warning mechanism in case of OS application
* terminate request (e.g. OS Shortcut Alt+F4, Command+Q, (...), or session end). */
- GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved);
+ GHOST_SetWindowModifiedState(win->ghostwin, (bool)!wm->file_saved);
}
}
@@ -1136,14 +1136,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
return 1;
}
if (!ghostwin) {
- /* XXX - should be checked, why are we getting an event here, and */
- /* what is it? */
+ /* XXX: should be checked, why are we getting an event here, and what is it? */
puts("<!> event has no window");
return 1;
}
if (!GHOST_ValidWindow(g_system, ghostwin)) {
- /* XXX - should be checked, why are we getting an event here, and */
- /* what is it? */
+ /* XXX: should be checked, why are we getting an event here, and what is it? */
puts("<!> event has invalid window");
return 1;
}
@@ -1724,7 +1722,7 @@ static char *wm_clipboard_text_get_ex(bool selection, int *r_len, bool firstline
return NULL;
}
- char *buf = (char *)GHOST_getClipboard(selection);
+ char *buf = GHOST_getClipboard(selection);
if (!buf) {
*r_len = 0;
return NULL;
@@ -1811,10 +1809,10 @@ void WM_clipboard_text_set(const char *buf, bool selection)
}
*p2 = '\0';
- GHOST_putClipboard((GHOST_TInt8 *)newbuf, selection);
+ GHOST_putClipboard(newbuf, selection);
MEM_freeN(newbuf);
#else
- GHOST_putClipboard((GHOST_TInt8 *)buf, selection);
+ GHOST_putClipboard(buf, selection);
#endif
}
}
@@ -2405,6 +2403,10 @@ void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complet
{
BLI_assert(win);
+ /* Convert to native OS window coordinates. */
+ float fac = GHOST_GetNativePixelSize(win->ghostwin);
+ x /= fac;
+ y /= fac;
GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete);
}
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index ccb6e47e7e3..c21bebe8062 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -352,8 +352,8 @@ enum {
/* for event checks */
/* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */
/* UNUSED - see wm_eventmatch - BUG T30479. */
-/* #define ISTEXTINPUT(event_type) ((event_type) >= ' ' && (event_type) <= 255) */
-/* note, an alternative could be to check 'event->utf8_buf' */
+// #define ISTEXTINPUT(event_type) ((event_type) >= ' ' && (event_type) <= 255)
+/* NOTE: an alternative could be to check `event->utf8_buf`. */
/* test whether the event is a key on the keyboard */
#define ISKEYBOARD(event_type) \
@@ -439,7 +439,7 @@ bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask ma
/* Gestures */
/* NOTE: these values are saved in keymap files, do not change them but just add new ones */
enum {
- /* value of tweaks and line gestures, note, KM_ANY (-1) works for this case too */
+ /* Value of tweaks and line gestures. #KM_ANY (-1) works for this case too. */
EVT_GESTURE_N = 1,
EVT_GESTURE_NE = 2,
EVT_GESTURE_E = 3,
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actions.c b/source/blender/windowmanager/xr/intern/wm_xr_actions.c
index 51ed3dcfd3c..7eabd29baa0 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_actions.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_actions.c
@@ -462,7 +462,7 @@ bool WM_xr_action_state_get(const wmXrData *xr,
bool WM_xr_haptic_action_apply(wmXrData *xr,
const char *action_set_name,
const char *action_name,
- const long long *duration,
+ const int64_t *duration,
const float *frequency,
const float *amplitude)
{
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 3f5ca84fbef..c75174dfff0 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -1954,7 +1954,7 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
/* Make the path absolute because its needed for relative linked blends to be found */
char filename[FILE_MAX];
- /* note, we could skip these, but so far we always tried to load these files */
+ /* NOTE: we could skip these, but so far we always tried to load these files. */
if (argv[0][0] == '-') {
fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
}
diff --git a/tests/performance/api/__init__.py b/tests/performance/api/__init__.py
new file mode 100644
index 00000000000..2dc9283c44a
--- /dev/null
+++ b/tests/performance/api/__init__.py
@@ -0,0 +1,7 @@
+# Apache License, Version 2.0
+
+from .environment import TestEnvironment
+from .device import TestDevice, TestMachine
+from .config import TestEntry, TestQueue, TestConfig
+from .test import Test, TestCollection
+from .graph import TestGraph
diff --git a/tests/performance/api/config.py b/tests/performance/api/config.py
new file mode 100644
index 00000000000..68f4df8d487
--- /dev/null
+++ b/tests/performance/api/config.py
@@ -0,0 +1,259 @@
+# Apache License, Version 2.0
+
+import fnmatch
+import json
+import pathlib
+import sys
+
+from dataclasses import dataclass, field
+from typing import Dict, List
+
+from .test import TestCollection
+
+
+def get_build_hash(args: None) -> str:
+ import bpy
+ import sys
+ build_hash = bpy.app.build_hash.decode('utf-8')
+ return '' if build_hash == 'Unknown' else build_hash
+
+
+@dataclass
+class TestEntry:
+ """Test to run, a combination of revision, test and device."""
+ test: str = ''
+ category: str = ''
+ revision: str = ''
+ git_hash: str = ''
+ executable: str = ''
+ date: int = 0
+ device_type: str = 'CPU'
+ device_id: str = 'CPU'
+ device_name: str = 'Unknown CPU'
+ status: str = 'queued'
+ output: Dict = field(default_factory=dict)
+ benchmark_type: str = 'comparison'
+
+ def to_json(self) -> Dict:
+ json_dict = {}
+ for field in self.__dataclass_fields__:
+ json_dict[field] = getattr(self, field)
+ return json_dict
+
+ def from_json(self, json_dict):
+ for field in self.__dataclass_fields__:
+ setattr(self, field, json_dict[field])
+
+
+class TestQueue:
+ """Queue of tests to be run or inspected. Matches JSON file on disk."""
+
+ def __init__(self, filepath: pathlib.Path):
+ self.filepath = filepath
+ self.has_multiple_revisions_to_build = False
+ self.has_multiple_categories = False
+ self.entries = []
+
+ if self.filepath.is_file():
+ with open(self.filepath, 'r') as f:
+ json_entries = json.load(f)
+
+ for json_entry in json_entries:
+ entry = TestEntry()
+ entry.from_json(json_entry)
+ self.entries.append(entry)
+
+ def rows(self, use_revision_columns: bool) -> List:
+ # Generate rows of entries for printing and running.
+ entries = sorted(self.entries, key=lambda entry:
+ (entry.revision,
+ entry.device_id,
+ entry.category,
+ entry.test))
+
+ if not use_revision_columns:
+ # One entry per row.
+ return [[entry] for entry in entries]
+ else:
+ # Multiple revisions per row.
+ rows = {}
+
+ for entry in entries:
+ key = (entry.device_id, entry.category, entry.test)
+ if key in rows:
+ rows[key].append(entry)
+ else:
+ rows[key] = [entry]
+
+ return [value for _, value in sorted(rows.items())]
+
+ def find(self, revision: str, test: str, category: str, device_id: str) -> Dict:
+ for entry in self.entries:
+ if entry.revision == revision and \
+ entry.test == test and \
+ entry.category == category and \
+ entry.device_id == device_id:
+ return entry
+
+ return None
+
+ def write(self) -> None:
+ json_entries = [entry.to_json() for entry in self.entries]
+ with open(self.filepath, 'w') as f:
+ json.dump(json_entries, f, indent=2)
+
+
+class TestConfig:
+ """Test configuration, containing a subset of revisions, tests and devices."""
+
+ def __init__(self, env, name: str):
+ # Init configuration from config.py file.
+ self.name = name
+ self.base_dir = env.base_dir / name
+ self.logs_dir = self.base_dir / 'logs'
+
+ config = self._read_config_module()
+ self.tests = TestCollection(env,
+ getattr(config, 'tests', ['*']),
+ getattr(config, 'categories', ['*']))
+ self.revisions = getattr(config, 'revisions', {})
+ self.builds = getattr(config, 'builds', {})
+ self.queue = TestQueue(self.base_dir / 'results.json')
+ self.benchmark_type = getattr(config, 'benchmark_type', 'comparison')
+
+ self.devices = []
+ self._update_devices(env, getattr(config, 'devices', ['CPU']))
+
+ self._update_queue(env)
+
+ def revision_names(self) -> List:
+ return sorted(list(self.revisions.keys()) + list(self.builds.keys()))
+
+ def device_name(self, device_id: str) -> str:
+ for device in self.devices:
+ if device.id == device_id:
+ return device.name
+
+ return "Unknown"
+
+ @staticmethod
+ def write_default_config(env, config_dir: pathlib.Path) -> None:
+ config_dir.mkdir(parents=True, exist_ok=True)
+
+ default_config = """devices = ['CPU']\n"""
+ default_config += """tests = ['*']\n"""
+ default_config += """categories = ['*']\n"""
+ default_config += """builds = {\n"""
+ default_config += """ 'master': '/home/user/blender-git/build/bin/blender',"""
+ default_config += """ '2.93': '/home/user/blender-2.93/blender',"""
+ default_config += """}\n"""
+ default_config += """revisions = {\n"""
+ default_config += """}\n"""
+
+ config_file = config_dir / 'config.py'
+ with open(config_file, 'w') as f:
+ f.write(default_config)
+
+ def _read_config_module(self) -> None:
+ # Import config.py as a module.
+ import importlib.util
+ spec = importlib.util.spec_from_file_location("testconfig", self.base_dir / 'config.py')
+ mod = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(mod)
+ return mod
+
+ def _update_devices(self, env, device_filters: List) -> None:
+ # Find devices matching the filters.
+ need_gpus = device_filters != ['CPU']
+ machine = env.get_machine(need_gpus)
+
+ self.devices = []
+ for device in machine.devices:
+ for device_filter in device_filters:
+ if fnmatch.fnmatch(device.id, device_filter):
+ self.devices.append(device)
+ break
+
+ def _update_queue(self, env) -> None:
+ # Update queue to match configuration, adding and removing entries
+ # so that there is one entry for each revision, device and test
+ # combination.
+ entries = []
+
+ # Get entries for specified commits, tags and branches.
+ for revision_name, revision_commit in self.revisions.items():
+ git_hash = env.resolve_git_hash(revision_commit)
+ date = env.git_hash_date(git_hash)
+ entries += self._get_entries(revision_name, git_hash, '', date)
+
+ # Optimization to avoid rebuilds.
+ revisions_to_build = set()
+ for entry in entries:
+ if entry.status in ('queued', 'outdated'):
+ revisions_to_build.add(entry.git_hash)
+ self.queue.has_multiple_revisions_to_build = len(revisions_to_build) > 1
+
+ # Get entries for revisions based on existing builds.
+ for revision_name, executable in self.builds.items():
+ executable_path = pathlib.Path(executable)
+ if not executable_path.exists():
+ sys.stderr.write(f'Error: build {executable} not found\n')
+ sys.exit(1)
+
+ env.set_blender_executable(executable_path)
+ git_hash, _ = env.run_in_blender(get_build_hash, {})
+ env.unset_blender_executable()
+
+ mtime = executable_path.stat().st_mtime
+ entries += self._get_entries(revision_name, git_hash, executable, mtime)
+
+ # Detect number of categories for more compact printing.
+ categories = set()
+ for entry in entries:
+ categories.add(entry.category)
+ self.queue.has_multiple_categories = len(categories) > 1
+
+ # Replace actual entries.
+ self.queue.entries = entries
+
+ def _get_entries(self,
+ revision_name: str,
+ git_hash: str,
+ executable: pathlib.Path,
+ date: int) -> None:
+ entries = []
+ for test in self.tests.tests:
+ test_name = test.name()
+ test_category = test.category()
+
+ for device in self.devices:
+ entry = self.queue.find(revision_name, test_name, test_category, device.id)
+ if entry:
+ # Test if revision hash or executable changed.
+ if entry.git_hash != git_hash or \
+ entry.executable != executable or \
+ entry.benchmark_type != self.benchmark_type or \
+ entry.date != date:
+ # Update existing entry.
+ entry.git_hash = git_hash
+ entry.executable = executable
+ entry.benchmark_type = self.benchmark_type
+ entry.date = date
+ if entry.status in ('done', 'failed'):
+ entry.status = 'outdated'
+ else:
+ # Add new entry if it did not exist yet.
+ entry = TestEntry(
+ revision=revision_name,
+ git_hash=git_hash,
+ executable=executable,
+ date=date,
+ test=test_name,
+ category=test_category,
+ device_type=device.type,
+ device_id=device.id,
+ device_name=device.name,
+ benchmark_type=self.benchmark_type)
+ entries.append(entry)
+
+ return entries
diff --git a/tests/performance/api/device.py b/tests/performance/api/device.py
new file mode 100644
index 00000000000..b61ae42be36
--- /dev/null
+++ b/tests/performance/api/device.py
@@ -0,0 +1,71 @@
+# Apache License, Version 2.0
+
+import platform
+import subprocess
+from typing import List
+
+
+def get_cpu_name() -> str:
+ # Get full CPU name.
+ if platform.system() == "Windows":
+ return platform.processor()
+ elif platform.system() == "Darwin":
+ cmd = ['/usr/sbin/sysctl', "-n", "machdep.cpu.brand_string"]
+ return subprocess.check_output(cmd).strip().decode('utf-8')
+ else:
+ with open('/proc/cpuinfo') as f:
+ for line in f:
+ if line.startswith('model name'):
+ return line.split(':')[1].strip()
+
+ return "Unknown CPU"
+
+
+def get_gpu_device(args: None) -> List:
+ # Get the list of available Cycles GPU devices.
+ import bpy
+ import sys
+
+ prefs = bpy.context.preferences
+ cprefs = prefs.addons['cycles'].preferences
+
+ result = []
+
+ for device_type, _, _, _ in cprefs.get_device_types(bpy.context):
+ cprefs.compute_device_type = device_type
+ devices = cprefs.get_devices_for_type(device_type)
+ index = 0
+ for device in devices:
+ if device.type == device_type:
+ result.append({'type': device.type, 'name': device.name, 'index': index})
+ index += 1
+ break
+
+ return result
+
+
+class TestDevice:
+ def __init__(self, device_type: str, device_id: str, name: str, operating_system: str):
+ self.type = device_type
+ self.id = device_id
+ self.name = name
+ self.operating_system = operating_system
+
+
+class TestMachine:
+ def __init__(self, env, need_gpus: bool):
+ operating_system = platform.system()
+
+ self.devices = [TestDevice('CPU', 'CPU', get_cpu_name(), operating_system)]
+ self.has_gpus = need_gpus
+
+ if need_gpus and env.blender_executable:
+ gpu_devices, _ = env.run_in_blender(get_gpu_device, {})
+ for gpu_device in gpu_devices:
+ device_type = gpu_device['type']
+ device_name = gpu_device['name']
+ device_id = gpu_device['type'] + "_" + str(gpu_device['index'])
+ self.devices.append(TestDevice(device_type, device_id, device_name, operating_system))
+
+ def cpu_device(self) -> TestDevice:
+ return self.devices[0]
diff --git a/tests/performance/api/environment.py b/tests/performance/api/environment.py
new file mode 100644
index 00000000000..c9ddd493394
--- /dev/null
+++ b/tests/performance/api/environment.py
@@ -0,0 +1,244 @@
+# Apache License, Version 2.0
+
+import base64
+import glob
+import inspect
+import multiprocessing
+import os
+import pathlib
+import platform
+import pickle
+import subprocess
+import sys
+from typing import Callable, Dict, List
+
+from .config import TestConfig
+from .device import TestMachine
+
+
+class TestEnvironment:
+ def __init__(self, blender_git_dir: pathlib.Path, base_dir: pathlib.Path):
+ self.blender_git_dir = blender_git_dir
+ self.base_dir = base_dir
+ self.blender_dir = base_dir / 'blender'
+ self.build_dir = base_dir / 'build'
+ self.lib_dir = base_dir / 'lib'
+ self.benchmarks_dir = self.blender_git_dir.parent / 'lib' / 'benchmarks'
+ self.git_executable = 'git'
+ self.cmake_executable = 'cmake'
+ self.cmake_options = ['-DWITH_INTERNATIONAL=OFF', '-DWITH_BUILDINFO=OFF']
+ self.unset_blender_executable()
+ self.log_file = None
+ self.machine = None
+
+ def get_machine(self, need_gpus: bool=True) -> None:
+ if not self.machine or (need_gpus and not self.machine.has_gpus):
+ self.machine = TestMachine(self, need_gpus)
+
+ return self.machine
+
+ def init(self, build) -> None:
+ if not self.benchmarks_dir.exists():
+ sys.stderr.write(f'Error: benchmark files directory not found at {self.benchmarks_dir}')
+ sys.exit(1)
+
+ # Create benchmarks folder contents.
+ print(f'Init {self.base_dir}')
+ self.base_dir.mkdir(parents=True, exist_ok=True)
+
+ if len(self.get_configs(names_only=True)) == 0:
+ config_dir = self.base_dir / 'default'
+ print(f'Creating default configuration in {config_dir}')
+ TestConfig.write_default_config(self, config_dir)
+
+ if build:
+ if not self.lib_dir.exists():
+ print(f'Creating symlink at {self.lib_dir}')
+ self.lib_dir.symlink_to(self.blender_git_dir.parent / 'lib')
+ else:
+ print(f'Exists {self.lib_dir}')
+
+ if not self.blender_dir.exists():
+ print(f'Init git worktree in {self.blender_dir}')
+ self.call([self.git_executable, 'worktree', 'add', '--detach', self.blender_dir, 'HEAD'], self.blender_git_dir)
+ else:
+ print(f'Exists {self.blender_dir}')
+
+ if not self.build_dir.exists():
+ print(f'Init build in {self.build_dir}')
+ self.build_dir.mkdir()
+ # No translation to avoid dealing with submodules
+ self.call([self.cmake_executable, self.blender_dir, '.'] + self.cmake_options, self.build_dir)
+ else:
+ print(f'Exists {self.build_dir}')
+
+ print("Building")
+ self.build()
+
+ print('Done')
+
+ def checkout(self) -> None:
+ # Checkout Blender revision
+ if not self.blender_dir.exists():
+ sys.stderr.write('\n\nError: no build set up, run `./benchmark init --build` first\n')
+ sys.exit(1)
+
+ self.call([self.git_executable, 'clean', '-f', '-d'], self.blender_dir)
+ self.call([self.git_executable, 'reset', '--hard', 'HEAD'], self.blender_dir)
+ self.call([self.git_executable, 'checkout', '--detach', git_hash], self.blender_dir)
+
+ self.build()
+
+ def build(self) -> None:
+ # Build Blender revision
+ if not self.build_dir.exists():
+ sys.stderr.write('\n\nError: no build set up, run `./benchmark init --build` first\n')
+ sys.exit(1)
+
+ jobs = str(multiprocessing.cpu_count())
+ self.call([self.cmake_executable, '.'] + self.cmake_options, self.build_dir)
+ self.call([self.cmake_executable, '--build', '.', '-j', jobs, '--target', 'install'], self.build_dir)
+
+ def set_blender_executable(self, executable_path: pathlib.Path) -> None:
+ # Run all Blender commands with this executable.
+ self.blender_executable = executable_path
+
+ def unset_blender_executable(self) -> None:
+ if platform.system() == "Windows":
+ self.blender_executable = self.build_dir / 'bin' / 'blender.exe'
+ elif platform.system() == "Darwin":
+ self.blender_executable = self.build_dir / 'bin' / 'Blender.app' / 'Contents' / 'MacOS' / 'Blender'
+ else:
+ self.blender_executable = self.build_dir / 'bin' / 'blender'
+
+ if not self.blender_executable.exists():
+ self.blender_executable = 'blender'
+
+ def set_log_file(self, filepath: pathlib.Path, clear=True) -> None:
+ # Log all commands and output to this file.
+ self.log_file = filepath
+
+ if clear:
+ self.log_file.unlink(missing_ok=True)
+
+ def unset_log_file(self) -> None:
+ self.log_file = None
+
+ def call(self, args: List[str], cwd: pathlib.Path, silent=False) -> List[str]:
+ # Execute command with arguments in specified directory,
+ # and return combined stdout and stderr output.
+
+ # Open log file for writing
+ f = None
+ if self.log_file:
+ if not self.log_file.exists():
+ self.log_file.parent.mkdir(parents=True, exist_ok=True)
+ f = open(self.log_file, 'a')
+ f.write('\n' + ' '.join([str(arg) for arg in args]) + '\n\n')
+
+ proc = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ # Read line by line
+ lines = []
+ try:
+ while proc.poll() is None:
+ line = proc.stdout.readline()
+ if line:
+ line_str = line.decode('utf-8', 'ignore')
+ lines.append(line_str)
+ if f:
+ f.write(line_str)
+ except KeyboardInterrupt:
+ # Avoid processes that keep running when interrupting.
+ proc.terminate()
+
+ if f:
+ f.close()
+
+ # Print command output on error
+ if proc.returncode != 0 and not silent:
+ for line in lines:
+ print(line.rstrip())
+ raise Exception("Error executing command")
+
+ return lines
+
+ def call_blender(self, args: List[str], foreground=False) -> List[str]:
+ # Execute Blender command with arguments.
+ common_args = ['--factory-startup', '--enable-autoexec', '--python-exit-code', '1']
+ if foreground:
+ common_args += ['--no-window-focus', '--window-geometry', '0', '0', '1024', '768']
+ else:
+ common_args += ['--background']
+
+ return self.call([self.blender_executable] + common_args + args, cwd=self.base_dir)
+
+ def run_in_blender(self,
+ function: Callable[[Dict], Dict],
+ args: Dict,
+ blender_args: List=[],
+ foreground=False) -> Dict:
+ # Run function in a Blender instance. Arguments and return values are
+ # passed as a Python object that must be serializable with pickle.
+
+ # Get information to call this function from Blender.
+ package_path = pathlib.Path(__file__).parent.parent
+ functionname = function.__name__
+ modulename = inspect.getmodule(function).__name__
+
+ # Serialize arguments in base64, to avoid having to escape it.
+ args = base64.b64encode(pickle.dumps(args))
+ output_prefix = 'TEST_OUTPUT: '
+
+ expression = (f'import sys, pickle, base64\n'
+ f'sys.path.append("{package_path}")\n'
+ f'import {modulename}\n'
+ f'args = pickle.loads(base64.b64decode({args}))\n'
+ f'result = {modulename}.{functionname}(args)\n'
+ f'result = base64.b64encode(pickle.dumps(result))\n'
+ f'print("{output_prefix}" + result.decode())\n')
+
+ expr_args = blender_args + ['--python-expr', expression]
+ lines = self.call_blender(expr_args, foreground=foreground)
+
+ # Parse output.
+ for line in lines:
+ if line.startswith(output_prefix):
+ output = line[len(output_prefix):].strip()
+ result = pickle.loads(base64.b64decode(output))
+ return result, lines
+
+ return {}, lines
+
+ def find_blend_files(self, dirpath: pathlib.Path) -> List:
+ # Find .blend files in subdirectories of the given directory in the
+ # lib/benchmarks directory.
+ dirpath = self.benchmarks_dir / dirpath
+ filepaths = []
+ for filename in glob.iglob(str(dirpath / '*.blend'), recursive=True):
+ filepaths.append(pathlib.Path(filename))
+ return filepaths
+
+ def get_configs(self, name: str=None, names_only: bool=False) -> List:
+ # Get list of configurations in the benchmarks directory.
+ configs = []
+
+ if self.base_dir.exists():
+ for dirname in os.listdir(self.base_dir):
+ if not name or dirname == name:
+ dirpath = self.base_dir / dirname / 'config.py'
+ if dirpath.exists():
+ if names_only:
+ configs.append(dirname)
+ else:
+ configs.append(TestConfig(self, dirname))
+
+ return configs
+
+ def resolve_git_hash(self, revision):
+ # Get git hash for a tag or branch.
+ return self.call([self.git_executable, 'rev-parse', revision], self.blender_git_dir)[0].strip()
+
+ def git_hash_date(self, git_hash):
+ # Get commit data for a git hash.
+ return int(self.call([self.git_executable, 'log', '-n1', git_hash, '--format=%at'], self.blender_git_dir)[0].strip())
diff --git a/tests/performance/api/graph.py b/tests/performance/api/graph.py
new file mode 100644
index 00000000000..b3c8329ff27
--- /dev/null
+++ b/tests/performance/api/graph.py
@@ -0,0 +1,114 @@
+# Apache License, Version 2.0
+
+from . import TestQueue
+
+import json
+import pathlib
+from typing import Dict, List
+
+
+class TestGraph:
+ def __init__(self, json_filepaths: List[pathlib.Path]):
+ # Initialize graph from JSON file. Note that this is implemented without
+ # accessing any benchmark environment or configuration. This ways benchmarks
+ # run on various machines can be aggregated and the graph generated on another
+ # machine.
+
+ # Gather entries for each device.
+ devices = {}
+
+ for json_filepath in json_filepaths:
+ queue = TestQueue(json_filepath)
+
+ for entry in queue.entries:
+ if entry.status in ('done', 'outdated'):
+ device_name = entry.device_name
+ if device_name in devices.keys():
+ devices[device_name].append(entry)
+ else:
+ devices[device_name] = [entry]
+
+ data = []
+ for device_name, device_entries in devices.items():
+ # Gather used categories.
+ categories = {}
+ for entry in device_entries:
+ category = entry.category
+ if category in categories.keys():
+ categories[category].append(entry)
+ else:
+ categories[category] = [entry]
+
+ # Generate one graph for every device x category x result key combination.
+ for category, category_entries in categories.items():
+ entries = sorted(category_entries, key=lambda entry: (entry.revision, entry.test))
+
+ outputs = set()
+ for entry in entries:
+ for output in entry.output.keys():
+ outputs.add(output)
+
+ chart_type = 'line' if entries[0].benchmark_type == 'time_series' else 'comparison'
+
+ for output in outputs:
+ chart_name = f"{category} ({output})"
+ data.append(self.chart(device_name, chart_name, entries, chart_type, output))
+
+ self.json = json.dumps(data, indent=2)
+
+ def chart(self, device_name: str, chart_name: str, entries: List, chart_type: str, output: str) -> Dict:
+ # Gather used tests.
+ tests = {}
+ for entry in entries:
+ test = entry.test
+ if test not in tests.keys():
+ tests[test] = len(tests)
+
+ # Gather used revisions.
+ revisions = {}
+ revision_dates = {}
+ for entry in entries:
+ revision = entry.revision
+ if revision not in revisions.keys():
+ revisions[revision] = len(revisions)
+ revision_dates[revision] = int(entry.date)
+
+ # Google Charts JSON data layout is like a spreadsheat table, with
+ # colums, rows and cells. We create one column for revision labels,
+ # and one column for each test.
+ cols = []
+ if chart_type == 'line':
+ cols.append({'id': '', 'label': 'Date', 'type': 'date'})
+ else:
+ cols.append({'id': '', 'label': ' ', 'type': 'string'})
+ for test, test_index in tests.items():
+ cols.append({'id': '', 'label': test, 'type': 'number'})
+
+ rows = []
+ for revision, revision_index in revisions.items():
+ if chart_type == 'line':
+ date = revision_dates[revision]
+ row = [{'f': None, 'v': 'Date({0})'.format(date * 1000)}]
+ else:
+ row = [{'f': None, 'v': revision}]
+ row += [{}] * len(tests)
+ rows.append({'c': row})
+
+ for entry in entries:
+ test_index = tests[entry.test]
+ revision_index = revisions[entry.revision]
+ time = entry.output[output] if output in entry.output else -1.0
+ rows[revision_index]['c'][test_index + 1] = {'f': None, 'v': time}
+
+ data = {'cols': cols, 'rows': rows}
+ return {'device': device_name, 'name': chart_name, 'data': data, 'chart_type': chart_type}
+
+ def write(self, filepath: pathlib.Path) -> None:
+ # Write HTML page with JSON graph data embedded.
+ template_dir = pathlib.Path(__file__).parent
+ with open(template_dir / 'graph.template.html', 'r') as f:
+ template = f.read()
+
+ contents = template.replace('%JSON_DATA%', self.json)
+ with open(filepath, "w") as f:
+ f.write(contents)
diff --git a/tests/performance/api/graph.template.html b/tests/performance/api/graph.template.html
new file mode 100644
index 00000000000..147f1628c23
--- /dev/null
+++ b/tests/performance/api/graph.template.html
@@ -0,0 +1,86 @@
+<html>
+<head>
+ <title>Benchmarks</title>
+ <meta charset="UTF-8">
+ <style type="text/css">
+ body { margin: 40px auto;
+ font-family: Arial;
+ font-size: 14px;
+ color: #333;
+ max-width: 900px; }
+ a { text-decoration: none; color: #06b; }
+ </style>
+ <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
+ <script>
+ google.charts.load('current', {'packages':['line', 'bar']});
+ google.charts.setOnLoadCallback(draw_charts);
+
+ function transposeDataTable(dt)
+ {
+ /* Swap rows and columns. Bar and line charts expect different layouts,
+ * with this function we can use the same data source for both. */
+ var ndt = new google.visualization.DataTable;
+ ndt.addColumn('string',dt.getColumnLabel(0));
+ for(var x=1; x<dt.getNumberOfColumns(); x++) {
+ ndt.addRow([dt.getColumnLabel(x)]);
+ }
+ for(var x=0; x<dt.getNumberOfRows(); x++) {
+ ndt.addColumn('number', dt.getValue(x,0));
+ for(var y=1; y<dt.getNumberOfColumns(); y++) {
+ ndt.setValue(y-1, x+1, dt.getValue(x,y));
+ }
+ }
+ return ndt;
+ }
+
+ function draw_charts()
+ {
+ /* Load JSON data. */
+ var json_data = %JSON_DATA%;
+
+ /* Clear contents. */
+ charts_elem = document.getElementById("charts");
+ while(charts_elem.firstChild)
+ {
+ charts_elem.removeChild(charts_elem.firstChild);
+ }
+
+ /* Draw charts for each device. */
+ for (var i = 0; i < json_data.length; i++)
+ {
+ device = json_data[i];
+
+ /* Chart drawing options. */
+ var options = {
+ chart: {title: device["name"], subtitle: device['device']},
+ pointsVisible: true,
+ pointSize: 2.5,
+ height: 500,
+ };
+
+ /* Create chart div. */
+ elem = document.createElement('div');
+ elem.id = device["id"];
+ charts_elem.appendChild(elem)
+
+ /* Create chart. */
+ var data = new google.visualization.DataTable(device["data"]);
+ if (device['chart_type'] == 'line') {
+ var chart = new google.charts.Line(elem);
+ chart.draw(data, options);
+ }
+ else {
+ var chart = new google.charts.Bar(elem);
+ chart.draw(transposeDataTable(data), options);
+ }
+ }
+ }
+ </script>
+</head>
+<body>
+ <h1>Benchmarks</h1>
+ <div id="charts">
+ ...
+ </div>
+</body>
+</html>
diff --git a/tests/performance/api/test.py b/tests/performance/api/test.py
new file mode 100644
index 00000000000..7e8193d2c21
--- /dev/null
+++ b/tests/performance/api/test.py
@@ -0,0 +1,73 @@
+# Apache License, Version 2.0
+
+import abc
+import fnmatch
+from typing import Dict, List
+
+
+class Test:
+ @abc.abstractmethod
+ def name(self) -> str:
+ """
+ Name of the test.
+ """
+
+ @abc.abstractmethod
+ def category(self) -> str:
+ """
+ Category of the test.
+ """
+
+ def use_device(self) -> bool:
+ """
+ Test uses a specific CPU or GPU device.
+ """
+ return False
+
+ @abc.abstractmethod
+ def run(self, env, device_id: str) -> Dict:
+ """
+ Execute the test and report results.
+ """
+
+
+class TestCollection:
+ def __init__(self, env, names_filter: List=['*'], categories_filter: List=['*']):
+ import importlib
+ import pkgutil
+ import tests
+
+ self.tests = []
+
+ # Find and import all Python files in the tests folder, and generate
+ # the list of tests for each.
+ for _, modname, _ in pkgutil.iter_modules(tests.__path__, 'tests.'):
+ module = importlib.import_module(modname)
+ tests = module.generate(env)
+
+ for test in tests:
+ test_category = test.category()
+ found = False
+ for category_filter in categories_filter:
+ if fnmatch.fnmatch(test_category, category_filter):
+ found = True
+ if not found:
+ continue
+
+ test_name = test.name()
+ found = False
+ for name_filter in names_filter:
+ if fnmatch.fnmatch(test_name, name_filter):
+ found = True
+ if not found:
+ continue
+
+ self.tests.append(test)
+
+ def find(self, test_name: str, test_category: str):
+ # Find a test based on name and category.
+ for test in self.tests:
+ if test.name() == test_name and test.category() == test_category:
+ return test
+
+ return None
diff --git a/tests/performance/benchmark b/tests/performance/benchmark
new file mode 100755
index 00000000000..3b43bd0aa96
--- /dev/null
+++ b/tests/performance/benchmark
@@ -0,0 +1,299 @@
+#!/usr/bin/env python3
+# Apache License, Version 2.0
+
+import api
+import argparse
+import fnmatch
+import pathlib
+import shutil
+import sys
+import time
+from typing import List
+
+def find_blender_git_dir() -> pathlib.Path:
+ # Find .git directory of the repository we are in.
+ cwd = pathlib.Path.cwd()
+
+ for path in [cwd] + list(cwd.parents):
+ if (path / '.git').exists():
+ return path
+
+ return None
+
+def get_tests_base_dir(blender_git_dir: pathlib.Path) -> pathlib.Path:
+ # Benchmarks dir is next to the Blender source folder.
+ return blender_git_dir.parent / 'benchmark'
+
+def use_revision_columns(config: api.TestConfig) -> bool:
+ return config.benchmark_type == "comparison" and \
+ len(config.queue.entries) > 0 and \
+ not config.queue.has_multiple_revisions_to_build
+
+def print_header(config: api.TestConfig) -> None:
+ # Print header with revision columns headers.
+ if use_revision_columns(config):
+ header = ""
+ if config.queue.has_multiple_categories:
+ header += f"{'': <15} "
+ header += f"{'': <40} "
+
+ for revision_name in config.revision_names():
+ header += f"{revision_name: <20} "
+ print(header)
+
+def print_row(config: api.TestConfig, entries: List, end='\n') -> None:
+ # Print one or more test entries on a row.
+ row = ""
+
+ # For time series, print revision first.
+ if not use_revision_columns(config):
+ revision = entries[0].revision
+ git_hash = entries[0].git_hash
+
+ row += f"{revision: <15} "
+
+ if config.queue.has_multiple_categories:
+ row += f"{entries[0].category: <15} "
+ row += f"{entries[0].test: <40} "
+
+ for entry in entries:
+ # Show time or status.
+ status = entry.status
+ output = entry.output
+ result = ''
+ if status in ('done', 'outdated') and output:
+ result = '%.4fs' % output['time']
+
+ if status == 'outdated':
+ result += " (outdated)"
+ else:
+ result = status
+
+ row += f"{result: <20} "
+
+ print(row, end=end, flush=True)
+
+
+def match_entry(entry: api.TestEntry, args: argparse.Namespace):
+ # Filter tests by name and category.
+ return fnmatch.fnmatch(entry.test, args.test) or \
+ fnmatch.fnmatch(entry.category, args.test) or \
+ entry.test.find(args.test) != -1 or \
+ entry.category.find(args.test) != -1
+
+def run_entry(env: api.TestEnvironment, config: api.TestConfig, row: List, entry: api.TestEntry):
+ # Check if entry needs to be run.
+ if entry.status not in ('queued', 'outdated'):
+ print_row(config, row, end='\r')
+ return False
+
+ # Run test entry.
+ revision = entry.revision
+ git_hash = entry.git_hash
+ testname = entry.test
+ testcategory = entry.category
+ device_type = entry.device_type
+ device_id = entry.device_id
+
+ test = config.tests.find(testname, testcategory)
+ if not test:
+ return False
+
+ # Log all output to dedicated log file.
+ logname = testcategory + '_' + testname + '_' + revision
+ if device_id != 'CPU':
+ logname += '_' + device_id
+ env.set_log_file(config.logs_dir / (logname + '.log'), clear=True)
+
+ # Build revision, or just set path to existing executable.
+ entry.status = 'building'
+ print_row(config, row, end='\r')
+ if len(entry.executable):
+ env.set_blender_executable(pathlib.Path(entry.executable))
+ else:
+ env.checkout(git_hash)
+ env.build(git_hash)
+
+ # Run test and update output and status.
+ entry.status = 'running'
+ print_row(config, row, end='\r')
+ entry.output = test.run(env, device_id)
+ entry.status = 'done' if entry.output else 'failed'
+ print_row(config, row, end='\r')
+
+ # Update device name in case the device changed since the entry was created.
+ entry.device_name = config.device_name(device_id)
+
+ # Restore default logging and Blender executable.
+ env.unset_log_file()
+ env.unset_blender_executable()
+
+ return True
+
+def cmd_init(env: api.TestEnvironment, argv: List):
+ # Initialize benchmarks folder.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--build', default=False, action='store_true')
+ args = parser.parse_args(argv)
+ env.set_log_file(env.base_dir / 'setup.log', clear=False)
+ env.init(args.build)
+ env.unset_log_file()
+
+def cmd_list(env: api.TestEnvironment, argv: List) -> None:
+ # List devices, tests and configurations.
+ print('DEVICES')
+ machine = env.get_machine()
+ for device in machine.devices:
+ name = f"{device.name} ({device.operating_system})"
+ print(f"{device.id: <15} {name}")
+ print('')
+
+ print('TESTS')
+ collection = api.TestCollection(env)
+ for test in collection.tests:
+ print(f"{test.category(): <15} {test.name(): <50}")
+ print('')
+
+ print('CONFIGS')
+ configs = env.get_configs(names_only=True)
+ for config_name in configs:
+ print(config_name)
+
+def cmd_status(env: api.TestEnvironment, argv: List):
+ # Print status of tests in configurations.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('config', nargs='?', default=None)
+ parser.add_argument('test', nargs='?', default='*')
+ args = parser.parse_args(argv)
+
+ configs = env.get_configs(args.config)
+ first = True
+ for config in configs:
+ if not args.config:
+ if first:
+ first = False
+ else:
+ print("")
+ print(config.name.upper())
+
+ print_header(config)
+ for row in config.queue.rows(use_revision_columns(config)):
+ if match_entry(row[0], args):
+ print_row(config, row)
+
+def cmd_reset(env: api.TestEnvironment, argv: List):
+ # Reset tests to re-run them.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('config', nargs='?', default=None)
+ parser.add_argument('test', nargs='?', default='*')
+ args = parser.parse_args(argv)
+
+ configs = env.get_configs(args.config)
+ for config in configs:
+ print_header(config)
+ for row in config.queue.rows(use_revision_columns(config)):
+ if match_entry(row[0], args):
+ for entry in row:
+ entry.status = 'queued'
+ entry.result = {}
+ print_row(config, row)
+
+ config.queue.write()
+
+def cmd_run(env: api.TestEnvironment, argv: List):
+ # Run tests.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('config', nargs='?', default=None)
+ parser.add_argument('test', nargs='?', default='*')
+ args = parser.parse_args(argv)
+
+ configs = env.get_configs(args.config)
+ for config in configs:
+ updated = False
+ print_header(config)
+ for row in config.queue.rows(use_revision_columns(config)):
+ if match_entry(row[0], args):
+ for entry in row:
+ if run_entry(env, config, row, entry):
+ updated = True
+ # Write queue every time in case running gets interrupted,
+ # so it can be resumed.
+ config.queue.write()
+ print_row(config, row)
+
+ if updated:
+ # Generate graph if test were run.
+ json_filepath = config.base_dir / "results.json"
+ html_filepath = config.base_dir / "results.html"
+ graph = api.TestGraph([json_filepath])
+ graph.write(html_filepath)
+
+ print("\nfile://" + str(html_filepath))
+
+def cmd_graph(argv: List):
+ # Create graph from a given JSON results file.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('json_file', nargs='+')
+ parser.add_argument('-o', '--output', type=str, required=True)
+ args = parser.parse_args(argv)
+
+ graph = api.TestGraph([pathlib.Path(path) for path in args.json_file])
+ graph.write(pathlib.Path(args.output))
+
+def main():
+ usage = ('benchmark <command> [<args>]\n'
+ '\n'
+ 'Commands:\n'
+ ' init [--build] Init benchmarks directory and default config\n'
+ ' Optionally with automated revision building setup\n'
+ ' \n'
+ ' list List available tests, devices and configurations\n'
+ ' \n'
+ ' run [<config>] [<test>] Execute tests for configuration\n'
+ ' reset [<config>] [<test>] Clear tests results from config, for re-running\n'
+ ' status [<config>] [<test>] List configurations and their tests\n'
+ ' \n'
+ ' graph a.json b.json... -o out.html Create graph from results in JSON files\n')
+
+ parser = argparse.ArgumentParser(
+ description='Blender performance testing',
+ usage=usage)
+
+ parser.add_argument('command', nargs='?', default='help')
+ args = parser.parse_args(sys.argv[1:2])
+
+ argv = sys.argv[2:]
+ blender_git_dir = find_blender_git_dir()
+ if blender_git_dir == None:
+ sys.stderr.write('Error: no blender git repository found from current working directory\n')
+ sys.exit(1)
+
+ if args.command == 'graph':
+ cmd_graph(argv)
+ sys.exit(0)
+
+ base_dir = get_tests_base_dir(blender_git_dir)
+ env = api.TestEnvironment(blender_git_dir, base_dir)
+ if args.command == 'init':
+ cmd_init(env, argv)
+ sys.exit(0)
+
+ if not env.base_dir.exists():
+ sys.stderr.write('Error: benchmark directory not initialized\n')
+ sys.exit(1)
+
+ if args.command == 'list':
+ cmd_list(env, argv)
+ elif args.command == 'run':
+ cmd_run(env, argv)
+ elif args.command == 'reset':
+ cmd_reset(env, argv)
+ elif args.command == 'status':
+ cmd_status(env, argv)
+ elif args.command == 'help':
+ parser.print_usage()
+ else:
+ sys.stderr.write(f'Unknown command: {args.command}\n')
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/performance/tests/__init__.py b/tests/performance/tests/__init__.py
new file mode 100644
index 00000000000..ac3e613174f
--- /dev/null
+++ b/tests/performance/tests/__init__.py
@@ -0,0 +1 @@
+# Apache License, Version 2.0
diff --git a/tests/performance/tests/animation.py b/tests/performance/tests/animation.py
new file mode 100644
index 00000000000..1a92f1a9718
--- /dev/null
+++ b/tests/performance/tests/animation.py
@@ -0,0 +1,41 @@
+# Apache License, Version 2.0
+
+import api
+import os
+
+
+def _run(args):
+ import bpy
+ import time
+
+ start_time = time.time()
+
+ scene = bpy.context.scene
+ for i in range(scene.frame_start, scene.frame_end):
+ scene.frame_set(scene.frame_start)
+
+ elapsed_time = time.time() - start_time
+
+ result = {'time': elapsed_time}
+ return result
+
+
+class AnimationTest(api.Test):
+ def __init__(self, filepath):
+ self.filepath = filepath
+
+ def name(self):
+ return self.filepath.stem
+
+ def category(self):
+ return "animation"
+
+ def run(self, env, device_id):
+ args = {}
+ result, _ = env.run_in_blender(_run, args)
+ return result
+
+
+def generate(env):
+ filepaths = env.find_blend_files('animation')
+ return [AnimationTest(filepath) for filepath in filepaths]
diff --git a/tests/performance/tests/blend_load.py b/tests/performance/tests/blend_load.py
new file mode 100644
index 00000000000..5fe498fd3d7
--- /dev/null
+++ b/tests/performance/tests/blend_load.py
@@ -0,0 +1,42 @@
+# Apache License, Version 2.0
+
+import api
+import os
+import pathlib
+
+
+def _run(filepath):
+ import bpy
+ import time
+
+ # Load once to ensure it's cached by OS
+ bpy.ops.wm.open_mainfile(filepath=filepath)
+ bpy.ops.wm.read_homefile()
+
+ # Measure loading the second time
+ start_time = time.time()
+ bpy.ops.wm.open_mainfile(filepath=filepath)
+ elapsed_time = time.time() - start_time
+
+ result = {'time': elapsed_time}
+ return result
+
+
+class BlendLoadTest(api.Test):
+ def __init__(self, filepath):
+ self.filepath = filepath
+
+ def name(self):
+ return self.filepath.stem
+
+ def category(self):
+ return "blend_load"
+
+ def run(self, env, device_id):
+ result, _ = env.run_in_blender(_run, str(self.filepath))
+ return result
+
+
+def generate(env):
+ filepaths = env.find_blend_files('*/*')
+ return [BlendLoadTest(filepath) for filepath in filepaths]
diff --git a/tests/performance/tests/cycles.py b/tests/performance/tests/cycles.py
new file mode 100644
index 00000000000..bac6b8a7ceb
--- /dev/null
+++ b/tests/performance/tests/cycles.py
@@ -0,0 +1,92 @@
+# Apache License, Version 2.0
+
+import api
+import os
+
+
+def _run(args):
+ import bpy
+ import time
+
+ device_type = args['device_type']
+ device_index = args['device_index']
+
+ scene = bpy.context.scene
+ scene.render.engine = 'CYCLES'
+ scene.render.filepath = args['render_filepath']
+ scene.render.image_settings.file_format = 'PNG'
+ scene.cycles.device = 'CPU' if device_type == 'CPU' else 'GPU'
+
+ if scene.cycles.device == 'GPU':
+ # Enable specified GPU in preferences.
+ prefs = bpy.context.preferences
+ cprefs = prefs.addons['cycles'].preferences
+ cprefs.compute_device_type = device_type
+ devices = cprefs.get_devices_for_type(device_type)
+ for device in devices:
+ device.use = False
+
+ index = 0
+ for device in devices:
+ if device.type == device_type:
+ if index == device_index:
+ device.use = True
+ break
+ else:
+ index += 1
+
+ # Render
+ bpy.ops.render.render(write_still=True)
+
+ return None
+
+
+class CyclesTest(api.Test):
+ def __init__(self, filepath):
+ self.filepath = filepath
+
+ def name(self):
+ return self.filepath.stem
+
+ def category(self):
+ return "cycles"
+
+ def use_device(self):
+ return True
+
+ def run(self, env, device_id):
+ tokens = device_id.split('_')
+ device_type = tokens[0]
+ device_index = int(tokens[1]) if len(tokens) > 1 else 0
+ args = {'device_type': device_type,
+ 'device_index': device_index,
+ 'render_filepath': str(env.log_file.parent / (env.log_file.stem + '.png'))}
+
+ _, lines = env.run_in_blender(_run, args, ['--debug-cycles', '--verbose', '1', self.filepath])
+
+ # Parse render time from output
+ prefix_time = "Render time (without synchronization): "
+ prefix_memory = "Peak: "
+ time = None
+ memory = None
+ for line in lines:
+ line = line.strip()
+ offset = line.find(prefix_time)
+ if offset != -1:
+ time = line[offset + len(prefix_time):]
+ time = float(time)
+ offset = line.find(prefix_memory)
+ if offset != -1:
+ memory = line[offset + len(prefix_memory):]
+ memory = memory.split()[0].replace(',', '')
+ memory = float(memory)
+
+ if not (time and memory):
+ raise Exception("Error parsing render time output")
+
+ return {'time': time, 'peak_memory': memory}
+
+
+def generate(env):
+ filepaths = env.find_blend_files('cycles-x/*')
+ return [CyclesTest(filepath) for filepath in filepaths]
diff --git a/tests/python/alembic_export_tests.py b/tests/python/alembic_export_tests.py
index 9d1738691f0..23a4a376533 100644
--- a/tests/python/alembic_export_tests.py
+++ b/tests/python/alembic_export_tests.py
@@ -197,7 +197,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest):
def test_hierarchical_export(self, tempdir: pathlib.Path):
abc = tempdir / 'cubes_hierarchical.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix()
+ "visible_objects_only=True, flatten=False)" % abc.as_posix()
self.run_blender('cubes-hierarchy.blend', script)
# Now check the resulting Alembic file.
@@ -215,7 +215,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest):
def test_flat_export(self, tempdir: pathlib.Path):
abc = tempdir / 'cubes_flat.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix()
+ "visible_objects_only=True, flatten=True)" % abc.as_posix()
self.run_blender('cubes-hierarchy.blend', script)
# Now check the resulting Alembic file.
@@ -236,7 +236,7 @@ class DupliGroupExportTest(AbstractAlembicTest):
def test_hierarchical_export(self, tempdir: pathlib.Path):
abc = tempdir / 'dupligroup_hierarchical.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix()
+ "visible_objects_only=True, flatten=False)" % abc.as_posix()
self.run_blender('dupligroup-scene.blend', script)
# Now check the resulting Alembic file.
@@ -254,7 +254,7 @@ class DupliGroupExportTest(AbstractAlembicTest):
def test_flat_export(self, tempdir: pathlib.Path):
abc = tempdir / 'dupligroup_hierarchical.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix()
+ "visible_objects_only=True, flatten=True)" % abc.as_posix()
self.run_blender('dupligroup-scene.blend', script)
# Now check the resulting Alembic file.
@@ -332,7 +332,7 @@ class CurveExportTest(AbstractAlembicTest):
def test_export_single_curve(self, tempdir: pathlib.Path):
abc = tempdir / 'single-curve.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix()
+ "visible_objects_only=True, flatten=False)" % abc.as_posix()
self.run_blender('single-curve.blend', script)
# Now check the resulting Alembic file.
@@ -353,7 +353,7 @@ class HairParticlesExportTest(AbstractAlembicTest):
def _do_test(self, tempdir: pathlib.Path, export_hair: bool, export_particles: bool) -> pathlib.Path:
abc = tempdir / 'hair-particles.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=True, visible_objects_only=True, flatten=False, " \
+ "visible_objects_only=True, flatten=False, " \
"export_hair=%r, export_particles=%r, as_background_job=False)" \
% (abc.as_posix(), export_hair, export_particles)
self.run_blender('hair-particles.blend', script)
@@ -419,7 +419,7 @@ class UVMapExportTest(AbstractAlembicTest):
basename = 'T77021-multiple-uvmaps-animated-mesh'
abc = tempdir / f'{basename}.abc'
script = f"import bpy; bpy.ops.wm.alembic_export(filepath='{abc.as_posix()}', start=1, end=1, " \
- f"renderable_only=True, visible_objects_only=True, flatten=False)"
+ f"visible_objects_only=True, flatten=False)"
self.run_blender(f'{basename}.blend', script)
self.maxDiff = 1000
@@ -468,7 +468,7 @@ class LongNamesExportTest(AbstractAlembicTest):
def test_export_long_names(self, tempdir: pathlib.Path):
abc = tempdir / 'long-names.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
- "renderable_only=False, visible_objects_only=False, flatten=False)" % abc.as_posix()
+ "visible_objects_only=False, flatten=False)" % abc.as_posix()
self.run_blender('long-names.blend', script)
name_parts = [
@@ -565,7 +565,7 @@ class InvisibleObjectExportTest(AbstractAlembicTest):
def test_hierarchical_export(self, tempdir: pathlib.Path):
abc = tempdir / 'visibility.abc'
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=2, " \
- "renderable_only=False, visible_objects_only=False)" % abc.as_posix()
+ "visible_objects_only=False)" % abc.as_posix()
self.run_blender('visibility.blend', script)
def test(cube_name: str, expect_visible: bool):
diff --git a/tests/python/bl_alembic_io_test.py b/tests/python/bl_alembic_io_test.py
index 53a0879f160..c0d0bcdea70 100644
--- a/tests/python/bl_alembic_io_test.py
+++ b/tests/python/bl_alembic_io_test.py
@@ -300,7 +300,6 @@ class CameraExportImportTest(unittest.TestCase):
abc_path = self.tempdir / "camera_transforms.abc"
self.assertIn('FINISHED', bpy.ops.wm.alembic_export(
filepath=str(abc_path),
- renderable_only=False,
flatten=flatten,
))
diff --git a/tests/python/bl_animation_fcurves.py b/tests/python/bl_animation_fcurves.py
index 2ec04749d70..9017c1ee037 100644
--- a/tests/python/bl_animation_fcurves.py
+++ b/tests/python/bl_animation_fcurves.py
@@ -40,6 +40,7 @@ class AbstractAnimationTest:
self.assertTrue(self.testdir.exists(),
'Test dir %s should exist' % self.testdir)
+
class FCurveEvaluationTest(AbstractAnimationTest, unittest.TestCase):
def test_fcurve_versioning_291(self):
# See D8752.
diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py
index 48625a1ecdb..c9c89c01cee 100644
--- a/tests/python/bl_blendfile_library_overrides.py
+++ b/tests/python/bl_blendfile_library_overrides.py
@@ -69,7 +69,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
assert(len(local_id.override_library.properties) == 1)
override_prop = local_id.override_library.properties[0]
- assert(override_prop.rna_path == "location");
+ assert(override_prop.rna_path == "location")
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'REPLACE')
@@ -96,7 +96,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
self.assertIsNone(local_id.data.override_library)
assert(len(local_id.override_library.properties) == 1)
override_prop = local_id.override_library.properties[0]
- assert(override_prop.rna_path == "scale");
+ assert(override_prop.rna_path == "scale")
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'NOOP')
@@ -116,14 +116,14 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
assert(len(local_id.override_library.properties) == 2)
override_prop = local_id.override_library.properties[0]
- assert(override_prop.rna_path == "scale");
+ assert(override_prop.rna_path == "scale")
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'NOOP')
assert(override_operation.subitem_local_index == -1)
override_prop = local_id.override_library.properties[1]
- assert(override_prop.rna_path == "location");
+ assert(override_prop.rna_path == "location")
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
assert(override_operation.operation == 'REPLACE')
diff --git a/tests/python/bl_constraints.py b/tests/python/bl_constraints.py
index 279c896c6af..a2690fa4e11 100644
--- a/tests/python/bl_constraints.py
+++ b/tests/python/bl_constraints.py
@@ -375,6 +375,70 @@ class CustomSpaceTest(AbstractConstraintTests):
)))
+class CopyTransformsTest(AbstractConstraintTests):
+ layer_collection = 'Copy Transforms'
+
+ def test_mix_mode_object(self):
+ """Copy Transforms: all mix modes for objects"""
+ constraint = bpy.data.objects["Copy Transforms.object.owner"].constraints["Copy Transforms"]
+
+ constraint.mix_mode = 'REPLACE'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-0.7818737626075745, 0.14389121532440186, 0.4845699667930603, -0.017531070858240128),
+ (-0.2741589844226837, -0.591389000415802, -1.2397242784500122, -0.08039521425962448),
+ (0.04909384995698929, -1.0109175443649292, 0.7942137122154236, 0.1584688276052475),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+ constraint.mix_mode = 'BEFORE_FULL'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-1.0791258811950684, -0.021011866629123688, 0.3120136260986328, 0.9082338809967041),
+ (0.2128538191318512, -0.3411901891231537, -1.7376484870910645, -0.39762523770332336),
+ (-0.03584420680999756, -1.0162957906723022, 0.8004404306411743, -0.9015425443649292),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+ constraint.mix_mode = 'BEFORE'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-0.9952367544174194, -0.03077685832977295, 0.05301344022154808, 0.9082338809967041),
+ (-0.013416174799203873, -0.39984768629074097, -1.8665285110473633, -0.39762523770332336),
+ (0.03660336509346962, -0.9833710193634033, 0.75728839635849, -0.9015425443649292),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+ constraint.mix_mode = 'BEFORE_SPLIT'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-0.9952367544174194, -0.03077685832977295, 0.05301344022154808, -1.0175310373306274),
+ (-0.013416174799203873, -0.39984768629074097, -1.8665285110473633, 0.9196047782897949),
+ (0.03660336509346962, -0.9833710193634033, 0.75728839635849, 0.1584688276052475),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+ constraint.mix_mode = 'AFTER_FULL'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-0.8939255475997925, -0.2866469621658325, 0.7563635110855103, -0.964445173740387),
+ (-0.09460853785276413, -0.73727947473526, -1.0267245769500732, 0.9622588753700256),
+ (0.37042146921157837, -1.1893107891082764, 1.0113294124603271, 0.21314144134521484),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+ constraint.mix_mode = 'AFTER'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-0.9033845067024231, -0.2048732340335846, 0.7542480826377869, -0.964445173740387),
+ (-0.1757974475622177, -0.6721230745315552, -1.5190268754959106, 0.9622588753700256),
+ (0.38079890608787537, -0.7963172793388367, 1.0880682468414307, 0.21314144134521484),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+ constraint.mix_mode = 'AFTER_SPLIT'
+ self.matrix_test('Copy Transforms.object.owner', Matrix((
+ (-0.9033845067024231, -0.2048732340335846, 0.7542480826377869, -1.0175310373306274),
+ (-0.1757974475622177, -0.6721230745315552, -1.5190268754959106, 0.9196047782897949),
+ (0.38079890608787537, -0.7963172793388367, 1.0880682468414307, 0.1584688276052475),
+ (0.0, 0.0, 0.0, 1.0)
+ )))
+
+
def main():
global args
import argparse
diff --git a/tests/python/bl_pyapi_idprop.py b/tests/python/bl_pyapi_idprop.py
index 1e570bf9a7f..38cd9d04a6b 100644
--- a/tests/python/bl_pyapi_idprop.py
+++ b/tests/python/bl_pyapi_idprop.py
@@ -140,6 +140,7 @@ class TestIdPropertyCreation(TestHelper, unittest.TestCase):
with self.assertRaises(TypeError):
self.id["a"] = self
+
class TestIdPropertyGroupView(TestHelper, unittest.TestCase):
def test_type(self):
diff --git a/tests/python/bl_run_operators_event_simulate.py b/tests/python/bl_run_operators_event_simulate.py
index 92315d3e853..1cc621b9684 100644
--- a/tests/python/bl_run_operators_event_simulate.py
+++ b/tests/python/bl_run_operators_event_simulate.py
@@ -165,6 +165,16 @@ def gen_events_type_text(text):
yield dict(type=type, value='RELEASE', **kw_extra)
+def repr_action(name, args, kwargs):
+ return "%s(%s)" % (
+ name,
+ ", ".join(
+ [repr(value) for value in args] +
+ [("%s=%r" % (key, value)) for key, value in kwargs.items()]
+ )
+ )
+
+
# -----------------------------------------------------------------------------
# Simulate Events
@@ -505,6 +515,18 @@ def argparse_create():
required=False,
)
+ parser.add_argument(
+ "--time-actions",
+ dest="time_actions",
+ default=False,
+ action="store_true",
+ help=(
+ "Display the time each action takes\n"
+ "(useful for measuring delay between key-presses)."
+ ),
+ required=False,
+ )
+
# Collect doc-strings from static methods in `actions`.
actions_docstring = []
for action_key in ACTION_DIR:
@@ -554,7 +576,7 @@ def setup_default_preferences(prefs):
# Main Function
-def main_event_iter(*, action_list):
+def main_event_iter(*, action_list, time_actions):
"""
Yield all events from action handlers.
"""
@@ -565,9 +587,18 @@ def main_event_iter(*, action_list):
yield dict(type='MOUSEMOVE', value='NOTHING', x=x_init, y=y_init)
+ if time_actions:
+ import time
+ t_prev = time.time()
+
for (op, args, kwargs) in action_list:
yield from handle_action(op, args, kwargs)
+ if time_actions:
+ t = time.time()
+ print("%.4f: %s" % ((t - t_prev), repr_action(op, args, kwargs)))
+ t_prev = t
+
def main():
from sys import argv
@@ -588,7 +619,7 @@ def main():
bpy.app.use_event_simulate = False
run_event_simulate(
- event_iter=main_event_iter(action_list=args.actions),
+ event_iter=main_event_iter(action_list=args.actions, time_actions=args.time_actions),
exit_fn=exit_fn,
)
diff --git a/tests/python/compositor_render_tests.py b/tests/python/compositor_render_tests.py
index 057d4a2e6dd..199e1c13b8e 100644
--- a/tests/python/compositor_render_tests.py
+++ b/tests/python/compositor_render_tests.py
@@ -16,6 +16,7 @@ try:
except ImportError:
inside_blender = False
+
def get_arguments(filepath, output_filepath):
return [
"--background",
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
index 36c3f7d9fe5..ca0bc9f18b9 100644
--- a/tests/python/cycles_render_tests.py
+++ b/tests/python/cycles_render_tests.py
@@ -57,6 +57,7 @@ BLACKLIST_GPU = [
'transparent_shadow_hair.*.blend',
]
+
def get_arguments(filepath, output_filepath):
dirname = os.path.dirname(filepath)
basedir = os.path.dirname(dirname)
diff --git a/tests/python/modules/mesh_test.py b/tests/python/modules/mesh_test.py
index 1749e798a32..6d921959e6f 100644
--- a/tests/python/modules/mesh_test.py
+++ b/tests/python/modules/mesh_test.py
@@ -680,7 +680,7 @@ class RunTest:
test_name = each_test.test_name
if self.verbose:
print()
- print("Running test {}/{}: {}...".format(test_number+1, len(self.tests), test_name))
+ print("Running test {}/{}: {}...".format(test_number + 1, len(self.tests), test_name))
success = self.run_test(test_name)
if not success:
diff --git a/tests/python/modules/render_report.py b/tests/python/modules/render_report.py
index c1ae0b05fcd..560f8e33585 100755
--- a/tests/python/modules/render_report.py
+++ b/tests/python/modules/render_report.py
@@ -287,7 +287,7 @@ class Report:
-moz-background-size:50px 50px;
background-size:50px 50px;
- -webkit-background-size:50px 51px; /* override value for shitty webkit */
+ -webkit-background-size:50px 51px; /* Override value for silly webkit. */
background-position:0 0, 25px 0, 25px -25px, 0px 25px;
}}
diff --git a/tests/python/operators.py b/tests/python/operators.py
index c209b01c20c..4501df82175 100644
--- a/tests/python/operators.py
+++ b/tests/python/operators.py
@@ -321,7 +321,7 @@ def main():
MeshTest("CubeEdgeUnsubdivide", "testCubeEdgeUnsubdivide", "expectedCubeEdgeUnsubdivide",
[OperatorSpecEditMode("unsubdivide", {}, "EDGE", {i for i in range(6)})]),
MeshTest("UVSphereUnsubdivide", "testUVSphereUnsubdivide", "expectedUVSphereUnsubdivide",
- [OperatorSpecEditMode("unsubdivide", {'iterations': 9}, "FACE", {i for i in range(512)})]),
+ [OperatorSpecEditMode("unsubdivide", {'iterations': 9}, "FACE", {i for i in range(512)})]),
# vert connect path
# Tip: It works only if there is an already existing face or more than 2 vertices.